| From 32c72165dbd0e246e69d16a3ad348a4851afd415 Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Kadlecsik=20J=C3=B3zsef?= <kadlec@blackhole.kfki.hu> |
| Date: Sun, 19 Jan 2020 22:06:49 +0100 |
| Subject: netfilter: ipset: use bitmap infrastructure completely |
| |
| From: Kadlecsik Jรณzsef <kadlec@blackhole.kfki.hu> |
| |
| commit 32c72165dbd0e246e69d16a3ad348a4851afd415 upstream. |
| |
| The bitmap allocation did not use full unsigned long sizes |
| when calculating the required size and that was triggered by KASAN |
| as slab-out-of-bounds read in several places. The patch fixes all |
| of them. |
| |
| Reported-by: syzbot+fabca5cbf5e54f3fe2de@syzkaller.appspotmail.com |
| Reported-by: syzbot+827ced406c9a1d9570ed@syzkaller.appspotmail.com |
| Reported-by: syzbot+190d63957b22ef673ea5@syzkaller.appspotmail.com |
| Reported-by: syzbot+dfccdb2bdb4a12ad425e@syzkaller.appspotmail.com |
| Reported-by: syzbot+df0d0f5895ef1f41a65b@syzkaller.appspotmail.com |
| Reported-by: syzbot+b08bd19bb37513357fd4@syzkaller.appspotmail.com |
| Reported-by: syzbot+53cdd0ec0bbabd53370a@syzkaller.appspotmail.com |
| Signed-off-by: Jozsef Kadlecsik <kadlec@netfilter.org> |
| Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| include/linux/netfilter/ipset/ip_set.h | 7 ------- |
| net/netfilter/ipset/ip_set_bitmap_gen.h | 2 +- |
| net/netfilter/ipset/ip_set_bitmap_ip.c | 6 +++--- |
| net/netfilter/ipset/ip_set_bitmap_ipmac.c | 6 +++--- |
| net/netfilter/ipset/ip_set_bitmap_port.c | 6 +++--- |
| 5 files changed, 10 insertions(+), 17 deletions(-) |
| |
| --- a/include/linux/netfilter/ipset/ip_set.h |
| +++ b/include/linux/netfilter/ipset/ip_set.h |
| @@ -537,13 +537,6 @@ ip6addrptr(const struct sk_buff *skb, bo |
| sizeof(*addr)); |
| } |
| |
| -/* Calculate the bytes required to store the inclusive range of a-b */ |
| -static inline int |
| -bitmap_bytes(u32 a, u32 b) |
| -{ |
| - return 4 * ((((b - a + 8) / 8) + 3) / 4); |
| -} |
| - |
| #include <linux/netfilter/ipset/ip_set_timeout.h> |
| #include <linux/netfilter/ipset/ip_set_comment.h> |
| |
| --- a/net/netfilter/ipset/ip_set_bitmap_gen.h |
| +++ b/net/netfilter/ipset/ip_set_bitmap_gen.h |
| @@ -81,7 +81,7 @@ mtype_flush(struct ip_set *set) |
| |
| if (set->extensions & IPSET_EXT_DESTROY) |
| mtype_ext_cleanup(set); |
| - memset(map->members, 0, map->memsize); |
| + bitmap_zero(map->members, map->elements); |
| } |
| |
| static int |
| --- a/net/netfilter/ipset/ip_set_bitmap_ip.c |
| +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c |
| @@ -40,7 +40,7 @@ MODULE_ALIAS("ip_set_bitmap:ip"); |
| |
| /* Type structure */ |
| struct bitmap_ip { |
| - void *members; /* the set members */ |
| + unsigned long *members; /* the set members */ |
| u32 first_ip; /* host byte order, included in range */ |
| u32 last_ip; /* host byte order, included in range */ |
| u32 elements; /* number of max elements in the set */ |
| @@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct b |
| u32 first_ip, u32 last_ip, |
| u32 elements, u32 hosts, u8 netmask) |
| { |
| - map->members = ip_set_alloc(map->memsize); |
| + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); |
| if (!map->members) |
| return false; |
| map->first_ip = first_ip; |
| @@ -315,7 +315,7 @@ bitmap_ip_create(struct net *net, struct |
| if (!map) |
| return -ENOMEM; |
| |
| - map->memsize = bitmap_bytes(0, elements - 1); |
| + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); |
| set->variant = &bitmap_ip; |
| if (!init_map_ip(set, map, first_ip, last_ip, |
| elements, hosts, netmask)) { |
| --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c |
| +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c |
| @@ -46,7 +46,7 @@ enum { |
| |
| /* Type structure */ |
| struct bitmap_ipmac { |
| - void *members; /* the set members */ |
| + unsigned long *members; /* the set members */ |
| u32 first_ip; /* host byte order, included in range */ |
| u32 last_ip; /* host byte order, included in range */ |
| u32 elements; /* number of max elements in the set */ |
| @@ -299,7 +299,7 @@ static bool |
| init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, |
| u32 first_ip, u32 last_ip, u32 elements) |
| { |
| - map->members = ip_set_alloc(map->memsize); |
| + map->members = bitmap_zalloc(elements, GFP_KERNEL | __GFP_NOWARN); |
| if (!map->members) |
| return false; |
| map->first_ip = first_ip; |
| @@ -363,7 +363,7 @@ bitmap_ipmac_create(struct net *net, str |
| if (!map) |
| return -ENOMEM; |
| |
| - map->memsize = bitmap_bytes(0, elements - 1); |
| + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); |
| set->variant = &bitmap_ipmac; |
| if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { |
| kfree(map); |
| --- a/net/netfilter/ipset/ip_set_bitmap_port.c |
| +++ b/net/netfilter/ipset/ip_set_bitmap_port.c |
| @@ -34,7 +34,7 @@ MODULE_ALIAS("ip_set_bitmap:port"); |
| |
| /* Type structure */ |
| struct bitmap_port { |
| - void *members; /* the set members */ |
| + unsigned long *members; /* the set members */ |
| u16 first_port; /* host byte order, included in range */ |
| u16 last_port; /* host byte order, included in range */ |
| u32 elements; /* number of max elements in the set */ |
| @@ -207,7 +207,7 @@ static bool |
| init_map_port(struct ip_set *set, struct bitmap_port *map, |
| u16 first_port, u16 last_port) |
| { |
| - map->members = ip_set_alloc(map->memsize); |
| + map->members = bitmap_zalloc(map->elements, GFP_KERNEL | __GFP_NOWARN); |
| if (!map->members) |
| return false; |
| map->first_port = first_port; |
| @@ -250,7 +250,7 @@ bitmap_port_create(struct net *net, stru |
| return -ENOMEM; |
| |
| map->elements = elements; |
| - map->memsize = bitmap_bytes(0, map->elements); |
| + map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long); |
| set->variant = &bitmap_port; |
| if (!init_map_port(set, map, first_port, last_port)) { |
| kfree(map); |