#include <unistd.h>
 #include <errno.h>
 #include <stdio.h>
+#include <fcntl.h>
 
 #include "../kselftest.h"
 
        pass("mlock limit is respected\n");
 }
 
+static void test_vmsplice(int fd, const char *desc)
+{
+       ssize_t transferred;
+       struct iovec iov;
+       int pipefd[2];
+       char *mem;
+
+       if (pipe(pipefd)) {
+               fail("pipe failed: %s\n", strerror(errno));
+               return;
+       }
+
+       mem = mmap(NULL, page_size, prot, mode, fd, 0);
+       if (mem == MAP_FAILED) {
+               fail("Unable to mmap secret memory\n");
+               goto close_pipe;
+       }
+
+       /*
+        * vmsplice() may use GUP-fast, which must also fail. Prefault the
+        * page table, so GUP-fast could find it.
+        */
+       memset(mem, PATTERN, page_size);
+
+       iov.iov_base = mem;
+       iov.iov_len = page_size;
+       transferred = vmsplice(pipefd[1], &iov, 1, 0);
+
+       if (transferred < 0 && errno == EFAULT)
+               pass("vmsplice is blocked as expected with %s\n", desc);
+       else
+               fail("vmsplice: unexpected memory access with %s\n", desc);
+
+       munmap(mem, page_size);
+close_pipe:
+       close(pipefd[0]);
+       close(pipefd[1]);
+}
+
 static void try_process_vm_read(int fd, int pipefd[2])
 {
        struct iovec liov, riov;
                return;
        }
 
-       ftruncate(fd, page_size);
        memset(mem, PATTERN, page_size);
 
        if (write(pipefd[1], &mem, sizeof(mem)) < 0) {
                                   strerror(errno));
 }
 
-#define NUM_TESTS 4
+#define NUM_TESTS 6
 
 int main(int argc, char *argv[])
 {
                        ksft_exit_fail_msg("memfd_secret failed: %s\n",
                                           strerror(errno));
        }
+       if (ftruncate(fd, page_size))
+               ksft_exit_fail_msg("ftruncate failed: %s\n", strerror(errno));
 
        test_mlock_limit(fd);
        test_file_apis(fd);
+       /*
+        * We have to run the first vmsplice test before any secretmem page was
+        * allocated for this fd.
+        */
+       test_vmsplice(fd, "fresh page");
+       test_vmsplice(fd, "existing page");
        test_process_vm_read(fd);
        test_ptrace(fd);