]> granicus.if.org Git - strace/commitdiff
Rework decoding and pathtrace of old select syscall
authorDmitry V. Levin <ldv@altlinux.org>
Mon, 22 Jan 2018 00:31:07 +0000 (00:31 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 23 Jan 2018 23:17:02 +0000 (23:17 +0000)
* linux/arch_defs_.h [!HAVE_ARCH_OLD_SELECT] (HAVE_ARCH_OLD_SELECT): New
macro.
* linux/aarch64/arch_defs_.h (HAVE_ARCH_OLD_SELECT): Likewise.
* linux/arm/arch_defs_.h: Likewise.
* linux/bfin/arch_defs_.h: Likewise.
* linux/i386/arch_defs_.h: Likewise.
* linux/m68k/arch_defs_.h: Likewise.
* linux/microblaze/arch_defs_.h: Likewise.
* linux/powerpc64/arch_defs_.h: Likewise.
* linux/sh/arch_defs_.h: Likewise.
* linux/x32/arch_defs_.h: Likewise.
* linux/x86_64/arch_defs_.h: Likewise.
* linux/powerpc/arch_defs_.h: New file.
* Makefile.am (EXTRA_DIST): Add it.
* desc.c (SYS_FUNC(oldselect)): Rewrite using
fetch_indirect_syscall_args, move under [HAVE_ARCH_OLD_SELECT].
* pathtrace.c (match_xselect_args): New function.
(pathtrace_match_set): Use it.

15 files changed:
Makefile.am
desc.c
linux/aarch64/arch_defs_.h
linux/arch_defs_.h
linux/arm/arch_defs_.h
linux/bfin/arch_defs_.h
linux/i386/arch_defs_.h
linux/m68k/arch_defs_.h
linux/microblaze/arch_defs_.h
linux/powerpc/arch_defs_.h [new file with mode: 0644]
linux/powerpc64/arch_defs_.h
linux/sh/arch_defs_.h
linux/x32/arch_defs_.h
linux/x86_64/arch_defs_.h
pathtrace.c

index 43795fe1d733e181a03235404352e702ebcf9a5c..16d1f2c7ad1313a01666f27bae983a070c5dda28 100644 (file)
@@ -643,6 +643,7 @@ EXTRA_DIST =                                \
        linux/or1k/syscallent.h         \
        linux/or1k/userent.h            \
        linux/packet_diag.h             \
+       linux/powerpc/arch_defs_.h      \
        linux/powerpc/arch_regs.c       \
        linux/powerpc/arch_regs.h       \
        linux/powerpc/arch_rt_sigframe.c\
diff --git a/desc.c b/desc.c
index b45a13b15efa867af012d9f72ff92181dff905d8..ff22fc0770e01f166ce6438e71c2012e03890992 100644 (file)
--- a/desc.c
+++ b/desc.c
@@ -196,29 +196,21 @@ decode_select(struct tcb *const tcp, const kernel_ulong_t *const args,
        return 0;
 }
 
+#if HAVE_ARCH_OLD_SELECT
 SYS_FUNC(oldselect)
 {
-       kernel_ulong_t select_args[5];
-       unsigned int oldselect_args[5];
+       kernel_ulong_t *args =
+               fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 5);
 
-       if (sizeof(*select_args) == sizeof(*oldselect_args)) {
-               if (umove_or_printaddr(tcp, tcp->u_arg[0], &select_args)) {
-                       return 0;
-               }
+       if (args) {
+               return decode_select(tcp, args, print_timeval, sprint_timeval);
        } else {
-               unsigned int i;
-
-               if (umove_or_printaddr(tcp, tcp->u_arg[0], &oldselect_args)) {
-                       return 0;
-               }
-
-               for (i = 0; i < 5; ++i) {
-                       select_args[i] = oldselect_args[i];
-               }
+               if (entering(tcp))
+                       printaddr(tcp->u_arg[0]);
+               return RVAL_DECODED;
        }
-
-       return decode_select(tcp, select_args, print_timeval, sprint_timeval);
 }
+#endif /* HAVE_ARCH_OLD_SELECT */
 
 #ifdef ALPHA
 SYS_FUNC(osf_select)
index ad9748ab95fae325bc4edb4c2dafdb03ab2ccb48..40232fd6a2c5e418493ea8c49acca52f538908cc 100644 (file)
@@ -1,3 +1,4 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
 #define SUPPORTED_PERSONALITIES 2
index c2aa62f8751a2a2f57d0924e90b961e1de8eba18..e4cdf91b4c057b522da95e551a00ad2615e723d2 100644 (file)
 # define HAVE_ARCH_OLD_MMAP_PGOFF 0
 #endif
 
+#ifndef HAVE_ARCH_OLD_SELECT
+# define HAVE_ARCH_OLD_SELECT 0
+#endif
+
 #ifndef HAVE_ARCH_UID16_SYSCALLS
 # define HAVE_ARCH_UID16_SYSCALLS 0
 #endif
index 4d264a1d72b9974917ddc532aaa0fa9b9060b1a1..a8e961f34603b98383159dea7ec40ae8a50df5c7 100644 (file)
@@ -1,2 +1,3 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
index 0c9ca19511ec129d188c0e9128117578c91a01de..d642058b2c3743a4ccb991f9b1c1db988c691ed0 100644 (file)
@@ -1 +1,2 @@
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
index 4d264a1d72b9974917ddc532aaa0fa9b9060b1a1..a8e961f34603b98383159dea7ec40ae8a50df5c7 100644 (file)
@@ -1,2 +1,3 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
index 86a4f7cc12f1bc705ccce5b11f0178bee2ea5d4e..67e815c4ff9e3e324aab2d554863c0a8c65423b0 100644 (file)
@@ -1,3 +1,4 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
 #define HAVE_ARCH_SA_RESTORER 1
index 0c9ca19511ec129d188c0e9128117578c91a01de..d642058b2c3743a4ccb991f9b1c1db988c691ed0 100644 (file)
@@ -1 +1,2 @@
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
diff --git a/linux/powerpc/arch_defs_.h b/linux/powerpc/arch_defs_.h
new file mode 100644 (file)
index 0000000..a72e680
--- /dev/null
@@ -0,0 +1 @@
+#define HAVE_ARCH_OLD_SELECT 1
index 640d68e0c35488495bedad4aa1a023bd91368fba..1b81d118f14a72e3d9a245f0c67ece65a2dc54aa 100644 (file)
@@ -1 +1,2 @@
+#define HAVE_ARCH_OLD_SELECT 1
 #define SUPPORTED_PERSONALITIES 2
index 473c349e3d8d4d824c08fb72428d50609946f0bd..b4d39f0a2f7c9b3a76c0f59deabbaf064acf6c20 100644 (file)
@@ -1,2 +1,3 @@
 #define HAVE_ARCH_GETRVAL2 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
index ad9748ab95fae325bc4edb4c2dafdb03ab2ccb48..40232fd6a2c5e418493ea8c49acca52f538908cc 100644 (file)
@@ -1,3 +1,4 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
 #define SUPPORTED_PERSONALITIES 2
index 1401c6a87b1739fb4655059c96281ad80a5ff127..169e0892c479e6fd822893a5334f22db0a4ea0b5 100644 (file)
@@ -1,3 +1,4 @@
 #define HAVE_ARCH_OLD_MMAP 1
+#define HAVE_ARCH_OLD_SELECT 1
 #define HAVE_ARCH_UID16_SYSCALLS 1
 #define SUPPORTED_PERSONALITIES 3
index b8799b39bba3d9a966ff34afdbf46dc4e9eccf2f..4297fb29793142406c23e5b5846bde27e3ed7305 100644 (file)
@@ -143,6 +143,41 @@ pathtrace_select_set(const char *path, struct path_set *set)
        storepath(rpath, set);
 }
 
+static bool
+match_xselect_args(struct tcb *tcp, const kernel_ulong_t *args,
+                  struct path_set *set)
+{
+       /* Kernel truncates arg[0] to int, we do the same. */
+       int nfds = (int) args[0];
+       /* Kernel rejects negative nfds, so we don't parse it either. */
+       if (nfds <= 0)
+               return false;
+       /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
+       if (nfds > 1024*1024)
+               nfds = 1024*1024;
+       unsigned int fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
+       fd_set *fds = xmalloc(fdsize);
+
+       for (unsigned int i = 1; i <= 3; ++i) {
+               if (args[i] == 0)
+                       continue;
+               if (umoven(tcp, args[i], fdsize, fds) < 0)
+                       continue;
+               for (int j = 0;; ++j) {
+                       j = next_set_bit(fds, j, nfds);
+                       if (j < 0)
+                               break;
+                       if (fdmatch(tcp, j, set)) {
+                               free(fds);
+                               return true;
+                       }
+               }
+       }
+
+       free(fds);
+       return false;
+}
+
 /*
  * Return true if syscall accesses a selected path
  * (or if no paths have been specified for tracing).
@@ -258,70 +293,18 @@ pathtrace_match_set(struct tcb *tcp, struct path_set *set)
                return fdmatch(tcp, tcp->u_arg[argn], set) ||
                        upathmatch(tcp, tcp->u_arg[argn + 1], set);
        }
+#if HAVE_ARCH_OLD_SELECT
        case SEN_oldselect:
-       case SEN_pselect6:
-       case SEN_select:
        {
-               int     i, j;
-               int     nfds;
-               kernel_ulong_t *args;
-               kernel_ulong_t select_args[5];
-               unsigned int oldselect_args[5];
-               unsigned int fdsize;
-               fd_set *fds;
-
-               if (SEN_oldselect == s->sen) {
-                       if (sizeof(*select_args) == sizeof(*oldselect_args)) {
-                               if (umove(tcp, tcp->u_arg[0], &select_args)) {
-                                       return false;
-                               }
-                       } else {
-                               unsigned int n;
-
-                               if (umove(tcp, tcp->u_arg[0], &oldselect_args)) {
-                                       return false;
-                               }
-
-                               for (n = 0; n < 5; ++n) {
-                                       select_args[n] = oldselect_args[n];
-                               }
-                       }
-                       args = select_args;
-               } else {
-                       args = tcp->u_arg;
-               }
+               kernel_ulong_t *args =
+                       fetch_indirect_syscall_args(tcp, tcp->u_arg[0], 5);
 
-               /* 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 false;
-               /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
-               if (nfds > 1024*1024)
-                       nfds = 1024*1024;
-               fdsize = (((nfds + 7) / 8) + current_wordsize-1) & -current_wordsize;
-               fds = xmalloc(fdsize);
-
-               for (i = 1; i <= 3; ++i) {
-                       if (args[i] == 0)
-                               continue;
-                       if (umoven(tcp, args[i], fdsize, fds) < 0) {
-                               continue;
-                       }
-                       for (j = 0;; j++) {
-                               j = next_set_bit(fds, j, nfds);
-                               if (j < 0)
-                                       break;
-                               if (fdmatch(tcp, j, set)) {
-                                       free(fds);
-                                       return true;
-                               }
-                       }
-               }
-               free(fds);
-               return false;
+               return args && match_xselect_args(tcp, args, set);
        }
-
+#endif
+       case SEN_pselect6:
+       case SEN_select:
+               return match_xselect_args(tcp, tcp->u_arg, set);
        case SEN_poll:
        case SEN_ppoll:
        {