From 1e03cbd0b406c492c12b7fa39a22c45bb208503f Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Sat, 9 Dec 2023 12:54:56 -0700 Subject: [PATCH] sudo_term_is_raw: only try to lock the fd if it is a tty This moves sudo_isatty() to libsudo_util so sudo_term_is_raw() can use it. Fixes GitHub issue #335 --- include/sudo_util.h | 2 ++ lib/util/term.c | 32 ++++++++++++++++++++++++++++++++ lib/util/ttysize.c | 12 +++++++----- lib/util/util.exp.in | 1 + src/sudo.h | 1 - src/ttyname.c | 24 ------------------------ 6 files changed, 42 insertions(+), 30 deletions(-) diff --git a/include/sudo_util.h b/include/sudo_util.h index 5aea06e51..d534d40b1 100644 --- a/include/sudo_util.h +++ b/include/sudo_util.h @@ -325,6 +325,8 @@ extern int (*sudo_printf)(int msg_type, const char * restrict fmt, ...); /* term.c */ #define SUDO_TERM_ISIG 0x01U #define SUDO_TERM_OFLAG 0x02U +sudo_dso_public bool sudo_isatty_v1(int fd, struct stat *sbp); +#define sudo_isatty(_a, _b) sudo_isatty_v1((_a), (_b)) sudo_dso_public bool sudo_term_cbreak_v1(int fd); #define sudo_term_cbreak(_a) sudo_term_cbreak_v1((_a)) sudo_dso_public bool sudo_term_copy_v1(int src, int dst); diff --git a/lib/util/term.c b/lib/util/term.c index a195c8151..a74e9d022 100644 --- a/lib/util/term.c +++ b/lib/util/term.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -286,6 +287,9 @@ sudo_term_is_raw_v1(int fd) struct termios term = { 0 }; debug_decl(sudo_term_is_raw, SUDO_DEBUG_UTIL); + if (!sudo_isatty(fd, NULL)) + debug_return_bool(false); + sudo_lock_file(fd, SUDO_LOCK); if (tcgetattr(fd, &term) == -1) { sudo_debug_printf(SUDO_DEBUG_ERROR|SUDO_DEBUG_ERRNO, @@ -457,3 +461,31 @@ unlock: sudo_lock_file(src, SUDO_UNLOCK); debug_return_bool(ret); } + +/* + * Like isatty(3) but stats the fd and stores the result in sb. + * Only calls isatty(3) if fd is a character special device. + * Returns true if a tty, else returns false and sets errno. + */ +bool +sudo_isatty_v1(int fd, struct stat *sbp) +{ + bool ret = false; + struct stat sb; + debug_decl(sudo_isatty, SUDO_DEBUG_EXEC); + + if (sbp == NULL) + sbp = &sb; + + if (fstat(fd, sbp) == 0) { + if (!S_ISCHR(sbp->st_mode)) { + errno = ENOTTY; + } else { + ret = isatty(fd) == 1; + } + } else if (sbp != &sb) { + /* Always initialize sbp. */ + memset(sbp, 0, sizeof(*sbp)); + } + debug_return_bool(ret); +} diff --git a/lib/util/ttysize.c b/lib/util/ttysize.c index 54085e7ac..0b582d0df 100644 --- a/lib/util/ttysize.c +++ b/lib/util/ttysize.c @@ -39,11 +39,13 @@ get_ttysize_ioctl(int fd, int *rowp, int *colp) struct winsize wsize; debug_decl(get_ttysize_ioctl, SUDO_DEBUG_UTIL); - if (fd != -1 && isatty(fd) && ioctl(fd, TIOCGWINSZ, &wsize) == 0) { - if (wsize.ws_row != 0 && wsize.ws_col != 0) { - *rowp = wsize.ws_row; - *colp = wsize.ws_col; - debug_return_int(0); + if (fd != -1 && sudo_isatty(fd, NULL)) { + if (ioctl(fd, TIOCGWINSZ, &wsize) == 0) { + if (wsize.ws_row != 0 && wsize.ws_col != 0) { + *rowp = wsize.ws_row; + *colp = wsize.ws_col; + debug_return_int(0); + } } } debug_return_int(-1); diff --git a/lib/util/util.exp.in b/lib/util/util.exp.in index 90c87e87b..ca9dcede2 100644 --- a/lib/util/util.exp.in +++ b/lib/util/util.exp.in @@ -96,6 +96,7 @@ sudo_gettime_awake_v1 sudo_gettime_mono_v1 sudo_gettime_real_v1 sudo_hexchar_v1 +sudo_isatty_v1 sudo_json_add_value_as_object_v1 sudo_json_add_value_v1 sudo_json_close_array_v1 diff --git a/src/sudo.h b/src/sudo.h index f4ce082ff..a7450dca9 100644 --- a/src/sudo.h +++ b/src/sudo.h @@ -318,7 +318,6 @@ int get_net_ifs(char **addrinfo); /* ttyname.c */ dev_t get_process_ttyname(char *name, size_t namelen); -bool sudo_isatty(int fd, struct stat *sb); /* signal.c */ struct sigaction; diff --git a/src/ttyname.c b/src/ttyname.c index d59e7457d..ae8bc9789 100644 --- a/src/ttyname.c +++ b/src/ttyname.c @@ -405,27 +405,3 @@ get_process_ttyname(char *name, size_t namelen) debug_return_dev_t((dev_t)-1); } #endif - -/* - * Like isatty(3) but stats the fd and stores the result in sb. - * Only calls isatty(3) if fd is a character special device. - * Returns true if a tty, else returns false and sets errno. - */ -bool -sudo_isatty(int fd, struct stat *sb) -{ - bool ret = false; - debug_decl(sudo_isatty, SUDO_DEBUG_EXEC); - - if (fstat(fd, sb) == 0) { - if (!S_ISCHR(sb->st_mode)) { - errno = ENOTTY; - } else { - ret = isatty(fd) == 1; - } - } else { - /* Always initialize sb. */ - memset(sb, 0, sizeof(*sb)); - } - debug_return_bool(ret); -}