]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
BugĀ 433873 - openat2 syscall unimplemented on Linux
authorPaul Floyd <pjfloyd@wanadoo.fr>
Fri, 6 Jan 2023 20:27:01 +0000 (21:27 +0100)
committerPaul Floyd <pjfloyd@wanadoo.fr>
Fri, 6 Jan 2023 20:27:01 +0000 (21:27 +0100)
This syscall is not exposed via glibc, so there is only an
addition to the scalar test.

NEWS
coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-x86-linux.c
include/vki/vki-linux.h
include/vki/vki-scnums-shared-linux.h
memcheck/tests/x86-linux/scalar.c
memcheck/tests/x86-linux/scalar.stderr.exp

diff --git a/NEWS b/NEWS
index 27fe0df19480118296d5bf576d6131ef9b0077f0..3f9e2987de5ded32bd3a445bd98f6703470f222f 100644 (file)
--- 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
index d929caf5edd0dc4b728db9915c75a459b6c5fd2e..4f85069476700d3806b0d3fd923dd57a7924e00f 100644 (file)
@@ -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);
index 430907c49ebc54c381b122d3e17e9d420ee0b961..9054199857a430b1ad3611d95115d28f2f9224c8 100644 (file)
@@ -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
 
index 35724660e5d42e4e5cddc22b715907bc8754f3ea..bb87c90bab5e62b22662f9c58ab8ac31e1598112 100644 (file)
@@ -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/<pid>/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/<pid>/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/<pid>/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
 
index 120cefc77a3d840ed1b50535e524a8b179bdc2f5..5968d49dbfb6f69da80a9bd390eb6ddaa0574ffd 100644 (file)
@@ -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
 
index 905c3ba36e4f88c23958c2b03eedbf079edfbe7a..c9638370152fd0feba52e2b8f074c779dff307a7 100644 (file)
@@ -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
index f591611f6dff65d6be4c84e372322539b6ca1e9a..048460d0b280990dc5c561060cd241306d633335 100644 (file)
@@ -41,6 +41,7 @@
 
 #define __NR_clone3            435
 #define __NR_close_range       436
+#define __NR_openat2        437
 
 #define __NR_faccessat2                439
 
index 54d0e0443ae2c77197fee16f42a2557aef6ac5b0..58b042ab77869b799e63e00d9c0fd2bf0affa638 100644 (file)
@@ -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;
index b9202a8c2f9cacf8c8812671584c3b2aa599d6f5..b12ca0cf41adb06ff217f5f536c1b223714f1bb9 100644 (file)
@@ -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)