diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-07-14 09:23:09 +0900 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2022-07-14 10:49:18 +0900 |
commit | 68870a46b3b5d3d5b51d1c27b4128b8fb5188ecb (patch) | |
tree | 99178bdeb92f42007a080d0f6ac74685b931b80e /src/libsystemd-network | |
parent | d81b5a191e6f06fe51befe7c7fb20cff4ff4f762 (diff) | |
download | systemd-68870a46b3b5d3d5b51d1c27b4128b8fb5188ecb.tar.gz |
sd-dhcp6-client: fix off-by-one error in parsing dhcp6 options
This fixes error in parsing message when the rapid commit option is
located at the end of the message.
Fixes an issure reported in #24002.
Diffstat (limited to 'src/libsystemd-network')
-rw-r--r-- | src/libsystemd-network/dhcp6-option.c | 4 | ||||
-rw-r--r-- | src/libsystemd-network/test-dhcp6-client.c | 42 |
2 files changed, 44 insertions, 2 deletions
diff --git a/src/libsystemd-network/dhcp6-option.c b/src/libsystemd-network/dhcp6-option.c index 0f46249533..5e91e86f53 100644 --- a/src/libsystemd-network/dhcp6-option.c +++ b/src/libsystemd-network/dhcp6-option.c @@ -508,7 +508,7 @@ int dhcp6_option_parse( if (buflen < offsetof(DHCP6Option, data)) return -EBADMSG; - if (*offset >= buflen - offsetof(DHCP6Option, data)) + if (*offset > buflen - offsetof(DHCP6Option, data)) return -EBADMSG; len = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, len)); @@ -518,7 +518,7 @@ int dhcp6_option_parse( *ret_option_code = unaligned_read_be16(buf + *offset + offsetof(DHCP6Option, code)); *ret_option_data_len = len; - *ret_option_data = buf + *offset + offsetof(DHCP6Option, data); + *ret_option_data = len == 0 ? NULL : buf + *offset + offsetof(DHCP6Option, data); *offset += offsetof(DHCP6Option, data) + len; return 0; diff --git a/src/libsystemd-network/test-dhcp6-client.c b/src/libsystemd-network/test-dhcp6-client.c index 95a6c514c6..e5c09f9664 100644 --- a/src/libsystemd-network/test-dhcp6-client.c +++ b/src/libsystemd-network/test-dhcp6-client.c @@ -443,6 +443,48 @@ TEST(client_parse_message_issue_22099) { assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0); } +TEST(client_parse_message_issue_24002) { + static const uint8_t msg[] = { + /* Message Type */ + 0x07, + /* Transaction ID */ + 0x0e, 0xa5, 0x7c, + /* Client ID */ + 0x00, SD_DHCP6_OPTION_CLIENTID, 0x00, 0x0e, + 0x00, 0x02, /* DUID-EN */ + 0x00, 0x00, 0xab, 0x11, /* pen */ + 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, /* id */ + /* Server ID */ + 0x00, 0x02, 0x00, 0x1a, + 0x00, 0x02, 0x00, 0x00, 0x05, 0x83, 0x30, 0x63, 0x3a, 0x38, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + /* IA_PD */ + 0x00, 0x19, 0x00, 0x29, + 0xaa, 0xbb, 0xcc, 0xdd, /* iaid */ + 0x00, 0x00, 0x03, 0x84, /* lifetime (T1) */ + 0x00, 0x00, 0x05, 0xa0, /* lifetime (T2) */ + /* IA_PD (iaprefix suboption) */ + 0x00, 0x1a, 0x00, 0x19, + 0x00, 0x00, 0x07, 0x08, /* preferred lifetime */ + 0x00, 0x00, 0x38, 0x40, /* valid lifetime */ + 0x38, /* prefixlen */ + 0x20, 0x03, 0x00, 0xff, 0xaa, 0xbb, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* prefix */ + /* Rapid commit */ + 0x00, 0x0e, 0x00, 0x00, + }; + static const uint8_t duid[] = { + 0x00, 0x00, 0xab, 0x11, 0x5c, 0x6b, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, + }; + _cleanup_(sd_dhcp6_client_unrefp) sd_dhcp6_client *client = NULL; + _cleanup_(sd_dhcp6_lease_unrefp) sd_dhcp6_lease *lease = NULL; + + assert_se(sd_dhcp6_client_new(&client) >= 0); + assert_se(sd_dhcp6_client_set_iaid(client, 0xaabbccdd) >= 0); + assert_se(sd_dhcp6_client_set_duid(client, 2, duid, sizeof(duid)) >= 0); + + assert_se(dhcp6_lease_new_from_message(client, (const DHCP6Message*) msg, sizeof(msg), NULL, NULL, &lease) >= 0); +} + static const uint8_t msg_information_request[] = { /* Message type */ DHCP6_MESSAGE_INFORMATION_REQUEST, |