]> git.alsa-project.org Git - alsa-lib.git/commitdiff
ucm: confine sysw and cfg-save paths with realpath()
authorHarsh Raj Singhania <raj.harshraut@gmail.com>
Wed, 30 Sep 2026 18:59:06 +0000 (00:29 +0530)
committerTakashi Iwai <tiwai@suse.de>
Thu, 15 Oct 2026 13:47:05 +0000 (15:47 +0200)
1: execute_sysw() concatenated the sysfs root with a caller path via
snprintf() with no traversal check. Use realpath() and reject paths
that escape the sysfs root.

2: execute_cfgsave() opened a caller-supplied filename with no
restriction. Confine writes to XDG_RUNTIME_DIR (or /tmp) via
realpath().

[ rewritten with check_realpath() helper function -- tiwai ]

Closes: https://github.com/alsa-project/alsa-lib/pull/527
Signed-off-by: Harsh Raj Singhania <raj.harshraut@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
src/ucm/main.c

index d2b3c2d93b82167edc4937de1be77d6bfbda4196..b27e71f0a0059a863eb345a3a1fe209149fae992 100644 (file)
@@ -523,6 +523,20 @@ static int execute_cset(snd_ctl_t *ctl, const char *cset, unsigned int type)
        return err;
 }
 
+static bool check_realpath(const char *path, const char *target)
+{
+       char *resolved = realpath(path, NULL);
+
+       if (!resolved)
+               return false;
+       if (strncmp(resolved, target, strlen(target)) != 0) {
+               free(resolved);
+               return false;
+       }
+       free(resolved);
+       return true;
+}
+
 static int execute_sysw(const char *sysw)
 {
        char path[PATH_MAX];
@@ -570,6 +584,12 @@ static int execute_sysw(const char *sysw)
        }
        snprintf(path, sizeof(path), "%s/%s", e, s);
 
+       if (!check_realpath(path, e)) {
+               free(s);
+               snd_error(UCM, "sysw path escapes sysfs root: '%s'", path);
+               return -EINVAL;
+       }
+
        fd = open(path, O_WRONLY|O_CLOEXEC);
        if (fd < 0) {
                free(s);
@@ -603,6 +623,7 @@ static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename)
        snd_config_t *config = uc_mgr->local_config;
        char *file, *root;
        snd_output_t *out;
+       const char *runtime;
        bool with_root = false;
        int err = 0;
 
@@ -625,6 +646,13 @@ static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename)
                }
        }
 
+       runtime = getenv("XDG_RUNTIME_DIR");
+       if (!runtime)
+               runtime = "/tmp";
+       if (!check_realpath(file, runtime)) {
+               snd_error(UCM, "cfg-save path escapes runtime dir: '%s'", file);
+               return -EINVAL;
+       }
        err = snd_output_stdio_open(&out, file, "w+");
        if (err < 0) {
                snd_error(UCM, "unable to open file '%s': %s", file, snd_strerror(err));