]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
tools: Check snprintf return value
authorTobias Stoeckmann <tobias@stoeckmann.org>
Wed, 14 Aug 2024 15:50:34 +0000 (17:50 +0200)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Mon, 23 Sep 2024 14:48:15 +0000 (09:48 -0500)
If an excessively large root directory is supplied, subsequent
operations might process unexpected parts in file system.

Inform user that supplied directory paths are too long and stop
program execution.

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
Reviewed-by: Emil Velikov <emil.l.velikov@gmail.com>
Link: https://github.com/kmod-project/kmod/pull/72
Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
tools/depmod.c
tools/modinfo.c
tools/modprobe.c
tools/static-nodes.c

index 847b4cb5916562488a55f641fa699ac58b01f4e4..daaa91883a0f655b9c0599b4fecf60b08b3bdd35 100644 (file)
@@ -2643,9 +2643,16 @@ static int depmod_output(struct depmod *depmod, FILE *out)
                        int flags = O_CREAT | O_EXCL | O_WRONLY;
                        int mode = 0644;
                        int fd;
+                       int n;
 
-                       snprintf(tmp, sizeof(tmp), "%s.%i.%lli.%lli", itr->name, getpid(),
+                       n = snprintf(tmp, sizeof(tmp), "%s.%i.%lli.%lli", itr->name, getpid(),
                                        (long long)tv.tv_usec, (long long)tv.tv_sec);
+                       if (n >= (int)sizeof(tmp)) {
+                               ERR("bad filename: %s.%i.%lli.%lli: path too long\n",
+                                       itr->name, getpid(), (long long)tv.tv_usec,
+                                       (long long)tv.tv_sec);
+                               continue;
+                       }
                        fd = openat(dfd, tmp, flags, mode);
                        if (fd < 0) {
                                ERR("openat(%s, %s, %o, %o): %m\n",
@@ -3054,10 +3061,21 @@ static int do_depmod(int argc, char *argv[])
        cfg.dirnamelen = snprintf(cfg.dirname, PATH_MAX,
                                  "%s%s/%s",
                                  root ?: "", module_directory, cfg.kversion);
+       if (cfg.dirnamelen >= PATH_MAX) {
+               ERR("Bad directory %s" MODULE_DIRECTORY
+                   "/%s: path too long\n", root ?: "", cfg.kversion);
+               goto cmdline_failed;
+       }
 
        cfg.outdirnamelen = snprintf(cfg.outdirname, PATH_MAX,
                                     "%s%s/%s",
                                     out_root ?: (root ?: ""), module_directory, cfg.kversion);
+       if (cfg.outdirnamelen >= PATH_MAX) {
+               ERR("Bad directory %s" MODULE_DIRECTORY
+                   "/%s: path too long\n", out_root ?: (root ?: ""),
+                   cfg.kversion);
+               goto cmdline_failed;
+       }
 
        if (optind == argc)
                all = 1;
index 59ecb17e2ffd46b587dfee69893c82f895170fc7..68c7b948d82a035aea46053c80c3bdf3a6d6c483 100644 (file)
@@ -440,6 +440,7 @@ static int do_modinfo(int argc, char *argv[])
 
        if (root != NULL || kversion != NULL) {
                struct utsname u;
+               int n;
                if (root == NULL)
                        root = "";
                if (kversion == NULL) {
@@ -449,8 +450,14 @@ static int do_modinfo(int argc, char *argv[])
                        }
                        kversion = u.release;
                }
-               snprintf(dirname_buf, sizeof(dirname_buf), "%s" MODULE_DIRECTORY "/%s",
-                        root, kversion);
+
+               n = snprintf(dirname_buf, sizeof(dirname_buf),
+                            "%s" MODULE_DIRECTORY "/%s", root, kversion);
+               if (n >= (int)sizeof(dirname_buf)) {
+                       ERR("bad directory %s" MODULE_DIRECTORY
+                           "/%s: path too long\n", root, kversion);
+                       return EXIT_FAILURE;
+               }
                dirname = dirname_buf;
        }
 
index 3c085e89a6539105290ec135cd4601b89f5f45f0..4070e552d27f386559f0a59e4a99e272eb29ae88 100644 (file)
@@ -976,6 +976,7 @@ static int do_modprobe(int argc, char **orig_argv)
 
        if (root != NULL || kversion != NULL) {
                struct utsname u;
+               int n;
                if (root == NULL)
                        root = "";
                if (kversion == NULL) {
@@ -986,9 +987,14 @@ static int do_modprobe(int argc, char **orig_argv)
                        }
                        kversion = u.release;
                }
-               snprintf(dirname_buf, sizeof(dirname_buf),
-                               "%s" MODULE_DIRECTORY "/%s", root,
-                               kversion);
+               n = snprintf(dirname_buf, sizeof(dirname_buf),
+                            "%s" MODULE_DIRECTORY "/%s", root, kversion);
+               if (n >= (int)sizeof(dirname_buf)) {
+                       ERR("bad directory %s" MODULE_DIRECTORY
+                           "/%s: path too long\n", root, kversion);
+                       err = -1;
+                       goto done;
+               }
                dirname = dirname_buf;
        }
 
index 435e0dc1539bc1e68fa457d446b88af44652e579..58c06cfb15fed282017c6500632fa48c53bc7eb2 100644 (file)
@@ -200,7 +200,13 @@ static int do_static_nodes(int argc, char *argv[])
                goto finish;
        }
 
-       snprintf(modules, sizeof(modules), MODULE_DIRECTORY "/%s/modules.devname", kernel.release);
+       r = snprintf(modules, sizeof(modules), MODULE_DIRECTORY "/%s/modules.devname", kernel.release);
+       if (r >= (int)sizeof(modules)) {
+               fprintf(stderr, "Error: could not open " MODULE_DIRECTORY "/%s/modules.devname - path too long\n",
+                       kernel.release);
+               ret = EXIT_FAILURE;
+               goto finish;
+       }
        in = fopen(modules, "re");
        if (in == NULL) {
                if (errno == ENOENT) {