]> git.alsa-project.org Git - alsa-utils.git/commitdiff
aplay: fix buffer overflow and tainted format string
authorMingjie Shen <shen497@purdue.edu>
Wed, 6 Dec 2023 21:09:58 +0000 (16:09 -0500)
committerJaroslav Kysela <perex@perex.cz>
Fri, 8 Dec 2023 19:00:13 +0000 (20:00 +0100)
Prior this commit, memcpy from names[0] to format[] will overwrite if
strlen(names[0]) is greater than 1024. Also, the length of malloc()ed
names[channel] is insufficient, leading to another buffer overwriting
when calling sprintf(). Moreover, the format string of sprintf()
can be controlled by user input. An attacker can exploit this weakness
to crash the program, disclose information or even execute arbitrary
code.

Fix by allocating enough space for arrays and using constant expressions
as the format strings.

Fixes: https://github.com/alsa-project/alsa-utils/pull/246/
Signed-off-by: Mingjie Shen <shen497@purdue.edu>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
aplay/aplay.c

index 9cf36dee2d9d56da73e081a6a3bed58e4835d2b9..f1c27b6c49295b8873783d576588623cd200f272 100644 (file)
@@ -3436,14 +3436,14 @@ static void playbackv(char **names, unsigned int count)
 
        if (count == 1 && channels > 1) {
                size_t len = strlen(names[0]);
-               char format[1024];
-               memcpy(format, names[0], len);
-               strcpy(format + len, ".%d");
-               len += 4;
+               char buf[len + 1];
+               strcpy(buf, names[0]);
+               /* 1 for "." + 3 for channel (<= 256) + 1 for null terminator */
+               len += 5;
                names = malloc(sizeof(*names) * channels);
                for (channel = 0; channel < channels; ++channel) {
                        names[channel] = malloc(len);
-                       sprintf(names[channel], format, channel);
+                       snprintf(names[channel], len, "%s.%d", buf, channel);
                }
                alloced = 1;
        } else if (count != channels) {
@@ -3489,14 +3489,14 @@ static void capturev(char **names, unsigned int count)
 
        if (count == 1) {
                size_t len = strlen(names[0]);
-               char format[1024];
-               memcpy(format, names[0], len);
-               strcpy(format + len, ".%d");
-               len += 4;
+               char buf[len + 1];
+               strcpy(buf, names[0]);
+               /* 1 for "." + 3 for channel (<= 256) + 1 for null terminator */
+               len += 5;
                names = malloc(sizeof(*names) * channels);
                for (channel = 0; channel < channels; ++channel) {
                        names[channel] = malloc(len);
-                       sprintf(names[channel], format, channel);
+                       snprintf(names[channel], len, "%s.%d", buf, channel);
                }
                alloced = 1;
        } else if (count != channels) {