ACK: [[SCRIPT=remove_re|Re: [PATCH 1/1] netfilter: ipset: Fix wraparound in hash:*net* types]]
Stefan Bader
stefan.bader at canonical.com
Fri Feb 22 10:10:13 UTC 2019
On 21.02.19 11:42, Kai-Heng Feng wrote:
> From: Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
>
> BugLink: https://bugs.launchpad.net/bugs/1811394
>
> 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: 48596a8ddc46 ("netfilter: ipset: Fix adding an IPv4 range containing more than 2^31 addresses")
> Signed-off-by: Jozsef Kadlecsik <kadlec at blackhole.kfki.hu>
> Signed-off-by: Pablo Neira Ayuso <pablo at netfilter.org>
> (cherry picked from commit 0b8d9073539e217f79ec1bff65eb205ac796723d)
> Signed-off-by: Kai-Heng Feng <kai.heng.feng at canonical.com>
Acked-by: Stefan Bader <stefan.bader at canonical.com>
> ---
Cherry-pick, tested.
> net/netfilter/ipset/ip_set_hash_ipportnet.c | 26 +++++++--------
> net/netfilter/ipset/ip_set_hash_net.c | 9 +++--
> net/netfilter/ipset/ip_set_hash_netiface.c | 9 +++--
> net/netfilter/ipset/ip_set_hash_netnet.c | 28 ++++++++--------
> net/netfilter/ipset/ip_set_hash_netport.c | 19 ++++++-----
> net/netfilter/ipset/ip_set_hash_netportnet.c | 35 ++++++++++----------
> 6 files changed, 63 insertions(+), 63 deletions(-)
>
> diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
> index 0f164e986bf1..88b83d6d3084 100644
> --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
> +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
> @@ -168,7 +168,7 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> struct hash_ipportnet4_elem e = { .cidr = HOST_MASK - 1 };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> u32 ip = 0, ip_to = 0, p = 0, port, port_to;
> - u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
> + u32 ip2_from = 0, ip2_to = 0, ip2;
> bool with_ports = false;
> u8 cidr;
> int ret;
> @@ -269,22 +269,21 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> ip_set_mask_from_to(ip2_from, ip2_to, e.cidr + 1);
> }
>
> - if (retried)
> + if (retried) {
> ip = ntohl(h->next.ip);
> + p = ntohs(h->next.port);
> + ip2 = ntohl(h->next.ip2);
> + } else {
> + p = port;
> + ip2 = ip2_from;
> + }
> for (; ip <= ip_to; ip++) {
> e.ip = htonl(ip);
> - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
> - : port;
> for (; p <= port_to; p++) {
> e.port = htons(p);
> - ip2 = retried &&
> - ip == ntohl(h->next.ip) &&
> - p == ntohs(h->next.port)
> - ? ntohl(h->next.ip2) : ip2_from;
> - while (ip2 <= ip2_to) {
> + do {
> e.ip2 = htonl(ip2);
> - ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
> - &cidr);
> + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &cidr);
> e.cidr = cidr - 1;
> ret = adtfn(set, &e, &ext, &ext, flags);
>
> @@ -292,9 +291,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> return ret;
>
> ret = 0;
> - ip2 = ip2_last + 1;
> - }
> + } while (ip2++ < ip2_to);
> + ip2 = ip2_from;
> }
> + p = port;
> }
> return ret;
> }
> diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
> index 1c67a1761e45..5449e23af13a 100644
> --- a/net/netfilter/ipset/ip_set_hash_net.c
> +++ b/net/netfilter/ipset/ip_set_hash_net.c
> @@ -143,7 +143,7 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
> ipset_adtfn adtfn = set->variant->adt[adt];
> struct hash_net4_elem e = { .cidr = HOST_MASK };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> - u32 ip = 0, ip_to = 0, last;
> + u32 ip = 0, ip_to = 0;
> int ret;
>
> if (tb[IPSET_ATTR_LINENO])
> @@ -193,16 +193,15 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
> }
> if (retried)
> ip = ntohl(h->next.ip);
> - while (ip <= ip_to) {
> + do {
> e.ip = htonl(ip);
> - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
> + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
> ret = adtfn(set, &e, &ext, &ext, flags);
> if (ret && !ip_set_eexist(ret, flags))
> return ret;
>
> ret = 0;
> - ip = last + 1;
> - }
> + } while (ip++ < ip_to);
> return ret;
> }
>
> diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
> index d417074f1c1a..f5164c1efce2 100644
> --- a/net/netfilter/ipset/ip_set_hash_netiface.c
> +++ b/net/netfilter/ipset/ip_set_hash_netiface.c
> @@ -200,7 +200,7 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
> ipset_adtfn adtfn = set->variant->adt[adt];
> struct hash_netiface4_elem e = { .cidr = HOST_MASK, .elem = 1 };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> - u32 ip = 0, ip_to = 0, last;
> + u32 ip = 0, ip_to = 0;
> int ret;
>
> if (tb[IPSET_ATTR_LINENO])
> @@ -255,17 +255,16 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
>
> if (retried)
> ip = ntohl(h->next.ip);
> - while (ip <= ip_to) {
> + do {
> e.ip = htonl(ip);
> - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
> + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr);
> ret = adtfn(set, &e, &ext, &ext, flags);
>
> if (ret && !ip_set_eexist(ret, flags))
> return ret;
>
> ret = 0;
> - ip = last + 1;
> - }
> + } while (ip++ < ip_to);
> return ret;
> }
>
> diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
> index 7f9ae2e9645b..5a2b923bd81f 100644
> --- a/net/netfilter/ipset/ip_set_hash_netnet.c
> +++ b/net/netfilter/ipset/ip_set_hash_netnet.c
> @@ -169,8 +169,8 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> ipset_adtfn adtfn = set->variant->adt[adt];
> struct hash_netnet4_elem e = { };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> - u32 ip = 0, ip_to = 0, last;
> - u32 ip2 = 0, ip2_from = 0, ip2_to = 0, last2;
> + u32 ip = 0, ip_to = 0;
> + u32 ip2 = 0, ip2_from = 0, ip2_to = 0;
> int ret;
>
> if (tb[IPSET_ATTR_LINENO])
> @@ -247,27 +247,27 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
> }
>
> - if (retried)
> + if (retried) {
> ip = ntohl(h->next.ip[0]);
> + ip2 = ntohl(h->next.ip[1]);
> + } else {
> + ip2 = ip2_from;
> + }
>
> - while (ip <= ip_to) {
> + do {
> e.ip[0] = htonl(ip);
> - last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
> - ip2 = (retried &&
> - ip == ntohl(h->next.ip[0])) ? ntohl(h->next.ip[1])
> - : ip2_from;
> - while (ip2 <= ip2_to) {
> + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
> + do {
> e.ip[1] = htonl(ip2);
> - last2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
> + ip2 = ip_set_range_to_cidr(ip2, ip2_to, &e.cidr[1]);
> ret = adtfn(set, &e, &ext, &ext, flags);
> if (ret && !ip_set_eexist(ret, flags))
> return ret;
>
> ret = 0;
> - ip2 = last2 + 1;
> - }
> - ip = last + 1;
> - }
> + } while (ip2++ < ip2_to);
> + ip2 = ip2_from;
> + } while (ip++ < ip_to);
> return ret;
> }
>
> diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
> index e6ef382febe4..1a187be9ebc8 100644
> --- a/net/netfilter/ipset/ip_set_hash_netport.c
> +++ b/net/netfilter/ipset/ip_set_hash_netport.c
> @@ -161,7 +161,7 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
> ipset_adtfn adtfn = set->variant->adt[adt];
> struct hash_netport4_elem e = { .cidr = HOST_MASK - 1 };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> - u32 port, port_to, p = 0, ip = 0, ip_to = 0, last;
> + u32 port, port_to, p = 0, ip = 0, ip_to = 0;
> bool with_ports = false;
> u8 cidr;
> int ret;
> @@ -239,25 +239,26 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
> ip_set_mask_from_to(ip, ip_to, e.cidr + 1);
> }
>
> - if (retried)
> + if (retried) {
> ip = ntohl(h->next.ip);
> - while (ip <= ip_to) {
> + p = ntohs(h->next.port);
> + } else {
> + p = port;
> + }
> + do {
> e.ip = htonl(ip);
> - last = ip_set_range_to_cidr(ip, ip_to, &cidr);
> + ip = ip_set_range_to_cidr(ip, ip_to, &cidr);
> e.cidr = cidr - 1;
> - p = retried && ip == ntohl(h->next.ip) ? ntohs(h->next.port)
> - : port;
> for (; p <= port_to; p++) {
> e.port = htons(p);
> ret = adtfn(set, &e, &ext, &ext, flags);
> -
> if (ret && !ip_set_eexist(ret, flags))
> return ret;
>
> ret = 0;
> }
> - ip = last + 1;
> - }
> + p = port;
> + } while (ip++ < ip_to);
> return ret;
> }
>
> diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
> index 8602f2595a1a..d391485a6acd 100644
> --- a/net/netfilter/ipset/ip_set_hash_netportnet.c
> +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c
> @@ -184,8 +184,8 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> ipset_adtfn adtfn = set->variant->adt[adt];
> struct hash_netportnet4_elem e = { };
> struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
> - u32 ip = 0, ip_to = 0, ip_last, p = 0, port, port_to;
> - u32 ip2_from = 0, ip2_to = 0, ip2_last, ip2;
> + u32 ip = 0, ip_to = 0, p = 0, port, port_to;
> + u32 ip2_from = 0, ip2_to = 0, ip2;
> bool with_ports = false;
> int ret;
>
> @@ -288,33 +288,34 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
> ip_set_mask_from_to(ip2_from, ip2_to, e.cidr[1]);
> }
>
> - if (retried)
> + if (retried) {
> ip = ntohl(h->next.ip[0]);
> + p = ntohs(h->next.port);
> + ip2 = ntohl(h->next.ip[1]);
> + } else {
> + p = port;
> + ip2 = ip2_from;
> + }
>
> - while (ip <= ip_to) {
> + do {
> e.ip[0] = htonl(ip);
> - ip_last = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
> - p = retried && ip == ntohl(h->next.ip[0]) ? ntohs(h->next.port)
> - : port;
> + ip = ip_set_range_to_cidr(ip, ip_to, &e.cidr[0]);
> for (; p <= port_to; p++) {
> e.port = htons(p);
> - ip2 = (retried && ip == ntohl(h->next.ip[0]) &&
> - p == ntohs(h->next.port)) ? ntohl(h->next.ip[1])
> - : ip2_from;
> - while (ip2 <= ip2_to) {
> + do {
> e.ip[1] = htonl(ip2);
> - ip2_last = ip_set_range_to_cidr(ip2, ip2_to,
> - &e.cidr[1]);
> + ip2 = ip_set_range_to_cidr(ip2, ip2_to,
> + &e.cidr[1]);
> ret = adtfn(set, &e, &ext, &ext, flags);
> if (ret && !ip_set_eexist(ret, flags))
> return ret;
>
> ret = 0;
> - ip2 = ip2_last + 1;
> - }
> + } while (ip2++ < ip2_to);
> + ip2 = ip2_from;
> }
> - ip = ip_last + 1;
> - }
> + p = port;
> + } while (ip++ < ip_to);
> return ret;
> }
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: OpenPGP digital signature
URL: <https://lists.ubuntu.com/archives/kernel-team/attachments/20190222/ddf6e3e4/attachment.sig>
More information about the kernel-team
mailing list