diff --git a/src/conf.c b/src/conf.c index a27e6786..1469c7ed 100644 --- a/src/conf.c +++ b/src/conf.c @@ -643,8 +643,11 @@ static int input_stdio_open(snd_input_t **inputp, const char *file, char full_path[PATH_MAX]; int err; - if (file[0] == '/') + if (file[0] == '/') { + if (strstr(file, "/../")) + return -ENOENT; return snd_input_stdio_open(inputp, file, "r"); + } /* search file in user specified include paths. These directories * are subdirectories of /usr/share/alsa. diff --git a/src/pcm/pcm_multi.c b/src/pcm/pcm_multi.c index 121c4c20..dc4f9190 100644 --- a/src/pcm/pcm_multi.c +++ b/src/pcm/pcm_multi.c @@ -1121,8 +1121,10 @@ int snd_pcm_multi_open(snd_pcm_t **pcmp, const char *name, } for (i = 0; i < channels_count; ++i) { snd_pcm_multi_channel_t *bind = &multi->channels[i]; - assert(sidxs[i] < (int)slaves_count); - assert(schannels[i] < schannels_count[sidxs[i]]); + if (sidxs[i] < 0 || sidxs[i] >= (int)slaves_count) { + SNDERR("multi: ch %d invalid slave idx %d", i, sidxs[i]); return -EINVAL; } + if (schannels[i] >= schannels_count[sidxs[i]]) { + SNDERR("multi: ch %d channel %d out of range", i, schannels[i]); return -EINVAL; } bind->slave_idx = sidxs[i]; bind->slave_channel = schannels[i]; if (sidxs[i] < 0) diff --git a/src/pcm/pcm_route.c b/src/pcm/pcm_route.c index 3836dcc3..34f4e1ee 100644 --- a/src/pcm/pcm_route.c +++ b/src/pcm/pcm_route.c @@ -1098,6 +1098,7 @@ static int _snd_pcm_route_determine_ttable(snd_config_t *tt, } if (cchannel + 1 > csize) csize = cchannel + 1; + if (csize > 1024) { SNDERR("route: client channel %d exceeds max (1024)", cchannel); return -EINVAL; } if (snd_config_get_type(in) != SND_CONFIG_TYPE_COMPOUND) return -EINVAL; snd_config_for_each(j, jnext, in) { @@ -1113,6 +1114,7 @@ static int _snd_pcm_route_determine_ttable(snd_config_t *tt, } if (schannel + 1 > ssize) ssize = schannel + 1; + if (ssize > 1024) { SNDERR("route: slave channel %d exceeds max (1024)", schannel); return -EINVAL; } } } if (csize == 0 || ssize == 0) { diff --git a/src/topology/ctl.c b/src/topology/ctl.c index 322c461c..93a09f1e 100644 --- a/src/topology/ctl.c +++ b/src/topology/ctl.c @@ -1315,7 +1315,12 @@ int tplg_decode_control_mixer(snd_tplg_t *tplg, } INIT_LIST_HEAD(&heap); mc = bin; - size2 = mc->size + mc->priv.size; + if (mc->priv.size > size || mc->size > size - mc->priv.size) { + snd_error(TOPOLOGY, "mixer: element sizes overflow (%d, priv %d)", + mc->size, mc->priv.size); + return -EINVAL; + } + size2 = (size_t)mc->size + (size_t)mc->priv.size; if (size2 > size) { snd_error(TOPOLOGY, "mixer: wrong element size (%d, priv %d)", mc->size, mc->priv.size); @@ -1419,7 +1424,12 @@ int tplg_decode_control_enum(snd_tplg_t *tplg, } INIT_LIST_HEAD(&heap); ec = bin; - size2 = ec->size + ec->priv.size; + if (ec->priv.size > size || ec->size > size - ec->priv.size) { + snd_error(TOPOLOGY, "enum: element sizes overflow (%d, priv %d)", + ec->size, ec->priv.size); + return -EINVAL; + } + size2 = (size_t)ec->size + (size_t)ec->priv.size; if (size2 > size) { snd_error(TOPOLOGY, "enum: wrong element size (%d, priv %d)", ec->size, ec->priv.size); @@ -1510,7 +1520,12 @@ int tplg_decode_control_bytes(snd_tplg_t *tplg, return -EINVAL; } bc = bin; - size2 = bc->size + bc->priv.size; + if (bc->priv.size > size || bc->size > size - bc->priv.size) { + snd_error(TOPOLOGY, "bytes: element sizes overflow (%d, priv %d)", + bc->size, bc->priv.size); + return -EINVAL; + } + size2 = (size_t)bc->size + (size_t)bc->priv.size; if (size2 > size) { snd_error(TOPOLOGY, "bytes: wrong element size (%d, priv %d)", bc->size, bc->priv.size); diff --git a/src/ucm/main.c b/src/ucm/main.c index d2b3c2d9..9329dfa3 100644 --- a/src/ucm/main.c +++ b/src/ucm/main.c @@ -570,6 +570,12 @@ static int execute_sysw(const char *sysw) } snprintf(path, sizeof(path), "%s/%s", e, s); + { char *resolved = realpath(path, NULL); size_t rootlen = strlen(e); + if (!resolved || strncmp(resolved, e, rootlen) != 0) { + free(resolved); free(s); + snd_error(UCM, "sysw path escapes sysfs root: '%s'", path); + return -EINVAL; } free(resolved); } + fd = open(path, O_WRONLY|O_CLOEXEC); if (fd < 0) { free(s); @@ -625,6 +631,11 @@ static int execute_cfgsave(snd_use_case_mgr_t *uc_mgr, const char *filename) } } + { const char *runtime = getenv("XDG_RUNTIME_DIR"); if (!runtime) runtime = "/tmp"; + char *resolved = realpath(file, NULL); + if (!resolved || strncmp(resolved, runtime, strlen(runtime)) != 0) { + free(resolved); snd_error(UCM, "cfg-save path escapes runtime dir: '%s'", file); + return -EINVAL; } free(resolved); } err = snd_output_stdio_open(&out, file, "w+"); if (err < 0) { snd_error(UCM, "unable to open file '%s': %s", file, snd_strerror(err));