]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch
add patch to fix ipset memory exhaustion
[pve-kernel.git] / patches / kernel / 0010-netfilter-ipset-Fix-wraparound-n-hash-net-types.patch
CommitLineData
c774433e
DL
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
3Date: Fri, 12 Jan 2018 11:16:50 +0100
4Subject: [PATCH] netfilter: ipset: Fix wraparound in hash:*net* types
5
6Fix wraparound bug which could lead to memory exhaustion when adding an
7x.x.x.x-255.255.255.255 range to any hash:*net* types.
8
9Fixes Netfilter's bugzilla id #1212, reported by Thomas Schwark.
10
11Fixes: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses")
12Signed-off-by: Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
13Signed-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
23diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
24index 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 }
81diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
82index 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
114diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
115index 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
148diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
149index 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
203diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
204index 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
251diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
252index 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--
3172.11.0
318