[英]Linux kernel module read from process VMA
I'm trying to build a small demonstration kernel module for Linux which finds a specific process and reads a value from that process' memory.我正在尝试为 Linux 构建一个小的演示内核模块,它可以找到一个特定的进程并从该进程的内存中读取一个值。
I have put together the following code:我整理了以下代码:
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/printk.h>
#include <linux/init.h>
#include <linux/highmem.h>
#include <asm/uaccess.h>
static void read_process_memory(struct task_struct *task) {
char buf[1024];
unsigned long size;
unsigned long ret;
void __user *addr;
struct mm_struct *mm = get_task_mm(task);
struct vm_area_struct *vma;
if (!mm) {
// Abort
return;
}
// Lock for reading
down_read(&mm->mmap_sem);
vma = mm->mmap;
memset(buf, 0, 1024);
// Make sure read is enabled for this region
if (vma && vma->vm_flags & VM_READ) {
// Read without overflowing
size = vma->vm_end - vma->vm_start;
if (size > 1023) {
size = 1023;
}
// Attempt to get the data from the start of the vma
addr = (void __user *)vma->vm_start;
if (access_ok(VERIFY_READ, addr, size)) {
ret = copy_from_user(buf, addr, size);
if (ret == 0) {
// Probably doesn't contain anything relevent
printk(KERN_ALERT "mymodule: Read '%s'\n", buf);
} else {
printk(KERN_ALERT "mymodule: Failed to copy %lu bytes from userspace\n", ret);
}
} else {
printk(KERN_ALERT "mymodule: access_ok check failed\n");
}
// Release the lock
up_read(&mm->mmap_sem);
mmput(mm);
}
}
static int __init mymodule_init(void) {
struct task_struct *task;
bool found = false;
printk(KERN_ALERT "mymodule: Starting\n");
// Find the process
rcu_read_lock();
for_each_process(task) {
if (strcmp(task->comm, "example-process") == 0) {
printk(KERN_ALERT "mymodule: Found pid %d for process %s\n", task->pid, task->comm);
found = true;
break;
}
}
rcu_read_unlock();
if (!found) {
printk(KERN_ALERT "mymodule: Process not found, aborting\n");
return -1;
}
read_process_memory(task);
return 0;
}
static void __exit mymodule_exit(void) {
printk(KERN_ALERT "mymodule: Stopped\n");
}
module_init(mymodule_init);
module_exit(mymodule_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("user");
Everything works fine until the copy_from_user
call, which returns a non-zero count (actually, it returns size
, meaning it didn't ready any data), regardless of the process and vma
I try to read from.一切正常,直到
copy_from_user
调用返回一个非零计数(实际上,它返回size
,这意味着它没有准备好任何数据),无论我尝试读取的进程和vma
什么。
Is there a misunderstanding on my part, or anything I'm doing wrong?是我有什么误解,还是我做错了什么?
EDIT: Here's a working version of read_process_memory
:编辑:这是
read_process_memory
的工作版本:
static void read_process_memory(struct task_struct *task) {
char buf[1024];
unsigned long size;
int ret;
void *addr;
struct mm_struct *mm = get_task_mm(task);
struct vm_area_struct *vma;
struct page *pages[1];
if (!mm) {
// Abort
return;
}
// Lock for reading
down_read(&mm->mmap_sem);
vma = mm->mmap;
memset(buf, 0, 1024);
// Make sure read is enabled for this region
if (vma && vma->vm_flags & VM_READ) {
// Get the first page
ret = get_user_pages_remote(task, mm, vma->vm_start, 1, FOLL_FORCE, pages, NULL);
if (ret > 0) {
// We got our page, we should now be able to map it and read directly
addr = kmap(*pages);
// Read without overflowing
size = vma->vm_end - vma->vm_start;
if (size > 1023) {
size = 1023;
}
strncpy(buf, addr, size);
// Probably doesn't contain anything relevent
printk(KERN_ALERT "mymodule: Read '%s'\n", buf);
// Make sure to release our page
kunmap(*pages);
put_page(*pages);
} else {
printk(KERN_ALERT "mymodule: Failed to read page at %p (errno=%d)\n", (void *)vma->vm_start, ret);
}
// Release the lock
up_read(&mm->mmap_sem);
mmput(mm);
}
}
I'd say your code is wrong.我会说你的代码是错误的。 Please be noted you are accessing memory of remote process (not current).
请注意,您正在访问远程进程(非当前)的内存。 To do that correctly you must use one of the GUP APIs(eg get_user_pages_remote()) to grab the pages first.
要正确执行此操作,您必须先使用 GUP API 之一(例如 get_user_pages_remote())来抓取页面。 The uaccess APIs (eg copy_from_user) only works for current process.
uaccess API(例如 copy_from_user)仅适用于当前进程。
Here is an example in iouring: https://elixir.bootlin.com/linux/latest/source/fs/io_uring.c#L4839这是 iouring 的一个例子: https ://elixir.bootlin.com/linux/latest/source/fs/io_uring.c#L4839
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.