赞
踩
entry_handler
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
ret_handler
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
其中结构体kretprobe_instance可以用来在entry_handler和ret_handler之间传递参数。
struct kretprobe_instance {
struct hlist_node hlist;
struct kretprobe *rp;
kprobe_opcode_t *ret_addr;
struct task_struct *task;
char data[0];
};
char data[0]
的大小是在register_kretprobe时根据设定的data_size来设定。
register_kretprobe() returns 0 on success, or a negative errno otherwise.
User’s return-probe handler (rp->handler)::
#include <linux/kprobes.h>
#include <linux/ptrace.h>
int kretprobe_handler(struct kretprobe_instance *ri,
struct pt_regs *regs);
regs is as described for kprobe.pre_handler. ri points to the
kretprobe_instance object, of which the following fields may be
of interest:
看完下边这段解释就会明白data的作用以及如何使用。
Multiple entry and return handler invocations are matched using the unique
kretprobe_instance object associated with them. Additionally, a user
may also specify per return-instance private data to be part of each
kretprobe_instance object. This is especially useful when sharing private
data between corresponding user entry and return handlers. The size of each
private data object can be specified at kretprobe registration time by
setting the data_size field of the kretprobe struct. This data can be
accessed through the data field of each kretprobe_instance object.
char data[0]
的size由结构体struct kretprobe的成员data_size来初始化。
/* * Function-return probe - * Note: * User needs to provide a handler function, and initialize maxactive. * maxactive - The maximum number of instances of the probed function that * can be active concurrently. * nmissed - tracks the number of times the probed function's return was * ignored, due to maxactive being too low. * */ struct kretprobe { struct kprobe kp; kretprobe_handler_t handler; kretprobe_handler_t entry_handler; int maxactive; // 可以同时活动的被探测函数的最大实例数。 int nmissed; size_t data_size; struct hlist_head free_instances; raw_spinlock_t lock; };
是不是同一个进程公用一个kretprobe_instance结构体?
comm df private addr = 0xffff88867513b570
comm df private addr = 0xffff88867513b2b0
comm ls private addr = 0xffff88867513b570
答:从打印的信息来看并不是,多个进程会访问同一段内存。
为什么存在多个进程共用data内存的场景?
不同的进程ri->data
也会指向同一个地址?从内核代码出发,看看在注册kretprobe的时候是怎么分配内存的?
int register_kretprobe(struct kretprobe *rp) { /*****/ INIT_HLIST_HEAD(&rp->free_instances); // 根据设定的最大实例数来分配data_size内存,且内存没有进行置零操作。 for (i = 0; i < rp->maxactive; i++) { inst = kmalloc(sizeof(struct kretprobe_instance) + rp->data_size, GFP_KERNEL); if (inst == NULL) { free_rp_inst(rp); return -ENOMEM; } INIT_HLIST_NODE(&inst->hlist); hlist_add_head(&inst->hlist, &rp->free_instances); } rp->nmissed = 0; /* Establish function entry probe point */ ret = register_kprobe(&rp->kp); if (ret != 0) free_rp_inst(rp); return ret; } EXPORT_SYMBOL_GPL(register_kretprobe);
从上述内存申请的逻辑来看,被跟踪的实例是存在限制的,在注册kretprobe时可以根据实际情况进行调整。
这段初始化申请的内存是所有kretprobe实例共用的,也就是说是轮转使用的,所以在ret_handler使用完这段内存之后,需要将私有数据区的相关字段set为0。
Documentation/kprobes.txt
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。