]>
Commit | Line | Data |
---|---|---|
c774433e DL |
1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 |
2 | From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | |
3 | Date: Fri, 12 Jan 2018 11:16:50 +0100 | |
4 | Subject: [PATCH] netfilter: ipset: Fix wraparound in hash:*net* types | |
5 | ||
6 | Fix wraparound bug which could lead to memory exhaustion when adding an | |
7 | x.x.x.x-255.255.255.255 range to any hash:*net* types. | |
8 | ||
9 | Fixes Netfilter's bugzilla id #1212, reported by Thomas Schwark. | |
10 | ||
11 | Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses") | |
12 | Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | |
13 | Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> | |
14 | --- | |
15 | net/netfilter/ipset/ip_set_hash_ipportnet.c | 26 ++++++++++----------- | |
16 | net/netfilter/ipset/ip_set_hash_net.c | 9 ++++--- | |
17 | net/netfilter/ipset/ip_set_hash_netiface.c | 9 ++++--- | |
18 | net/netfilter/ipset/ip_set_hash_netnet.c | 28 +++++++++++----------- | |
19 | net/netfilter/ipset/ip_set_hash_netport.c | 19 ++++++++------- | |
20 | net/netfilter/ipset/ip_set_hash_netportnet.c | 35 ++++++++++++++-------------- | |
21 | 6 files changed, 63 insertions(+), 63 deletions(-) | |
22 | ||
23 | diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |
24 | index 0f164e986bf1..88b83d6d3084 100644 | |
25 | --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c | |
26 | +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |
27 | @@ -168,7 +168,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
28 | struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 }; | |
29 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
30 | u32 ip = 0, ip_to = 0, p = 0, port, port_to; | |
31 | - u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; | |
32 | + u32 ip2_from = 0, ip2_to = 0, ip2; | |
33 | bool with_ports = false; | |
34 | u8 cidr; | |
35 | int ret; | |
36 | @@ -269,22 +269,21 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
37 | ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1); | |
38 | } | |
39 | ||
40 | - if (retried) | |
41 | + if (retried) { | |
42 | ip = ntohl(h->next.ip); | |
43 | + p = ntohs(h->next.port); | |
44 | + ip2 = ntohl(h->next.ip2); | |
45 | + } else { | |
46 | + p = port; | |
47 | + ip2 = ip2_from; | |
48 | + } | |
49 | for (; ip <= ip_to; ip++) { | |
50 | e.ip = htonl(ip); | |
51 | - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) | |
52 | - : port; | |
53 | for (; p <= port_to; p++) { | |
54 | e.port = htons(p); | |
55 | - ip2 = retried && | |
56 | - ip == ntohl(h->next.ip) && | |
57 | - p == ntohs(h->next.port) | |
58 | - ? ntohl(h->next.ip2) : ip2_from; | |
59 | - while (ip2 <= ip2_to) { | |
60 | + do { | |
61 | e.ip2 = htonl(ip2); | |
62 | - ip2_last = ip_set_range_to_cidr(ip2, ip2_to, | |
63 | - &cidr); | |
64 | + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr); | |
65 | e.cidr = cidr - 1; | |
66 | ret = adtfn(set, &e, &ext, &ext, flags); | |
67 | ||
68 | @@ -292,9 +291,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
69 | return ret; | |
70 | ||
71 | ret = 0; | |
72 | - ip2 = ip2_last + 1; | |
73 | - } | |
74 | + } while (ip2++ < ip2_to); | |
75 | + ip2 = ip2_from; | |
76 | } | |
77 | + p = port; | |
78 | } | |
79 | return ret; | |
80 | } | |
81 | diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c | |
82 | index 1c67a1761e45..5449e23af13a 100644 | |
83 | --- a/net/netfilter/ipset/ip_set_hash_net.c | |
84 | +++ b/net/netfilter/ipset/ip_set_hash_net.c | |
85 | @@ -143,7 +143,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |
86 | ipset_adtfn adtfn = set->variant->adt[adt]; | |
87 | struct hash_net4_elem e = { .cidr = HOST_MASK }; | |
88 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
89 | - u32 ip = 0, ip_to = 0, last; | |
90 | + u32 ip = 0, ip_to = 0; | |
91 | int ret; | |
92 | ||
93 | if (tb[IPSET_ATTR_LINENO]) | |
94 | @@ -193,16 +193,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[], | |
95 | } | |
96 | if (retried) | |
97 | ip = ntohl(h->next.ip); | |
98 | - while (ip <= ip_to) { | |
99 | + do { | |
100 | e.ip = htonl(ip); | |
101 | - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | |
102 | + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | |
103 | ret = adtfn(set, &e, &ext, &ext, flags); | |
104 | if (ret && !ip_set_eexist(ret, flags)) | |
105 | return ret; | |
106 | ||
107 | ret = 0; | |
108 | - ip = last + 1; | |
109 | - } | |
110 | + } while (ip++ < ip_to); | |
111 | return ret; | |
112 | } | |
113 | ||
114 | diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c | |
115 | index d417074f1c1a..f5164c1efce2 100644 | |
116 | --- a/net/netfilter/ipset/ip_set_hash_netiface.c | |
117 | +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |
118 | @@ -200,7 +200,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |
119 | ipset_adtfn adtfn = set->variant->adt[adt]; | |
120 | struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 }; | |
121 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
122 | - u32 ip = 0, ip_to = 0, last; | |
123 | + u32 ip = 0, ip_to = 0; | |
124 | int ret; | |
125 | ||
126 | if (tb[IPSET_ATTR_LINENO]) | |
127 | @@ -255,17 +255,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[], | |
128 | ||
129 | if (retried) | |
130 | ip = ntohl(h->next.ip); | |
131 | - while (ip <= ip_to) { | |
132 | + do { | |
133 | e.ip = htonl(ip); | |
134 | - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | |
135 | + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr); | |
136 | ret = adtfn(set, &e, &ext, &ext, flags); | |
137 | ||
138 | if (ret && !ip_set_eexist(ret, flags)) | |
139 | return ret; | |
140 | ||
141 | ret = 0; | |
142 | - ip = last + 1; | |
143 | - } | |
144 | + } while (ip++ < ip_to); | |
145 | return ret; | |
146 | } | |
147 | ||
148 | diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c | |
149 | index 7f9ae2e9645b..5a2b923bd81f 100644 | |
150 | --- a/net/netfilter/ipset/ip_set_hash_netnet.c | |
151 | +++ b/net/netfilter/ipset/ip_set_hash_netnet.c | |
152 | @@ -169,8 +169,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
153 | ipset_adtfn adtfn = set->variant->adt[adt]; | |
154 | struct hash_netnet4_elem e = { }; | |
155 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
156 | - u32 ip = 0, ip_to = 0, last; | |
157 | - u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2; | |
158 | + u32 ip = 0, ip_to = 0; | |
159 | + u32 ip2 = 0, ip2_from = 0, ip2_to = 0; | |
160 | int ret; | |
161 | ||
162 | if (tb[IPSET_ATTR_LINENO]) | |
163 | @@ -247,27 +247,27 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
164 | ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); | |
165 | } | |
166 | ||
167 | - if (retried) | |
168 | + if (retried) { | |
169 | ip = ntohl(h->next.ip[0]); | |
170 | + ip2 = ntohl(h->next.ip[1]); | |
171 | + } else { | |
172 | + ip2 = ip2_from; | |
173 | + } | |
174 | ||
175 | - while (ip <= ip_to) { | |
176 | + do { | |
177 | e.ip[0] = htonl(ip); | |
178 | - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | |
179 | - ip2 = (retried && | |
180 | - ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1]) | |
181 | - : ip2_from; | |
182 | - while (ip2 <= ip2_to) { | |
183 | + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | |
184 | + do { | |
185 | e.ip[1] = htonl(ip2); | |
186 | - last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); | |
187 | + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]); | |
188 | ret = adtfn(set, &e, &ext, &ext, flags); | |
189 | if (ret && !ip_set_eexist(ret, flags)) | |
190 | return ret; | |
191 | ||
192 | ret = 0; | |
193 | - ip2 = last2 + 1; | |
194 | - } | |
195 | - ip = last + 1; | |
196 | - } | |
197 | + } while (ip2++ < ip2_to); | |
198 | + ip2 = ip2_from; | |
199 | + } while (ip++ < ip_to); | |
200 | return ret; | |
201 | } | |
202 | ||
203 | diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c | |
204 | index e6ef382febe4..1a187be9ebc8 100644 | |
205 | --- a/net/netfilter/ipset/ip_set_hash_netport.c | |
206 | +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |
207 | @@ -161,7 +161,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |
208 | ipset_adtfn adtfn = set->variant->adt[adt]; | |
209 | struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 }; | |
210 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
211 | - u32 port, port_to, p = 0, ip = 0, ip_to = 0, last; | |
212 | + u32 port, port_to, p = 0, ip = 0, ip_to = 0; | |
213 | bool with_ports = false; | |
214 | u8 cidr; | |
215 | int ret; | |
216 | @@ -239,25 +239,26 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[], | |
217 | ip_set_mask_from_to(ip, ip_to, e.cidr + 1); | |
218 | } | |
219 | ||
220 | - if (retried) | |
221 | + if (retried) { | |
222 | ip = ntohl(h->next.ip); | |
223 | - while (ip <= ip_to) { | |
224 | + p = ntohs(h->next.port); | |
225 | + } else { | |
226 | + p = port; | |
227 | + } | |
228 | + do { | |
229 | e.ip = htonl(ip); | |
230 | - last = ip_set_range_to_cidr(ip, ip_to, &cidr); | |
231 | + ip = ip_set_range_to_cidr(ip, ip_to, &cidr); | |
232 | e.cidr = cidr - 1; | |
233 | - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port) | |
234 | - : port; | |
235 | for (; p <= port_to; p++) { | |
236 | e.port = htons(p); | |
237 | ret = adtfn(set, &e, &ext, &ext, flags); | |
238 | - | |
239 | if (ret && !ip_set_eexist(ret, flags)) | |
240 | return ret; | |
241 | ||
242 | ret = 0; | |
243 | } | |
244 | - ip = last + 1; | |
245 | - } | |
246 | + p = port; | |
247 | + } while (ip++ < ip_to); | |
248 | return ret; | |
249 | } | |
250 | ||
251 | diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c | |
252 | index 8602f2595a1a..d391485a6acd 100644 | |
253 | --- a/net/netfilter/ipset/ip_set_hash_netportnet.c | |
254 | +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c | |
255 | @@ -184,8 +184,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
256 | ipset_adtfn adtfn = set->variant->adt[adt]; | |
257 | struct hash_netportnet4_elem e = { }; | |
258 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | |
259 | - u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to; | |
260 | - u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2; | |
261 | + u32 ip = 0, ip_to = 0, p = 0, port, port_to; | |
262 | + u32 ip2_from = 0, ip2_to = 0, ip2; | |
263 | bool with_ports = false; | |
264 | int ret; | |
265 | ||
266 | @@ -288,33 +288,34 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[], | |
267 | ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]); | |
268 | } | |
269 | ||
270 | - if (retried) | |
271 | + if (retried) { | |
272 | ip = ntohl(h->next.ip[0]); | |
273 | + p = ntohs(h->next.port); | |
274 | + ip2 = ntohl(h->next.ip[1]); | |
275 | + } else { | |
276 | + p = port; | |
277 | + ip2 = ip2_from; | |
278 | + } | |
279 | ||
280 | - while (ip <= ip_to) { | |
281 | + do { | |
282 | e.ip[0] = htonl(ip); | |
283 | - ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | |
284 | - p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port) | |
285 | - : port; | |
286 | + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]); | |
287 | for (; p <= port_to; p++) { | |
288 | e.port = htons(p); | |
289 | - ip2 = (retried && ip == ntohl(h->next.ip[0]) && | |
290 | - p == ntohs(h->next.port)) ? ntohl(h->next.ip[1]) | |
291 | - : ip2_from; | |
292 | - while (ip2 <= ip2_to) { | |
293 | + do { | |
294 | e.ip[1] = htonl(ip2); | |
295 | - ip2_last = ip_set_range_to_cidr(ip2, ip2_to, | |
296 | - &e.cidr[1]); | |
297 | + ip2 = ip_set_range_to_cidr(ip2, ip2_to, | |
298 | + &e.cidr[1]); | |
299 | ret = adtfn(set, &e, &ext, &ext, flags); | |
300 | if (ret && !ip_set_eexist(ret, flags)) | |
301 | return ret; | |
302 | ||
303 | ret = 0; | |
304 | - ip2 = ip2_last + 1; | |
305 | - } | |
306 | + } while (ip2++ < ip2_to); | |
307 | + ip2 = ip2_from; | |
308 | } | |
309 | - ip = ip_last + 1; | |
310 | - } | |
311 | + p = port; | |
312 | + } while (ip++ < ip_to); | |
313 | return ret; | |
314 | } | |
315 | ||
316 | -- | |
317 | 2.11.0 | |
318 |