Commit d6d3f08b0fd998b647a05540cedd11a067b72867

Authored by Jan Engelhardt
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,