]>
Commit | Line | Data |
---|---|---|
eb2c670e SLM |
1 | From 6255a964f4da99e383ff4382ebce2efae4d26b3b Mon Sep 17 00:00:00 2001 |
2 | From: Florian Westphal <fw@strlen.de> | |
3 | Date: Fri, 12 Apr 2019 10:55:03 -0700 | |
4 | Subject: netfilter: nfnetlink_cttimeout: fetch timeouts for udplite and gre, | |
5 | too | |
6 | ||
7 | commit 89259088c1b7fecb43e8e245dc931909132a4e03 upstream | |
8 | ||
9 | syzbot was able to trigger the WARN in cttimeout_default_get() by | |
10 | passing UDPLITE as l4protocol. Alias UDPLITE to UDP, both use | |
11 | same timeout values. | |
12 | ||
13 | Furthermore, also fetch GRE timeouts. GRE is a bit more complicated, | |
14 | as it still can be a module and its netns_proto_gre struct layout isn't | |
15 | visible outside of the gre module. Can't move timeouts around, it | |
16 | appears conntrack sysctl unregister assumes net_generic() returns | |
17 | nf_proto_net, so we get crash. Expose layout of netns_proto_gre instead. | |
18 | ||
19 | A followup nf-next patch could make gre tracker be built-in as well | |
20 | if needed, its not that large. | |
21 | ||
22 | Last, make the WARN() mention the missing protocol value in case | |
23 | anything else is missing. | |
24 | ||
25 | Reported-by: syzbot+2fae8fa157dd92618cae@syzkaller.appspotmail.com | |
26 | Fixes: 8866df9264a3 ("netfilter: nfnetlink_cttimeout: pass default timeout policy to obj_to_nlattr") | |
27 | Signed-off-by: Florian Westphal <fw@strlen.de> | |
28 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |
29 | Signed-off-by: Zubin Mithra <zsm@chromium.org> | |
30 | Signed-off-by: Sasha Levin (Microsoft) <sashal@kernel.org> | |
31 | --- | |
32 | include/linux/netfilter/nf_conntrack_proto_gre.h | 13 +++++++++++++ | |
33 | net/netfilter/nf_conntrack_proto_gre.c | 14 ++------------ | |
34 | net/netfilter/nfnetlink_cttimeout.c | 15 +++++++++++++-- | |
35 | 3 files changed, 28 insertions(+), 14 deletions(-) | |
36 | ||
37 | diff --git a/include/linux/netfilter/nf_conntrack_proto_gre.h b/include/linux/netfilter/nf_conntrack_proto_gre.h | |
38 | index b8d95564bd53..14edb795ab43 100644 | |
39 | --- a/include/linux/netfilter/nf_conntrack_proto_gre.h | |
40 | +++ b/include/linux/netfilter/nf_conntrack_proto_gre.h | |
41 | @@ -21,6 +21,19 @@ struct nf_ct_gre_keymap { | |
42 | struct nf_conntrack_tuple tuple; | |
43 | }; | |
44 | ||
45 | +enum grep_conntrack { | |
46 | + GRE_CT_UNREPLIED, | |
47 | + GRE_CT_REPLIED, | |
48 | + GRE_CT_MAX | |
49 | +}; | |
50 | + | |
51 | +struct netns_proto_gre { | |
52 | + struct nf_proto_net nf; | |
53 | + rwlock_t keymap_lock; | |
54 | + struct list_head keymap_list; | |
55 | + unsigned int gre_timeouts[GRE_CT_MAX]; | |
56 | +}; | |
57 | + | |
58 | /* add new tuple->key_reply pair to keymap */ | |
59 | int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir, | |
60 | struct nf_conntrack_tuple *t); | |
61 | diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c | |
62 | index 650eb4fba2c5..841c472aae1c 100644 | |
63 | --- a/net/netfilter/nf_conntrack_proto_gre.c | |
64 | +++ b/net/netfilter/nf_conntrack_proto_gre.c | |
65 | @@ -43,24 +43,12 @@ | |
66 | #include <linux/netfilter/nf_conntrack_proto_gre.h> | |
67 | #include <linux/netfilter/nf_conntrack_pptp.h> | |
68 | ||
69 | -enum grep_conntrack { | |
70 | - GRE_CT_UNREPLIED, | |
71 | - GRE_CT_REPLIED, | |
72 | - GRE_CT_MAX | |
73 | -}; | |
74 | - | |
75 | static const unsigned int gre_timeouts[GRE_CT_MAX] = { | |
76 | [GRE_CT_UNREPLIED] = 30*HZ, | |
77 | [GRE_CT_REPLIED] = 180*HZ, | |
78 | }; | |
79 | ||
80 | static unsigned int proto_gre_net_id __read_mostly; | |
81 | -struct netns_proto_gre { | |
82 | - struct nf_proto_net nf; | |
83 | - rwlock_t keymap_lock; | |
84 | - struct list_head keymap_list; | |
85 | - unsigned int gre_timeouts[GRE_CT_MAX]; | |
86 | -}; | |
87 | ||
88 | static inline struct netns_proto_gre *gre_pernet(struct net *net) | |
89 | { | |
90 | @@ -408,6 +396,8 @@ static int __init nf_ct_proto_gre_init(void) | |
91 | { | |
92 | int ret; | |
93 | ||
94 | + BUILD_BUG_ON(offsetof(struct netns_proto_gre, nf) != 0); | |
95 | + | |
96 | ret = register_pernet_subsys(&proto_gre_net_ops); | |
97 | if (ret < 0) | |
98 | goto out_pernet; | |
99 | diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c | |
100 | index 1dc4ea327cbe..70a7382b9787 100644 | |
101 | --- a/net/netfilter/nfnetlink_cttimeout.c | |
102 | +++ b/net/netfilter/nfnetlink_cttimeout.c | |
103 | @@ -469,7 +469,8 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |
104 | case IPPROTO_TCP: | |
105 | timeouts = net->ct.nf_ct_proto.tcp.timeouts; | |
106 | break; | |
107 | - case IPPROTO_UDP: | |
108 | + case IPPROTO_UDP: /* fallthrough */ | |
109 | + case IPPROTO_UDPLITE: | |
110 | timeouts = net->ct.nf_ct_proto.udp.timeouts; | |
111 | break; | |
112 | case IPPROTO_DCCP: | |
113 | @@ -483,13 +484,23 @@ static int cttimeout_default_get(struct net *net, struct sock *ctnl, | |
114 | case IPPROTO_SCTP: | |
115 | #ifdef CONFIG_NF_CT_PROTO_SCTP | |
116 | timeouts = net->ct.nf_ct_proto.sctp.timeouts; | |
117 | +#endif | |
118 | + break; | |
119 | + case IPPROTO_GRE: | |
120 | +#ifdef CONFIG_NF_CT_PROTO_GRE | |
121 | + if (l4proto->net_id) { | |
122 | + struct netns_proto_gre *net_gre; | |
123 | + | |
124 | + net_gre = net_generic(net, *l4proto->net_id); | |
125 | + timeouts = net_gre->gre_timeouts; | |
126 | + } | |
127 | #endif | |
128 | break; | |
129 | case 255: | |
130 | timeouts = &net->ct.nf_ct_proto.generic.timeout; | |
131 | break; | |
132 | default: | |
133 | - WARN_ON_ONCE(1); | |
134 | + WARN_ONCE(1, "Missing timeouts for proto %d", l4proto->l4proto); | |
135 | break; | |
136 | } | |
137 | ||
138 | -- | |
139 | 2.19.1 | |
140 |