Fix sigset printing via print_sigset().
Replace print_sigset() with print_sigset_addr_len(), which takes not only addr, but also len parameter. This allows us to drop "do we need to print RT signals?" parameter, and this fixes RT signals printing in many syscalls. sys_epoll_pwait: print RT signals too, print sigmask size argument. sys_sigprocmask: print_sigset -> print_sigset_addr_len(current_wordsize), no change in functionality. sys_sigpending: use print_sigset_addr_len(current_wordsize) instead of open-coding it. sys_rt_sigprocmask: use print_sigset_addr_len instead of open-coding it. sys_rt_sigpending: ditto. sys_rt_sigsuspend: ditto. sys_rt_sigtimedwait: ditto. do_signalfd: print_sigset -> print_sigset_addr_len. This fixes RT signals printing (wasn't showing them before). sys_ppoll: ditto. copy_sigset_len() is folded into its only user, print_sigset_addr_len(), and copy_sigset() is gone. While at it, checked kernel sources and noted where kernel enforces sigset_size == NSIG / 8 (== sizeof(kernel_sigset_t)), and where it allows word-sized sigset_size ([rt_]sigpending). Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
parent
80b73a24a9
commit
5e133aa684
2
defs.h
2
defs.h
@ -695,7 +695,7 @@ extern void printrusage(struct tcb *, long);
|
||||
extern void printrusage32(struct tcb *, long);
|
||||
#endif
|
||||
extern void printuid(const char *, unsigned long);
|
||||
extern void print_sigset(struct tcb *, long, 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);
|
||||
extern void tprint_iov_upto(struct tcb *, unsigned long, unsigned long, int decode_iov, unsigned long);
|
||||
|
10
desc.c
10
desc.c
@ -790,7 +790,9 @@ sys_epoll_pwait(struct tcb *tcp)
|
||||
epoll_wait_common(tcp);
|
||||
if (exiting(tcp)) {
|
||||
tprints(", ");
|
||||
print_sigset(tcp, tcp->u_arg[4], 0);
|
||||
/* NB: kernel requires arg[5] == NSIG / 8 */
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[4], tcp->u_arg[5]);
|
||||
tprintf(", %lu", tcp->u_arg[5]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1054,10 +1056,8 @@ sys_pselect6(struct tcb *tcp)
|
||||
tprintf(", %#lx", tcp->u_arg[5]);
|
||||
else {
|
||||
tprints(", {");
|
||||
if (data.len < sizeof(long))
|
||||
tprintf("%#lx", (long)data.ss);
|
||||
else
|
||||
print_sigset(tcp, (long)data.ss, 0);
|
||||
/* NB: kernel requires data.len == NSIG / 8 */
|
||||
print_sigset_addr_len(tcp, (long)data.ss, data.len);
|
||||
tprintf(", %lu}", data.len);
|
||||
}
|
||||
}
|
||||
|
115
signal.c
115
signal.c
@ -220,20 +220,6 @@ long_to_sigset(long l, sigset_t *s)
|
||||
*(long *)s = l;
|
||||
}
|
||||
|
||||
static int
|
||||
copy_sigset_len(struct tcb *tcp, long addr, sigset_t *s, int len)
|
||||
{
|
||||
if (len > sizeof(*s))
|
||||
len = sizeof(*s);
|
||||
sigemptyset(s);
|
||||
if (umoven(tcp, addr, len, (char *)s) < 0)
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Original sigset is unsigned long */
|
||||
#define copy_sigset(tcp, addr, s) copy_sigset_len(tcp, addr, s, sizeof(long))
|
||||
|
||||
static const char *
|
||||
sprintsigmask(const char *str, sigset_t *mask, int rt)
|
||||
/* set might include realtime sigs */
|
||||
@ -313,16 +299,28 @@ printsignal(int nr)
|
||||
}
|
||||
|
||||
void
|
||||
print_sigset(struct tcb *tcp, long addr, int rt)
|
||||
print_sigset_addr_len(struct tcb *tcp, long addr, long len)
|
||||
{
|
||||
sigset_t ss;
|
||||
|
||||
if (!addr)
|
||||
if (!addr) {
|
||||
tprints("NULL");
|
||||
else if (copy_sigset(tcp, addr, &ss) < 0)
|
||||
return;
|
||||
}
|
||||
/* Here len is usually equals NSIG / 8 or current_wordsize.
|
||||
* But we code this defensively:
|
||||
*/
|
||||
if (len < 0) {
|
||||
bad:
|
||||
tprintf("%#lx", addr);
|
||||
else
|
||||
printsigmask(&ss, rt);
|
||||
return;
|
||||
}
|
||||
if (len > NSIG / 8)
|
||||
len = NSIG / 8;
|
||||
sigemptyset(&ss);
|
||||
if (umoven(tcp, addr, len, (char *)&ss) < 0)
|
||||
goto bad;
|
||||
printsigmask(&ss, /*rt:*/ 1);
|
||||
}
|
||||
|
||||
#ifndef ILL_ILLOPC
|
||||
@ -1124,10 +1122,11 @@ sys_sigaltstack(struct tcb *tcp)
|
||||
|
||||
#ifdef HAVE_SIGACTION
|
||||
|
||||
/* "Old" sigprocmask, which operates with word-sized signal masks */
|
||||
int
|
||||
sys_sigprocmask(struct tcb *tcp)
|
||||
{
|
||||
#ifdef ALPHA
|
||||
# ifdef ALPHA
|
||||
sigset_t ss;
|
||||
if (entering(tcp)) {
|
||||
/*
|
||||
@ -1151,22 +1150,20 @@ sys_sigprocmask(struct tcb *tcp)
|
||||
tcp->auxstr = sprintsigmask("old mask ", &ss, 0);
|
||||
return RVAL_HEX | RVAL_STR;
|
||||
}
|
||||
#else /* !ALPHA */
|
||||
# else /* !ALPHA */
|
||||
if (entering(tcp)) {
|
||||
printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
|
||||
tprints(", ");
|
||||
print_sigset(tcp, tcp->u_arg[1], 0);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[1], current_wordsize);
|
||||
tprints(", ");
|
||||
}
|
||||
else {
|
||||
if (!tcp->u_arg[2])
|
||||
tprints("NULL");
|
||||
else if (syserror(tcp))
|
||||
if (syserror(tcp))
|
||||
tprintf("%#lx", tcp->u_arg[2]);
|
||||
else
|
||||
print_sigset(tcp, tcp->u_arg[2], 0);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[2], current_wordsize);
|
||||
}
|
||||
#endif /* !ALPHA */
|
||||
# endif /* !ALPHA */
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1200,15 +1197,11 @@ sys_tgkill(struct tcb *tcp)
|
||||
int
|
||||
sys_sigpending(struct tcb *tcp)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
if (exiting(tcp)) {
|
||||
if (syserror(tcp))
|
||||
tprintf("%#lx", tcp->u_arg[0]);
|
||||
else if (copy_sigset(tcp, tcp->u_arg[0], &sigset) < 0)
|
||||
tprints("[?]");
|
||||
else
|
||||
printsigmask(&sigset, 0);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[0], current_wordsize);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1216,30 +1209,18 @@ sys_sigpending(struct tcb *tcp)
|
||||
int
|
||||
sys_rt_sigprocmask(struct tcb *tcp)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
/* Note: arg[3] is the length of the sigset. */
|
||||
/* Note: arg[3] is the length of the sigset. Kernel requires NSIG / 8 */
|
||||
if (entering(tcp)) {
|
||||
printxval(sigprocmaskcmds, tcp->u_arg[0], "SIG_???");
|
||||
tprints(", ");
|
||||
if (!tcp->u_arg[1])
|
||||
tprints("NULL, ");
|
||||
else if (copy_sigset_len(tcp, tcp->u_arg[1], &sigset, tcp->u_arg[3]) < 0)
|
||||
tprintf("%#lx, ", tcp->u_arg[1]);
|
||||
else {
|
||||
printsigmask(&sigset, 1);
|
||||
tprints(", ");
|
||||
}
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[1], tcp->u_arg[3]);
|
||||
tprints(", ");
|
||||
}
|
||||
else {
|
||||
if (!tcp->u_arg[2])
|
||||
tprints("NULL");
|
||||
else if (syserror(tcp))
|
||||
if (syserror(tcp))
|
||||
tprintf("%#lx", tcp->u_arg[2]);
|
||||
else if (copy_sigset_len(tcp, tcp->u_arg[2], &sigset, tcp->u_arg[3]) < 0)
|
||||
tprints("[?]");
|
||||
else
|
||||
printsigmask(&sigset, 1);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[2], tcp->u_arg[3]);
|
||||
tprintf(", %lu", tcp->u_arg[3]);
|
||||
}
|
||||
return 0;
|
||||
@ -1367,16 +1348,18 @@ sys_rt_sigaction(struct tcb *tcp)
|
||||
int
|
||||
sys_rt_sigpending(struct tcb *tcp)
|
||||
{
|
||||
sigset_t sigset;
|
||||
|
||||
if (exiting(tcp)) {
|
||||
/*
|
||||
* One of the few syscalls where sigset size (arg[1])
|
||||
* is allowed to be <= NSIG / 8, not strictly ==.
|
||||
* This allows non-rt sigpending() syscall
|
||||
* to reuse rt_sigpending() code in kernel.
|
||||
*/
|
||||
if (syserror(tcp))
|
||||
tprintf("%#lx", tcp->u_arg[0]);
|
||||
else if (copy_sigset_len(tcp, tcp->u_arg[0],
|
||||
&sigset, tcp->u_arg[1]) < 0)
|
||||
tprints("[?]");
|
||||
else
|
||||
printsigmask(&sigset, 1);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[0], tcp->u_arg[1]);
|
||||
tprintf(", %lu", tcp->u_arg[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1385,11 +1368,9 @@ int
|
||||
sys_rt_sigsuspend(struct tcb *tcp)
|
||||
{
|
||||
if (entering(tcp)) {
|
||||
sigset_t sigm;
|
||||
if (copy_sigset_len(tcp, tcp->u_arg[0], &sigm, tcp->u_arg[1]) < 0)
|
||||
tprints("[?]");
|
||||
else
|
||||
printsigmask(&sigm, 1);
|
||||
/* NB: kernel requires arg[1] == NSIG / 8 */
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[0], tcp->u_arg[1]);
|
||||
tprintf(", %lu", tcp->u_arg[1]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1424,14 +1405,9 @@ sys_rt_tgsigqueueinfo(struct tcb *tcp)
|
||||
|
||||
int sys_rt_sigtimedwait(struct tcb *tcp)
|
||||
{
|
||||
/* NB: kernel requires arg[3] == NSIG / 8 */
|
||||
if (entering(tcp)) {
|
||||
sigset_t sigset;
|
||||
|
||||
if (copy_sigset_len(tcp, tcp->u_arg[0],
|
||||
&sigset, tcp->u_arg[3]) < 0)
|
||||
tprints("[?]");
|
||||
else
|
||||
printsigmask(&sigset, 1);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[0], tcp->u_arg[3]);
|
||||
tprints(", ");
|
||||
/* This is the only "return" parameter, */
|
||||
if (tcp->u_arg[1] != 0)
|
||||
@ -1449,7 +1425,7 @@ int sys_rt_sigtimedwait(struct tcb *tcp)
|
||||
return 0;
|
||||
}
|
||||
print_timespec(tcp, tcp->u_arg[2]);
|
||||
tprintf(", %d", (int) tcp->u_arg[3]);
|
||||
tprintf(", %lu", tcp->u_arg[3]);
|
||||
return 0;
|
||||
};
|
||||
|
||||
@ -1464,10 +1440,11 @@ sys_restart_syscall(struct tcb *tcp)
|
||||
static int
|
||||
do_signalfd(struct tcb *tcp, int flags_arg)
|
||||
{
|
||||
/* NB: kernel requires arg[2] == NSIG / 8 */
|
||||
if (entering(tcp)) {
|
||||
printfd(tcp, tcp->u_arg[0]);
|
||||
tprints(", ");
|
||||
print_sigset(tcp, tcp->u_arg[1], 1);
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[1], tcp->u_arg[2]);
|
||||
tprintf(", %lu", tcp->u_arg[2]);
|
||||
if (flags_arg >= 0) {
|
||||
tprints(", ");
|
||||
|
3
stream.c
3
stream.c
@ -422,7 +422,8 @@ sys_ppoll(struct tcb *tcp)
|
||||
if (entering(tcp)) {
|
||||
print_timespec(tcp, tcp->u_arg[2]);
|
||||
tprints(", ");
|
||||
print_sigset(tcp, tcp->u_arg[3], 0);
|
||||
/* NB: kernel requires arg[4] == NSIG / 8 */
|
||||
print_sigset_addr_len(tcp, tcp->u_arg[3], tcp->u_arg[4]);
|
||||
tprintf(", %lu", tcp->u_arg[4]);
|
||||
}
|
||||
return rc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user