]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
sd-dhcp6-client: fix off-by-one error in parsing dhcp6 options 24002/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Jul 2022 00:23:09 +0000 (09:23 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 14 Jul 2022 01:49:18 +0000 (10:49 +0900)
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.

src/libsystemd-network/dhcp6-option.c
src/libsystemd-network/test-dhcp6-client.c

index 0f4624953353da4947c286c8a227fda06cc5d8a1..5e91e86f536d36ac29fe4d5d774e1cac01a26828 100644 (file)
@@ -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;
index 95a6c514c6df0299fc4cff4a5d6ab3800e33243c..e5c09f96648ed0480d0dbdc3c4db101bc54eb668 100644 (file)
@@ -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,