summaryrefslogtreecommitdiff
path: root/src/libsystemd-network
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2022-07-14 09:23:09 +0900
committerYu Watanabe <watanabe.yu+github@gmail.com>2022-07-14 10:49:18 +0900
commit68870a46b3b5d3d5b51d1c27b4128b8fb5188ecb (patch)
tree99178bdeb92f42007a080d0f6ac74685b931b80e /src/libsystemd-network
parentd81b5a191e6f06fe51befe7c7fb20cff4ff4f762 (diff)
downloadsystemd-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.c4
-rw-r--r--src/libsystemd-network/test-dhcp6-client.c42
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,