platform: don't read past end of address array (bgo #742937)

The address might be zero-size, and therefore nl_addr_get_binary_addr()
returns a pointer to a zero-size array.  We don't want to read past the
end of that array.  Since zero-size addresses really mean an address
of all zeros, just make that happen.

As an additional optimization, if the prefix length is zero, the whole
address is host bits and should be cleared.

==30286== Invalid read of size 4
==30286==    at 0x478090: clear_host_address (nm-linux-platform.c:3786)
==30286==    by 0x4784D4: route_search_cache (nm-linux-platform.c:3883)
==30286==    by 0x4785A1: refresh_route (nm-linux-platform.c:3901)
==30286==    by 0x4787B6: ip4_route_delete (nm-linux-platform.c:3978)
==30286==    by 0x47F674: nm_platform_ip4_route_delete (nm-platform.c:1980)
==30286==    by 0x4B279D: _v4_platform_route_delete_default (nm-default-route-manager.c:1122)
==30286==    by 0x4AEF03: _platform_route_sync_flush (nm-default-route-manager.c:320)
==30286==    by 0x4B043E: _resync_all (nm-default-route-manager.c:574)
==30286==    by 0x4B0CA7: _entry_at_idx_remove (nm-default-route-manager.c:631)
==30286==    by 0x4B1A66: _ipx_update_default_route (nm-default-route-manager.c:806)
==30286==    by 0x4B1A9C: nm_default_route_manager_ip4_update_default_route (nm-default-route-manager.c:813)
==30286==    by 0x45C3BC: _cleanup_generic_post (nm-device.c:7143)
==30286==  Address 0xee33514 is 0 bytes after a block of size 20 alloc'd
==30286==    at 0x4C2C080: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==30286==    by 0x6B2B0B1: nl_addr_alloc (in /usr/lib/libnl-3.so.200.20.0)
==30286==    by 0x6B2B0E3: nl_addr_build (in /usr/lib/libnl-3.so.200.20.0)
==30286==    by 0x6B2B181: nl_addr_clone (in /usr/lib/libnl-3.so.200.20.0)
==30286==    by 0x66DB0D7: ??? (in /usr/lib/libnl-route-3.so.200.20.0)
==30286==    by 0x6B33CE6: nl_object_clone (in /usr/lib/libnl-3.so.200.20.0)
==30286==    by 0x6B2D303: nl_cache_add (in /usr/lib/libnl-3.so.200.20.0)
==30286==    by 0x472E55: refresh_object (nm-linux-platform.c:1735)
==30286==    by 0x473137: add_object (nm-linux-platform.c:1795)
==30286==    by 0x478373: ip4_route_add (nm-linux-platform.c:3846)
==30286==    by 0x47F375: nm_platform_ip4_route_add (nm-platform.c:1939)
==30286==    by 0x4AEC06: _platform_route_sync_add (nm-default-route-manager.c:254)

https://bugzilla.gnome.org/show_bug.cgi?id=742937
This commit is contained in:
Dan Williams
2015-01-14 13:57:50 -06:00
parent 6c1a6d2d5f
commit d2871089a8

View File

@@ -3891,7 +3891,14 @@ route_search_cache (struct nl_cache *cache, int family, int ifindex, const void
|| nl_addr_get_prefixlen (dst) != plen) || nl_addr_get_prefixlen (dst) != plen)
continue; continue;
/* plen = 0 means all host bits, so all bits should be cleared.
* Likewise if the binary address is not present or all zeros.
*/
if (plen == 0 || nl_addr_iszero (dst))
memset (dst_clean, 0, sizeof (dst_clean));
else
clear_host_address (family, nl_addr_get_binary_addr (dst), plen, dst_clean); clear_host_address (family, nl_addr_get_binary_addr (dst), plen, dst_clean);
if (memcmp (dst_clean, network_clean, if (memcmp (dst_clean, network_clean,
family == AF_INET ? sizeof (guint32) : sizeof (struct in6_addr)) != 0) family == AF_INET ? sizeof (guint32) : sizeof (struct in6_addr)) != 0)
continue; continue;