From 6d7cb9a6b8361d2b327222bc12872a3676358bc3 Mon Sep 17 00:00:00 2001 From: Nandakumar Raghavan Date: Tue, 10 Mar 2026 06:54:33 +0000 Subject: [PATCH] networkd: fix for networkd crash when client sends Option 82 via SendOption= 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 | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/libsystemd-network/dhcp-option.c b/src/libsystemd-network/dhcp-option.c index a840b61462..c78e3cdad9 100644 --- a/src/libsystemd-network/dhcp-option.c +++ b/src/libsystemd-network/dhcp-option.c @@ -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;