]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Linux: Add wrapper for fcntl(F_{GET,ADD}_SEALS)
authorAllison Karlitskaya <allison.karlitskaya@redhat.com>
Tue, 13 Oct 2020 11:17:11 +0000 (13:17 +0200)
committerMark Wielaard <mark@klomp.org>
Sat, 20 Feb 2021 20:04:12 +0000 (21:04 +0100)
Add also a testcase to memcheck/tests/linux, enabled according to a new
check for memfd_create() in configure.ac.

https://bugs.kde.org/show_bug.cgi?id=361770

.gitignore
NEWS
configure.ac
coregrind/m_syswrap/syswrap-linux.c
include/vki/vki-linux.h
memcheck/tests/linux/Makefile.am
memcheck/tests/linux/memfd.c [new file with mode: 0644]
memcheck/tests/linux/memfd.stderr.exp [new file with mode: 0644]
memcheck/tests/linux/memfd.vgtest [new file with mode: 0644]

index dff20848e6051e9100f0e85ac3fd8761c52d2296..eec616989105744e42625a12bef2d7c7fc0dea55 100644 (file)
 /memcheck/tests/linux/lsframe2
 /memcheck/tests/linux/Makefile
 /memcheck/tests/linux/Makefile.in
+/memcheck/tests/linux/memfd
 /memcheck/tests/linux/rfcomm
 /memcheck/tests/linux/sigqueue
 /memcheck/tests/linux/stack_changes
diff --git a/NEWS b/NEWS
index cdd103b01ed9d3f5030f28f9591aa883dde3b5ed..55bf58ae8ac65217bf99b4f903f5ebde823aee59 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -78,6 +78,7 @@ where XXXXXX is the bug number as listed below.
 140939 --track-fds reports leakage of stdout/in/err and doesn't respect -q
 217695  malloc/calloc/realloc/memalign failure doesn't set errno to ENOMEM
 345077  linux syscall execveat support (linux 3.19)
+361770  Missing F_ADD_SEALS
 369029  handle linux syscalls sched_getattr and sched_setattr
 384729  __libc_freeres inhibits cross-platform valgrind
 391853  Makefile.all.am:L247 and @SOLARIS_UNDEF_LARGESOURCE@ being empty
index 41ae942429284ac2455af5d629e7c7bf5471c222..4648450fe3b1395041293a4e25c2068b4fe49491 100755 (executable)
@@ -4358,6 +4358,7 @@ AC_CHECK_FUNCS([     \
         klogctl      \
         mallinfo     \
         memchr       \
+        memfd_create \
         memset       \
         mkdir        \
         mremap       \
@@ -4409,6 +4410,8 @@ AM_CONDITIONAL([HAVE_PREADV_PWRITEV],
                [test x$ac_cv_func_preadv = xyes && test x$ac_cv_func_pwritev = xyes])
 AM_CONDITIONAL([HAVE_PREADV2_PWRITEV2],
                [test x$ac_cv_func_preadv2 = xyes && test x$ac_cv_func_pwritev2 = xyes])
+AM_CONDITIONAL([HAVE_MEMFD_CREATE],
+               [test x$ac_cv_func_memfd_create = xyes])
 
 if test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
      -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
index fcc534454af2068c100f6392a175c08e0a5455f1..3d6939d147ad5f9e802c48f24d328fc28b6ba747 100644 (file)
@@ -6784,6 +6784,7 @@ PRE(sys_fcntl)
    case VKI_F_GETSIG:
    case VKI_F_GETLEASE:
    case VKI_F_GETPIPE_SZ:
+   case VKI_F_GET_SEALS:
       PRINT("sys_fcntl ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2);
       PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
       break;
@@ -6798,6 +6799,7 @@ PRE(sys_fcntl)
    case VKI_F_SETOWN:
    case VKI_F_SETSIG:
    case VKI_F_SETPIPE_SZ:
+   case VKI_F_ADD_SEALS:
       PRINT("sys_fcntl[ARG3=='arg'] ( %" FMT_REGWORD "u, %" FMT_REGWORD
             "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3);
       PRE_REG_READ3(long, "fcntl",
@@ -6930,6 +6932,7 @@ PRE(sys_fcntl64)
    case VKI_F_GETSIG:
    case VKI_F_SETSIG:
    case VKI_F_GETLEASE:
+   case VKI_F_GET_SEALS:
       PRINT("sys_fcntl64 ( %" FMT_REGWORD "u, %" FMT_REGWORD "u )", ARG1, ARG2);
       PRE_REG_READ2(long, "fcntl64", unsigned int, fd, unsigned int, cmd);
       break;
@@ -6941,6 +6944,7 @@ PRE(sys_fcntl64)
    case VKI_F_SETFL:
    case VKI_F_SETLEASE:
    case VKI_F_NOTIFY:
+   case VKI_F_ADD_SEALS:
       PRINT("sys_fcntl64[ARG3=='arg'] ( %" FMT_REGWORD "u, %" FMT_REGWORD
             "u, %" FMT_REGWORD "u )", ARG1, ARG2, ARG3);
       PRE_REG_READ3(long, "fcntl64",
index 3b9dc37796bcdd5b983d2596ec6a2719cc7ba9ba..426d9db92f695c15cf67fb57057f2d5a32c2ea77 100644 (file)
@@ -1504,6 +1504,9 @@ struct vki_dirent64 {
 #define VKI_F_SETPIPE_SZ    (VKI_F_LINUX_SPECIFIC_BASE + 7)
 #define VKI_F_GETPIPE_SZ    (VKI_F_LINUX_SPECIFIC_BASE + 8)
 
+#define VKI_F_ADD_SEALS     (VKI_F_LINUX_SPECIFIC_BASE + 9)
+#define VKI_F_GET_SEALS     (VKI_F_LINUX_SPECIFIC_BASE + 10)
+
 struct vki_flock {
        short                   l_type;
        short                   l_whence;
index 1c53ffbaf88b24136278bd1319b9df1f879fd40b..7e796aa7faae4c4ea6fd2860905a573944168c50 100644 (file)
@@ -13,6 +13,7 @@ EXTRA_DIST = \
        ioctl-tiocsig.vgtest ioctl-tiocsig.stderr.exp \
        lsframe1.vgtest lsframe1.stdout.exp lsframe1.stderr.exp \
        lsframe2.vgtest lsframe2.stdout.exp lsframe2.stderr.exp \
+       memfd.vgtest memfd.stderr.exp \
        rfcomm.vgtest rfcomm.stderr.exp \
        sigqueue.vgtest sigqueue.stderr.exp \
        stack_changes.stderr.exp stack_changes.stdout.exp \
@@ -58,6 +59,10 @@ if HAVE_AT_FDCWD
 check_PROGRAMS += sys-openat
 endif
 
+if HAVE_MEMFD_CREATE
+check_PROGRAMS += memfd
+endif
+
 if HAVE_COPY_FILE_RANGE
         check_PROGRAMS += sys-copy_file_range
 endif
diff --git a/memcheck/tests/linux/memfd.c b/memcheck/tests/linux/memfd.c
new file mode 100644 (file)
index 0000000..f37e4b5
--- /dev/null
@@ -0,0 +1,75 @@
+#define _GNU_SOURCE
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#include "../../memcheck.h"
+
+static void
+assert_expected (int fd, int expected_seals)
+{
+  int current_seals = fcntl (fd, F_GET_SEALS);
+  assert (current_seals == expected_seals);
+}
+
+static void
+add_seal (int fd, int *expected_seals, int new_seal)
+{
+  int r = fcntl (fd, F_ADD_SEALS, new_seal);
+  assert (r == 0);
+
+  *expected_seals |= new_seal;
+
+  // Make sure we get the result we expected.
+  assert_expected (fd, *expected_seals);
+}
+
+static void
+add_seal_expect_fail (int fd, int new_seal, int expected_errno)
+{
+  int r = fcntl (fd, F_ADD_SEALS, new_seal);
+  assert (r == -1 && errno == expected_errno);
+}
+
+int
+main (void)
+{
+  int expected_seals = 0;
+  int fd;
+
+  // Try with an fd that doesn't support sealing.
+  fd = memfd_create ("xyz", 0);
+  if (fd < 0)
+    {
+      // Not supported, nothing to test...
+      return 1;
+    }
+
+  assert_expected (fd, F_SEAL_SEAL);
+  add_seal_expect_fail (fd, F_SEAL_WRITE, EPERM);
+  assert_expected (fd, F_SEAL_SEAL); // ...should still be unset after failed attempt
+  close (fd);
+
+  // Now, try the successful case.
+  fd = memfd_create ("xyz", MFD_ALLOW_SEALING);
+  add_seal (fd, &expected_seals, F_SEAL_SHRINK);
+  add_seal (fd, &expected_seals, F_SEAL_GROW);
+
+  // Now prevent more sealing.
+  add_seal (fd, &expected_seals, F_SEAL_SEAL);
+
+  // And make sure that it indeed fails.
+  add_seal_expect_fail (fd, F_SEAL_WRITE, EPERM);
+  assert_expected (fd, expected_seals);
+  close (fd);
+
+  // Test the only memory failure possible: passing an undefined argument to F_ADD_SEALS
+  int undefined_seal = 0;
+  VALGRIND_MAKE_MEM_UNDEFINED(&undefined_seal, sizeof undefined_seal);
+  fcntl (-1, F_ADD_SEALS, undefined_seal);
+
+  return 0;
+}
diff --git a/memcheck/tests/linux/memfd.stderr.exp b/memcheck/tests/linux/memfd.stderr.exp
new file mode 100644 (file)
index 0000000..13009d8
--- /dev/null
@@ -0,0 +1,6 @@
+Syscall param fcntl(arg) contains uninitialised byte(s)
+   ...
+   by 0x........: main (memfd.c:72)
+ Uninitialised value was created by a client request
+   at 0x........: main (memfd.c:71)
+
diff --git a/memcheck/tests/linux/memfd.vgtest b/memcheck/tests/linux/memfd.vgtest
new file mode 100644 (file)
index 0000000..4096401
--- /dev/null
@@ -0,0 +1,3 @@
+prereq: test -e memfd
+vgopts: -q --track-origins=yes
+prog: memfd