]> granicus.if.org Git - libnl/commitdiff
nl-addr: avoid read-out-of-bound in nl_addr_fill_sockaddr()
authorThomas Haller <thaller@redhat.com>
Sun, 14 Aug 2016 09:44:53 +0000 (11:44 +0200)
committerThomas Haller <thaller@redhat.com>
Sun, 14 Aug 2016 09:46:19 +0000 (11:46 +0200)
https://github.com/thom311/libnl/issues/103

Signed-off-by: Thomas Haller <thaller@redhat.com>
include/netlink/utils.h
lib/addr.c
lib/utils.c

index 1115bb4355d1368556e2e36e46b820adddae0bd1..4e2a90ae240ed3f9f3697f7a42d5d9049db1884b 100644 (file)
@@ -224,6 +224,13 @@ enum {
        NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX = 20,
 #define NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX
 
+       /**
+        * nl_addr_fill_sockaddr() properly checks that the provided address to
+        * avoid read-out-of-bounds for invalid addresses.
+        */
+       NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR = 21,
+#define NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR
+
        __NL_CAPABILITY_MAX,
        NL_CAPABILITY_MAX = (__NL_CAPABILITY_MAX - 1),
 #define NL_CAPABILITY_MAX NL_CAPABILITY_MAX
index 333787896be91b415c99b46b8b34194b1ca2de63..8cf64c22e8a78ce0b097407ca2573ab79af7a073 100644 (file)
@@ -707,8 +707,14 @@ int nl_addr_fill_sockaddr(const struct nl_addr *addr, struct sockaddr *sa,
                if (*salen < sizeof(*sai))
                        return -NLE_INVAL;
 
+               if (addr->a_len == 4)
+                       memcpy(&sai->sin_addr, addr->a_addr, 4);
+               else if (addr->a_len != 0)
+                       return -NLE_INVAL;
+               else
+                       memset(&sai->sin_addr, 0, 4);
+
                sai->sin_family = addr->a_family;
-               memcpy(&sai->sin_addr, addr->a_addr, 4);
                *salen = sizeof(*sai);
        }
                break;
@@ -719,8 +725,14 @@ int nl_addr_fill_sockaddr(const struct nl_addr *addr, struct sockaddr *sa,
                if (*salen < sizeof(*sa6))
                        return -NLE_INVAL;
 
+               if (addr->a_len == 16)
+                       memcpy(&sa6->sin6_addr, addr->a_addr, 16);
+               else if (addr->a_len != 0)
+                       return -NLE_INVAL;
+               else
+                       memset(&sa6->sin6_addr, 0, 16);
+
                sa6->sin6_family = addr->a_family;
-               memcpy(&sa6->sin6_addr, addr->a_addr, 16);
                *salen = sizeof(*sa6);
        }
                break;
index 3e98ab5d172af35cd923b7fccc22b0d036e11887..61c3d955b57d789010dbc179de6c1d49b609bdfd 100644 (file)
@@ -1165,7 +1165,7 @@ int nl_has_capability (int capability)
                        NL_CAPABILITY_RTNL_ADDR_PEER_FIX,
                        NL_CAPABILITY_VERSION_3_2_28,
                        NL_CAPABILITY_RTNL_ADDR_PEER_ID_FIX,
-                       0,
+                       NL_CAPABILITY_NL_ADDR_FILL_SOCKADDR,
                        0,
                        0,
                        0),