Kprobe can be used in latest kernels when the jprobe is discontinued. I am updating the blog with latest 5.19 linux kernel.
In the pre-handler the arguments need to be fetched using the registers. The arguments are passed in following sequence for x86 :
first 6 arguments in rdi, rsi, rdx, rcx, r8, r9
So if we are trying to probe a function "submit_bio" which has signature :
void submit_bio(struct bio *bio)
Then we can take fetch the first argument using rdi register. It can be done like :
bio_ptr = (struct bio *)regs->di;
/*kprobe_example.c*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/sched.h>
#include <linux/blk_types.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
static char symbol[KSYM_NAME_LEN] = "submit_bio";
module_param_string(symbol, symbol, KSYM_NAME_LEN, 0644);
/* For each probe you need to allocate a kprobe structure */
static struct kprobe kp = {
.symbol_name = symbol,
};
/* For each probe you need to allocate a kprobe structure */
static struct kprobe kp;
/* kprobe pre_handler: called just before the probed instruction is executed */
int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
static int x = 0;
struct bio *bio_ptr = NULL;
if (x%10 == 0)
{
// first 6 arguments in rdi, rsi, rdx, rcx, r8, r9
printk("MY pre_handler:rdi=0x%08lx, rsi=0x%08lx, rdx=0x%08lx\n",
regs->di, regs->si, regs->dx);
bio_ptr = (struct bio *)regs->di;
if (bio_ptr && bio_ptr->bi_bdev && bio_ptr->bi_bdev->bd_disk ) {
printk("disk_name = %s\n", bio_ptr->bi_bdev->bd_disk->disk_name);
printk("disk_ptr = %p\n",bio_ptr->bi_bdev->bd_disk);
}
printk("MY pre_handler: p->addr=0x%p, eip=%lx, eflags=0x%lx\n",
p->addr, regs->ip, regs->flags);
dump_stack();
}
x++;
return 0;
}
/* kprobe post_handler: called after the probed instruction is executed */
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
static int y = 0;
if (y%1000 == 0) {
printk("MY post_handler: p->addr=0x%p, eflags=0x%lx\n", p->addr, regs->flags);
}
y++;
}
int init_module(void)
{
int ret;
kp.pre_handler = handler_pre;
kp.post_handler = handler_post;
if ((ret = register_kprobe(&kp) < 0)) {
printk("register_kprobe failed, returned %d\n", ret);
return -1;
}
printk("kprobe registered\n");
return 0;
}
void cleanup_module(void)
{
unregister_kprobe(&kp);
printk("kprobe unregistered\n");
}
MODULE_LICENSE("GPL");
Makefile for this module :
obj-m = kprobe_example.o
all:
make -C /lib/modules/$(shell uname -r)/build/ M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
When ran this program gives the output :
Sep 7 14:05:01 kernel: [530764.156938] MY pre_handler:rdi=0xffff95ae0cbdd000, rsi=0xfffff7480af750c0, rdx=0x00000000
Sep 7 14:05:01 kernel: [530764.156942] disk_name = sdb
Sep 7 14:05:01 kernel: [530764.156945] disk_ptr = 00000000241100e9
Sep 7 14:05:01 kernel: [530764.156948] MY pre_handler: p->addr=0x000000004b03cd92, eip=ffffffff9bff6001, eflags=0x246
Sep 7 14:05:01 kernel: [530764.156952] CPU: 8 PID: 33831 Comm: sync Tainted: P W OE 5.15.0-47-generic #51-Ubuntu
Sep 7 14:05:01 kernel: [530764.156956] Hardware name: VMware, Inc. VMware7,1/440BX Desktop Reference Platform, BIOS VMW71.00V.17369862.B64.2012240522 12/24/2020
Sep 7 14:05:01 kernel: [530764.156960] Call Trace:
Sep 7 14:05:01 kernel: [530764.156963] <TASK>
Sep 7 14:05:01 kernel: [530764.156966] show_stack+0x52/0x5c
Sep 7 14:05:01 kernel: [530764.156975] dump_stack_lvl+0x4a/0x63
Sep 7 14:05:01 kernel: [530764.156982] dump_stack+0x10/0x16
Sep 7 14:05:01 kernel: [530764.156988] handler_pre.cold+0x90/0xac [kprobe_example]
Sep 7 14:05:01 kernel: [530764.156996] kprobe_ftrace_handler+0xf3/0x1c0
Sep 7 14:05:01 kernel: [530764.157001] ? submit_bio+0x5/0x130
Sep 7 14:05:01 kernel: [530764.157009] ? submit_bio_noacct+0x120/0x120
Sep 7 14:05:01 kernel: [530764.157015] ftrace_ops_list_func+0x181/0x1c0
Sep 7 14:05:01 kernel: [530764.157021] ? submit_bh_wbc+0x18d/0x1c0
Sep 7 14:05:01 kernel: [530764.157029] ? submit_bh_wbc+0x185/0x1c0
Sep 7 14:05:01 kernel: [530764.157040] ftrace_regs_call+0x5/0x57
Sep 7 14:05:01 kernel: [530764.157046] RIP: 0010:submit_bio+0x1/0x130
Sep 7 14:05:01 kernel: [530764.157052] Code: 0c 00 00 00 00 00 00 e9 4b ff ff ff 48 c7 44 24 08 00 00 00 00 eb c7 48 89 38 e9 70 ff ff ff e8 f5 67 7a 00 0f 1f 44 00 00 e8 <1b> 54 a9 ff 55 48 89 e5 41 54 49 89 fc 48 83 ec 18 65 48 8b 04 25
Sep 7 14:05:01 kernel: [530764.157056] RSP: 0018:ffffa6b8c124ba98 EFLAGS: 00000246 ORIG_RAX: 0000000000000000
Sep 7 14:05:01 kernel: [530764.157062] RAX: ffff95ae03e6b000 RBX: ffff95ae07206750 RCX: 0000000000000000
Sep 7 14:05:01 kernel: [530764.157065] RDX: 0000000000000000 RSI: fffff7480af750c0 RDI: ffff95ae0cbdd000
Sep 7 14:05:01 kernel: [530764.157069] RBP: ffffa6b8c124bad0 R08: 0000000000000000 R09: 0000000000003801
Sep 7 14:05:01 kernel: [530764.157072] R10: ffff95ae0cbdd000 R11: 00000000000bffff R12: ffff95ae0cbdd000
Sep 7 14:05:01 kernel: [530764.157076] R13: 0000000000000001 R14: ffffa6b8c124bdf0 R15: 0000000000003800
Sep 7 14:05:01 kernel: [530764.157091] ? submit_bio+0x5/0x130
Sep 7 14:05:01 kernel: [530764.157097] ? submit_bh_wbc+0x18d/0x1c0
Sep 7 14:05:01 kernel: [530764.157104] ? submit_bio+0x5/0x130
Sep 7 14:05:01 kernel: [530764.157109] ? submit_bh_wbc+0x18d/0x1c0
Sep 7 14:05:01 kernel: [530764.157119] __block_write_full_page+0x227/0x4a0
Sep 7 14:05:01 kernel: [530764.157126] ? block_invalidatepage+0x160/0x160
Sep 7 14:05:01 kernel: [530764.157135] ? blkdev_llseek+0x70/0x70
Sep 7 14:05:01 kernel: [530764.157141] block_write_full_page+0x6f/0xa0
Sep 7 14:05:01 kernel: [530764.157149] blkdev_writepage+0x18/0x20
Sep 7 14:05:01 kernel: [530764.157156] __writepage+0x1b/0x70
Sep 7 14:05:01 kernel: [530764.157164] write_cache_pages+0x1a6/0x460
Sep 7 14:05:01 kernel: [530764.157172] ? __set_page_dirty_no_writeback+0x50/0x50
Sep 7 14:05:01 kernel: [530764.157183] ? __set_page_dirty_no_writeback+0x50/0x50
Sep 7 14:05:01 kernel: [530764.157191] ? write_cache_pages+0x5/0x460
Sep 7 14:05:01 kernel: [530764.157202] generic_writepages+0x58/0x90
Sep 7 14:05:01 kernel: [530764.157211] ? generic_writepages+0x5/0x90
Sep 7 14:05:01 kernel: [530764.157219] blkdev_writepages+0xe/0x20
Sep 7 14:05:01 kernel: [530764.157226] do_writepages+0xd7/0x200
Sep 7 14:05:01 kernel: [530764.157235] ? do_writepages+0x5/0x200
Sep 7 14:05:01 kernel: [530764.157240] ? rcu_read_unlock_strict+0x5/0x10
Sep 7 14:05:01 kernel: [530764.157248] ? wbc_attach_and_unlock_inode+0xc2/0x150
Sep 7 14:05:01 kernel: [530764.157257] filemap_fdatawrite_wbc+0x89/0xe0
Sep 7 14:05:01 kernel: [530764.157262] ? filemap_fdatawrite_wbc+0x5/0xe0
Sep 7 14:05:01 kernel: [530764.157269] filemap_fdatawrite+0x50/0x70
Sep 7 14:05:01 kernel: [530764.157281] sync_bdevs+0x154/0x160
Sep 7 14:05:01 kernel: [530764.157291] ksys_sync+0x69/0xa0
Sep 7 14:05:01 kernel: [530764.157297] __do_sys_sync+0xe/0x20
Sep 7 14:05:01 kernel: [530764.157302] do_syscall_64+0x59/0xc0
No comments:
Post a Comment