Skip to content

Commit 5515c5b

Browse files
Jozsef Kadlecsikgregkh
Jozsef Kadlecsik
authored andcommitted
netfilter: ipset: Fix wraparound in hash:*net* types
[ Upstream commit 0b8d907 ] Fix wraparound bug which could lead to memory exhaustion when adding an x.x.x.x-255.255.255.255 range to any hash:*net* types. Fixes Netfilter's bugzilla id #1212, reported by Thomas Schwark. Fixes: 48596a8 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses") Signed-off-by: Jozsef Kadlecsik <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 2a35d21 commit 5515c5b

6 files changed

+63
-63
lines changed

net/netfilter/ipset/ip_set_hash_ipportnet.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
168168
struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
169169
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
170170
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
171-
u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
171+
u32 ip2_from = 0, ip2_to = 0, ip2;
172172
bool with_ports = false;
173173
u8 cidr;
174174
int ret;
@@ -269,32 +269,32 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
269269
ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1);
270270
}
271271

272-
if (retried)
272+
if (retried) {
273273
ip = ntohl(h->next.ip);
274+
p = ntohs(h->next.port);
275+
ip2 = ntohl(h->next.ip2);
276+
} else {
277+
p = port;
278+
ip2 = ip2_from;
279+
}
274280
for (; ip <= ip_to; ip++) {
275281
e.ip = htonl(ip);
276-
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
277-
: port;
278282
for (; p <= port_to; p++) {
279283
e.port = htons(p);
280-
ip2 = retried &&
281-
ip == ntohl(h->next.ip) &&
282-
p == ntohs(h->next.port)
283-
? ntohl(h->next.ip2) : ip2_from;
284-
while (ip2 <= ip2_to) {
284+
do {
285285
e.ip2 = htonl(ip2);
286-
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
287-
&cidr);
286+
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr);
288287
e.cidr = cidr - 1;
289288
ret = adtfn(set, &e, &ext, &ext, flags);
290289

291290
if (ret && !ip_set_eexist(ret, flags))
292291
return ret;
293292

294293
ret = 0;
295-
ip2 = ip2_last + 1;
296-
}
294+
} while (ip2++ < ip2_to);
295+
ip2 = ip2_from;
297296
}
297+
p = port;
298298
}
299299
return ret;
300300
}

net/netfilter/ipset/ip_set_hash_net.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
143143
ipset_adtfn adtfn = set->variant->adt[adt];
144144
struct hash_net4_elem e = { .cidr = HOST_MASK };
145145
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
146-
u32 ip = 0, ip_to = 0, last;
146+
u32 ip = 0, ip_to = 0;
147147
int ret;
148148

149149
if (tb[IPSET_ATTR_LINENO])
@@ -193,16 +193,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
193193
}
194194
if (retried)
195195
ip = ntohl(h->next.ip);
196-
while (ip <= ip_to) {
196+
do {
197197
e.ip = htonl(ip);
198-
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
198+
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
199199
ret = adtfn(set, &e, &ext, &ext, flags);
200200
if (ret && !ip_set_eexist(ret, flags))
201201
return ret;
202202

203203
ret = 0;
204-
ip = last + 1;
205-
}
204+
} while (ip++ < ip_to);
206205
return ret;
207206
}
208207

net/netfilter/ipset/ip_set_hash_netiface.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
200200
ipset_adtfn adtfn = set->variant->adt[adt];
201201
struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
202202
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
203-
u32 ip = 0, ip_to = 0, last;
203+
u32 ip = 0, ip_to = 0;
204204
int ret;
205205

206206
if (tb[IPSET_ATTR_LINENO])
@@ -255,17 +255,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
255255

256256
if (retried)
257257
ip = ntohl(h->next.ip);
258-
while (ip <= ip_to) {
258+
do {
259259
e.ip = htonl(ip);
260-
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
260+
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
261261
ret = adtfn(set, &e, &ext, &ext, flags);
262262

263263
if (ret && !ip_set_eexist(ret, flags))
264264
return ret;
265265

266266
ret = 0;
267-
ip = last + 1;
268-
}
267+
} while (ip++ < ip_to);
269268
return ret;
270269
}
271270

net/netfilter/ipset/ip_set_hash_netnet.c

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -169,8 +169,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
169169
ipset_adtfn adtfn = set->variant->adt[adt];
170170
struct hash_netnet4_elem e = { };
171171
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
172-
u32 ip = 0, ip_to = 0, last;
173-
u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2;
172+
u32 ip = 0, ip_to = 0;
173+
u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
174174
int ret;
175175

176176
if (tb[IPSET_ATTR_LINENO])
@@ -247,27 +247,27 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
247247
ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
248248
}
249249

250-
if (retried)
250+
if (retried) {
251251
ip = ntohl(h->next.ip[0]);
252+
ip2 = ntohl(h->next.ip[1]);
253+
} else {
254+
ip2 = ip2_from;
255+
}
252256

253-
while (ip <= ip_to) {
257+
do {
254258
e.ip[0] = htonl(ip);
255-
last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
256-
ip2 = (retried &&
257-
ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
258-
: ip2_from;
259-
while (ip2 <= ip2_to) {
259+
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
260+
do {
260261
e.ip[1] = htonl(ip2);
261-
last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
262+
ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
262263
ret = adtfn(set, &e, &ext, &ext, flags);
263264
if (ret && !ip_set_eexist(ret, flags))
264265
return ret;
265266

266267
ret = 0;
267-
ip2 = last2 + 1;
268-
}
269-
ip = last + 1;
270-
}
268+
} while (ip2++ < ip2_to);
269+
ip2 = ip2_from;
270+
} while (ip++ < ip_to);
271271
return ret;
272272
}
273273

net/netfilter/ipset/ip_set_hash_netport.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
161161
ipset_adtfn adtfn = set->variant->adt[adt];
162162
struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
163163
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
164-
u32 port, port_to, p = 0, ip = 0, ip_to = 0, last;
164+
u32 port, port_to, p = 0, ip = 0, ip_to = 0;
165165
bool with_ports = false;
166166
u8 cidr;
167167
int ret;
@@ -239,25 +239,26 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
239239
ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
240240
}
241241

242-
if (retried)
242+
if (retried) {
243243
ip = ntohl(h->next.ip);
244-
while (ip <= ip_to) {
244+
p = ntohs(h->next.port);
245+
} else {
246+
p = port;
247+
}
248+
do {
245249
e.ip = htonl(ip);
246-
last = ip_set_range_to_cidr(ip, ip_to, &cidr);
250+
ip = ip_set_range_to_cidr(ip, ip_to, &cidr);
247251
e.cidr = cidr - 1;
248-
p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
249-
: port;
250252
for (; p <= port_to; p++) {
251253
e.port = htons(p);
252254
ret = adtfn(set, &e, &ext, &ext, flags);
253-
254255
if (ret && !ip_set_eexist(ret, flags))
255256
return ret;
256257

257258
ret = 0;
258259
}
259-
ip = last + 1;
260-
}
260+
p = port;
261+
} while (ip++ < ip_to);
261262
return ret;
262263
}
263264

net/netfilter/ipset/ip_set_hash_netportnet.c

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
184184
ipset_adtfn adtfn = set->variant->adt[adt];
185185
struct hash_netportnet4_elem e = { };
186186
struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
187-
u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to;
188-
u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
187+
u32 ip = 0, ip_to = 0, p = 0, port, port_to;
188+
u32 ip2_from = 0, ip2_to = 0, ip2;
189189
bool with_ports = false;
190190
int ret;
191191

@@ -288,33 +288,34 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
288288
ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
289289
}
290290

291-
if (retried)
291+
if (retried) {
292292
ip = ntohl(h->next.ip[0]);
293+
p = ntohs(h->next.port);
294+
ip2 = ntohl(h->next.ip[1]);
295+
} else {
296+
p = port;
297+
ip2 = ip2_from;
298+
}
293299

294-
while (ip <= ip_to) {
300+
do {
295301
e.ip[0] = htonl(ip);
296-
ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
297-
p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port)
298-
: port;
302+
ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
299303
for (; p <= port_to; p++) {
300304
e.port = htons(p);
301-
ip2 = (retried && ip == ntohl(h->next.ip[0]) &&
302-
p == ntohs(h->next.port)) ? ntohl(h->next.ip[1])
303-
: ip2_from;
304-
while (ip2 <= ip2_to) {
305+
do {
305306
e.ip[1] = htonl(ip2);
306-
ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
307-
&e.cidr[1]);
307+
ip2 = ip_set_range_to_cidr(ip2, ip2_to,
308+
&e.cidr[1]);
308309
ret = adtfn(set, &e, &ext, &ext, flags);
309310
if (ret && !ip_set_eexist(ret, flags))
310311
return ret;
311312

312313
ret = 0;
313-
ip2 = ip2_last + 1;
314-
}
314+
} while (ip2++ < ip2_to);
315+
ip2 = ip2_from;
315316
}
316-
ip = ip_last + 1;
317-
}
317+
p = port;
318+
} while (ip++ < ip_to);
318319
return ret;
319320
}
320321

0 commit comments

Comments
 (0)