From 1031b2bb5c97bd48ff93f85537b3f5ce0f6f64bf Mon Sep 17 00:00:00 2001 From: Thomas Haller Date: Mon, 10 Sep 2018 15:22:28 +0200 Subject: [PATCH 1/6] systemd/dhcp: fix assertion starting DHCP client without MAC address An assertion in dhcp_network_bind_raw_socket() is triggered when starting an sd_dhcp_client without setting setting a MAC address first. - sd_dhcp_client_start() - client_start() - client_start_delayed() - dhcp_network_bind_raw_socket() In that case, the arp-type and MAC address is still unset. Note that dhcp_network_bind_raw_socket() already checks for a valid arp-type and MAC address below, so we should just gracefully return -EINVAL. Maybe sd_dhcp_client_start() should fail earlier when starting without MAC address. But the failure here will be correctly propagated and the start aborted. See-also: https://github.com/systemd/systemd/pull/10054 (cherry picked from commit 34af574d5810ab2b0d6d354cbc28135cde4a55b1) (cherry picked from commit 0a797bdc2a592385a21e7ed918c08ef54a346d99) (cherry picked from commit f37ed84ca495ee212b1e82b9c5a5682c4acfebcd) --- src/systemd/src/libsystemd-network/dhcp-network.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/systemd/src/libsystemd-network/dhcp-network.c b/src/systemd/src/libsystemd-network/dhcp-network.c index f01b2cfe04..5d6f227b5d 100644 --- a/src/systemd/src/libsystemd-network/dhcp-network.c +++ b/src/systemd/src/libsystemd-network/dhcp-network.c @@ -144,8 +144,6 @@ int dhcp_network_bind_raw_socket(int ifindex, union sockaddr_union *link, const uint8_t *bcast_addr = NULL; uint8_t dhcp_hlen = 0; - assert_return(mac_addr_len > 0, -EINVAL); - if (arp_type == ARPHRD_ETHER) { assert_return(mac_addr_len == ETH_ALEN, -EINVAL); memcpy(ð_mac, mac_addr, ETH_ALEN); From 0f25f47767794fb179edb9916566a208fbcfcb8f Mon Sep 17 00:00:00 2001 From: Evgeny Vereshchagin Date: Sat, 29 Sep 2018 03:06:10 +0000 Subject: [PATCH 2/6] dhcp6: fix an off-by-one error in dhcp6_option_parse_domainname ==14==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200055fa9c at pc 0x0000005458f1 bp 0x7ffc78940d90 sp 0x7ffc78940d88 READ of size 1 at 0x60200055fa9c thread T0 #0 0x5458f0 in dhcp6_option_parse_domainname /work/build/../../src/systemd/src/libsystemd-network/dhcp6-option.c:555:29 #1 0x54706e in dhcp6_lease_set_domains /work/build/../../src/systemd/src/libsystemd-network/sd-dhcp6-lease.c:242:13 #2 0x53fce0 in client_parse_message /work/build/../../src/systemd/src/libsystemd-network/sd-dhcp6-client.c:984:29 #3 0x53f3bc in client_receive_advertise /work/build/../../src/systemd/src/libsystemd-network/sd-dhcp6-client.c:1083:13 #4 0x53d57f in client_receive_message /work/build/../../src/systemd/src/libsystemd-network/sd-dhcp6-client.c:1182:21 #5 0x7f0f7159deee in source_dispatch /work/build/../../src/systemd/src/libsystemd/sd-event/sd-event.c:3042:21 #6 0x7f0f7159d431 in sd_event_dispatch /work/build/../../src/systemd/src/libsystemd/sd-event/sd-event.c:3455:21 #7 0x7f0f7159ea8d in sd_event_run /work/build/../../src/systemd/src/libsystemd/sd-event/sd-event.c:3512:21 #8 0x531f2b in fuzz_client /work/build/../../src/systemd/src/fuzz/fuzz-dhcp6-client.c:44:9 #9 0x531bc1 in LLVMFuzzerTestOneInput /work/build/../../src/systemd/src/fuzz/fuzz-dhcp6-client.c:53:9 #10 0x57bec8 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) /src/libfuzzer/FuzzerLoop.cpp:570:15 #11 0x579d67 in fuzzer::Fuzzer::RunOne(unsigned char const*, unsigned long, bool, fuzzer::InputInfo*, bool*) /src/libfuzzer/FuzzerLoop.cpp:479:3 #12 0x57dc92 in fuzzer::Fuzzer::MutateAndTestOne() /src/libfuzzer/FuzzerLoop.cpp:707:19 #13 0x580ca6 in fuzzer::Fuzzer::Loop(std::__1::vector, std::__1::allocator >, fuzzer::fuzzer_allocator, std::__1::allocator > > > const&) /src/libfuzzer/FuzzerLoop.cpp:838:5 #14 0x55e968 in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) /src/libfuzzer/FuzzerDriver.cpp:764:6 #15 0x551a1c in main /src/libfuzzer/FuzzerMain.cpp:20:10 #16 0x7f0f701a082f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f) #17 0x41e928 in _start (/out/fuzz-dhcp6-client+0x41e928) https://github.com/systemd/systemd/pull/10200 https://github.com/systemd/systemd/commit/b387d3c1327a3ad2a2509bd3d3491e674392ff21 (cherry picked from commit 7cb7cffc4962245a32e87017bcf264005c043250) (cherry picked from commit cd3aacefdd0b91741b7b2e7b5ee5baab210addd9) (cherry picked from commit 5b140a77bc7b01dc002dbf28a7a2507a27a63d7c) --- src/systemd/src/libsystemd-network/dhcp6-option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index 3a77e34d57..d8812c36fd 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -366,7 +366,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * /* Literal label */ label = (const char *)&optval[pos]; pos += c; - if (pos > optlen) + if (pos >= optlen) return -EMSGSIZE; if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) { From 4439f07841bdddc6878132a993c229df032e8e85 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 27 Sep 2018 18:04:59 +0900 Subject: [PATCH 3/6] sd-dhcp-lease: fix memleaks (cherry picked from commit e2975f854831d08a25b4f5eb329b6d04102e115f) (cherry picked from commit 157094abd83f933fad142758a7d177cfa1a347f7) (cherry picked from commit 3fd9d11619a5e60d375076fbe13851dd1d3a4a63) --- src/systemd/src/libsystemd-network/sd-dhcp-lease.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c index c00190b5a0..c840e316ee 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-lease.c @@ -292,6 +292,8 @@ sd_dhcp_lease *sd_dhcp_lease_unref(sd_dhcp_lease *lease) { free(option); } + free(lease->root_path); + free(lease->timezone); free(lease->hostname); free(lease->domainname); free(lease->dns); From 4ca0e57c46cf6861ec6f6b6c8e0d430edb3fa5b1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 19 Oct 2018 03:42:10 +0900 Subject: [PATCH 4/6] sd-dhcp6: make dhcp6_option_parse_domainname() not store empty domain This improves performance of fuzzer. C.f. oss-fuzz#11019. (cherry picked from commit 3c72b6ed4252e7ff5f7704bfe44557ec197b47fa) (cherry picked from commit 50403cccee28c7dcd54b138a0d3b3f69ea0204fe) (cherry picked from commit f11f5abb1a8b96b553d2d156f8b5cf440695c04d) (cherry picked from commit c836279fca80fb22ca7ef02acaa5b987fee61123) --- .../src/libsystemd-network/dhcp6-option.c | 56 ++++++++----------- 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index d8812c36fd..d496244370 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -353,6 +353,7 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * bool first = true; for (;;) { + const char *label; uint8_t c; c = optval[pos++]; @@ -360,47 +361,41 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * if (c == 0) /* End of name */ break; - else if (c <= 63) { - const char *label; + if (c > 63) + return -EBADMSG; - /* Literal label */ - label = (const char *)&optval[pos]; - pos += c; - if (pos >= optlen) - return -EMSGSIZE; + /* Literal label */ + label = (const char *)&optval[pos]; + pos += c; + if (pos >= optlen) + return -EMSGSIZE; - if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) { - r = -ENOMEM; - goto fail; - } + if (!GREEDY_REALLOC(ret, allocated, n + !first + DNS_LABEL_ESCAPED_MAX)) + return -ENOMEM; - if (first) - first = false; - else - ret[n++] = '.'; + if (first) + first = false; + else + ret[n++] = '.'; - r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); - if (r < 0) - goto fail; + r = dns_label_escape(label, c, ret + n, DNS_LABEL_ESCAPED_MAX); + if (r < 0) + return r; - n += r; - continue; - } else { - r = -EBADMSG; - goto fail; - } + n += r; } - if (!GREEDY_REALLOC(ret, allocated, n + 1)) { - r = -ENOMEM; - goto fail; - } + if (n == 0) + continue; + + if (!GREEDY_REALLOC(ret, allocated, n + 1)) + return -ENOMEM; ret[n] = 0; r = strv_extend(&names, ret); if (r < 0) - goto fail; + return r; idx++; } @@ -409,7 +404,4 @@ int dhcp6_option_parse_domainname(const uint8_t *optval, uint16_t optlen, char * names = NULL; return idx; - -fail: - return r; } From 1cfefbb99ff3c2ab7a0f54829c6f3f787d9e6d77 Mon Sep 17 00:00:00 2001 From: Li Song Date: Fri, 19 Oct 2018 13:41:51 -0400 Subject: [PATCH 5/6] sd-dhcp: remove unreachable route after rebinding return NAK (cherry picked from commit cc3981b1272b9ce37e7d734a7b2f42e84acac535) (cherry picked from commit 915c2f675a23b2ae16d292d1ac570706f76b384d) (cherry picked from commit cb77290a696dce924e2a993690634986ac035490) (cherry picked from commit f211b140a5861ddedc2424946e3ab07d3b642b5f) --- src/systemd/src/libsystemd-network/sd-dhcp-client.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/systemd/src/libsystemd-network/sd-dhcp-client.c b/src/systemd/src/libsystemd-network/sd-dhcp-client.c index 5eab005029..f3f067b051 100644 --- a/src/systemd/src/libsystemd-network/sd-dhcp-client.c +++ b/src/systemd/src/libsystemd-network/sd-dhcp-client.c @@ -1616,6 +1616,8 @@ static int client_handle_message(sd_dhcp_client *client, DHCPMessage *message, i client->timeout_resend = sd_event_source_unref(client->timeout_resend); + client_notify(client, SD_DHCP_CLIENT_EVENT_EXPIRED); + r = client_initialize(client); if (r < 0) goto error; From c3221cb0c5b4a2936c198e33b6f7853141991277 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 19 Oct 2018 12:12:33 +0200 Subject: [PATCH 6/6] dhcp6: make sure we have enough space for the DHCP6 option header Fixes a vulnerability originally discovered by Felix Wilhelm from Google. CVE-2018-15688 LP: #1795921 https://bugzilla.redhat.com/show_bug.cgi?id=1639067 (cherry picked from commit 4dac5eaba4e419b29c97da38a8b1f82336c2c892) (cherry picked from commit 01ca2053bbea09f35b958c8cc7631e15469acb79) (cherry picked from commit fc230dca139142f409d7bac99dbfabe9b004e2fb) (cherry picked from commit cc1e5a7f5731f223d1eb8473fa0eecbedfc0ae5f) --- src/systemd/src/libsystemd-network/dhcp6-option.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/systemd/src/libsystemd-network/dhcp6-option.c b/src/systemd/src/libsystemd-network/dhcp6-option.c index d496244370..7615cb80e0 100644 --- a/src/systemd/src/libsystemd-network/dhcp6-option.c +++ b/src/systemd/src/libsystemd-network/dhcp6-option.c @@ -103,7 +103,7 @@ int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia) { return -EINVAL; } - if (*buflen < len) + if (*buflen < offsetof(DHCP6Option, data) + len) return -ENOBUFS; ia_hdr = *buf;