Commit f09736fc authored by Kadlecsik József's avatar Kadlecsik József Committed by Kleber Sacilotto de Souza

netfilter: ipset: use bitmap infrastructure completely

BugLink: https://bugs.launchpad.net/bugs/1864773

commit 32c72165 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: default avatarJozsef Kadlecsik <kadlec@netfilter.org>
Signed-off-by: default avatarPablo Neira Ayuso <pablo@netfilter.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
Signed-off-by: default avatarKleber Sacilotto de Souza <kleber.souza@canonical.com>
parent 4fbd40b6
...@@ -534,13 +534,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr) ...@@ -534,13 +534,6 @@ ip6addrptr(const struct sk_buff *skb, bool src, struct in6_addr *addr)
sizeof(*addr)); 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_timeout.h>
#include <linux/netfilter/ipset/ip_set_comment.h> #include <linux/netfilter/ipset/ip_set_comment.h>
......
...@@ -81,7 +81,7 @@ mtype_flush(struct ip_set *set) ...@@ -81,7 +81,7 @@ mtype_flush(struct ip_set *set)
if (set->extensions & IPSET_EXT_DESTROY) if (set->extensions & IPSET_EXT_DESTROY)
mtype_ext_cleanup(set); mtype_ext_cleanup(set);
memset(map->members, 0, map->memsize); bitmap_zero(map->members, map->elements);
} }
static int static int
......
...@@ -40,7 +40,7 @@ MODULE_ALIAS("ip_set_bitmap:ip"); ...@@ -40,7 +40,7 @@ MODULE_ALIAS("ip_set_bitmap:ip");
/* Type structure */ /* Type structure */
struct bitmap_ip { struct bitmap_ip {
void *members; /* the set members */ unsigned long *members; /* the set members */
u32 first_ip; /* host byte order, included in range */ u32 first_ip; /* host byte order, included in range */
u32 last_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 */ u32 elements; /* number of max elements in the set */
...@@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map, ...@@ -222,7 +222,7 @@ init_map_ip(struct ip_set *set, struct bitmap_ip *map,
u32 first_ip, u32 last_ip, u32 first_ip, u32 last_ip,
u32 elements, u32 hosts, u8 netmask) 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) if (!map->members)
return false; return false;
map->first_ip = first_ip; map->first_ip = first_ip;
...@@ -315,7 +315,7 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[], ...@@ -315,7 +315,7 @@ bitmap_ip_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
map->memsize = bitmap_bytes(0, elements - 1); map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_ip; set->variant = &bitmap_ip;
if (!init_map_ip(set, map, first_ip, last_ip, if (!init_map_ip(set, map, first_ip, last_ip,
elements, hosts, netmask)) { elements, hosts, netmask)) {
......
...@@ -46,7 +46,7 @@ enum { ...@@ -46,7 +46,7 @@ enum {
/* Type structure */ /* Type structure */
struct bitmap_ipmac { struct bitmap_ipmac {
void *members; /* the set members */ unsigned long *members; /* the set members */
u32 first_ip; /* host byte order, included in range */ u32 first_ip; /* host byte order, included in range */
u32 last_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 */ u32 elements; /* number of max elements in the set */
...@@ -297,7 +297,7 @@ static bool ...@@ -297,7 +297,7 @@ static bool
init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map, init_map_ipmac(struct ip_set *set, struct bitmap_ipmac *map,
u32 first_ip, u32 last_ip, u32 elements) 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) if (!map->members)
return false; return false;
map->first_ip = first_ip; map->first_ip = first_ip;
...@@ -361,7 +361,7 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[], ...@@ -361,7 +361,7 @@ bitmap_ipmac_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (!map) if (!map)
return -ENOMEM; return -ENOMEM;
map->memsize = bitmap_bytes(0, elements - 1); map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_ipmac; set->variant = &bitmap_ipmac;
if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) { if (!init_map_ipmac(set, map, first_ip, last_ip, elements)) {
kfree(map); kfree(map);
......
...@@ -34,7 +34,7 @@ MODULE_ALIAS("ip_set_bitmap:port"); ...@@ -34,7 +34,7 @@ MODULE_ALIAS("ip_set_bitmap:port");
/* Type structure */ /* Type structure */
struct bitmap_port { struct bitmap_port {
void *members; /* the set members */ unsigned long *members; /* the set members */
u16 first_port; /* host byte order, included in range */ u16 first_port; /* host byte order, included in range */
u16 last_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 */ u32 elements; /* number of max elements in the set */
...@@ -207,7 +207,7 @@ static bool ...@@ -207,7 +207,7 @@ static bool
init_map_port(struct ip_set *set, struct bitmap_port *map, init_map_port(struct ip_set *set, struct bitmap_port *map,
u16 first_port, u16 last_port) 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) if (!map->members)
return false; return false;
map->first_port = first_port; map->first_port = first_port;
...@@ -250,7 +250,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[], ...@@ -250,7 +250,7 @@ bitmap_port_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
return -ENOMEM; return -ENOMEM;
map->elements = elements; map->elements = elements;
map->memsize = bitmap_bytes(0, map->elements); map->memsize = BITS_TO_LONGS(elements) * sizeof(unsigned long);
set->variant = &bitmap_port; set->variant = &bitmap_port;
if (!init_map_port(set, map, first_port, last_port)) { if (!init_map_port(set, map, first_port, last_port)) {
kfree(map); kfree(map);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment