Commit 1cde64365b0c4f576f8f45b834e6a6de081b5914

Authored by Pablo Neira Ayuso
Committed by David S. Miller
1 parent 50b521aa54

[NETFILTER]: ctnetlink: Fix expectaction mask dumping

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>

Showing 2 changed files with 117 additions and 39 deletions Side-by-side Diff

net/ipv4/netfilter/ip_conntrack_netlink.c
... ... @@ -4,7 +4,7 @@
4 4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 5 * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
6 6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7   - * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
  7 + * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 8 *
9 9 * I've reworked this stuff to use attributes instead of conntrack
10 10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
11 11  
12 12  
13 13  
14 14  
... ... @@ -53,20 +53,18 @@
53 53  
54 54 static inline int
55 55 ctnetlink_dump_tuples_proto(struct sk_buff *skb,
56   - const struct ip_conntrack_tuple *tuple)
  56 + const struct ip_conntrack_tuple *tuple,
  57 + struct ip_conntrack_protocol *proto)
57 58 {
58   - struct ip_conntrack_protocol *proto;
59 59 int ret = 0;
  60 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
60 61  
61 62 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
62 63  
63   - /* If no protocol helper is found, this function will return the
64   - * generic protocol helper, so proto won't *ever* be NULL */
65   - proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
66 64 if (likely(proto->tuple_to_nfattr))
67 65 ret = proto->tuple_to_nfattr(skb, tuple);
68 66  
69   - ip_conntrack_proto_put(proto);
  67 + NFA_NEST_END(skb, nest_parms);
70 68  
71 69 return ret;
72 70  
73 71  
74 72  
75 73  
76 74  
77 75  
78 76  
... ... @@ -75,28 +73,41 @@
75 73 }
76 74  
77 75 static inline int
78   -ctnetlink_dump_tuples(struct sk_buff *skb,
79   - const struct ip_conntrack_tuple *tuple)
  76 +ctnetlink_dump_tuples_ip(struct sk_buff *skb,
  77 + const struct ip_conntrack_tuple *tuple)
80 78 {
81   - struct nfattr *nest_parms;
82   - int ret;
  79 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
83 80  
84   - nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
85 81 NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
86 82 NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
87   - NFA_NEST_END(skb, nest_parms);
88 83  
89   - nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
90   - ret = ctnetlink_dump_tuples_proto(skb, tuple);
91 84 NFA_NEST_END(skb, nest_parms);
92 85  
93   - return ret;
  86 + return 0;
94 87  
95 88 nfattr_failure:
96 89 return -1;
97 90 }
98 91  
99 92 static inline int
  93 +ctnetlink_dump_tuples(struct sk_buff *skb,
  94 + const struct ip_conntrack_tuple *tuple)
  95 +{
  96 + int ret;
  97 + struct ip_conntrack_protocol *proto;
  98 +
  99 + ret = ctnetlink_dump_tuples_ip(skb, tuple);
  100 + if (unlikely(ret < 0))
  101 + return ret;
  102 +
  103 + proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
  104 + ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
  105 + ip_conntrack_proto_put(proto);
  106 +
  107 + return ret;
  108 +}
  109 +
  110 +static inline int
100 111 ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
101 112 {
102 113 u_int32_t status = htonl((u_int32_t) ct->status);
... ... @@ -1135,6 +1146,33 @@
1135 1146 }
1136 1147  
1137 1148 static inline int
  1149 +ctnetlink_exp_dump_mask(struct sk_buff *skb,
  1150 + const struct ip_conntrack_tuple *tuple,
  1151 + const struct ip_conntrack_tuple *mask)
  1152 +{
  1153 + int ret;
  1154 + struct ip_conntrack_protocol *proto;
  1155 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
  1156 +
  1157 + ret = ctnetlink_dump_tuples_ip(skb, mask);
  1158 + if (unlikely(ret < 0))
  1159 + goto nfattr_failure;
  1160 +
  1161 + proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
  1162 + ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
  1163 + ip_conntrack_proto_put(proto);
  1164 + if (unlikely(ret < 0))
  1165 + goto nfattr_failure;
  1166 +
  1167 + NFA_NEST_END(skb, nest_parms);
  1168 +
  1169 + return 0;
  1170 +
  1171 +nfattr_failure:
  1172 + return -1;
  1173 +}
  1174 +
  1175 +static inline int
1138 1176 ctnetlink_exp_dump_expect(struct sk_buff *skb,
1139 1177 const struct ip_conntrack_expect *exp)
1140 1178 {
... ... @@ -1144,7 +1182,7 @@
1144 1182  
1145 1183 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1146 1184 goto nfattr_failure;
1147   - if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
  1185 + if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1148 1186 goto nfattr_failure;
1149 1187 if (ctnetlink_exp_dump_tuple(skb,
1150 1188 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
net/netfilter/nf_conntrack_netlink.c
... ... @@ -4,7 +4,7 @@
4 4 * (C) 2001 by Jay Schulist <jschlst@samba.org>
5 5 * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
6 6 * (C) 2003 by Patrick Mchardy <kaber@trash.net>
7   - * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
  7 + * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
8 8 *
9 9 * I've reworked this stuff to use attributes instead of conntrack
10 10 * structures. 5.44 am. I need more tea. --pablo 05/07/11.
11 11  
12 12  
13 13  
14 14  
... ... @@ -55,20 +55,18 @@
55 55  
56 56 static inline int
57 57 ctnetlink_dump_tuples_proto(struct sk_buff *skb,
58   - const struct nf_conntrack_tuple *tuple)
  58 + const struct nf_conntrack_tuple *tuple,
  59 + struct nf_conntrack_protocol *proto)
59 60 {
60   - struct nf_conntrack_protocol *proto;
61 61 int ret = 0;
  62 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
62 63  
63 64 NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
64 65  
65   - /* If no protocol helper is found, this function will return the
66   - * generic protocol helper, so proto won't *ever* be NULL */
67   - proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
68 66 if (likely(proto->tuple_to_nfattr))
69 67 ret = proto->tuple_to_nfattr(skb, tuple);
70 68  
71   - nf_ct_proto_put(proto);
  69 + NFA_NEST_END(skb, nest_parms);
72 70  
73 71 return ret;
74 72  
75 73  
76 74  
77 75  
78 76  
79 77  
80 78  
... ... @@ -77,33 +75,44 @@
77 75 }
78 76  
79 77 static inline int
80   -ctnetlink_dump_tuples(struct sk_buff *skb,
81   - const struct nf_conntrack_tuple *tuple)
  78 +ctnetlink_dump_tuples_ip(struct sk_buff *skb,
  79 + const struct nf_conntrack_tuple *tuple,
  80 + struct nf_conntrack_l3proto *l3proto)
82 81 {
83   - struct nfattr *nest_parms;
84   - struct nf_conntrack_l3proto *l3proto;
85 82 int ret = 0;
86   -
87   - l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
88   -
89   - nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
  83 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
  84 +
90 85 if (likely(l3proto->tuple_to_nfattr))
91 86 ret = l3proto->tuple_to_nfattr(skb, tuple);
  87 +
92 88 NFA_NEST_END(skb, nest_parms);
93 89  
  90 + return ret;
  91 +
  92 +nfattr_failure:
  93 + return -1;
  94 +}
  95 +
  96 +static inline int
  97 +ctnetlink_dump_tuples(struct sk_buff *skb,
  98 + const struct nf_conntrack_tuple *tuple)
  99 +{
  100 + int ret;
  101 + struct nf_conntrack_l3proto *l3proto;
  102 + struct nf_conntrack_protocol *proto;
  103 +
  104 + l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
  105 + ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
94 106 nf_ct_l3proto_put(l3proto);
95 107  
96 108 if (unlikely(ret < 0))
97 109 return ret;
98 110  
99   - nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
100   - ret = ctnetlink_dump_tuples_proto(skb, tuple);
101   - NFA_NEST_END(skb, nest_parms);
  111 + proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
  112 + ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
  113 + nf_ct_proto_put(proto);
102 114  
103 115 return ret;
104   -
105   -nfattr_failure:
106   - return -1;
107 116 }
108 117  
109 118 static inline int
... ... @@ -1153,6 +1162,37 @@
1153 1162 }
1154 1163  
1155 1164 static inline int
  1165 +ctnetlink_exp_dump_mask(struct sk_buff *skb,
  1166 + const struct nf_conntrack_tuple *tuple,
  1167 + const struct nf_conntrack_tuple *mask)
  1168 +{
  1169 + int ret;
  1170 + struct nf_conntrack_l3proto *l3proto;
  1171 + struct nf_conntrack_protocol *proto;
  1172 + struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
  1173 +
  1174 + l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
  1175 + ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
  1176 + nf_ct_l3proto_put(l3proto);
  1177 +
  1178 + if (unlikely(ret < 0))
  1179 + goto nfattr_failure;
  1180 +
  1181 + proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
  1182 + ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
  1183 + nf_ct_proto_put(proto);
  1184 + if (unlikely(ret < 0))
  1185 + goto nfattr_failure;
  1186 +
  1187 + NFA_NEST_END(skb, nest_parms);
  1188 +
  1189 + return 0;
  1190 +
  1191 +nfattr_failure:
  1192 + return -1;
  1193 +}
  1194 +
  1195 +static inline int
1156 1196 ctnetlink_exp_dump_expect(struct sk_buff *skb,
1157 1197 const struct nf_conntrack_expect *exp)
1158 1198 {
... ... @@ -1162,7 +1202,7 @@
1162 1202  
1163 1203 if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
1164 1204 goto nfattr_failure;
1165   - if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
  1205 + if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
1166 1206 goto nfattr_failure;
1167 1207 if (ctnetlink_exp_dump_tuple(skb,
1168 1208 &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,