From 4f8a6a85c58770b3c4212780026215faab2f33a4 Mon Sep 17 00:00:00 2001 From: Tobias Stoeckmann Date: Wed, 14 Aug 2024 17:50:34 +0200 Subject: [PATCH] tools: Check snprintf return value 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 Reviewed-by: Emil Velikov Link: https://github.com/kmod-project/kmod/pull/72 Signed-off-by: Lucas De Marchi --- tools/depmod.c | 20 +++++++++++++++++++- tools/modinfo.c | 11 +++++++++-- tools/modprobe.c | 12 +++++++++--- tools/static-nodes.c | 8 +++++++- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/tools/depmod.c b/tools/depmod.c index 847b4cb5..daaa9188 100644 --- a/tools/depmod.c +++ b/tools/depmod.c @@ -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; diff --git a/tools/modinfo.c b/tools/modinfo.c index 59ecb17e..68c7b948 100644 --- a/tools/modinfo.c +++ b/tools/modinfo.c @@ -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; } diff --git a/tools/modprobe.c b/tools/modprobe.c index 3c085e89..4070e552 100644 --- a/tools/modprobe.c +++ b/tools/modprobe.c @@ -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; } diff --git a/tools/static-nodes.c b/tools/static-nodes.c index 435e0dc1..58c06cfb 100644 --- a/tools/static-nodes.c +++ b/tools/static-nodes.c @@ -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) { -- 2.47.3