[NETFILTER]: ctnetlink: Fix expectaction mask dumping
authorPablo Neira Ayuso <pablo@netfilter.org>
Wed, 22 Mar 2006 21:54:15 +0000 (13:54 -0800)
committerDavid S. Miller <davem@davemloft.net>
Wed, 22 Mar 2006 21:54:15 +0000 (13:54 -0800)
The expectation mask has some particularities that requires a different
handling. The protocol number fields can be set to non-valid protocols,
ie. l3num is set to 0xFFFF. Since that protocol does not exist, the mask
tuple will not be dumped. Moreover, this results in a kernel panic when
nf_conntrack accesses the array of protocol handlers, that is PF_MAX (0x1F)
long.

This patch introduces the function ctnetlink_exp_dump_mask, that correctly
dumps the expectation mask. Such function uses the l3num value from the
expectation tuple that is a valid layer 3 protocol number. The value of the
l3num mask isn't dumped since it is meaningless from the userspace side.

Thanks to Yasuyuki Kozakai and Patrick McHardy for the feedback.

Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/netfilter/ip_conntrack_netlink.c
net/netfilter/nf_conntrack_netlink.c

index 5ce2e3fc2c7f18b16452ff9838a8e34f08bbc1ba..9b6e19bae90feeb5faa54dcd258df56517d643cb 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 2001 by Jay Schulist <jschlst@samba.org>
  * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
  *
  * I've reworked this stuff to use attributes instead of conntrack 
  * structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -53,20 +53,18 @@ static char __initdata version[] = "0.90";
 
 static inline int
 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
-                           const struct ip_conntrack_tuple *tuple)
+                           const struct ip_conntrack_tuple *tuple,
+                           struct ip_conntrack_protocol *proto)
 {
-       struct ip_conntrack_protocol *proto;
        int ret = 0;
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
 
        NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
 
-       /* If no protocol helper is found, this function will return the
-        * generic protocol helper, so proto won't *ever* be NULL */
-       proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
        if (likely(proto->tuple_to_nfattr))
                ret = proto->tuple_to_nfattr(skb, tuple);
        
-       ip_conntrack_proto_put(proto);
+       NFA_NEST_END(skb, nest_parms);
 
        return ret;
 
@@ -75,27 +73,40 @@ nfattr_failure:
 }
 
 static inline int
-ctnetlink_dump_tuples(struct sk_buff *skb, 
-                     const struct ip_conntrack_tuple *tuple)
+ctnetlink_dump_tuples_ip(struct sk_buff *skb,
+                        const struct ip_conntrack_tuple *tuple)
 {
-       struct nfattr *nest_parms;
-       int ret;
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
        
-       nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
        NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
        NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
-       NFA_NEST_END(skb, nest_parms);
 
-       nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
-       ret = ctnetlink_dump_tuples_proto(skb, tuple);
        NFA_NEST_END(skb, nest_parms);
 
-       return ret;
+       return 0;
 
 nfattr_failure:
        return -1;
 }
 
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+                     const struct ip_conntrack_tuple *tuple)
+{
+       int ret;
+       struct ip_conntrack_protocol *proto;
+
+       ret = ctnetlink_dump_tuples_ip(skb, tuple);
+       if (unlikely(ret < 0))
+               return ret;
+
+       proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+       ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
+       ip_conntrack_proto_put(proto);
+
+       return ret;
+}
+
 static inline int
 ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
 {
@@ -1134,6 +1145,33 @@ nfattr_failure:
        return -1;
 }                      
 
+static inline int
+ctnetlink_exp_dump_mask(struct sk_buff *skb,
+                       const struct ip_conntrack_tuple *tuple,
+                       const struct ip_conntrack_tuple *mask)
+{
+       int ret;
+       struct ip_conntrack_protocol *proto;
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+
+       ret = ctnetlink_dump_tuples_ip(skb, mask);
+       if (unlikely(ret < 0))
+               goto nfattr_failure;
+
+       proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
+       ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
+       ip_conntrack_proto_put(proto);
+       if (unlikely(ret < 0))
+               goto nfattr_failure;
+
+       NFA_NEST_END(skb, nest_parms);
+
+       return 0;
+
+nfattr_failure:
+       return -1;
+}
+
 static inline int
 ctnetlink_exp_dump_expect(struct sk_buff *skb,
                           const struct ip_conntrack_expect *exp)
@@ -1144,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 
        if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
                goto nfattr_failure;
-       if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+       if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
                goto nfattr_failure;
        if (ctnetlink_exp_dump_tuple(skb,
                                 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
index 5eadf009bb157b5a24b8100852d34d41e85d7bb8..0e0e9d7b34c806d4ea1594f821cb4b2125fd248a 100644 (file)
@@ -4,7 +4,7 @@
  * (C) 2001 by Jay Schulist <jschlst@samba.org>
  * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
  * (C) 2003 by Patrick Mchardy <kaber@trash.net>
- * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
+ * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
  *
  * I've reworked this stuff to use attributes instead of conntrack 
  * structures. 5.44 am. I need more tea. --pablo 05/07/11.
@@ -55,20 +55,18 @@ static char __initdata version[] = "0.93";
 
 static inline int
 ctnetlink_dump_tuples_proto(struct sk_buff *skb, 
-                           const struct nf_conntrack_tuple *tuple)
+                           const struct nf_conntrack_tuple *tuple,
+                           struct nf_conntrack_protocol *proto)
 {
-       struct nf_conntrack_protocol *proto;
        int ret = 0;
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
 
        NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
 
-       /* If no protocol helper is found, this function will return the
-        * generic protocol helper, so proto won't *ever* be NULL */
-       proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
        if (likely(proto->tuple_to_nfattr))
                ret = proto->tuple_to_nfattr(skb, tuple);
        
-       nf_ct_proto_put(proto);
+       NFA_NEST_END(skb, nest_parms);
 
        return ret;
 
@@ -77,33 +75,44 @@ nfattr_failure:
 }
 
 static inline int
-ctnetlink_dump_tuples(struct sk_buff *skb, 
-                     const struct nf_conntrack_tuple *tuple)
+ctnetlink_dump_tuples_ip(struct sk_buff *skb,
+                        const struct nf_conntrack_tuple *tuple,
+                        struct nf_conntrack_l3proto *l3proto)
 {
-       struct nfattr *nest_parms;
-       struct nf_conntrack_l3proto *l3proto;
        int ret = 0;
-       
-       l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
-       
-       nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
+
        if (likely(l3proto->tuple_to_nfattr))
                ret = l3proto->tuple_to_nfattr(skb, tuple);
+
        NFA_NEST_END(skb, nest_parms);
 
+       return ret;
+
+nfattr_failure:
+       return -1;
+}
+
+static inline int
+ctnetlink_dump_tuples(struct sk_buff *skb,
+                     const struct nf_conntrack_tuple *tuple)
+{
+       int ret;
+       struct nf_conntrack_l3proto *l3proto;
+       struct nf_conntrack_protocol *proto;
+
+       l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+       ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
        nf_ct_l3proto_put(l3proto);
 
        if (unlikely(ret < 0))
                return ret;
 
-       nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
-       ret = ctnetlink_dump_tuples_proto(skb, tuple);
-       NFA_NEST_END(skb, nest_parms);
+       proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+       ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
+       nf_ct_proto_put(proto);
 
        return ret;
-
-nfattr_failure:
-       return -1;
 }
 
 static inline int
@@ -1152,6 +1161,37 @@ nfattr_failure:
        return -1;
 }                      
 
+static inline int
+ctnetlink_exp_dump_mask(struct sk_buff *skb,
+                       const struct nf_conntrack_tuple *tuple,
+                       const struct nf_conntrack_tuple *mask)
+{
+       int ret;
+       struct nf_conntrack_l3proto *l3proto;
+       struct nf_conntrack_protocol *proto;
+       struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
+
+       l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
+       ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
+       nf_ct_l3proto_put(l3proto);
+
+       if (unlikely(ret < 0))
+               goto nfattr_failure;
+
+       proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
+       ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
+       nf_ct_proto_put(proto);
+       if (unlikely(ret < 0))
+               goto nfattr_failure;
+
+       NFA_NEST_END(skb, nest_parms);
+
+       return 0;
+
+nfattr_failure:
+       return -1;
+}
+
 static inline int
 ctnetlink_exp_dump_expect(struct sk_buff *skb,
                           const struct nf_conntrack_expect *exp)
@@ -1162,7 +1202,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
 
        if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
                goto nfattr_failure;
-       if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
+       if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
                goto nfattr_failure;
        if (ctnetlink_exp_dump_tuple(skb,
                                 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,