1

I'm hooking some system calls using kprobes inside the linux kernel. During that, I would like to read from a file using mmap.

It's not possible to use system calls inside the kernel, but often there are other ways around it. (e.g. sys_open vs. vfs_read).

Is that possible and if so, how?

9
  • 1
    mmap creates a new mapping in virtual address space of a calling process, since there isnt any process since we are in kernel, it would really tricky to get it working. On the other hand why not just open in the kernel and read it (filp_open/vfs_read) ? Commented Jan 26, 2018 at 12:46
  • static int file_write(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) { mm_segment_t oldfs; int ret; oldfs = get_fs(); set_fs(get_ds()); ret = vfs_write(file, data, size, &offset); set_fs(oldfs); return ret; } static int file_read(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size) { mm_segment_t oldfs; int ret; oldfs = get_fs(); set_fs(get_ds()); ret = vfs_read(file, (void __force __user *)data, size, &offset); set_fs(oldfs); return ret; } Commented Jan 26, 2018 at 12:48
  • If I understand the inner workings of the kernel correctly, there is a process because I'm hooking the syscall. So all my code is run inside a process. Thanks for the code. vfs_read is indeed an alternative, but an mmap'ed file would work better with my existing code and I could avoid copying some memory. Commented Jan 26, 2018 at 12:54
  • 1
    just for my clarification, kernel mmap/filp_open would return you a pointer which is in kernel space, how would that avoid copying some memory ? Commented Jan 26, 2018 at 13:19
  • 1
    just gave another thought (I haven’t tried it, but curious if it works !), allocate some physical memory in the kernel and then pass it on the do_mmap() and check the return value, if it succeeds, do not use the address returned, instead use the addr which you passed for do_mmap() call to access the file. the only disadvantage would be you will have to allocate large physical memory if the file is BIG. Commented Jan 29, 2018 at 8:57

1 Answer 1

2

From my understanding, functionality of mmap() cannot be used from the kernel space.

While one may successfully call do_mmap() or similar, the function returns user space address, which kernel cannot use directly. The only correct way for access user space memory from the kernel is copy_to_user/copy_from_user. But using these functions implies copiing, so advantage of mmap() (compared to read()) is lost.


For use functionality of read() in the kernel, set_fs(KERNEL_DS) technique can be used for mask pointer to kernel space, passed to this function, as a pointer to user space, so copy_to_user works correctly.

But with mmap() one has reversed problem: he needs to work with user space pointer, returned from the function, as with a pointer to kernel space. And this cannot be done with normal means.

Attempt to dereference a pointer to user space region which hasn't mapped yet may crash the kernel. And most of mmap() implementations actually returns not-mapped memory, which is intended to be mapped on the first page fault.

Sign up to request clarification or add additional context in comments.

1 Comment

yep, also, mmap accepts an int as file descriptor and from kernel there is not such option. The file you are going to open is returned as structs.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.