From: Philippe Waroquiers Date: Sat, 11 Aug 2018 13:56:56 +0000 (+0200) Subject: Fix 392118 - unhandled amd64-linux syscall: 332 (statx) X-Git-Tag: VALGRIND_3_14_0~62 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8bc2b6fd26070f9f4d3f067910eb3e3b5e662fd7;p=thirdparty%2Fvalgrind.git Fix 392118 - unhandled amd64-linux syscall: 332 (statx) Code patch provided by Mattias Andrée Added a regression test to (somewhat) test stat and statx. Tested on amd64 only. --- diff --git a/.gitignore b/.gitignore index 72b7c3d46b..fc22c94425 100644 --- a/.gitignore +++ b/.gitignore @@ -1090,6 +1090,7 @@ /memcheck/tests/linux/stack_changes /memcheck/tests/linux/stack_switch /memcheck/tests/linux/syscalls-2007 +/memcheck/tests/linux/sys-statx /memcheck/tests/linux/syslog-syscall /memcheck/tests/linux/timerfd-syscall /memcheck/tests/linux/proc-auxv diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h index 65704cd605..296ef6599d 100644 --- a/coregrind/m_syswrap/priv_syswrap-linux.h +++ b/coregrind/m_syswrap/priv_syswrap-linux.h @@ -295,6 +295,9 @@ DECL_TEMPLATE(linux, sys_syncfs); DECL_TEMPLATE(linux, sys_membarrier); +// Linux-specific (new in Linux 4.11) +DECL_TEMPLATE(linux, sys_statx); + /* --------------------------------------------------------------------- Wrappers for sockets and ipc-ery. These are split into standalone procedures because x86-linux hides them inside multiplexors diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 407af7f76d..9255e7bad8 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -846,7 +846,10 @@ static SyscallTableEntry syscall_table[] = { LINXY(__NR_memfd_create, sys_memfd_create), // 319 // LIN__(__NR_kexec_file_load, sys_ni_syscall), // 320 -// LIN__(__NR_bpf, sys_ni_syscall) // 321 +// LIN__(__NR_bpf, sys_ni_syscall), // 321 + + + LINXY(__NR_statx, sys_statx), // 332 LINX_(__NR_membarrier, sys_membarrier), // 324 }; diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c index 4ae4e891d2..9f1bdab5f0 100644 --- a/coregrind/m_syswrap/syswrap-arm-linux.c +++ b/coregrind/m_syswrap/syswrap-arm-linux.c @@ -1014,7 +1014,9 @@ static SyscallTableEntry syscall_main_table[] = { LINX_(__NR_renameat2, sys_renameat2), // 382 LINXY(__NR_getrandom, sys_getrandom), // 384 - LINXY(__NR_memfd_create, sys_memfd_create) // 385 + LINXY(__NR_memfd_create, sys_memfd_create), // 385 + + LINXY(__NR_statx, sys_statx), // 397 }; diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c index 24a6493c60..9ef54b40a2 100644 --- a/coregrind/m_syswrap/syswrap-arm64-linux.c +++ b/coregrind/m_syswrap/syswrap-arm64-linux.c @@ -821,6 +821,8 @@ static SyscallTableEntry syscall_main_table[] = { // (__NR_pkey_mprotect, sys_ni_syscall), // 288 // (__NR_pkey_alloc, sys_ni_syscall), // 289 // (__NR_pkey_free, sys_ni_syscall), // 290 + + LINXY(__NR_statx, sys_statx), // 397 }; diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 2336c29784..bd7d447762 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -3659,6 +3659,22 @@ PRE(sys_syncfs) PRE_REG_READ1(long, "syncfs", unsigned int, fd); } +PRE(sys_statx) +{ + FUSE_COMPATIBLE_MAY_BLOCK(); + PRINT("sys_statx ( %ld, %#" FMT_REGWORD "x(%s), %ld, %ld, %#" FMT_REGWORD "x )", + ARG1,ARG2,(char*)(Addr)ARG2,ARG3,ARG4,ARG5); + PRE_REG_READ5(long, "statx", + int, dirfd, char *, file_name, int, flags, + unsigned int, mask, struct statx *, buf); + PRE_MEM_RASCIIZ( "statx(file_name)", ARG2 ); + PRE_MEM_WRITE( "statx(buf)", ARG5, sizeof(struct vki_statx) ); +} +POST(sys_statx) +{ + POST_MEM_WRITE( ARG5, sizeof(struct vki_statx) ); +} + /* --------------------------------------------------------------------- utime wrapper ------------------------------------------------------------------ */ diff --git a/coregrind/m_syswrap/syswrap-mips32-linux.c b/coregrind/m_syswrap/syswrap-mips32-linux.c index c754987fd3..89cf126a7b 100644 --- a/coregrind/m_syswrap/syswrap-mips32-linux.c +++ b/coregrind/m_syswrap/syswrap-mips32-linux.c @@ -1065,6 +1065,8 @@ static SyscallTableEntry syscall_main_table[] = { LINXY(__NR_memfd_create, sys_memfd_create), // 354 //.. LINX_(__NR_membarrier, sys_membarrier), // 358 + //.. + LINXY(__NR_statx, sys_statx) // 366 }; SyscallTableEntry* ML_(get_linux_syscall_entry) (UInt sysno) diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c index d1506028c2..f812f1f6cb 100644 --- a/coregrind/m_syswrap/syswrap-ppc32-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c @@ -1019,7 +1019,9 @@ static SyscallTableEntry syscall_table[] = { LINX_(__NR_process_vm_writev, sys_process_vm_writev),// 352 LINXY(__NR_getrandom, sys_getrandom), // 359 - LINXY(__NR_memfd_create, sys_memfd_create) // 360 + LINXY(__NR_memfd_create, sys_memfd_create), // 360 + + LINXY(__NR_statx, sys_statx), // 383 }; SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno ) diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c index 46bb317783..2d699a4ed9 100644 --- a/coregrind/m_syswrap/syswrap-ppc64-linux.c +++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c @@ -937,7 +937,9 @@ static SyscallTableEntry syscall_table[] = { LINX_(__NR_renameat2, sys_renameat2), // 357 LINXY(__NR_getrandom, sys_getrandom), // 359 - LINXY(__NR_memfd_create, sys_memfd_create) // 360 + LINXY(__NR_memfd_create, sys_memfd_create), // 360 + + LINXY(__NR_statx, sys_statx), // 383 }; SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno ) diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 11bb13d894..ea4f354195 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -1606,6 +1606,8 @@ static SyscallTableEntry syscall_table[] = { LINXY(__NR_recvmsg, sys_recvmsg), // 372 LINX_(__NR_shutdown, sys_shutdown), // 373 + LINXY(__NR_statx, sys_statx), // 383 + /* Explicitly not supported on i386 yet. */ GENX_(__NR_arch_prctl, sys_ni_syscall) // 384 }; diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 707208040c..1beeebba11 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -1381,6 +1381,44 @@ struct vki_robust_list_head { #define VKI_S_IWOTH 00002 #define VKI_S_IXOTH 00001 +struct vki_statx_timestamp { + __vki_s64 tv_sec; + __vki_u32 tv_nsec; + __vki_s32 __reserved; +}; + +struct vki_statx { + /* 0x00 */ + __vki_u32 stx_mask; /* What results were written [uncond] */ + __vki_u32 stx_blksize; /* Preferred general I/O size [uncond] */ + __vki_u64 stx_attributes; /* Flags conveying information about the file [uncond] */ + /* 0x10 */ + __vki_u32 stx_nlink; /* Number of hard links */ + __vki_u32 stx_uid; /* User ID of owner */ + __vki_u32 stx_gid; /* Group ID of owner */ + __vki_u16 stx_mode; /* File mode */ + __vki_u16 __spare0[1]; + /* 0x20 */ + __vki_u64 stx_ino; /* Inode number */ + __vki_u64 stx_size; /* File size */ + __vki_u64 stx_blocks; /* Number of 512-byte blocks allocated */ + __vki_u64 stx_attributes_mask; /* Mask to show what's supported in stx_attributes */ + /* 0x40 */ + struct vki_statx_timestamp stx_atime; /* Last access time */ + struct vki_statx_timestamp stx_btime; /* File creation time */ + struct vki_statx_timestamp stx_ctime; /* Last attribute change time */ + struct vki_statx_timestamp stx_mtime; /* Last data modification time */ + /* 0x80 */ + __vki_u32 stx_rdev_major; /* Device ID of special file [if bdev/cdev] */ + __vki_u32 stx_rdev_minor; + __vki_u32 stx_dev_major; /* ID of device containing file [uncond] */ + __vki_u32 stx_dev_minor; + /* 0x90 */ + __vki_u64 __spare2[14]; /* Spare space for future expansion */ + /* 0x100 */ +}; + + //---------------------------------------------------------------------- // From linux-2.6.8.1/include/linux/dirent.h //---------------------------------------------------------------------- diff --git a/memcheck/tests/linux/Makefile.am b/memcheck/tests/linux/Makefile.am index 5f49a3fe22..d7515d9c75 100644 --- a/memcheck/tests/linux/Makefile.am +++ b/memcheck/tests/linux/Makefile.am @@ -21,6 +21,7 @@ EXTRA_DIST = \ syscalls-2007.vgtest syscalls-2007.stderr.exp \ syslog-syscall.vgtest syslog-syscall.stderr.exp \ sys-openat.vgtest sys-openat.stderr.exp sys-openat.stdout.exp \ + sys-statx.vgtest sys-statx.stderr.exp \ timerfd-syscall.vgtest timerfd-syscall.stderr.exp \ with-space.stderr.exp with-space.stdout.exp with-space.vgtest \ proc-auxv.vgtest proc-auxv.stderr.exp getregset.vgtest \ @@ -40,6 +41,7 @@ check_PROGRAMS = \ stack_switch \ syscalls-2007 \ syslog-syscall \ + sys-statx \ timerfd-syscall \ proc-auxv diff --git a/memcheck/tests/linux/sys-statx.c b/memcheck/tests/linux/sys-statx.c new file mode 100644 index 0000000000..7b6ee34d53 --- /dev/null +++ b/memcheck/tests/linux/sys-statx.c @@ -0,0 +1,56 @@ +/* Test (somewhat) stats and stat. */ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int check_stat2; + +#define field(fieldname,s) s->st_##fieldname +#if defined(__NR_statx) +#define checkfield(fieldname) \ + assert(!check_stat2 || stat1.st_##fieldname == stat2.stx_##fieldname) +#else +#define checkfield(fieldname) \ + assert(!check_stat2 || stat1.st_##fieldname == stat2.st_##fieldname) +#endif + +int main (void) +{ + struct stat stat1; + + memset(&stat1, 0x55, sizeof(stat1)); + + assert (stat ("/tmp", &stat1) == 0); +#if defined(__NR_statx) + struct statx stat2; + memset(&stat2, 0x22, sizeof(stat2)); + if (syscall (__NR_statx, 0, "/tmp", 0, STATX_ALL, &stat2) == 0) + check_stat2 = 1; + else { + if (errno == ENOSYS) + check_stat2 = 0; // Defined but not provided by kernel. + else + check_stat2 = 1; // Probably better fail ... + } +#else + struct stat stat2; + check_stat2 = 1; + memset(&stat2, 0x22, sizeof(stat2)); + assert (stat ("/tmp", &stat2) == 0); +#endif + + checkfield(nlink); + checkfield(uid); + checkfield(gid); + checkfield(mode); + checkfield(ino); + + return 0; +} diff --git a/memcheck/tests/linux/sys-statx.stderr.exp b/memcheck/tests/linux/sys-statx.stderr.exp new file mode 100644 index 0000000000..c22dd7f4c0 --- /dev/null +++ b/memcheck/tests/linux/sys-statx.stderr.exp @@ -0,0 +1,10 @@ + + +HEAP SUMMARY: + in use at exit: 0 bytes in 0 blocks + total heap usage: 0 allocs, 0 frees, 0 bytes allocated + +For a detailed leak analysis, rerun with: --leak-check=full + +For counts of detected and suppressed errors, rerun with: -v +ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) diff --git a/memcheck/tests/linux/sys-statx.vgtest b/memcheck/tests/linux/sys-statx.vgtest new file mode 100644 index 0000000000..e4864ac689 --- /dev/null +++ b/memcheck/tests/linux/sys-statx.vgtest @@ -0,0 +1 @@ +prog: sys-statx