Skip to content

Commit 46274e7

Browse files
committed
Fix formatting of ttydev on systems with signed 32-bit dev_t
If dev_t is 32-bit and signed, formatting as an unsigned long long may result in a bogus value due to sign extension.
1 parent f3aa3f1 commit 46274e7

5 files changed

Lines changed: 74 additions & 4 deletions

File tree

config.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,9 @@
12931293
/* Define to 1 if you want sudo to set $HOME in shell mode. */
12941294
#undef SHELL_SETS_HOME
12951295

1296+
/* The size of 'dev_t', as computed by sizeof. */
1297+
#undef SIZEOF_DEV_T
1298+
12961299
/* The size of 'id_t', as computed by sizeof. */
12971300
#undef SIZEOF_ID_T
12981301

configure

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21003,6 +21003,41 @@ printf "%s\n" "$ac_cv_sizeof_long_long" >&6; }
2100321003
printf "%s\n" "#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long" >>confdefs.h
2100421004

2100521005

21006+
# The cast to long int works around a bug in the HP C Compiler
21007+
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
21008+
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.
21009+
# This bug is HP SR number 8606223364.
21010+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking size of dev_t" >&5
21011+
printf %s "checking size of dev_t... " >&6; }
21012+
if test ${ac_cv_sizeof_dev_t+y}
21013+
then :
21014+
printf %s "(cached) " >&6
21015+
else case e in #(
21016+
e) if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (dev_t))" "ac_cv_sizeof_dev_t" "$ac_includes_default"
21017+
then :
21018+
21019+
else case e in #(
21020+
e) if test "$ac_cv_type_dev_t" = yes; then
21021+
{ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: error: in '$ac_pwd':" >&5
21022+
printf "%s\n" "$as_me: error: in '$ac_pwd':" >&2;}
21023+
as_fn_error 77 "cannot compute sizeof (dev_t)
21024+
See 'config.log' for more details" "$LINENO" 5; }
21025+
else
21026+
ac_cv_sizeof_dev_t=0
21027+
fi ;;
21028+
esac
21029+
fi
21030+
;;
21031+
esac
21032+
fi
21033+
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_dev_t" >&5
21034+
printf "%s\n" "$ac_cv_sizeof_dev_t" >&6; }
21035+
21036+
21037+
21038+
printf "%s\n" "#define SIZEOF_DEV_T $ac_cv_sizeof_dev_t" >>confdefs.h
21039+
21040+
2100621041
# The cast to long int works around a bug in the HP C Compiler
2100721042
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
2100821043
# declarations like 'int a3[[(sizeof (unsigned char)) >= 0]];'.

configure.ac

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2507,6 +2507,7 @@ SUDO_SOCK_SA_LEN
25072507
SUDO_SOCK_SIN_LEN
25082508
AC_CHECK_SIZEOF([long])
25092509
AC_CHECK_SIZEOF([long long])
2510+
AC_CHECK_SIZEOF([dev_t])
25102511
AC_CHECK_SIZEOF([id_t])
25112512
AC_CHECK_SIZEOF([time_t])
25122513
AC_CHECK_SIZEOF([uid_t])

src/regress/ttyname/check_ttyname.c

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,10 @@ int
6767
main(int argc, char *argv[])
6868
{
6969
char *tty_libc = NULL, *tty_sudo = NULL;
70-
int ch, errors = 0, ntests = 1;
7170
char pathbuf[PATH_MAX];
7271
bool verbose = false;
73-
dev_t ttydev;
72+
dev_t ttydev = -1;
73+
int ch, errors = 0, ntests = 1;
7474

7575
initprogname(argc > 0 ? argv[0] : "check_ttyname");
7676

@@ -87,9 +87,35 @@ main(int argc, char *argv[])
8787

8888
/* Lookup tty name using kernel info if possible. */
8989
ttydev = get_process_ttyname(pathbuf, sizeof(pathbuf));
90-
if (ttydev != (dev_t)-1)
90+
if (ttydev != (dev_t)-1) {
91+
char numbuf[STRLEN_MAX_UNSIGNED(unsigned long long) + 1];
92+
unsigned long long ullval;
93+
const char *errstr;
94+
dev_t newdev;
95+
96+
/* For comparison below. */
9197
tty_sudo = pathbuf;
9298

99+
/* Check that we can format a dev_t as a string and parse it. */
100+
ntests++;
101+
#if SIZEOF_DEV_T == SIZEOF_LONG
102+
ullval = (unsigned long)ttydev;
103+
#else
104+
ullval = (unsigned long long)ttydev;
105+
#endif
106+
(void)snprintf(numbuf, sizeof(numbuf), "%llu", ullval);
107+
newdev = sudo_strtonum(numbuf, LLONG_MIN, LLONG_MAX, &errstr);
108+
if (errstr != NULL) {
109+
printf("%s: FAIL unable to parse device number %s: %s",
110+
getprogname(), numbuf, errstr);
111+
errors++;
112+
} else if (ttydev != newdev) {
113+
printf("%s: FAIL device mismatch for %s, %s != %llu",
114+
getprogname(), pathbuf, numbuf, ullval);
115+
errors++;
116+
}
117+
}
118+
93119
#if defined(HAVE_KINFO_PROC2_NETBSD) || \
94120
defined(HAVE_KINFO_PROC_OPENBSD) || \
95121
defined(HAVE_KINFO_PROC_FREEBSD) || \

src/sudo.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,12 @@ get_user_info(struct user_details *ud)
620620

621621
ttydev = get_process_ttyname(path, sizeof(path));
622622
if (ttydev != (dev_t)-1) {
623-
if (asprintf(&info[++i], "ttydev=%llu", (unsigned long long)ttydev) == -1)
623+
#if SIZEOF_DEV_T == SIZEOF_LONG
624+
n = asprintf(&info[++i], "ttydev=%lu", (unsigned long)ttydev);
625+
#else
626+
n = asprintf(&info[++i], "ttydev=%llu", (unsigned long long)ttydev);
627+
#endif
628+
if (n == -1)
624629
goto oom;
625630
info[++i] = sudo_new_key_val("tty", path);
626631
if (info[i] == NULL)

0 commit comments

Comments
 (0)