]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
networkd: fix for networkd crash when client sends Option 82 via SendOption=
authorNandakumar Raghavan <naraghavan@microsoft.com>
Tue, 10 Mar 2026 06:54:33 +0000 (06:54 +0000)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Tue, 10 Mar 2026 17:29:59 +0000 (18:29 +0100)
When a DHCP client uses SendOption=82:string:..., option_append() calls
the SD_DHCP_OPTION_RELAY_AGENT_INFORMATION case which was written for
the server relay path. It casts optval to sd_dhcp_server* and calls
strlen() on its members, but optval is actually raw binary data from
the client, causing SIGSEGV. The same is applicable when option 43 and
option 77 are passed to SendOption.

Fix by checking optlen > 0 and appending the option as a plain TLV,
skipping the server-specific relay agent logic.

src/libsystemd-network/dhcp-option.c

index a840b614621574c10a24e55b4822d0173f3c9bdf..c78e3cdad9d7258e3f1e3021c187e9ca901b1c75 100644 (file)
@@ -59,6 +59,11 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 break;
 
         case SD_DHCP_OPTION_USER_CLASS: {
+                /* When called with raw data (optlen > 0), e.g. from SendOption=, append as a plain TLV.
+                 * The structured handling below expects optval to be a strv. */
+                if (optlen > 0)
+                        return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
+
                 size_t total = 0;
 
                 if (strv_isempty((char **) optval))
@@ -103,6 +108,11 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
 
                 break;
         case SD_DHCP_OPTION_VENDOR_SPECIFIC: {
+                /* When called with raw data (optlen > 0), e.g. from SendOption=, append as a plain TLV.
+                 * The structured handling below expects optval to be an OrderedSet*. */
+                if (optlen > 0)
+                        return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
+
                 OrderedSet *s = (OrderedSet *) optval;
                 struct sd_dhcp_option *p;
                 size_t l = 0;
@@ -125,6 +135,11 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 break;
         }
         case SD_DHCP_OPTION_RELAY_AGENT_INFORMATION: {
+                /* When called with raw data (optlen > 0), e.g. from SendOption=, append as a plain TLV.
+                 * The structured handling below expects optval to be an sd_dhcp_server*. */
+                if (optlen > 0)
+                        return dhcp_option_append_tlv(options, size, offset, code, optlen, optval);
+
                 sd_dhcp_server *server = (sd_dhcp_server *) optval;
                 size_t current_offset = *offset + 2;