]> git.ipfire.org Git - thirdparty/iproute2.git/commitdiff
ipnetns: use-after-free problem in get_netnsid_from_name func
authorZhiqiang Liu <liuzhiqiang26@huawei.com>
Sun, 5 May 2019 01:59:51 +0000 (09:59 +0800)
committerStephen Hemminger <stephen@networkplumber.org>
Mon, 6 May 2019 15:36:18 +0000 (08:36 -0700)
Follow the following steps:
 # ip netns add net1
 # export MALLOC_MMAP_THRESHOLD_=0
 # ip netns list
then Segmentation fault (core dumped) will occur.

In get_netnsid_from_name func, answer is freed before
rta_getattr_u32(tb[NETNSA_NSID]), where tb[] refers to answer`s
content. If we set MALLOC_MMAP_THRESHOLD_=0, mmap will be adoped to
malloc memory, which will be freed immediately after calling free
func.  So reading tb[NETNSA_NSID] will access the released memory
after free(answer).

Here, we will call get_netnsid_from_name(tb[NETNSA_NSID]) before free(answer).

Fixes: 86bf43c7c2f ("lib/libnetlink: update rtnl_talk to support malloc buff at run time")
Reported-by: Huiying Kou <kouhuiying@huawei.com>
Signed-off-by: Zhiqiang Liu <liuzhiqiang26@huawei.com>
Acked-by: Phil Sutter <phil@nwl.cc>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
ip/ipnetns.c

index 430d88443b55e10e81cae219fad9f3cfd9a292fd..52aefacf4dc2e35be14f2560a649d777f9b17a59 100644 (file)
@@ -107,7 +107,7 @@ int get_netnsid_from_name(const char *name)
        struct nlmsghdr *answer;
        struct rtattr *tb[NETNSA_MAX + 1];
        struct rtgenmsg *rthdr;
-       int len, fd;
+       int len, fd, ret = -1;
 
        netns_nsid_socket_init();
 
@@ -124,23 +124,22 @@ int get_netnsid_from_name(const char *name)
 
        /* Validate message and parse attributes */
        if (answer->nlmsg_type == NLMSG_ERROR)
-               goto err_out;
+               goto out;
 
        rthdr = NLMSG_DATA(answer);
        len = answer->nlmsg_len - NLMSG_SPACE(sizeof(*rthdr));
        if (len < 0)
-               goto err_out;
+               goto out;
 
        parse_rtattr(tb, NETNSA_MAX, NETNS_RTA(rthdr), len);
 
        if (tb[NETNSA_NSID]) {
-               free(answer);
-               return rta_getattr_u32(tb[NETNSA_NSID]);
+               ret = rta_getattr_u32(tb[NETNSA_NSID]);
        }
 
-err_out:
+out:
        free(answer);
-       return -1;
+       return ret;
 }
 
 struct nsid_cache {