From c381e45f4a63bca4a95da6961ce4fccfa8262301 Mon Sep 17 00:00:00 2001 From: Dan Streetman Date: Fri, 3 Sep 2021 12:43:33 -0400 Subject: [PATCH 1/2] meson.build: change operator combining bools from + to and upstream meson stopped allowing combining boolean with the plus operator, and now requires using the logical and operator reference: https://github.com/mesonbuild/meson/commit/43302d3296baff6aeaf8e03f5d701b0402e37a6c Fixes: #20632 (cherry picked from commit c29537f39e4f413a6cbfe9669fa121bdd6d8b36f) --- meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meson.build b/meson.build index f0e28cc5ca7..177cd4fb660 100644 --- a/meson.build +++ b/meson.build @@ -43,7 +43,7 @@ conf.set('BUILD_MODE', 'BUILD_MODE_' + get_option('mode').to_upper(), want_ossfuzz = get_option('oss-fuzz') want_libfuzzer = get_option('llvm-fuzz') -if want_ossfuzz + want_libfuzzer > 1 +if want_ossfuzz and want_libfuzzer error('only one of oss-fuzz or llvm-fuzz can be specified') endif From 5dc5c9a6495680dd78da0ad1fa37307ff70ee18a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 22 Sep 2021 10:35:56 +0300 Subject: [PATCH 2/2] sd-dhcp6-client: ignore IAs whose IAID do not match client's IAID But do not refuse whole message. (cherry picked from commit 469fd57f181e2a8d93f01662418ca998e1239ea5) --- src/libsystemd-network/dhcp6-internal.h | 2 +- src/libsystemd-network/dhcp6-option.c | 35 +++++++++++++++++-- src/libsystemd-network/sd-dhcp6-client.c | 29 +++------------- src/libsystemd-network/test-dhcp6-client.c | 39 ++++++++++++++-------- 4 files changed, 63 insertions(+), 42 deletions(-) diff --git a/src/libsystemd-network/dhcp6-internal.h b/src/libsystemd-network/dhcp6-internal.h index 681c4623155..942901a5b7d 100644 --- a/src/libsystemd-network/dhcp6-internal.h +++ b/src/libsystemd-network/dhcp6-internal.h @@ -105,7 +105,7 @@ int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHash int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode, size_t *optlen, uint8_t **optvalue); int dhcp6_option_parse_status(DHCP6Option *option, size_t len); -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code); +int dhcp6_option_parse_ia(DHCP6Option *iaoption, be32_t iaid, DHCP6IA *ia, uint16_t *ret_status_code); int dhcp6_option_parse_ip6addrs(uint8_t *optval, uint16_t optlen, struct in6_addr **addrs, size_t count, size_t *allocated); diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index 91162d636bf..1376ca53f50 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -515,7 +515,12 @@ static int dhcp6_option_parse_pdprefix(DHCP6Option *option, DHCP6IA *ia, uint32_ return 0; } -int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_status_code) { +int dhcp6_option_parse_ia( + DHCP6Option *iaoption, + be32_t iaid, + DHCP6IA *ia, + uint16_t *ret_status_code) { + uint32_t lt_t1, lt_t2, lt_valid = 0, lt_min = UINT32_MAX; uint16_t iatype, optlen; size_t iaaddr_offset; @@ -535,6 +540,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat if (len < DHCP6_OPTION_IA_NA_LEN) return -ENOBUFS; + /* According to RFC8415, IAs which do not match the client's IAID should be ignored, + * but not necessary to ignore or refuse the whole message. */ + if (((const struct ia_na*) iaoption->data)->id != iaid) + /* ENOANO indicates the option should be ignored. */ + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO), + "Received an IA_NA option with a different IAID " + "from the one chosen by the client, ignoring."); + iaaddr_offset = DHCP6_OPTION_IA_NA_LEN; memcpy(&ia->ia_na, iaoption->data, sizeof(ia->ia_na)); @@ -553,6 +566,14 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat if (len < sizeof(ia->ia_pd)) return -ENOBUFS; + /* According to RFC8415, IAs which do not match the client's IAID should be ignored, + * but not necessary to ignore or refuse the whole message. */ + if (((const struct ia_pd*) iaoption->data)->id != iaid) + /* ENOANO indicates the option should be ignored. */ + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO), + "Received an IA_PD option with a different IAID " + "from the one chosen by the client, ignoring."); + iaaddr_offset = sizeof(ia->ia_pd); memcpy(&ia->ia_pd, iaoption->data, sizeof(ia->ia_pd)); @@ -570,13 +591,21 @@ int dhcp6_option_parse_ia(DHCP6Option *iaoption, DHCP6IA *ia, uint16_t *ret_stat if (len < DHCP6_OPTION_IA_TA_LEN) return -ENOBUFS; + /* According to RFC8415, IAs which do not match the client's IAID should be ignored, + * but not necessary to ignore or refuse the whole message. */ + if (((const struct ia_ta*) iaoption->data)->id != iaid) + /* ENOANO indicates the option should be ignored. */ + return log_dhcp6_client_errno(client, SYNTHETIC_ERRNO(ENOANO), + "Received an IA_TA option with a different IAID " + "from the one chosen by the client, ignoring."); + iaaddr_offset = DHCP6_OPTION_IA_TA_LEN; - memcpy(&ia->ia_ta.id, iaoption->data, sizeof(ia->ia_ta)); + memcpy(&ia->ia_ta, iaoption->data, sizeof(ia->ia_ta)); break; default: - return -ENOMSG; + return -EINVAL; } ia->type = iatype; diff --git a/src/libsystemd-network/sd-dhcp6-client.c b/src/libsystemd-network/sd-dhcp6-client.c index 66f87c4b956..bd0f9114c4c 100644 --- a/src/libsystemd-network/sd-dhcp6-client.c +++ b/src/libsystemd-network/sd-dhcp6-client.c @@ -1102,7 +1102,6 @@ static int client_parse_message( while (pos < len) { DHCP6Option *option = (DHCP6Option *) &message->options[pos]; uint16_t optcode, optlen; - be32_t iaid_lease; int status; uint8_t *optval; @@ -1181,8 +1180,8 @@ static int client_parse_message( break; } - r = dhcp6_option_parse_ia(option, &lease->ia, &ia_na_status); - if (r < 0 && r != -ENOMSG) + r = dhcp6_option_parse_ia(option, client->ia_pd.ia_na.id, &lease->ia, &ia_na_status); + if (r < 0 && r != -ENOANO) return r; if (ia_na_status == DHCP6_STATUS_NO_ADDRS_AVAIL) { @@ -1190,16 +1189,6 @@ static int client_parse_message( continue; } - r = dhcp6_lease_get_iaid(lease, &iaid_lease); - if (r < 0) - return r; - - if (client->ia_na.ia_na.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA NA", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - if (lease->ia.addresses) { lt_t1 = MIN(lt_t1, be32toh(lease->ia.ia_na.lifetime_t1)); lt_t2 = MIN(lt_t2, be32toh(lease->ia.ia_na.lifetime_t1)); @@ -1214,8 +1203,8 @@ static int client_parse_message( break; } - r = dhcp6_option_parse_ia(option, &lease->pd, &ia_pd_status); - if (r < 0 && r != -ENOMSG) + r = dhcp6_option_parse_ia(option, client->ia_pd.ia_pd.id, &lease->pd, &ia_pd_status); + if (r < 0 && r != -ENOANO) return r; if (ia_pd_status == DHCP6_STATUS_NO_PREFIX_AVAIL) { @@ -1223,16 +1212,6 @@ static int client_parse_message( continue; } - r = dhcp6_lease_get_pd_iaid(lease, &iaid_lease); - if (r < 0) - return r; - - if (client->ia_pd.ia_pd.id != iaid_lease) { - log_dhcp6_client(client, "%s has wrong IAID for IA PD", - dhcp6_message_type_to_string(message->type)); - return -EINVAL; - } - if (lease->pd.addresses) { lt_t1 = MIN(lt_t1, be32toh(lease->pd.ia_pd.lifetime_t1)); lt_t2 = MIN(lt_t2, be32toh(lease->pd.ia_pd.lifetime_t2)); diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c index cb363b3973f..6d6fa12d2aa 100644 --- a/src/libsystemd-network/test-dhcp6-client.c +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -287,25 +287,31 @@ static int test_option_status(sd_event *e) { }; DHCP6Option *option; DHCP6IA ia, pd; + be32_t iaid; int r = 0; log_debug("/* %s */", __func__); + memcpy(&iaid, option1 + 4, sizeof(iaid)); + zero(ia); option = (DHCP6Option *)option1; assert_se(sizeof(option1) == sizeof(DHCP6Option) + be16toh(option->len)); - r = dhcp6_option_parse_ia(option, &ia, NULL); + r = dhcp6_option_parse_ia(option, 0, &ia, NULL); + assert_se(r == -ENOANO); + + r = dhcp6_option_parse_ia(option, iaid, &ia, NULL); assert_se(r == 0); assert_se(ia.addresses == NULL); option->len = htobe16(17); - r = dhcp6_option_parse_ia(option, &ia, NULL); + r = dhcp6_option_parse_ia(option, iaid, &ia, NULL); assert_se(r == -ENOBUFS); assert_se(ia.addresses == NULL); option->len = htobe16(sizeof(DHCP6Option)); - r = dhcp6_option_parse_ia(option, &ia, NULL); + r = dhcp6_option_parse_ia(option, iaid, &ia, NULL); assert_se(r == -ENOBUFS); assert_se(ia.addresses == NULL); @@ -313,7 +319,7 @@ static int test_option_status(sd_event *e) { option = (DHCP6Option *)option2; assert_se(sizeof(option2) == sizeof(DHCP6Option) + be16toh(option->len)); - r = dhcp6_option_parse_ia(option, &ia, NULL); + r = dhcp6_option_parse_ia(option, iaid, &ia, NULL); assert_se(r >= 0); assert_se(ia.addresses == NULL); @@ -321,7 +327,7 @@ static int test_option_status(sd_event *e) { option = (DHCP6Option *)option3; assert_se(sizeof(option3) == sizeof(DHCP6Option) + be16toh(option->len)); - r = dhcp6_option_parse_ia(option, &ia, NULL); + r = dhcp6_option_parse_ia(option, iaid, &ia, NULL); assert_se(r >= 0); assert_se(ia.addresses != NULL); dhcp6_lease_free_ia(&ia); @@ -330,7 +336,7 @@ static int test_option_status(sd_event *e) { option = (DHCP6Option *)option4; assert_se(sizeof(option4) == sizeof(DHCP6Option) + be16toh(option->len)); - r = dhcp6_option_parse_ia(option, &pd, NULL); + r = dhcp6_option_parse_ia(option, iaid, &pd, NULL); assert_se(r >= 0); assert_se(pd.addresses != NULL); assert_se(memcmp(&pd.ia_pd.id, &option4[4], 4) == 0); @@ -342,7 +348,7 @@ static int test_option_status(sd_event *e) { option = (DHCP6Option *)option5; assert_se(sizeof(option5) == sizeof(DHCP6Option) + be16toh(option->len)); - r = dhcp6_option_parse_ia(option, &pd, NULL); + r = dhcp6_option_parse_ia(option, iaid, &pd, NULL); assert_se(r >= 0); assert_se(pd.addresses != NULL); dhcp6_lease_free_ia(&pd); @@ -447,12 +453,13 @@ static int test_advertise_option(sd_event *e) { opt_clientid = true; break; - case SD_DHCP6_OPTION_IA_NA: + case SD_DHCP6_OPTION_IA_NA: { + be32_t iaid = htobe32(0x0ecfa37d); + assert_se(optlen == 94); assert_se(!memcmp(optval, &msg_advertise[26], optlen)); - val = htobe32(0x0ecfa37d); - assert_se(!memcmp(optval, &val, sizeof(val))); + assert_se(!memcmp(optval, &iaid, sizeof(val))); val = htobe32(80); assert_se(!memcmp(optval + 4, &val, sizeof(val))); @@ -460,10 +467,10 @@ static int test_advertise_option(sd_event *e) { val = htobe32(120); assert_se(!memcmp(optval + 8, &val, sizeof(val))); - assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0); + assert_se(dhcp6_option_parse_ia(option, iaid, &lease->ia, NULL) >= 0); break; - + } case SD_DHCP6_OPTION_SERVERID: assert_se(optlen == 14); assert_se(!memcmp(optval, &msg_advertise[179], optlen)); @@ -596,6 +603,8 @@ static void test_client_solicit_cb(sd_dhcp6_client *client, int event, static int test_client_send_reply(DHCP6Message *request) { DHCP6Message reply; + log_debug("/* %s */", __func__); + reply.transaction_id = request->transaction_id; reply.type = DHCP6_REPLY; @@ -656,7 +665,7 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) { assert_se(!memcmp(optval + 8, &val, sizeof(val))); /* Then, this should refuse all addresses. */ - assert_se(dhcp6_option_parse_ia(option, &lease->ia, NULL) >= 0); + assert_se(dhcp6_option_parse_ia(option, test_iaid, &lease->ia, NULL) >= 0); break; @@ -702,6 +711,8 @@ static int test_client_verify_request(DHCP6Message *request, size_t len) { static int test_client_send_advertise(DHCP6Message *solicit) { DHCP6Message advertise; + log_debug("/* %s */", __func__); + advertise.transaction_id = solicit->transaction_id; advertise.type = DHCP6_ADVERTISE; @@ -897,6 +908,8 @@ int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address, IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT; DHCP6Message *message; + log_debug("/* %s */", __func__); + assert_se(s == test_dhcp_fd[0]); assert_se(server_address); assert_se(packet);