kretprobe kretprobe_instance私有数据区

本文解析了Linux内核中的kretprobe机制,涉及entry_handler和ret_handler的调用过程,kretprobe_instance结构的使用,以及register_kretprobe函数中内存分配策略。特别关注了多个进程共享data内存的情况和内存管理细节。
摘要由CSDN通过智能技术生成

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:

  • ret_addr: the return address
  • rp: points to the corresponding kretprobe object
  • task: points to the corresponding task struct
  • data: points to per return-instance(实例) private data; see “Kretprobe entry-handler” for details.
    The regs_return_value(regs) macro provides a simple abstraction to extract the return value from the appropriate register as defined by
    the architecture’s ABI.

看完下边这段解释就会明白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

  • 21
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值