3

For educational purposes, I've managed to create a custom syscall that just prints a message in the kernel's log.

What I was thinking about now is to create a "cross-process memcpy" syscall that receives another process' PID, a memory address of that process' memory space, a lenght, and a pointer in the current's process memory space, and that copies memory from the other process to the current one.

My idea would be to write a program that asks the user for a string, and then prints its PID, the address of the variable in which the string is stored, and it's length. Then I'd write another process that asks for that PID, address and length, and uses my custom syscall to copy that info from the other process to this one.

In theory, I understand that the kernel should be able to access everything, including the other process memory. But in practice I've found that there are copy_from_user or copy_to_user functions to copy memory between userspace and kernelspace, but they don't receive a PID or any other process identifier. So it seems the syscall has somehow context information regarding the caller process - and I don't know if there's any limitation or API that prevents/allows to access another process' memory space from a syscall.

Does the Linux kernel have any API to access another process' memory, given it's PID and memory address?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
mgarciaisaia
  • 14,521
  • 8
  • 57
  • 81
  • 1
    `copy_to_user` takes a pointer into userspace, so it actually points to a userspace program, that owns the memory behind that pointer. I don't understand the "has somehow" - yes, the userspace passes the pointer to it's space with syscall argument. Just iterate over tasks until you find your pid. Why do you need a syscall for that anyway? Just read `/proc/pid/mem` – KamilCuk Nov 24 '19 at 21:15
  • Why you can't use shared memory? It even implements zero copy mechanism, while your idea not. You can't copy to arbitrary process because its address space is not mapped all the time. Instead you should use intermediate kernel buffer and read through the file node (like most ipc methods do). – Alex Hoppus Nov 25 '19 at 05:46
  • @AlexHoppus I'm just trying to come up with a not-trivial syscall to show how the kernel plays with other rules. I'm not trying to send a patch to the kernel maintainers - just to prove a point to other fellow students. And this is the simplest non-trivial idea I could come with. – mgarciaisaia Nov 25 '19 at 12:36

1 Answers1

3

Does the Linux kernel have any API to access another process' memory, given it's PID and memory address?

Yes, get_user_pages.

Note that the other process is not mapped into the address space of the caller. get_user_pages obtains the underlying pages.

We can use get_user_pages to get a reference on a range of pages which covers the requested area to be read or written. Then carefully copy the data into and out of those pages such that we only touch the requested area.

The /proc/<pid>/mem mechanism might be based on get_user_pages; in any case, it's worth taking a look to see how it works.

Also look at the ptrace system call and its PTRACE_PEEKDATA and PTRACE_POKEDATA operations. You may be able to solve your problem using ptrace or else crib something from its implementation.

Introducing a system call to access memory is probably a bad idea. You have to make sure it's securely coded and that it checks the credentials of the caller, otherwise you can open up a huge security hole.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • 1
    worth noting that such a sys call already exists `process_vm_readv` for reading and `process_vm_writev` for writing. Under the hood they use `pin_user_pages_remote`, which in turn uses `__get_user_pages_remote`... look here for a code reference to the actual linux kernel https://elixir.bootlin.com/linux/latest/A/ident/process_vm_rw – Nanyo Mar 28 '22 at 22:01