From e636ba2bc8790420a63ebf8317acc759bf6b2bb1 Mon Sep 17 00:00:00 2001 From: Roy Marples Date: Sun, 21 Jun 2026 11:13:53 +0100 Subject: [PATCH] DHCP: Sanitise messages from servers for output They could contain anything! Reported by NVIDIA Project Vanessa --- src/dhcp.c | 46 +++++++++++++++++----------------------------- src/dhcp6.c | 19 ++++++++++++++----- 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/src/dhcp.c b/src/dhcp.c index 799a7466..915a6240 100644 --- a/src/dhcp.c +++ b/src/dhcp.c @@ -495,7 +495,8 @@ static char * get_option_string(struct dhcpcd_ctx *ctx, const struct bootp *bootp, size_t bootp_len, uint8_t option) { - size_t len; + size_t len, sl; + ssize_t pl; const uint8_t *p; char *s; @@ -503,10 +504,18 @@ get_option_string(struct dhcpcd_ctx *ctx, const struct bootp *bootp, if (!p || len == 0 || *p == '\0') return NULL; - s = malloc(sizeof(char) * (len + 1)); - if (s) { - memcpy(s, p, len); - s[len] = '\0'; + pl = print_string(NULL, 0, OT_ESCSTRING, p, len); + if (pl == -1) + return NULL; + + sl = (size_t)pl + 1; + s = malloc(sl); + if (s != NULL) { + pl = print_string(s, sl, OT_ESCSTRING, p, len); + if (pl == -1) { + free(s); + return NULL; + } } return s; } @@ -2949,25 +2958,9 @@ log_dhcp(int loglevel, const char *msg, const struct interface *ifp, int r; uint8_t overl; - if (strcmp(msg, "NAK:") == 0) { + if (strcmp(msg, "NAK:") == 0) a = get_option_string(ifp->ctx, bootp, bootp_len, DHO_MESSAGE); - if (a) { - char *tmp; - size_t al, tmpl; - - al = strlen(a); - tmpl = (al * 4) + 1; - tmp = malloc(tmpl); - if (tmp == NULL) { - logerr(__func__); - free(a); - return; - } - print_string(tmp, tmpl, OT_STRING, a, al); - free(a); - a = tmp; - } - } else if (ad && bootp->yiaddr != 0) { + else if (ad && bootp->yiaddr != 0) { addr.s_addr = bootp->yiaddr; a = strdup(inet_ntoa(addr)); if (a == NULL) { @@ -3222,12 +3215,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len, } /* We should restart on a NAK */ - LOGDHCP(LOG_WARNING, "NAK:"); - if ((msg = get_option_string(ifp->ctx, bootp, bootp_len, - DHO_MESSAGE))) { - logwarnx("%s: message: %s", ifp->name, msg); - free(msg); - } + LOGDHCP(LOG_WARNING, "NAK:"); /* This also logs DHO_MESSAGE */ if (state->state == DHS_INFORM) /* INFORM should not be NAKed */ return; if (!(ifp->ctx->options & DHCPCD_TEST)) { diff --git a/src/dhcp6.c b/src/dhcp6.c index 61a90633..4a15319c 100644 --- a/src/dhcp6.c +++ b/src/dhcp6.c @@ -2129,6 +2129,7 @@ dhcp6_checkstatusok(const struct interface *ifp, struct dhcp6_message *m, opt += sizeof(code); mlen = opt_len - sizeof(code); if (mlen == 0) { + status_code: sbuf = NULL; if (code < sizeof(dhcp6_statuses) / sizeof(char *)) status = dhcp6_statuses[code]; @@ -2137,12 +2138,20 @@ dhcp6_checkstatusok(const struct interface *ifp, struct dhcp6_message *m, status = buf; } } else { - if ((sbuf = malloc(mlen + 1)) == NULL) { - logerr(__func__); - return -1; + size_t slen; + ssize_t plen = print_string(NULL, 0, OT_ESCSTRING, opt, mlen); + + if (plen == -1) + goto status_code; /* log something */ + slen = (size_t)plen + 1; + sbuf = malloc(slen); + if (sbuf == NULL) + goto status_code; /* log something */ + + if (print_string(sbuf, slen, OT_ESCSTRING, opt, mlen) == -1) { + free(sbuf); + goto status_code; } - memcpy(sbuf, opt, mlen); - sbuf[mlen] = '\0'; status = sbuf; } -- 2.47.3