From 03cb7092d3a155c2030172ef3ce79a9ef65822a5 Mon Sep 17 00:00:00 2001 From: Eugene Syromyatnikov Date: Sun, 7 Jan 2018 03:53:53 +0100 Subject: [PATCH] syscall.c: add support for printing return value and error code Some weird syscalls (like modify_ldt) return value that doesn't indicate an error (less than -4096), but it is, in fact, erroneous (because they decide to clip the return value to 32-bit, for example). Add a flag to print decoded error code along with syscall return value. * defs.h (RVAL_PRINT_ERR_VAL): New rval flag. * syscall.c (syscall_exiting_trace): Handle it. --- defs.h | 4 ++++ syscall.c | 11 +++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/defs.h b/defs.h index b470c6d6..e7d7b2df 100644 --- a/defs.h +++ b/defs.h @@ -312,6 +312,10 @@ extern const struct xlat whence_codes[]; #define RVAL_DECODED 0100 /* syscall decoding finished */ #define RVAL_IOCTL_DECODED 0200 /* ioctl sub-parser successfully decoded the argument */ +#define RVAL_PRINT_ERR_VAL 0400 /* Print decoded error code along with + syscall return value. Needed for modify_ldt + that for some reason decides to return + an error with higher bits set to 0. */ #define IOCTL_NUMBER_UNKNOWN 0 #define IOCTL_NUMBER_HANDLED 1 diff --git a/syscall.c b/syscall.c index 4deb1e8b..d36abf2e 100644 --- a/syscall.c +++ b/syscall.c @@ -808,6 +808,7 @@ syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res) tprints(") "); tabto(); unsigned long u_error = tcp->u_error; + kernel_long_t u_rval; if (raw(tcp)) { if (u_error) { @@ -875,13 +876,15 @@ syscall_exiting_trace(struct tcb *tcp, struct timeval tv, int res) tprints("= ? ERESTART_RESTARTBLOCK (Interrupted by signal)"); break; default: + u_rval = sys_res & RVAL_PRINT_ERR_VAL ? + tcp->u_rval : -1; u_error_str = err_name(u_error); if (u_error_str) - tprintf("= -1 %s (%s)", - u_error_str, strerror(u_error)); + tprintf("= %" PRI_kld " %s (%s)", + u_rval, u_error_str, strerror(u_error)); else - tprintf("= -1 %lu (%s)", - u_error, strerror(u_error)); + tprintf("= %" PRI_kld " %lu (%s)", + u_rval, u_error, strerror(u_error)); break; } if (syscall_tampered(tcp)) -- 2.40.0