This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: unregistering kretprobe mid-function (was: stpd issues)


On Sat, 2005-08-20 at 04:23, Frank Ch. Eigler wrote:
> hiet wrote:
> 
> > [...]  I observed some issues with the new transport with the
> > attached module (insert jprobes and kretprobes on all system
> > calls). [...]
> 
> I wonder what happens if one has a kretprobe on an cunning function
> (sys_delete_module), which indirectly may end up trying to remove the
> probe (unregister_kretprobe) during its execution (systemtap probe
> cleanup).  In other words, how does the kretprobe logic handle the
> removal function, when the entry half of a return probe has been hit,
> and the return part is pending?
> 
> - FChE

This situation is covered.  A kretprobe_instance object always hangs
around until the function returns.  If the kretprobe is unregistered
before the probed function returns, the instance's kretprobe pointer is
set to NULL.  When the function returns, no handler is run but the
instance is freed.

Attached is a test to verify that.  It should print the following lines
on /var/log/messages:

... kernel: kretunreg: register_kretprobe returns 0
... kernel: nret = 4, sum = 65
... kernel: kretunreg: register_kretprobe returns 0
... kernel: nret = 4, sum = 65

Jim
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kprobes.h>

/*
 * Test of unregistering a return probe while the probed function
 * is running.
 * Usage: insmod kretunreg.ko
 */

static int nret;

static int inst_bump(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	nret++;
	return 0;
}

static noinline int bump(int i, struct kretprobe *r)
{
	if (i == 5)
		unregister_kretprobe(r);
	return i+1;
}

struct kretprobe rp = {
	.kp.addr = (kprobe_opcode_t*) bump,
	.handler = inst_bump,
	.maxactive = 1
};

static int runtest(void)
{
	int i, ret;
	int sum = 0;
	nret = 0;

	ret = register_kretprobe(&rp);
	printk(KERN_ERR "kretunreg: register_kretprobe returns %d\n", ret);
	if (ret != 0)
		return -1;
	for (i=1; i<=10; i++) {
		sum += bump(i, &rp);
	}
	printk(KERN_INFO "nret = %d, sum = %d\n", nret, sum);
	return 0;
}

static int __init kretunreg_init(void)
{
	int i;
	for (i = 1; i <= 2; i++) {
		if (runtest() != 0)
			return -1;
	}
	return 0;
}

static void __exit kretunreg_exit(void)
{
	printk(KERN_INFO "kretunreg: exiting...\n");
}

module_init(kretunreg_init);
module_exit(kretunreg_exit);
MODULE_LICENSE("GPL");
#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>

/*
 * Test of unregistering a return probe while the probed function
 * is running.
 * Usage: insmod kretunreg.ko
 */

static int nret;

static int inst_bump(struct kretprobe_instance *ri, struct pt_regs *regs)
{
	nret++;
	return 0;
}

static noinline int bump(int i, struct kretprobe *r)
{
	if (i == 5)
		unregister_kretprobe(r);
	return i+1;
}

struct kretprobe rp = {
	.handler = inst_bump,
	.maxactive = 1
};

static int runtest(void)
{
	int i, ret;
	int sum = 0;
	nret = 0;

	ret = register_kretprobe(&rp);
	printk(KERN_ERR "kretunreg: register_kretprobe returns %d\n", ret);
	if (ret != 0)
		return -1;
	for (i=1; i<=10; i++) {
		sum += bump(i, &rp);
	}
	printk(KERN_INFO "nret = %d, sum = %d\n", nret, sum);
	return 0;
}

static int __init kretunreg_init(void)
{
	int i;
	rp.kp.addr = (kprobe_opcode_t*) kallsyms_lookup_name(".bump");
	for (i = 1; i <= 2; i++) {
		if (runtest() != 0)
			return -1;
	}
	return 0;
}

static void __exit kretunreg_exit(void)
{
	printk(KERN_INFO "kretunreg: exiting...\n");
}

module_init(kretunreg_init);
module_exit(kretunreg_exit);
MODULE_LICENSE("GPL");

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]