Re: BUG: unable to handle kernel paging request in fuse_copy_do

From: David Hildenbrand
Date: Fri Mar 22 2024 - 17:08:28 EST


On 22.03.24 20:46, Miklos Szeredi wrote:
On Fri, 22 Mar 2024 at 16:41, David Hildenbrand <david@xxxxxxxxxx> wrote:

But at least the vmsplice() just seems to work. Which is weird, because
GUP-fast should not apply (page not faulted in?)

But it is faulted in, and that indeed seems to be the root cause.

secretmem mmap() won't populate the page tables. So it's not faulted in yet.

When we GUP via vmsplice, GUP-fast should not find it in the page tables and fallback to slow GUP.

There, we seem to pass check_vma_flags(), trigger faultin_page() to fault it in, and then find it via follow_page_mask().

.. and I wonder how we manage to skip check_vma_flags(), or otherwise managed to GUP it.

vmsplice() should, in theory, never succeed here.

Weird :/

Improved repro:

#define _GNU_SOURCE

#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <sys/mman.h>
#include <sys/syscall.h>

int main(void)
{
int fd1, fd2;
int pip[2];
struct iovec iov;
char *addr;
int ret;

fd1 = syscall(__NR_memfd_secret, 0);
addr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
ftruncate(fd1, 7);
addr[0] = 1; /* fault in page */
pipe(pip);
iov.iov_base = addr;
iov.iov_len = 0x50;
ret = vmsplice(pip[1], &iov, 1, 0);
if (ret == -1 && errno == EFAULT) {
printf("Success\n");
return 0;
}

fd2 = open("/tmp/repro-secretmem.test", O_RDWR | O_CREAT, 0x600);
splice(pip[0], NULL, fd2, NULL, 0x50, 0);

return 0;
}


--
Cheers,

David / dhildenb