summaryrefslogtreecommitdiff
path: root/signal.c
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2013-07-18 10:10:46 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2013-07-18 10:10:46 +0200
commit80b73a24a9c94e2a76dc8e6b49160e6792cfc3d3 (patch)
treea87b6abe932d3bcba6bb6822918d303e8fd0d5f6 /signal.c
parent94e10354d888d1f09bc803616869802a13a576bf (diff)
downloadstrace-80b73a24a9c94e2a76dc8e6b49160e6792cfc3d3.tar.gz
strace-80b73a24a9c94e2a76dc8e6b49160e6792cfc3d3.tar.bz2
strace-80b73a24a9c94e2a76dc8e6b49160e6792cfc3d3.tar.xz
sys_rt_sigaction: fix sigset copying
In practice, we always copy as many bytes as syscall param says (8, or 16 on mips). However, malicious program can call sigaction with wrong sigset size. Such syscall will result in EINVAL, but we (strace) end up copying 128 bytes (sizeof(sigset_t)), which copyes some garbage from stack after struct sigaction. Now we always copy NSIG / 8 bytes (which is 8 bytes, or 16 on mips). Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Diffstat (limited to 'signal.c')
-rw-r--r--signal.c25
1 files changed, 10 insertions, 15 deletions
diff --git a/signal.c b/signal.c
index 7f8ed52..66ce613 100644
--- a/signal.c
+++ b/signal.c
@@ -1331,23 +1331,18 @@ sys_rt_sigaction(struct tcb *tcp)
tprints("{SIG_IGN, ");
else
tprintf("{%#lx, ", (long) sa.__sa_handler);
- /* Questionable code below.
- * Kernel won't handle sys_rt_sigaction
- * with wrong sigset size (just returns EINVAL)
- * therefore tcp->u_arg[3(4)] _must_ be NSIG / 8 here,
- * and we always use smaller memcpy. */
+ /*
+ * Sigset size is in tcp->u_arg[4] (SPARC)
+ * or in tcp->u_arg[3] (all other),
+ * but kernel won't handle sys_rt_sigaction
+ * with wrong sigset size (just returns EINVAL instead).
+ * We just fetch the right size, which is NSIG / 8.
+ */
sigemptyset(&sigset);
-#if defined(SPARC) || defined(SPARC64)
- if (tcp->u_arg[4] <= sizeof(sigset))
- memcpy(&sigset, &sa.sa_mask, tcp->u_arg[4]);
-#else
- if (tcp->u_arg[3] <= sizeof(sigset))
- memcpy(&sigset, &sa.sa_mask, tcp->u_arg[3]);
-#endif
- else
- memcpy(&sigset, &sa.sa_mask, sizeof(sigset));
- printsigmask(&sigset, 1);
+ memcpy(&sigset, &sa.sa_mask, NSIG / 8);
+ printsigmask(&sigset, /*rt:*/ 1);
tprints(", ");
+
printflags(sigact_flags, sa.sa_flags, "SA_???");
#ifdef SA_RESTORER
if (sa.sa_flags & SA_RESTORER)