Commit d6d3f08b0fd998b647a05540cedd11a067b72867
Committed by
Patrick McHardy
1 parent
8a3af79361
netfilter: xtables: conntrack match revision 2
As reported by Philip, the UNTRACKED state bit does not fit within the 8-bit state_mask member. Enlarge state_mask and give status_mask a few more bits too. Reported-by: Philip Craig <philipc@snapgear.com> References: http://markmail.org/thread/b7eg6aovfh4agyz7 Signed-off-by: Jan Engelhardt <jengelh@medozas.de> Signed-off-by: Patrick McHardy <kaber@trash.net>
Showing 2 changed files with 73 additions and 6 deletions Side-by-side Diff
include/linux/netfilter/xt_conntrack.h
... | ... | @@ -81,5 +81,18 @@ |
81 | 81 | __u8 state_mask, status_mask; |
82 | 82 | }; |
83 | 83 | |
84 | +struct xt_conntrack_mtinfo2 { | |
85 | + union nf_inet_addr origsrc_addr, origsrc_mask; | |
86 | + union nf_inet_addr origdst_addr, origdst_mask; | |
87 | + union nf_inet_addr replsrc_addr, replsrc_mask; | |
88 | + union nf_inet_addr repldst_addr, repldst_mask; | |
89 | + __u32 expires_min, expires_max; | |
90 | + __u16 l4proto; | |
91 | + __be16 origsrc_port, origdst_port; | |
92 | + __be16 replsrc_port, repldst_port; | |
93 | + __u16 match_flags, invert_flags; | |
94 | + __u16 state_mask, status_mask; | |
95 | +}; | |
96 | + | |
84 | 97 | #endif /*_XT_CONNTRACK_H*/ |
net/netfilter/xt_conntrack.c
... | ... | @@ -129,7 +129,7 @@ |
129 | 129 | |
130 | 130 | static inline bool |
131 | 131 | conntrack_mt_origsrc(const struct nf_conn *ct, |
132 | - const struct xt_conntrack_mtinfo1 *info, | |
132 | + const struct xt_conntrack_mtinfo2 *info, | |
133 | 133 | u_int8_t family) |
134 | 134 | { |
135 | 135 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, |
... | ... | @@ -138,7 +138,7 @@ |
138 | 138 | |
139 | 139 | static inline bool |
140 | 140 | conntrack_mt_origdst(const struct nf_conn *ct, |
141 | - const struct xt_conntrack_mtinfo1 *info, | |
141 | + const struct xt_conntrack_mtinfo2 *info, | |
142 | 142 | u_int8_t family) |
143 | 143 | { |
144 | 144 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.u3, |
... | ... | @@ -147,7 +147,7 @@ |
147 | 147 | |
148 | 148 | static inline bool |
149 | 149 | conntrack_mt_replsrc(const struct nf_conn *ct, |
150 | - const struct xt_conntrack_mtinfo1 *info, | |
150 | + const struct xt_conntrack_mtinfo2 *info, | |
151 | 151 | u_int8_t family) |
152 | 152 | { |
153 | 153 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3, |
... | ... | @@ -156,7 +156,7 @@ |
156 | 156 | |
157 | 157 | static inline bool |
158 | 158 | conntrack_mt_repldst(const struct nf_conn *ct, |
159 | - const struct xt_conntrack_mtinfo1 *info, | |
159 | + const struct xt_conntrack_mtinfo2 *info, | |
160 | 160 | u_int8_t family) |
161 | 161 | { |
162 | 162 | return conntrack_addrcmp(&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3, |
... | ... | @@ -164,7 +164,7 @@ |
164 | 164 | } |
165 | 165 | |
166 | 166 | static inline bool |
167 | -ct_proto_port_check(const struct xt_conntrack_mtinfo1 *info, | |
167 | +ct_proto_port_check(const struct xt_conntrack_mtinfo2 *info, | |
168 | 168 | const struct nf_conn *ct) |
169 | 169 | { |
170 | 170 | const struct nf_conntrack_tuple *tuple; |
... | ... | @@ -204,7 +204,7 @@ |
204 | 204 | static bool |
205 | 205 | conntrack_mt(const struct sk_buff *skb, const struct xt_match_param *par) |
206 | 206 | { |
207 | - const struct xt_conntrack_mtinfo1 *info = par->matchinfo; | |
207 | + const struct xt_conntrack_mtinfo2 *info = par->matchinfo; | |
208 | 208 | enum ip_conntrack_info ctinfo; |
209 | 209 | const struct nf_conn *ct; |
210 | 210 | unsigned int statebit; |
... | ... | @@ -278,6 +278,16 @@ |
278 | 278 | return true; |
279 | 279 | } |
280 | 280 | |
281 | +static bool | |
282 | +conntrack_mt_v1(const struct sk_buff *skb, const struct xt_match_param *par) | |
283 | +{ | |
284 | + const struct xt_conntrack_mtinfo2 *const *info = par->matchinfo; | |
285 | + struct xt_match_param newpar = *par; | |
286 | + | |
287 | + newpar.matchinfo = *info; | |
288 | + return conntrack_mt(skb, &newpar); | |
289 | +} | |
290 | + | |
281 | 291 | static bool conntrack_mt_check(const struct xt_mtchk_param *par) |
282 | 292 | { |
283 | 293 | if (nf_ct_l3proto_try_module_get(par->family) < 0) { |
284 | 294 | |
... | ... | @@ -288,11 +298,45 @@ |
288 | 298 | return true; |
289 | 299 | } |
290 | 300 | |
301 | +static bool conntrack_mt_check_v1(const struct xt_mtchk_param *par) | |
302 | +{ | |
303 | + struct xt_conntrack_mtinfo1 *info = par->matchinfo; | |
304 | + struct xt_conntrack_mtinfo2 *up; | |
305 | + int ret = conntrack_mt_check(par); | |
306 | + | |
307 | + if (ret < 0) | |
308 | + return ret; | |
309 | + | |
310 | + up = kmalloc(sizeof(*up), GFP_KERNEL); | |
311 | + if (up == NULL) { | |
312 | + nf_ct_l3proto_module_put(par->family); | |
313 | + return -ENOMEM; | |
314 | + } | |
315 | + | |
316 | + /* | |
317 | + * The strategy here is to minimize the overhead of v1 matching, | |
318 | + * by prebuilding a v2 struct and putting the pointer into the | |
319 | + * v1 dataspace. | |
320 | + */ | |
321 | + memcpy(up, info, offsetof(typeof(*info), state_mask)); | |
322 | + up->state_mask = info->state_mask; | |
323 | + up->status_mask = info->status_mask; | |
324 | + *(void **)info = up; | |
325 | + return true; | |
326 | +} | |
327 | + | |
291 | 328 | static void conntrack_mt_destroy(const struct xt_mtdtor_param *par) |
292 | 329 | { |
293 | 330 | nf_ct_l3proto_module_put(par->family); |
294 | 331 | } |
295 | 332 | |
333 | +static void conntrack_mt_destroy_v1(const struct xt_mtdtor_param *par) | |
334 | +{ | |
335 | + struct xt_conntrack_mtinfo2 **info = par->matchinfo; | |
336 | + kfree(*info); | |
337 | + conntrack_mt_destroy(par); | |
338 | +} | |
339 | + | |
296 | 340 | #ifdef CONFIG_COMPAT |
297 | 341 | struct compat_xt_conntrack_info |
298 | 342 | { |
... | ... | @@ -363,6 +407,16 @@ |
363 | 407 | .revision = 1, |
364 | 408 | .family = NFPROTO_UNSPEC, |
365 | 409 | .matchsize = sizeof(struct xt_conntrack_mtinfo1), |
410 | + .match = conntrack_mt_v1, | |
411 | + .checkentry = conntrack_mt_check_v1, | |
412 | + .destroy = conntrack_mt_destroy_v1, | |
413 | + .me = THIS_MODULE, | |
414 | + }, | |
415 | + { | |
416 | + .name = "conntrack", | |
417 | + .revision = 2, | |
418 | + .family = NFPROTO_UNSPEC, | |
419 | + .matchsize = sizeof(struct xt_conntrack_mtinfo2), | |
366 | 420 | .match = conntrack_mt, |
367 | 421 | .checkentry = conntrack_mt_check, |
368 | 422 | .destroy = conntrack_mt_destroy, |