我试图窃取 Linux 6.8 上的
statx
系统调用并修改返回参数。
但是,当尝试加载模块时,我在第 行遇到了关于 NULL 指针引用的 BUG
r = strncpy_from_user(path, (char __user *)user_regs->si, 128);
这是我的代码:
我使用这个问题(无法从 kprobe 处理程序读取系统调用参数)。 但我确实设法处理了这个争论。
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
MODULE_VERSION("v.0");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Flavien <flav> ASTRAUD <[email protected]>");
MODULE_DESCRIPTION("ex. pour interception d'un syscall");
static int m_statx(struct kretprobe_instance *ri, struct pt_regs *regs)
{
long r = 0;
char path[128];
struct pt_regs *user_regs = (struct pt_regs *)regs->di;
struct statx statxbuf; // (struct statx *) regs->r8;
r = strncpy_from_user(path, (char __user *)user_regs->si, 128);
r = copy_from_user(&statxbuf, (struct statx *)user_regs->r8,
sizeof (struct statx));
pr_info("STATX_V3 %s size=%lld\n", path, statxbuf.stx_size);
statxbuf.stx_size = 42;
r = copy_to_user((struct statx *)user_regs->r8,
&statxbuf, sizeof(statxbuf));
return 0;
}
static struct kretprobe kret = {
// .symbol_name = "__x64_sys_statx",
.handler = m_statx,
};
static int override_statx(void)
{
kret.kp.symbol_name = "__x64_sys_statx";
if (register_kretprobe(&kret) < 0)
return 0;
return 0;
}
static void pullback_syscall(void)
{
unregister_kretprobe(&kret);
return;
}
static int __init kstatx_init(void)
{
pr_info("kstatx INIT\n=============\n");
override_statx();
return 0;
}
static void __exit kstatx_exit(void)
{
pr_info("kstatx END\n=============\n");
pullback_syscall();
}
module_init(kstatx_init);
module_exit(kstatx_exit);
这是@tsyvarev 帮助下的解决方案
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kprobes.h>
MODULE_VERSION("v.0");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("flav <[email protected]>");
MODULE_DESCRIPTION("ex. pour interception d'un syscall");
struct my_data {
char *ppath;
struct statx *s_statx;
};
static int m_statx_pre(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct my_data *data;
char *ppath;
pr_info("STATX entry\n");
ppath = (char *)((struct pt_regs *)regs->di)->si;
struct statx *statx = (struct statx *)((struct pt_regs *)regs->di)->r8;
data = (struct my_data *)ri->data;
data->s_statx = statx;
data->ppath = ppath;
return 0;
}
static int m_statx(struct kretprobe_instance *ri, struct pt_regs *regs)
{
struct my_data *data;
long r = 0;
char path[128];
struct statx statxbuf;
data = (struct my_data *)ri->data;
r = strncpy_from_user(path, data->ppath, 128);
r = copy_from_user(&statxbuf, data->s_statx, sizeof (struct statx));
pr_info("STATX_V3 %s size=%lld\n", path, statxbuf.stx_size);
pr_info("STATX_ret: [%s]\n", path);
statxbuf.stx_size = 42;
statxbuf.stx_uid = 42;
statxbuf.stx_gid = 42;
r = copy_to_user(data->ppath, path, strlen(path)+1);
r = copy_to_user(data->s_statx, &statxbuf, sizeof(statxbuf));
return 0;
}
static struct kretprobe kret = {
.handler = m_statx,
.entry_handler = m_statx_pre,
.data_size = sizeof (struct my_data),
};
static int override_statx(void)
{
kret.kp.symbol_name = "__x64_sys_statx";
if (register_kretprobe(&kret) < 0)
return 0;
return 0;
}
static void pullback_syscall(void)
{
unregister_kretprobe(&kret);
return;
}
static int __init kstatx_init(void)
{
pr_info("kstatx INIT\n=============\n");
override_statx();
return 0;
}
static void __exit kstatx_exit(void)
{
pr_info("kstatx END\n=============\n");
pullback_syscall();
}
module_init(kstatx_init);
module_exit(kstatx_exit);
没有模块:
# stat kparm.ko
File: kparm.ko
Size: 302816 Blocks: 592 IO Block: 4096 regular file
Device: 252,0 Inode: 393542 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
# ls -ln kparm.ko
-rw-r--r-- 1 0 0 302816 Oct 7 10:23 kparm.ko
使用模块:
# stat kparm.ko
File: kparm.ko
Size: 42 Blocks: 592 IO Block: 4096 regular file
Device: 252,0 Inode: 393542 Links: 1
Access: (0644/-rw-r--r--) Uid: ( 42/ _apt) Gid: ( 42/ shadow)
# ls -ln kparm.ko
-rw-r--r-- 1 42 42 42 Oct 7 10:23 kparm.ko