From: Vincent Bernat Date: Tue, 10 Mar 2026 20:03:37 +0000 (+0100) Subject: daemon/priv: factor out check of authorized paths X-Git-Tag: 1.0.21~4 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=479afbb6240dbc0d439dcff668ce4f5197da9648;p=thirdparty%2Flldpd.git daemon/priv: factor out check of authorized paths --- diff --git a/src/daemon/priv-linux.c b/src/daemon/priv-linux.c index b204d678..3eda8995 100644 --- a/src/daemon/priv-linux.c +++ b/src/daemon/priv-linux.c @@ -60,29 +60,17 @@ priv_open(const char *file) return receive_fd(PRIV_UNPRIVILEGED); } -void -asroot_open() +/** + * Read a file path from the privileged channel and validate it against a list + * of authorized regex patterns. Returns the allocated path on success or NULL + * on failure. + */ +static char * +asroot_read_authorized_path(const char **authorized) { - const char *authorized[] = { - "^" PROCFS_SYS_NET "ipv4/ip_forward" "$", - "^" PROCFS_SYS_NET "ipv6/conf/all/forwarding" "$", - "^" "/proc/net/bonding/[^/]*" "$", - "^" "/proc/self/net/bonding/[^/]*" "$", -#ifdef ENABLE_OLDIES - "^" SYSFS_CLASS_NET "[^/]*/brforward" "$", - "^" SYSFS_CLASS_NET "[^/]*/brport" "$", - "^" SYSFS_CLASS_NET "[^/]*/brif/[^/]*/port_no" "$", -#endif - "^" SYSFS_CLASS_DMI "product_version" "$", - "^" SYSFS_CLASS_DMI "product_serial" "$", - "^" SYSFS_CLASS_DMI "product_name" "$", - "^" SYSFS_CLASS_DMI "bios_version" "$", - "^" SYSFS_CLASS_DMI "sys_vendor" "$", - "^" SYSFS_CLASS_DMI "chassis_asset_tag" "$", - NULL }; const char **f; char *file; - int fd, len, rc; + int len; regex_t preg; must_read(PRIV_PRIVILEGED, &len, sizeof(len)); @@ -92,7 +80,7 @@ asroot_open() file[len] = '\0'; for (f = authorized; *f != NULL; f++) { - if (regcomp(&preg, *f, REG_NOSUB) != 0) /* Should not happen */ + if (regcomp(&preg, *f, REG_NOSUB) != 0) fatal("privsep", "unable to compile a regex"); if (regexec(&preg, file, 0, NULL, 0) == 0) { regfree(&preg); @@ -101,13 +89,39 @@ asroot_open() regfree(&preg); } if (*f == NULL || strstr(file, "/..")) { - log_warnx("privsep", "not authorized to open %s", file); - rc = -1; - must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); + log_warnx("privsep", "not authorized to access %s", file); free(file); - return; + return NULL; } - if ((fd = open(file, O_RDONLY)) == -1) { + return file; +} + +void +asroot_open() +{ + const char *authorized[] = { + "^" PROCFS_SYS_NET "ipv4/ip_forward" "$", + "^" PROCFS_SYS_NET "ipv6/conf/all/forwarding" "$", + "^" "/proc/net/bonding/[^/]*" "$", + "^" "/proc/self/net/bonding/[^/]*" "$", +#ifdef ENABLE_OLDIES + "^" SYSFS_CLASS_NET "[^/]*/brforward" "$", + "^" SYSFS_CLASS_NET "[^/]*/brport" "$", + "^" SYSFS_CLASS_NET "[^/]*/brif/[^/]*/port_no" "$", +#endif + "^" SYSFS_CLASS_DMI "product_version" "$", + "^" SYSFS_CLASS_DMI "product_serial" "$", + "^" SYSFS_CLASS_DMI "product_name" "$", + "^" SYSFS_CLASS_DMI "bios_version" "$", + "^" SYSFS_CLASS_DMI "sys_vendor" "$", + "^" SYSFS_CLASS_DMI "chassis_asset_tag" "$", + NULL, + }; + char *file; + int fd, rc; + + if ((file = asroot_read_authorized_path(authorized)) == NULL || + (fd = open(file, O_RDONLY)) == -1) { rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); free(file); @@ -141,32 +155,13 @@ asroot_exist() "^" SYSFS_CLASS_NET "[^/]*/wireless" "$", NULL, }; - const char **f; char *file; - int len, rc; - regex_t preg; + int rc; struct stat st; - must_read(PRIV_PRIVILEGED, &len, sizeof(len)); - if (len < 0 || len > PATH_MAX) fatalx("privsep", "too large value requested"); - if ((file = (char *)malloc(len + 1)) == NULL) fatal("privsep", NULL); - must_read(PRIV_PRIVILEGED, file, len); - file[len] = '\0'; - - for (f = authorized; *f != NULL; f++) { - if (regcomp(&preg, *f, REG_NOSUB) != 0) - fatal("privsep", "unable to compile a regex"); - if (regexec(&preg, file, 0, NULL, 0) == 0) { - regfree(&preg); - break; - } - regfree(&preg); - } - if (*f == NULL || strstr(file, "/..")) { - log_warnx("privsep", "not authorized to check %s", file); + if ((file = asroot_read_authorized_path(authorized)) == NULL) { rc = -1; must_write(PRIV_PRIVILEGED, &rc, sizeof(int)); - free(file); return; } rc = stat(file, &st) == 0 ? 0 : -1;