]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
daemon/priv: factor out check of authorized paths
authorVincent Bernat <vincent@bernat.ch>
Tue, 10 Mar 2026 20:03:37 +0000 (21:03 +0100)
committerVincent Bernat <vincent@bernat.ch>
Tue, 10 Mar 2026 20:20:15 +0000 (21:20 +0100)
src/daemon/priv-linux.c

index b204d6785477dec315ce37bf51f45aa6659a80a3..3eda8995a37d565772c44e1f92e8ff87353589c4 100644 (file)
@@ -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;