summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2013-11-09 20:46:55 +0100
committerDenys Vlasenko <dvlasenk@redhat.com>2013-11-09 20:46:55 +0100
commit64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9 (patch)
tree6823f86d436dde7888bec09598797fb5d6a068de
parentb338f2d65ea9d911a0fead3229ba336bc30e6214 (diff)
downloadstrace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.gz
strace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.bz2
strace-64778cbfa62d9584c59d3a48b69ba1ebf8bd24e9.tar.xz
Fix pathtrace_match() to match recent fixes to select decoding.
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--pathtrace.c29
1 files changed, 16 insertions, 13 deletions
diff --git a/pathtrace.c b/pathtrace.c
index d4c2dc4..f76f3ce 100644
--- a/pathtrace.c
+++ b/pathtrace.c
@@ -257,11 +257,12 @@ pathtrace_match(struct tcb *tcp)
s->sys_func == sys_pselect6)
{
int i, j;
- unsigned nfds;
+ int nfds;
long *args, oldargs[5];
unsigned fdsize;
fd_set *fds;
+ args = tcp->u_arg;
if (s->sys_func == sys_oldselect) {
if (umoven(tcp, tcp->u_arg[0], sizeof oldargs,
(char*) oldargs) < 0)
@@ -270,17 +271,17 @@ pathtrace_match(struct tcb *tcp)
return 0;
}
args = oldargs;
- } else
- args = tcp->u_arg;
+ }
- nfds = args[0];
+ /* Kernel truncates arg[0] to int, we do the same. */
+ nfds = (int) args[0];
+ /* Kernel rejects negative nfds, so we don't parse it either. */
+ if (nfds <= 0)
+ return 0;
/* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
- if (args[0] > 1024*1024)
+ if (nfds > 1024*1024)
nfds = 1024*1024;
- if (args[0] < 0)
- nfds = 0;
- fdsize = ((((nfds + 7) / 8) + sizeof(long) - 1)
- & -sizeof(long));
+ fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
fds = malloc(fdsize);
if (!fds)
die_out_of_memory();
@@ -288,17 +289,19 @@ pathtrace_match(struct tcb *tcp)
for (i = 1; i <= 3; ++i) {
if (args[i] == 0)
continue;
-
if (umoven(tcp, args[i], fdsize, (char *) fds) < 0) {
fprintf(stderr, "umoven() failed\n");
continue;
}
-
- for (j = 0; j < nfds; ++j)
- if (FD_ISSET(j, fds) && fdmatch(tcp, j)) {
+ for (j = 0;; j++) {
+ j = next_set_bit(fds, j, nfds);
+ if (j < 0)
+ break;
+ if (fdmatch(tcp, j)) {
free(fds);
return 1;
}
+ }
}
free(fds);
return 0;