From: Paul Floyd Date: Fri, 6 Jan 2023 20:27:01 +0000 (+0100) Subject: BugĀ 433873 - openat2 syscall unimplemented on Linux X-Git-Tag: VALGRIND_3_21_0~237 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c93baf53a652fd503c0c21bccb7e85363f43e58;p=thirdparty%2Fvalgrind.git BugĀ 433873 - openat2 syscall unimplemented on Linux This syscall is not exposed via glibc, so there is only an addition to the scalar test. --- diff --git a/NEWS b/NEWS index 27fe0df194..3f9e2987de 100644 --- a/NEWS +++ b/NEWS @@ -44,6 +44,7 @@ are not entered into bugzilla tend to get forgotten about or ignored. 351857 confusing error message about valid command line option 392331 Spurious lock not held error from inside pthread_cond_timedwait 400793 pthread_rwlock_timedwrlock false positive +433873 openat2 syscall unimplemented on Linux 444110 priv/guest_ppc_toIR.c:36198:31: warning: duplicated 'if' condition. 444488 Use glibc.pthread.stack_cache_size tunable 444568 drd/tests/pth_barrier_thr_cr fails on Fedora 38 diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h index d929caf5ed..4f85069476 100644 --- a/coregrind/m_syswrap/priv_syswrap-linux.h +++ b/coregrind/m_syswrap/priv_syswrap-linux.h @@ -322,6 +322,7 @@ DECL_TEMPLATE(linux, sys_io_uring_register); // Linux-specific (new in Linux 5.9) DECL_TEMPLATE(linux, sys_close_range); +DECL_TEMPLATE(linux, sys_openat2); // Linux-specific (new in Linux 5.14) DECL_TEMPLATE(linux, sys_memfd_secret); diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c index 430907c49e..9054199857 100644 --- a/coregrind/m_syswrap/syswrap-amd64-linux.c +++ b/coregrind/m_syswrap/syswrap-amd64-linux.c @@ -878,6 +878,7 @@ static SyscallTableEntry syscall_table[] = { GENX_(__NR_clone3, sys_ni_syscall), // 435 LINXY(__NR_close_range, sys_close_range), // 436 + LINXY(__NR_openat2, sys_openat2), // 437 LINX_(__NR_faccessat2, sys_faccessat2), // 439 diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c index 35724660e5..bb87c90bab 100644 --- a/coregrind/m_syswrap/syswrap-linux.c +++ b/coregrind/m_syswrap/syswrap-linux.c @@ -13434,6 +13434,121 @@ POST(sys_close_range) ML_(record_fd_close)(fd); } + +#define VKI_O_DIRECTORY 00200000 +#define VKI___O_TMPFILE 020000000 +#define VKI_O_TMPFILE (VKI___O_TMPFILE | VKI_O_DIRECTORY) + +// long syscall(SYS_openat2, int dirfd, const char *pathname, +// struct open_how *how, size_t size); +PRE(sys_openat2) +{ + HChar name[30]; // large enough + SysRes sres; + struct vki_open_how * how; + + PRINT("sys_openat2 ( %ld, %#" FMT_REGWORD "x(%s), %#" FMT_REGWORD "x, %ld )", + SARG1, ARG2, (HChar*)(Addr)ARG2, ARG3, SARG4); + PRE_REG_READ4(long, "openat2", + int, dfd, const char *, filename, struct vki_open_how *, how, vki_size_t, size); + + PRE_MEM_RASCIIZ( "openat2(filename)", ARG2 ); + PRE_MEM_READ( "openat2(how)", ARG3, sizeof(struct vki_open_how)); + + /* For absolute filenames, dfd is ignored. If dfd is AT_FDCWD, + filename is relative to cwd. When comparing dfd against AT_FDCWD, + be sure only to compare the bottom 32 bits. */ + if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 ) + && *(Char *)(Addr)ARG2 != '/' + && ((Int)ARG1) != ((Int)VKI_AT_FDCWD) + && !ML_(fd_allowed)(ARG1, "openat2", tid, False)) + SET_STATUS_Failure( VKI_EBADF ); + + how = (struct vki_open_how *)ARG3; + + if (how && ML_(safe_to_deref) (how, sizeof(struct vki_open_how))) { + if (how->vki_mode) { + if (!(how->vki_flags & ((vki_uint64_t)VKI_O_CREAT | VKI_O_TMPFILE))) { + SET_STATUS_Failure( VKI_EINVAL ); + } + } + if (how->vki_resolve & ~((vki_uint64_t)VKI_RESOLVE_NO_XDEV | + VKI_RESOLVE_NO_MAGICLINKS | + VKI_RESOLVE_NO_SYMLINKS | + VKI_RESOLVE_BENEATH | + VKI_RESOLVE_IN_ROOT | + VKI_RESOLVE_CACHED)) { + SET_STATUS_Failure( VKI_EINVAL ); + } + } + + /* Handle the case where the open is of /proc/self/cmdline or + /proc//cmdline, and just give it a copy of the fd for the + fake file we cooked up at startup (in m_main). Also, seek the + cloned fd back to the start. */ + + VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)()); + if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 ) + && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0 + || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/cmdline") == 0)) { + sres = VG_(dup)( VG_(cl_cmdline_fd) ); + SET_STATUS_from_SysRes( sres ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); + if (off < 0) + SET_STATUS_Failure( VKI_EMFILE ); + } + return; + } + + /* Do the same for /proc/self/auxv or /proc//auxv case. */ + + VG_(sprintf)(name, "/proc/%d/auxv", VG_(getpid)()); + if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 ) + && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0 + || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/auxv") == 0)) { + sres = VG_(dup)( VG_(cl_auxv_fd) ); + SET_STATUS_from_SysRes( sres ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); + if (off < 0) + SET_STATUS_Failure( VKI_EMFILE ); + } + return; + } + + /* And for /proc/self/exe or /proc//exe case. */ + + VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)()); + if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 ) + && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0 + || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/exe") == 0)) { + sres = VG_(dup)( VG_(cl_exec_fd) ); + SET_STATUS_from_SysRes( sres ); + if (!sr_isError(sres)) { + OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET ); + if (off < 0) + SET_STATUS_Failure( VKI_EMFILE ); + } + return; + } + + /* Otherwise handle normally */ + *flags |= SfMayBlock; +} + +POST(sys_openat2) +{ + vg_assert(SUCCESS); + if (!ML_(fd_allowed)(RES, "openat2", tid, True)) { + VG_(close)(RES); + SET_STATUS_Failure( VKI_EMFILE ); + } else { + if (VG_(clo_track_fds)) + ML_(record_fd_open_with_given_name)(tid, RES, (HChar*)(Addr)ARG2); + } +} + #undef PRE #undef POST diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c index 120cefc77a..5968d49dbf 100644 --- a/coregrind/m_syswrap/syswrap-x86-linux.c +++ b/coregrind/m_syswrap/syswrap-x86-linux.c @@ -1649,6 +1649,8 @@ static SyscallTableEntry syscall_table[] = { GENX_(__NR_clone3, sys_ni_syscall), // 435 LINXY(__NR_close_range, sys_close_range), // 436 + LINXY(__NR_openat2, sys_openat2), // 437 + LINX_(__NR_faccessat2, sys_faccessat2), // 439 diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h index 905c3ba36e..c963837015 100644 --- a/include/vki/vki-linux.h +++ b/include/vki/vki-linux.h @@ -5375,6 +5375,21 @@ struct vki_itimerspec64 { struct vki_timespec it_value; }; +/* From include/linux/openat2.h */ + +struct vki_open_how { + vki_uint64_t vki_flags; + vki_uint64_t vki_mode; + vki_uint64_t vki_resolve; +}; + +#define VKI_RESOLVE_NO_XDEV 0x01 +#define VKI_RESOLVE_NO_MAGICLINKS 0x02 +#define VKI_RESOLVE_NO_SYMLINKS 0x04 +#define VKI_RESOLVE_BENEATH 0x08 +#define VKI_RESOLVE_IN_ROOT 0x10 +#define VKI_RESOLVE_CACHED 0x20 + #ifndef VKI_RLIM_INFINITY #define VKI_RLIM_INFINITY (~0UL) #endif diff --git a/include/vki/vki-scnums-shared-linux.h b/include/vki/vki-scnums-shared-linux.h index f591611f6d..048460d0b2 100644 --- a/include/vki/vki-scnums-shared-linux.h +++ b/include/vki/vki-scnums-shared-linux.h @@ -41,6 +41,7 @@ #define __NR_clone3 435 #define __NR_close_range 436 +#define __NR_openat2 437 #define __NR_faccessat2 439 diff --git a/memcheck/tests/x86-linux/scalar.c b/memcheck/tests/x86-linux/scalar.c index 54d0e0443a..58b042ab77 100644 --- a/memcheck/tests/x86-linux/scalar.c +++ b/memcheck/tests/x86-linux/scalar.c @@ -1276,6 +1276,10 @@ int main(void) GO(__NR_epoll_create1, "1s 0m"); SY(__NR_epoll_create1, x0); SUCC_OR_FAIL; + // __NR_openat2 337 + GO(__NR_openat2, "4s 2m"); + SY(__NR_openat2, x0, x0+1, x0+1, x0); FAIL; + // __NR_process_vm_readv 347 GO(__NR_process_vm_readv, "6s 2m"); SY(__NR_process_vm_readv, x0, x0, x0+1, x0, x0+1, x0); FAIL; diff --git a/memcheck/tests/x86-linux/scalar.stderr.exp b/memcheck/tests/x86-linux/scalar.stderr.exp index b9202a8c2f..b12ca0cf41 100644 --- a/memcheck/tests/x86-linux/scalar.stderr.exp +++ b/memcheck/tests/x86-linux/scalar.stderr.exp @@ -4145,41 +4145,70 @@ Syscall param epoll_create1(flags) contains uninitialised byte(s) ... by 0x........: main (scalar.c:1277) +----------------------------------------------------- +437: __NR_openat2 4s 2m +----------------------------------------------------- +Syscall param openat2(dfd) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c:1281) + +Syscall param openat2(filename) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c:1281) + +Syscall param openat2(how) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c:1281) + +Syscall param openat2(size) contains uninitialised byte(s) + ... + by 0x........: main (scalar.c:1281) + +Syscall param openat2(filename) points to unaddressable byte(s) + ... + by 0x........: main (scalar.c:1281) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + +Syscall param openat2(how) points to unaddressable byte(s) + ... + by 0x........: main (scalar.c:1281) + Address 0x........ is not stack'd, malloc'd or (recently) free'd + ----------------------------------------------------- 347:__NR_process_vm_readv 6s 2m ----------------------------------------------------- Syscall param process_vm_readv(pid) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(lvec) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(liovcnt) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(rvec) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(riovcnt) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(flags) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Syscall param process_vm_readv(lvec) points to unaddressable byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Address 0x........ is not stack'd, malloc'd or (recently) free'd Syscall param process_vm_readv(rvec) points to unaddressable byte(s) ... - by 0x........: main (scalar.c:1281) + by 0x........: main (scalar.c:1285) Address 0x........ is not stack'd, malloc'd or (recently) free'd ----------------------------------------------------- @@ -4187,36 +4216,36 @@ Syscall param process_vm_readv(rvec) points to unaddressable byte(s) ----------------------------------------------------- Syscall param process_vm_writev(pid) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(lvec) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(liovcnt) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(rvec) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(riovcnt) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(flags) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Syscall param process_vm_writev(lvec) points to unaddressable byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Address 0x........ is not stack'd, malloc'd or (recently) free'd Syscall param process_vm_writev(rvec) points to unaddressable byte(s) ... - by 0x........: main (scalar.c:1285) + by 0x........: main (scalar.c:1289) Address 0x........ is not stack'd, malloc'd or (recently) free'd ----------------------------------------------------- @@ -4232,5 +4261,5 @@ it at http://valgrind.org/support/bug_reports.html. ----------------------------------------------------- Syscall param exit(status) contains uninitialised byte(s) ... - by 0x........: main (scalar.c:1293) + by 0x........: main (scalar.c:1297)