Commit 1cde64365b0c4f576f8f45b834e6a6de081b5914
Committed by
David S. Miller
1 parent
50b521aa54
Exists in
master
and in
7 other branches
[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, |