From: Lennart Poettering Date: Mon, 13 Apr 2026 09:20:57 +0000 (+0200) Subject: stat-util: also add stat_verify_char() and use it everywhere X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa0da09127f4c5c4a2063cf0bc4e629b878a7e27;p=thirdparty%2Fsystemd.git stat-util: also add stat_verify_char() and use it everywhere --- diff --git a/src/basic/stat-util.c b/src/basic/stat-util.c index 2bdd8af21dc..116b36a346f 100644 --- a/src/basic/stat-util.c +++ b/src/basic/stat-util.c @@ -225,6 +225,21 @@ int fd_verify_block(int fd) { return verify_stat_at(fd, /* path= */ NULL, /* follow= */ false, stat_verify_block, /* verify= */ true); } +int stat_verify_char(const struct stat *st) { + assert(st); + + if (S_ISDIR(st->st_mode)) + return -EISDIR; + + if (S_ISLNK(st->st_mode)) + return -ELOOP; + + if (!S_ISCHR(st->st_mode)) + return -EBADFD; + + return 0; +} + int stat_verify_device_node(const struct stat *st) { assert(st); diff --git a/src/basic/stat-util.h b/src/basic/stat-util.h index 55bc5b6c7ea..ec04a2b80cd 100644 --- a/src/basic/stat-util.h +++ b/src/basic/stat-util.h @@ -31,6 +31,8 @@ int fd_verify_linked(int fd); int stat_verify_block(const struct stat *st); int fd_verify_block(int fd); +int stat_verify_char(const struct stat *st); + int stat_verify_device_node(const struct stat *st); int is_device_node(const char *path); diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index ecdc2412472..d7ff92ae892 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1861,6 +1861,8 @@ int terminal_set_cursor_position(int fd, unsigned row, unsigned column) { } static int terminal_verify_same(int input_fd, int output_fd) { + int r; + assert(input_fd >= 0); assert(output_fd >= 0); @@ -1871,15 +1873,17 @@ static int terminal_verify_same(int input_fd, int output_fd) { if (fstat(input_fd, &sti) < 0) return -errno; - if (!S_ISCHR(sti.st_mode)) /* TTYs are character devices */ - return -ENOTTY; + r = stat_verify_char(&sti); /* TTYs are character devices */ + if (r < 0) + return r; struct stat sto; if (fstat(output_fd, &sto) < 0) return -errno; - if (!S_ISCHR(sto.st_mode)) - return -ENOTTY; + r = stat_verify_char(&sto); + if (r < 0) + return r; if (sti.st_rdev != sto.st_rdev) return -ENOLINK; diff --git a/src/core/manager.c b/src/core/manager.c index 73368ec18ae..8db6c471a12 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -4519,10 +4519,9 @@ const char* manager_get_confirm_spawn(Manager *m) { goto fail; } - if (!S_ISCHR(st.st_mode)) { - r = -ENOTTY; + r = stat_verify_char(&st); + if (r < 0) goto fail; - } last_errno = 0; return m->confirm_spawn; diff --git a/src/shared/watchdog.c b/src/shared/watchdog.c index 5b113013950..8b74bb4bbde 100644 --- a/src/shared/watchdog.c +++ b/src/shared/watchdog.c @@ -17,6 +17,7 @@ #include "log.h" #include "path-util.h" #include "ratelimit.h" +#include "stat-util.h" #include "string-util.h" #include "strv.h" #include "time-util.h" @@ -55,6 +56,7 @@ static int saturated_usec_to_sec(usec_t val) { static int watchdog_get_sysfs_path(const char *filename, char **ret_path) { struct stat st; + int r; if (watchdog_fd < 0) return -EBADF; @@ -62,8 +64,9 @@ static int watchdog_get_sysfs_path(const char *filename, char **ret_path) { if (fstat(watchdog_fd, &st)) return -errno; - if (!S_ISCHR(st.st_mode)) - return -EBADF; + r = stat_verify_char(&st); + if (r < 0) + return r; if (asprintf(ret_path, "/sys/dev/char/"DEVNUM_FORMAT_STR"/%s", DEVNUM_FORMAT_VAL(st.st_rdev), filename) < 0) return -ENOMEM;