From: Roy Marples Date: Sun, 21 Jun 2026 12:29:41 +0000 (+0100) Subject: privsep: Check data is terminated when a string X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=99804fbee084359bfa0dd16c6e675c283b9ef06e;p=thirdparty%2Fdhcpcd.git privsep: Check data is terminated when a string Reported by NVIDIA Project Vanessa --- diff --git a/src/privsep-root.c b/src/privsep-root.c index 798076f2..497ca893 100644 --- a/src/privsep-root.c +++ b/src/privsep-root.c @@ -261,12 +261,19 @@ ps_root_run_script(struct dhcpcd_ctx *ctx, const void *data, size_t len) } static bool -ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path) +ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path, + size_t len) { + /* path must be a valid string */ + if (memchr(path, '\0', len) == NULL) { + errno = EINVAL; + return false; + } + /* Avoid a previous directory attack to avoid /proc/../ * dhcpcd should never use a path with double dots. */ if (strstr(path, "..") != NULL) - return false; + goto noperm; if (cmd == PS_READFILE) { #ifdef EMBEDDED_CONFIG @@ -288,6 +295,7 @@ ps_root_validpath(const struct dhcpcd_ctx *ctx, uint16_t cmd, const char *path) return true; #endif +noperm: errno = EPERM; return false; } @@ -297,6 +305,7 @@ ps_root_dowritefile(const struct dhcpcd_ctx *ctx, mode_t mode, void *data, size_t len) { char *file = data, *nc; + size_t flen; nc = memchr(file, '\0', len); if (nc == NULL) { @@ -304,10 +313,11 @@ ps_root_dowritefile(const struct dhcpcd_ctx *ctx, mode_t mode, void *data, return -1; } - if (!ps_root_validpath(ctx, PS_WRITEFILE, file)) + flen = (size_t)(nc - file) + 1; + if (!ps_root_validpath(ctx, PS_WRITEFILE, file, flen)) return -1; nc++; - return writefile(file, mode, nc, len - (size_t)(nc - file)); + return writefile(file, mode, nc, len - flen); } #ifdef AUTH @@ -515,14 +525,14 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) err = ps_stopwait(ctx); break; case PS_UNLINK: - if (!ps_root_validpath(ctx, psm->ps_cmd, data)) { + if (!ps_root_validpath(ctx, psm->ps_cmd, data, len)) { err = -1; break; } err = unlink(data); break; case PS_READFILE: - if (!ps_root_validpath(ctx, psm->ps_cmd, data)) { + if (!ps_root_validpath(ctx, psm->ps_cmd, data, len)) { err = -1; break; } @@ -540,6 +550,10 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) len); break; case PS_FILEMTIME: + if (!ps_root_validpath(ctx, psm->ps_cmd, data, len)) { + err = -1; + break; + } err = filemtime(data, &mtime); if (err != -1) { rdata = &mtime; @@ -578,6 +592,12 @@ ps_root_recvmsgcb(void *arg, struct ps_msghdr *psm, struct msghdr *msg) #endif #ifdef PLUGIN_DEV case PS_DEV_INITTED: + /* Check ifname is terminated */ + if (memchr(data, '\0', len) == NULL) { + err = -1; + errno = EINVAL; + break; + } err = dev_initialised(ctx, data); break; case PS_DEV_LISTENING: