From a8b842ba715e32867593e772db0e712a7b518355 Mon Sep 17 00:00:00 2001 From: Ilias Aberkane Date: Thu, 17 Sep 2026 12:02:23 +0200 Subject: [PATCH 1/2] if-options: bound encapsulated vendor option payload The encapsulated 'vendor' option appends each parsed option into ifo->vendor as [code][len][data] records, with ifo->vendor[0] tracking the used length. The remaining-space computation s = sizeof(ifo->vendor) - 1 - ifo->vendor[0] - 2 goes negative once ifo->vendor[0] reaches 254. (size_t)s then wraps to a huge value and parse_string() performs an unbounded intra-object overwrite past ifo->vendor, corrupting the adjacent mudurl buffer, blacklist/whitelist lengths and pointers. A following whitelist directive then aborts in reallocarray() (ASan allocation-size-too-big). Reject the append when no room remains for the 2-byte record header, mirroring the ENOBUFS handling already used for the inet_aton path. Fixes #732. --- src/if-options.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/if-options.c b/src/if-options.c index 7b445f45..89340adc 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1126,6 +1126,11 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, arg = p + 1; s = (ssize_t)sizeof(ifo->vendor) - 1 - ifo->vendor[0] - 2; + if (s < 0) { + errno = ENOBUFS; + logerr("vendor"); + return -1; + } if (inet_aton(arg, &addr) == 1) { if (s < 6) { s = -1; From 8562837cdb27dc8d2fa7af60401a28dfeff0a8c6 Mon Sep 17 00:00:00 2001 From: Ilias Aberkane Date: Wed, 30 Sep 2026 17:30:11 +0200 Subject: [PATCH 2/2] if-options: use descriptive error for full vendor option list --- src/if-options.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/if-options.c b/src/if-options.c index 89340adc..0b4d5deb 100644 --- a/src/if-options.c +++ b/src/if-options.c @@ -1127,8 +1127,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo, arg = p + 1; s = (ssize_t)sizeof(ifo->vendor) - 1 - ifo->vendor[0] - 2; if (s < 0) { - errno = ENOBUFS; - logerr("vendor"); + logerrx("vendor option list is full"); return -1; } if (inet_aton(arg, &addr) == 1) {