]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Add support for the copy_file_range syscall
authorAlexandra Hajkova <ahajkova@redhat.com>
Thu, 2 May 2019 12:24:02 +0000 (08:24 -0400)
committerMark Wielaard <mark@klomp.org>
Sun, 5 May 2019 13:27:13 +0000 (15:27 +0200)
Support amd64, x86, arm64, ppc64, ppc32 and s390x architectures.
Also add sys-copy_file_range test case.

14 files changed:
NEWS
configure.ac
coregrind/m_syswrap/priv_syswrap-linux.h
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-arm64-linux.c
coregrind/m_syswrap/syswrap-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-ppc64-linux.c
coregrind/m_syswrap/syswrap-s390x-linux.c
coregrind/m_syswrap/syswrap-x86-linux.c
memcheck/tests/linux/Makefile.am
memcheck/tests/linux/sys-copy_file_range.c [new file with mode: 0644]
memcheck/tests/linux/sys-copy_file_range.stderr.exp [new file with mode: 0644]
memcheck/tests/linux/sys-copy_file_range.vgtest [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 4b5e044ff8a6a68ea70848b0c4d0403444410b0d..5cbf336b3bc1222e6eead1c050b727dac2ff3626 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -41,6 +41,7 @@ To see details of a given bug, visit
 where XXXXXX is the bug number as listed below.
 
 406561  mcinfcallWSRU gdbserver_test fails on ppc64
+407218  Add support for the copy_file_range syscall
 n-i-bz  Fix minor one time leaks in dhat.
 n-i-bz  Add --run-cxx-freeres=no in outer args to avoid inner crashes.
 
index d043ce346443aae6efdd22eca2077ce53c6c0977..352892565e04ebd9e7c985631bccc91d6a336f09 100755 (executable)
@@ -4172,6 +4172,7 @@ AC_CHECK_FUNCS([     \
         utimensat    \
         process_vm_readv  \
         process_vm_writev \
+        copy_file_range \
         ])
 
 # AC_CHECK_LIB adds any library found to the variable LIBS, and links these
@@ -4187,6 +4188,8 @@ AM_CONDITIONAL([HAVE_PTHREAD_SPINLOCK],
                [test x$ac_cv_func_pthread_spin_lock = xyes])
 AM_CONDITIONAL([HAVE_PTHREAD_SETNAME_NP],
                [test x$ac_cv_func_pthread_setname_np = xyes])
+AM_CONDITIONAL([HAVE_COPY_FILE_RANGE],
+               [test x$ac_cv_func_copy_file_range = xyes])
 
 if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
      -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX ; then
index f76191adafa030254aeedeff324dd2861ec2091e..1edf9eb4949e1cb243faa4ca452462e0e80f1a33 100644 (file)
@@ -379,6 +379,7 @@ DECL_TEMPLATE(linux, sys_getsockname);
 DECL_TEMPLATE(linux, sys_getpeername);
 DECL_TEMPLATE(linux, sys_socketpair);
 DECL_TEMPLATE(linux, sys_kcmp);
+DECL_TEMPLATE(linux, sys_copy_file_range);
 
 // Some arch specific functions called from syswrap-linux.c
 extern Int do_syscall_clone_x86_linux ( Word (*fn)(void *), 
index 30e7d0e910fb19344cda4f662ab40fc08b58f226..0c1d8d12fe1987122fefd778291b8bc66c508aa4 100644 (file)
@@ -863,6 +863,8 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_statx,             sys_statx),             // 332
 
    LINX_(__NR_membarrier,        sys_membarrier),        // 324
+
+   LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 326
 };
 
 SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
index 290320a9e8e524e023b913b938df083ffe756a30..f66be2de8b344e4dacdfb5bf44429e3ad570f761 100644 (file)
@@ -819,7 +819,7 @@ static SyscallTableEntry syscall_main_table[] = {
    //   (__NR_userfaultfd,       sys_ni_syscall),        // 282
    LINX_(__NR_membarrier,        sys_membarrier),        // 283
    //   (__NR_mlock2,            sys_ni_syscall),        // 284
-   //   (__NR_copy_file_range,   sys_ni_syscall),        // 285
+   LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 285
    //   (__NR_preadv2,           sys_ni_syscall),        // 286
    //   (__NR_pwritev2,          sys_ni_syscall),        // 287
    //   (__NR_pkey_mprotect,     sys_ni_syscall),        // 288
index 73ef98d447c83a343ce5a53bf70c071b0e7b10ac..cd0ee74d288588ecb122e5d3a16580dffad4d86e 100644 (file)
@@ -12093,6 +12093,36 @@ POST(sys_bpf)
    }
 }
 
+PRE(sys_copy_file_range)
+{
+  PRINT("sys_copy_file_range (%lu, %lu, %lu, %lu, %lu, %lu)", ARG1, ARG2, ARG3,
+        ARG4, ARG5, ARG6);
+
+  PRE_REG_READ6(vki_size_t, "copy_file_range",
+                int, "fd_in",
+                vki_loff_t *, "off_in",
+                int, "fd_out",
+                vki_loff_t *, "off_out",
+                vki_size_t, "len",
+                unsigned int, "flags");
+
+  /* File descriptors are "specially" tracked by valgrind.
+     valgrind itself uses some, so make sure someone didn't
+     put in one of our own...  */
+  if (!ML_(fd_allowed)(ARG1, "copy_file_range(fd_in)", tid, False) ||
+      !ML_(fd_allowed)(ARG3, "copy_file_range(fd_in)", tid, False)) {
+     SET_STATUS_Failure( VKI_EBADF );
+  } else {
+     /* Now see if the offsets are defined. PRE_MEM_READ will
+        double check it can dereference them. */
+     if (ARG2 != 0)
+        PRE_MEM_READ( "copy_file_range(off_in)", ARG2, sizeof(vki_loff_t));
+     if (ARG4 != 0)
+        PRE_MEM_READ( "copy_file_range(off_out)", ARG4, sizeof(vki_loff_t));
+  }
+}
+
+
 #undef PRE
 #undef POST
 
index f812f1f6cb3f88ca0c3194855421ef2c306bba45..71f208d725287d4053715601ff6cda8e333e5e1f 100644 (file)
@@ -1021,6 +1021,8 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_getrandom,         sys_getrandom),        // 359
    LINXY(__NR_memfd_create,      sys_memfd_create),     // 360
 
+   LINX_(__NR_copy_file_range,   sys_copy_file_range),  // 379
+
    LINXY(__NR_statx,             sys_statx),            // 383
 };
 
index eada099817e37574ecfe9bc105166e46928593f0..1a42c1fb0906a26511b55d8808da7180847ef585 100644 (file)
@@ -1007,6 +1007,8 @@ static SyscallTableEntry syscall_table[] = {
 
    LINX_(__NR_membarrier,        sys_membarrier),       // 365
 
+   LINX_(__NR_copy_file_range,   sys_copy_file_range),  // 379
+
    LINXY(__NR_statx,             sys_statx),            // 383
 };
 
index ad78384d1680f10024d619b7109b5e056270ae46..41ada8d600b7c8b7c5595f501b97dc70e00f7fb9 100644 (file)
@@ -854,6 +854,8 @@ static SyscallTableEntry syscall_table[] = {
    LINXY(__NR_recvmsg, sys_recvmsg),                                  // 372
    LINX_(__NR_shutdown, sys_shutdown),                                // 373
 
+   LINX_(__NR_copy_file_range, sys_copy_file_range),                  // 375
+
    LINXY(__NR_statx, sys_statx),                                      // 379
 };
 
index f05619e0bb0e078166664efa94642f24f1a38b9a..f8d97ea85dc51a37487b40b308cc6adea107fe4e 100644 (file)
@@ -1608,6 +1608,8 @@ static SyscallTableEntry syscall_table[] = {
 
    LINX_(__NR_membarrier,        sys_membarrier),       // 375
 
+   LINX_(__NR_copy_file_range,   sys_copy_file_range),   // 377
+
    LINXY(__NR_statx,             sys_statx),            // 383
 
    /* Explicitly not supported on i386 yet. */
index d7515d9c7593f2698c9379f84e16cb9c43d3e983..00e99a52a4eed7108e8943d6bac5a8471ae135b1 100644 (file)
@@ -20,6 +20,7 @@ EXTRA_DIST = \
        stack_switch.stderr.exp stack_switch.vgtest \
        syscalls-2007.vgtest syscalls-2007.stderr.exp \
        syslog-syscall.vgtest syslog-syscall.stderr.exp \
+       sys-copy_file_range.vgtest sys-copy_file_range.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 \
@@ -49,6 +50,10 @@ if HAVE_AT_FDCWD
 check_PROGRAMS += sys-openat
 endif
 
+if HAVE_COPY_FILE_RANGE
+        check_PROGRAMS += sys-copy_file_range
+endif
+
 AM_CFLAGS   += $(AM_FLAG_M3264_PRI)
 AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
 
diff --git a/memcheck/tests/linux/sys-copy_file_range.c b/memcheck/tests/linux/sys-copy_file_range.c
new file mode 100644 (file)
index 0000000..83981c6
--- /dev/null
@@ -0,0 +1,67 @@
+#define _GNU_SOURCE
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+int main(int argc, char **argv)
+{
+    int fd_in, fd_out;
+    struct stat stat;
+    loff_t len, ret;
+
+    fd_in = open("copy_file_range_source", O_CREAT | O_RDWR);
+    if (fd_in == -1) {
+        perror("open copy_file_range_source");
+        exit(EXIT_FAILURE);
+    }
+
+    if (write(fd_in, "foo bar\n", 8) != 8) {
+        perror("writing to the copy_file_range_source");
+        exit(EXIT_FAILURE);
+    }
+    lseek(fd_in, 0, SEEK_SET);
+
+    if (fstat(fd_in, &stat) == -1) {
+        perror("fstat");
+        exit(EXIT_FAILURE);
+    }
+
+    len = stat.st_size;
+
+    fd_out = open("copy_file_range_dest", O_CREAT | O_WRONLY | O_TRUNC, 0644);
+    if (fd_out == -1) {
+        perror("open copy_file_range_dest");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Check copy_file_range called with the correct arguments works. */
+    do {
+        ret = copy_file_range(fd_in, NULL, fd_out, NULL, len, 0);
+        if (ret == -1) {
+            perror("copy_file_range");
+            exit(EXIT_FAILURE);
+        }
+
+        len -= ret;
+    } while (len > 0);
+
+    /* Check valgrind will produce expected warnings for the
+       various wrong arguments. */
+    do {
+        void *t;
+        void *z = (void *) -1;
+
+        ret = copy_file_range(fd_in, t, fd_out, NULL, len, 0);
+        ret = copy_file_range(fd_in, NULL, fd_out, z, len, 0);
+        ret = copy_file_range(- 1, NULL, - 1, NULL, len, 0);
+    } while (0);
+
+    close(fd_in);
+    close(fd_out);
+    unlink("copy_file_range_source");
+    unlink("copy_file_range_dest");
+    exit(EXIT_SUCCESS);
+}
diff --git a/memcheck/tests/linux/sys-copy_file_range.stderr.exp b/memcheck/tests/linux/sys-copy_file_range.stderr.exp
new file mode 100644 (file)
index 0000000..1aa4dc2
--- /dev/null
@@ -0,0 +1,21 @@
+
+Syscall param copy_file_range("off_in") contains uninitialised byte(s)
+   ...
+   by 0x........: main (sys-copy_file_range.c:57)
+
+Syscall param copy_file_range(off_out) points to unaddressable byte(s)
+   ...
+   by 0x........: main (sys-copy_file_range.c:58)
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Warning: invalid file descriptor -1 in syscall copy_file_range(fd_in)()
+
+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
+
+Use --track-origins=yes to see where uninitialised values come from
+For lists of detected and suppressed errors, rerun with: -s
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
diff --git a/memcheck/tests/linux/sys-copy_file_range.vgtest b/memcheck/tests/linux/sys-copy_file_range.vgtest
new file mode 100644 (file)
index 0000000..b7741e8
--- /dev/null
@@ -0,0 +1,2 @@
+prereq: test -e sys-copy_file_range
+prog: sys-copy_file_range