From 1da7c95b62537f066c74972e2b59a322446ca86e Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Sat, 13 Dec 2014 18:24:13 +0000 Subject: [PATCH] printuid: fix uid_t decoding on 64-bit architectures It was not a good idea to treat uid_t as a long int type because the latter is twice larger than uid_t on 64-bit architectures. * defs.h (printuid): Change uid argument type from "unsigned long" to "unsigned int". * util.c (printuid): Likewise. When uid equals to -1, print "-1". * tests/uid.awk: New file. * tests/uid.c: New file. * tests/uid32.c: Likewise. * tests/uid.test: New test. * tests/uid32.test: Likewise. * tests/Makefile.am (CHECK_PROGRAMS): Add uid and uid32. (TESTS): Add uid.test and uid32.test. (EXTRA_DIST): Add uid.awk. * tests/.gitignore: Add uid and uid32. --- defs.h | 2 +- tests/.gitignore | 3 ++ tests/Makefile.am | 5 +++ tests/uid.awk | 86 +++++++++++++++++++++++++++++++++++++++++++++++ tests/uid.c | 29 ++++++++++++++++ tests/uid.test | 32 ++++++++++++++++++ tests/uid32.c | 29 ++++++++++++++++ tests/uid32.test | 7 ++++ util.c | 7 ++-- 9 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 tests/uid.awk create mode 100644 tests/uid.c create mode 100755 tests/uid.test create mode 100644 tests/uid32.c create mode 100755 tests/uid32.test diff --git a/defs.h b/defs.h index ddffbf20..92b35723 100644 --- a/defs.h +++ b/defs.h @@ -706,7 +706,7 @@ extern void printrusage(struct tcb *, long); #ifdef ALPHA extern void printrusage32(struct tcb *, long); #endif -extern void printuid(const char *, unsigned long); +extern void printuid(const char *, const unsigned int); extern void print_sigset_addr_len(struct tcb *, long, long); extern void printsignal(int); extern void tprint_iov(struct tcb *, unsigned long, unsigned long, int decode_iov); diff --git a/tests/.gitignore b/tests/.gitignore index aa808c20..ef0545ef 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -1,3 +1,4 @@ +caps inet-accept-connect-send-recv mmsg net-accept-connect @@ -7,6 +8,8 @@ set_ptracer_any sigaction stack-fcall statfs +uid +uid32 uio *.log *.log.* diff --git a/tests/Makefile.am b/tests/Makefile.am index 0784f24e..85fe9c6f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,6 +13,8 @@ check_PROGRAMS = \ sigaction \ stack-fcall \ statfs \ + uid \ + uid32 \ uio statfs_CFLAGS = $(AM_CFLAGS) -D_FILE_OFFSET_BITS=64 @@ -34,6 +36,8 @@ TESTS = \ net.test \ net-fd.test \ net-yy.test \ + uid.test \ + uid32.test \ uio.test \ count.test \ detach-sleeping.test \ @@ -52,6 +56,7 @@ EXTRA_DIST = init.sh run.sh \ net-yy-accept.awk \ net-yy-connect.awk \ sigaction.awk \ + uid.awk \ $(TESTS) CLEANFILES = $(TESTS:=.tmp) diff --git a/tests/uid.awk b/tests/uid.awk new file mode 100644 index 00000000..7c431aa7 --- /dev/null +++ b/tests/uid.awk @@ -0,0 +1,86 @@ +BEGIN { + ok = 0 + fail = 0 + r_uid = "(0|[1-9][0-9]*)" + r_getuid = "^getuid" suffix "\\(\\)[[:space:]]+= " r_uid "$" + r_setuid = "^/$" + r_getresuid = "^/$" + r_setreuid = "^/$" + r_setresuid = "^/$" + r_chown = "^/$" + s_last = "/" +} + +ok == 1 { + fail = 1 + next +} + +$0 == s_last { + ok = 1 + next +} + +{ + if (match($0, r_getuid, a)) { + r_uid = a[1] + r_setuid = "^setuid" suffix "\\(" r_uid "\\)[[:space:]]+= 0$" + next + } + if (match($0, r_setuid)) { + r_getresuid = "^getresuid" suffix "\\(\\[" r_uid "\\], \\[" r_uid "\\], \\[" r_uid "\\]\\)[[:space:]]+= 0$" + next + } + if (match($0, r_getresuid)) { + r_setreuid = "^setreuid" suffix "\\(-1, -1\\)[[:space:]]+= 0$" + next + } + if (match($0, r_setreuid)) { + r_setresuid = "^setresuid" suffix "\\(-1, " r_uid ", -1\\)[[:space:]]+= 0$" + next + } + if (match($0, r_setresuid)) { + r_chown = "^chown" suffix "\\(\".\", -1, -1\\)[[:space:]]+= 0$" + next + } + if (match($0, r_chown)) { + s_last = "+++ exited with 0 +++" + next + } + next +} + +END { + if (fail) { + print "Unexpected output after exit" + exit 1 + } + if (ok) + exit 0 + if (r_setuid == "^/$") { + print "getuid doesn't match" + exit 1 + } + if (r_getresuid == "^/$") { + print "setuid doesn't match" + exit 1 + } + if (r_setreuid == "^/$") { + print "getresuid doesn't match" + exit 1 + } + if (r_setresuid == "^/$") { + print "setreuid doesn't match" + exit 1 + } + if (r_chown == "^/$") { + print "setresuid doesn't match" + exit 1 + } + if (s_last == "/") { + print "chown doesn't match" + exit 1 + } + print "The last line doesn't match" + exit 1 +} diff --git a/tests/uid.c b/tests/uid.c new file mode 100644 index 00000000..b4b98139 --- /dev/null +++ b/tests/uid.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +int +main(void) +{ +#if defined(__NR_getuid) \ + && defined(__NR_setuid) \ + && defined(__NR_getresuid) \ + && defined(__NR_setreuid) \ + && defined(__NR_setresuid) \ + && defined(__NR_chown) + uid_t r, e, s; + + e = syscall(__NR_getuid); + assert(syscall(__NR_setuid, e) == 0); + assert(syscall(__NR_getresuid, &r, &e, &s) == 0); + assert(syscall(__NR_setreuid, -1, -1L) == 0); + assert(syscall(__NR_setresuid, -1, e, -1L) == 0); + assert(syscall(__NR_chown, ".", -1, -1L) == 0); + return 0; +#else + return 77; +#endif +} diff --git a/tests/uid.test b/tests/uid.test new file mode 100755 index 00000000..02fea2aa --- /dev/null +++ b/tests/uid.test @@ -0,0 +1,32 @@ +#!/bin/sh + +# Check uid decoding. + +. "${srcdir=.}/init.sh" + +check_prog awk + +s="${uid_syscall_suffix-}" +w="${uid_t_size-}" +uid="uid$s$w" +./"$uid" || { + if [ $? -eq 77 ]; then + framework_skip_ "some uid$s or uid${w}_t syscalls are not available" + else + fail_ "$uid failed" + fi +} + +syscalls="getuid$s,setuid$s,getresuid$s,setreuid$s,setresuid$s,chown$s" +args="-e trace=$syscalls" +$STRACE -o "$LOG" $args ./"$uid"|| { + cat "$LOG" + fail_ "$STRACE $args ./$uid failed" +} + +awk -f "$srcdir"/uid.awk -v suffix="$s" "$LOG" || { + cat "$LOG" + fail_ 'unexpected output' +} + +exit 0 diff --git a/tests/uid32.c b/tests/uid32.c new file mode 100644 index 00000000..94301b77 --- /dev/null +++ b/tests/uid32.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif +#include +#include +#include + +int +main(void) +{ +#if defined(__NR_getuid32) \ + && defined(__NR_setuid32) \ + && defined(__NR_getresuid32) \ + && defined(__NR_setreuid32) \ + && defined(__NR_setresuid32) \ + && defined(__NR_chown32) + uid_t r, e, s; + + e = syscall(__NR_getuid32); + assert(syscall(__NR_setuid32, e) == 0); + assert(syscall(__NR_getresuid32, &r, &e, &s) == 0); + assert(syscall(__NR_setreuid32, -1, -1L) == 0); + assert(syscall(__NR_setresuid32, -1, e, -1L) == 0); + assert(syscall(__NR_chown32, ".", -1, -1L) == 0); + return 0; +#else + return 77; +#endif +} diff --git a/tests/uid32.test b/tests/uid32.test new file mode 100755 index 00000000..82ba9b7f --- /dev/null +++ b/tests/uid32.test @@ -0,0 +1,7 @@ +#!/bin/sh + +# Check uid32 decoding. + +uid_syscall_suffix=32 + +. "${srcdir=.}/uid.test" diff --git a/util.c b/util.c index 71e921d0..3201b09d 100644 --- a/util.c +++ b/util.c @@ -504,9 +504,12 @@ printfd(struct tcb *tcp, int fd) } void -printuid(const char *text, unsigned long uid) +printuid(const char *text, const unsigned int uid) { - tprintf(((long) uid == -1) ? "%s%ld" : "%s%lu", text, uid); + if ((unsigned int) -1 == uid) + tprintf("%s-1", text); + else + tprintf("%s%u", text, uid); } /* -- 2.34.1