]> granicus.if.org Git - strace/commitdiff
x32: implement automatic argument truncation for compat syscalls
authorDmitry V. Levin <ldv@altlinux.org>
Tue, 20 Dec 2016 01:52:20 +0000 (01:52 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Tue, 20 Dec 2016 05:10:21 +0000 (05:10 +0000)
x32 syscalls starting with number 512 are compat syscalls that operate
on compat types.  Set COMPAT_SYSCALL_TYPES flag to these syscall entries
and make get_syscall_args truncate arguments of syscalls that have this
flag set, to avoid unpleasant alternative of adding multiple
widen_to_ulong invocations to individual syscall parsers.

preadv, pwritev, preadv2, and pwritev2 are exceptions: while these
syscalls operate on compat types, the offset argument has a regular
64-bit type, so the automatic argument truncation cannot be applied.

* defs.h (COMPAT_SYSCALL_TYPES): New macro.
* syscall.c (CST): New macro, defined to COMPAT_SYSCALL_TYPES.
* linux/ia64/syscallent.h: Do not include "../i386/syscallent.h"
unless [CST > 0].
* linux/x32/syscallent.h [512..533, 536..545]: Add CST flag.
* linux/x86_64/get_syscall_args.c (get_syscall_args): Truncate arguments
of compat syscalls to 32-bit values.
* tests/ksysent.c (CST): New macro, defined to 0.
* tests/nsyscalls.c (CST): Likewise.

defs.h
linux/ia64/syscallent.h
linux/x32/syscallent.h
linux/x86_64/get_syscall_args.c
syscall.c
tests/ksysent.c
tests/nsyscalls.c

diff --git a/defs.h b/defs.h
index 06b1dcd3f2243869eede8e736b41356ea1d7e8f3..2b6ca9d18dad366b89b9f6a752ab5d7068ac375c 100644 (file)
--- a/defs.h
+++ b/defs.h
@@ -356,6 +356,7 @@ extern const struct xlat whence_codes[];
 #define STACKTRACE_INVALIDATE_CACHE 0400  /* Trigger proc/maps cache updating */
 #define STACKTRACE_CAPTURE_ON_ENTER 01000 /* Capture stacktrace on "entering" stage */
 #define TRACE_INDIRECT_SUBCALL 02000   /* Syscall is an indirect socket/ipc subcall. */
+#define COMPAT_SYSCALL_TYPES   04000   /* A compat syscall that uses compat types. */
 
 #define IOCTL_NUMBER_UNKNOWN 0
 #define IOCTL_NUMBER_HANDLED 1
index 5ba6afb0c51d07729ca5bde9a7f0f05f82584860..d3cb3d6a80cfe33028a916adfbc959a31d8c7654 100644 (file)
  * IA-32 syscalls that have pointer arguments which are incompatible
  * with 64-bit layout get redirected to printargs.
  */
-#undef SYS_FUNC_NAME
-#define SYS_FUNC_NAME(syscall_name) printargs
-#include "../i386/syscallent.h"
-#undef SYS_FUNC_NAME
-#define SYS_FUNC_NAME(syscall_name) MPERS_FUNC_NAME(syscall_name)
+#if CST > 0
+# undef SYS_FUNC_NAME
+# define SYS_FUNC_NAME(syscall_name) printargs
+# include "../i386/syscallent.h"
+# undef SYS_FUNC_NAME
+# define SYS_FUNC_NAME(syscall_name) MPERS_FUNC_NAME(syscall_name)
+#endif
 
 /* You must be careful to check ../i386/syscallent.h so that this table
    starts where that one leaves off.
 */
-[(SYS_ipc_subcall + SYS_ipc_nsubcalls) ... 1023] = { },
 [1024] = { 0,  0,              SEN(printargs),                 "ni_syscall"            },
 [1025] = { 1,  TP|SE,          SEN(exit),                      "exit"                  },
 [1026] = { 3,  TD,             SEN(read),                      "read"                  },
index 8749b9de37345d141fa04cfc83758f0c7c0cdfa7..107aa2bbc3259017feceb946dcaca8bc82444086 100644 (file)
  * x32-specific system call numbers start at 512 to avoid cache impact
  * for native 64-bit operation.
  */
-[512] = { 4,   TS,             SEN(rt_sigaction),              "rt_sigaction"          },
-[513] = { 0,   TS,             SEN(sigreturn),                 "rt_sigreturn"          },
-[514] = { 3,   TD,             SEN(ioctl),                     "ioctl"                 },
-[515] = { 3,   TD,             SEN(readv),                     "readv"                 },
-[516] = { 3,   TD,             SEN(writev),                    "writev"                },
-[517] = { 6,   TN,             SEN(recvfrom),                  "recvfrom"              },
-[518] = { 3,   TN,             SEN(sendmsg),                   "sendmsg"               },
-[519] = { 3,   TN,             SEN(recvmsg),                   "recvmsg"               },
-[520] = { 3,   TF|TP|SE|SI,    SEN(execve),                    "execve"                },
-[521] = { 4,   0,              SEN(ptrace),                    "ptrace"                },
-[522] = { 2,   TS,             SEN(rt_sigpending),             "rt_sigpending"         },
-[523] = { 4,   TS,             SEN(rt_sigtimedwait),           "rt_sigtimedwait"       },
-[524] = { 3,   TS,             SEN(rt_sigqueueinfo),           "rt_sigqueueinfo"       },
-[525] = { 2,   TS,             SEN(sigaltstack),               "sigaltstack"           },
-[526] = { 3,   0,              SEN(timer_create),              "timer_create"          },
-[527] = { 2,   0,              SEN(mq_notify),                 "mq_notify"             },
-[528] = { 4,   0,              SEN(kexec_load),                "kexec_load"            },
-[529] = { 5,   TP,             SEN(waitid),                    "waitid"                },
-[530] = { 2,   0,              SEN(set_robust_list),           "set_robust_list"       },
-[531] = { 3,   0,              SEN(get_robust_list),           "get_robust_list"       },
-[532] = { 4,   TD,             SEN(vmsplice),                  "vmsplice"              },
-[533] = { 6,   TM,             SEN(move_pages),                "move_pages"            },
+[512] = { 4,   CST|TS,         SEN(rt_sigaction),              "rt_sigaction"          },
+[513] = { 0,   CST|TS,         SEN(sigreturn),                 "rt_sigreturn"          },
+[514] = { 3,   CST|TD,         SEN(ioctl),                     "ioctl"                 },
+[515] = { 3,   CST|TD,         SEN(readv),                     "readv"                 },
+[516] = { 3,   CST|TD,         SEN(writev),                    "writev"                },
+[517] = { 6,   CST|TN,         SEN(recvfrom),                  "recvfrom"              },
+[518] = { 3,   CST|TN,         SEN(sendmsg),                   "sendmsg"               },
+[519] = { 3,   CST|TN,         SEN(recvmsg),                   "recvmsg"               },
+[520] = { 3,   CST|TF|TP|SE|SI,SEN(execve),                    "execve"                },
+[521] = { 4,   CST,            SEN(ptrace),                    "ptrace"                },
+[522] = { 2,   CST|TS,         SEN(rt_sigpending),             "rt_sigpending"         },
+[523] = { 4,   CST|TS,         SEN(rt_sigtimedwait),           "rt_sigtimedwait"       },
+[524] = { 3,   CST|TS,         SEN(rt_sigqueueinfo),           "rt_sigqueueinfo"       },
+[525] = { 2,   CST|TS,         SEN(sigaltstack),               "sigaltstack"           },
+[526] = { 3,   CST,            SEN(timer_create),              "timer_create"          },
+[527] = { 2,   CST,            SEN(mq_notify),                 "mq_notify"             },
+[528] = { 4,   CST,            SEN(kexec_load),                "kexec_load"            },
+[529] = { 5,   CST|TP,         SEN(waitid),                    "waitid"                },
+[530] = { 2,   CST,            SEN(set_robust_list),           "set_robust_list"       },
+[531] = { 3,   CST,            SEN(get_robust_list),           "get_robust_list"       },
+[532] = { 4,   CST|TD,         SEN(vmsplice),                  "vmsplice"              },
+[533] = { 6,   CST|TM,         SEN(move_pages),                "move_pages"            },
 [534] = { 4,   TD,             SEN(preadv),                    "preadv"                },
 [535] = { 4,   TD,             SEN(pwritev),                   "pwritev"               },
-[536] = { 4,   TP|TS,          SEN(rt_tgsigqueueinfo),         "rt_tgsigqueueinfo"     },
-[537] = { 5,   TN,             SEN(recvmmsg),                  "recvmmsg"              },
-[538] = { 4,   TN,             SEN(sendmmsg),                  "sendmmsg"              },
-[539] = { 6,   0,              SEN(process_vm_readv),          "process_vm_readv"      },
-[540] = { 6,   0,              SEN(process_vm_writev),         "process_vm_writev"     },
-[541] = { 5,   TN,             SEN(setsockopt),                "setsockopt"            },
-[542] = { 5,   TN,             SEN(getsockopt),                "getsockopt"            },
-[543] = { 2,   TM,             SEN(io_setup),                  "io_setup"              },
-[544] = { 3,   0,              SEN(io_submit),                 "io_submit"             },
-[545] = { 5,   TD|TF|TP|SE|SI, SEN(execveat),                  "execveat",             },
+[536] = { 4,   CST|TP|TS,      SEN(rt_tgsigqueueinfo),         "rt_tgsigqueueinfo"     },
+[537] = { 5,   CST|TN,         SEN(recvmmsg),                  "recvmmsg"              },
+[538] = { 4,   CST|TN,         SEN(sendmmsg),                  "sendmmsg"              },
+[539] = { 6,   CST,            SEN(process_vm_readv),          "process_vm_readv"      },
+[540] = { 6,   CST,            SEN(process_vm_writev),         "process_vm_writev"     },
+[541] = { 5,   CST|TN,         SEN(setsockopt),                "setsockopt"            },
+[542] = { 5,   CST|TN,         SEN(getsockopt),                "getsockopt"            },
+[543] = { 2,   CST|TM,         SEN(io_setup),                  "io_setup"              },
+[544] = { 3,   CST,            SEN(io_submit),                 "io_submit"             },
+[545] = { 5,   CST|TD|TF|TP|SE|SI,     SEN(execveat),          "execveat",             },
 [546] = { 6,   TD,             SEN(preadv2),                   "preadv2"               },
 [547] = { 6,   TD,             SEN(pwritev2),                  "pwritev2"              },
index fa591fb63f085d4231b4424d5b8e01d4ee166a9d..51d03f5df2f6a6fce30f6efd995a554969330dc4 100644 (file)
@@ -4,32 +4,56 @@ get_syscall_args(struct tcb *tcp)
 {
        if (x86_io.iov_len != sizeof(i386_regs)) {
                /* x86-64 or x32 ABI */
-               tcp->u_arg[0] = x86_64_regs.rdi;
-               tcp->u_arg[1] = x86_64_regs.rsi;
-               tcp->u_arg[2] = x86_64_regs.rdx;
-               tcp->u_arg[3] = x86_64_regs.r10;
-               tcp->u_arg[4] = x86_64_regs.r8;
-               tcp->u_arg[5] = x86_64_regs.r9;
+               if (tcp->s_ent->sys_flags & COMPAT_SYSCALL_TYPES) {
+                       /*
+                        * X32 compat syscall: zero-extend from 32 bits.
+                        * Use widen_to_long(tcp->u_arg[N]) in syscall handlers
+                        * if you need to use *sign-extended* parameter.
+                        */
 #ifdef X32
-               tcp->ext_arg[0] = x86_64_regs.rdi;
-               tcp->ext_arg[1] = x86_64_regs.rsi;
-               tcp->ext_arg[2] = x86_64_regs.rdx;
-               tcp->ext_arg[3] = x86_64_regs.r10;
-               tcp->ext_arg[4] = x86_64_regs.r8;
-               tcp->ext_arg[5] = x86_64_regs.r9;
+                       tcp->u_arg[0] = tcp->ext_arg[0] = (uint32_t) x86_64_regs.rdi;
+                       tcp->u_arg[1] = tcp->ext_arg[1] = (uint32_t) x86_64_regs.rsi;
+                       tcp->u_arg[2] = tcp->ext_arg[2] = (uint32_t) x86_64_regs.rdx;
+                       tcp->u_arg[3] = tcp->ext_arg[3] = (uint32_t) x86_64_regs.r10;
+                       tcp->u_arg[4] = tcp->ext_arg[4] = (uint32_t) x86_64_regs.r8;
+                       tcp->u_arg[5] = tcp->ext_arg[5] = (uint32_t) x86_64_regs.r9;
+#else
+                       tcp->u_arg[0] = (uint32_t) x86_64_regs.rdi;
+                       tcp->u_arg[1] = (uint32_t) x86_64_regs.rsi;
+                       tcp->u_arg[2] = (uint32_t) x86_64_regs.rdx;
+                       tcp->u_arg[3] = (uint32_t) x86_64_regs.r10;
+                       tcp->u_arg[4] = (uint32_t) x86_64_regs.r8;
+                       tcp->u_arg[5] = (uint32_t) x86_64_regs.r9;
 #endif
+               } else {
+#ifdef X32
+                       tcp->u_arg[0] = tcp->ext_arg[0] = x86_64_regs.rdi;
+                       tcp->u_arg[1] = tcp->ext_arg[1] = x86_64_regs.rsi;
+                       tcp->u_arg[2] = tcp->ext_arg[2] = x86_64_regs.rdx;
+                       tcp->u_arg[3] = tcp->ext_arg[3] = x86_64_regs.r10;
+                       tcp->u_arg[4] = tcp->ext_arg[4] = x86_64_regs.r8;
+                       tcp->u_arg[5] = tcp->ext_arg[5] = x86_64_regs.r9;
+#else
+                       tcp->u_arg[0] = x86_64_regs.rdi;
+                       tcp->u_arg[1] = x86_64_regs.rsi;
+                       tcp->u_arg[2] = x86_64_regs.rdx;
+                       tcp->u_arg[3] = x86_64_regs.r10;
+                       tcp->u_arg[4] = x86_64_regs.r8;
+                       tcp->u_arg[5] = x86_64_regs.r9;
+#endif
+               }
        } else {
-               /* i386 ABI */
-               /* Zero-extend from 32 bits */
-               /* Use widen_to_long(tcp->u_arg[N]) in syscall handlers
+               /*
+                * i386 ABI: zero-extend from 32 bits.
+                * Use widen_to_long(tcp->u_arg[N]) in syscall handlers
                 * if you need to use *sign-extended* parameter.
                 */
-               tcp->u_arg[0] = (long)(uint32_t)i386_regs.ebx;
-               tcp->u_arg[1] = (long)(uint32_t)i386_regs.ecx;
-               tcp->u_arg[2] = (long)(uint32_t)i386_regs.edx;
-               tcp->u_arg[3] = (long)(uint32_t)i386_regs.esi;
-               tcp->u_arg[4] = (long)(uint32_t)i386_regs.edi;
-               tcp->u_arg[5] = (long)(uint32_t)i386_regs.ebp;
+               tcp->u_arg[0] = (uint32_t) i386_regs.ebx;
+               tcp->u_arg[1] = (uint32_t) i386_regs.ecx;
+               tcp->u_arg[2] = (uint32_t) i386_regs.edx;
+               tcp->u_arg[3] = (uint32_t) i386_regs.esi;
+               tcp->u_arg[4] = (uint32_t) i386_regs.edi;
+               tcp->u_arg[5] = (uint32_t) i386_regs.ebp;
        }
        return 1;
 }
index e3924c58890ae85e20536b43cbd6c4147c976621..c27c669da6a012dd907f7ba7341eb920c00fd741 100644 (file)
--- a/syscall.c
+++ b/syscall.c
@@ -82,6 +82,7 @@
 #define MA MAX_ARGS
 #define SI STACKTRACE_INVALIDATE_CACHE
 #define SE STACKTRACE_CAPTURE_ON_ENTER
+#define CST COMPAT_SYSCALL_TYPES
 
 #define SEN(syscall_name) SEN_ ## syscall_name, SYS_FUNC_NAME(sys_ ## syscall_name)
 
@@ -116,6 +117,7 @@ static const struct_sysent sysent2[] = {
 #undef MA
 #undef SI
 #undef SE
+#undef CST
 
 /*
  * `ioctlent[012].h' files are automatically generated by the auxiliary
index 66b4ffb4115b0ec8b0635c73c7d0049e14ca5c4f..9b7bf49b2a71f04f07a285bb86e320aafa031e3d 100644 (file)
@@ -39,6 +39,7 @@
 #define MA 0
 #define SI 0
 #define SE 0
+#define CST 0
 #define SEN(arg) 0,0
 
 static const struct_sysent syscallent[] = {
index 9c8b30a71f958fc804472a10425244b13423ed5c..9a4d72affdf93d9d21f047a64033b650b6ee9b85 100644 (file)
@@ -41,6 +41,7 @@
 #define MA 0
 #define SI 0
 #define SE 0
+#define CST 0
 #define SEN(arg) 0,0
 
 static const struct_sysent syscallent[] = {