From c5d69183af17e4fe7080f3e6835d16ca7f35b40f Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" <ldv@altlinux.org> Date: Fri, 15 Jul 2016 17:33:26 +0000 Subject: [PATCH] Fix race condition in decoding rt_sigtimedwait's timeout argument As the value returned by sprint_timespec points to a static area and may be overwritten by subsequent calls to sprint_timespec, it is not safe to save this value on entering syscall and use it later on exiting. * signal.c (SYS_FUNC(rt_sigtimedwait)): On entering syscall, copy the value returned by sprint_timespec to a dynamically allocated memory, and save the pointer using set_tcb_priv_data. On exiting, restore it using get_tcb_priv_data. --- signal.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/signal.c b/signal.c index 8d36675a..cb200bfd 100644 --- a/signal.c +++ b/signal.c @@ -662,23 +662,26 @@ SYS_FUNC(rt_sigtimedwait) if (entering(tcp)) { print_sigset_addr_len(tcp, tcp->u_arg[0], tcp->u_arg[3]); tprints(", "); - if (!tcp->u_arg[1]) { + if (!(tcp->u_arg[1] && verbose(tcp))) { /* * This is the only "return" parameter, - * if it's NULL, decode all parameters on entry. + * if we are not going to fetch it on exit, + * decode all parameters on entry. */ - tprints("NULL, "); + printaddr(tcp->u_arg[1]); + tprints(", "); print_timespec(tcp, tcp->u_arg[2]); tprintf(", %lu", tcp->u_arg[3]); - tcp->auxstr = NULL; } else { - tcp->auxstr = sprint_timespec(tcp, tcp->u_arg[2]); + char *sts = xstrdup(sprint_timespec(tcp, tcp->u_arg[2])); + set_tcb_priv_data(tcp, sts, free); } } else { - if (tcp->auxstr) { + if (tcp->u_arg[1] && verbose(tcp)) { printsiginfo_at(tcp, tcp->u_arg[1]); - tprintf(", %s, %lu", tcp->auxstr, tcp->u_arg[3]); - tcp->auxstr = NULL; + tprints(", "); + tprints(get_tcb_priv_data(tcp)); + tprintf(", %lu", tcp->u_arg[3]); } if (!syserror(tcp) && tcp->u_rval) { -- 2.40.0