Re: [PATCH] kernel/kprobes: add check to avoid memory leaks

2017-10-30 Thread Bixuan Cui
On 2017/10/30 12:42, Masami Hiramatsu wrote:
> I don't like this kind of check, since this is obviously caller's bug.
> Why doesn't each caller check this?
Thank you for your answer.

Thanks,
Bixuan Cui



Re: [PATCH] kernel/kprobes: add check to avoid memory leaks

2017-10-29 Thread Masami Hiramatsu
On Mon, 30 Oct 2017 09:10:57 +0800
Bixuan Cui  wrote:

> On 2017/10/25 20:29, Bixuan Cui wrote:
> And test again with this patch:
> 
> insmod testRegKretprobes_004.ko
> [  163.853281] register_kretprobe failed, returned -22
> insmod: can't insert 'testRegKretprobes_004.ko': Operation not permitted
> 
> Thanks,
> Bixuan Cui
> > The register_kretprobe(struct kretprobe *rp) creates and initializes
> > a hash list for rp->free_instances when register kretprobe every time.
> > Then malloc memory for it.
> > 
> > The test case:
> > static struct kretprobe rp;
> > struct  kretprobe *rps[2]={&rp, &rp};
> > static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
> > {
> > printk(KERN_DEBUG "ret_handler\n");
> > return 0;
> > }
> > static int entry_handler(struct kretprobe_instance *ri, struct pt_regs 
> > *regs)
> > {
> > printk(KERN_DEBUG "entry_handler\n");
> > return 0;
> > }
> > static int __init kretprobe_init(void)
> > {
> > int ret;
> > rp.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("do_fork");
> > rp.handler=ret_handler;
> > rp.entry_handler=entry_handler;
> > rp.maxactive = 3;
> > 
> > ret = register_kretprobes(rps,2);
> > 
> > Result:
> > unreferenced object 0x8010b12ad980 (size 64):
> > comm "insmod", pid 17352, jiffies 4298977824 (age 63065.756s)
> > hex dump (first 32 bytes):
> > 00 00 00 00 00 00 00 00 d8 84 12 fc ff 7f ff ff 
> > 74 65 73 74 52 65 67 4b 72 65 74 70 72 6f 62 65 testRegKretprobe
> > backtrace:
> > [] create_object+0x1e0/0x3f0
> > [] kmemleak_alloc+0x6c/0xf0
> > [] __kmalloc+0x23c/0x2e0
> > [] register_kretprobe+0x12c/0x350
> > 
> > When call register_kretprobes(struct kretprobe **rps, int num) with the
> > same rps(num>=2).
> > The first time,call INIT_HLIST_HEAD() and kmalloc() to malloc memory for the
> > hash list,then save into rp->free_instances.
> > The second time,call INIT_HLIST_HEAD() and kmalloc() then create a new
> > hash list into rp->free_instances and lost the first rp->free_instances.
> > So add check to avoid it.
> > 

I don't like this kind of check, since this is obviously caller's bug.
Why doesn't each caller check this?

Thank you,

> > Reported-and-tested-by: kangwen 
> > Signed-off-by: Bixuan Cui 
> > ---
> >  kernel/kprobes.c | 8 +++-
> >  1 file changed, 7 insertions(+), 1 deletion(-)
> > 
> > diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> > index 6301dae..f19f191 100644
> > --- a/kernel/kprobes.c
> > +++ b/kernel/kprobes.c
> > @@ -1890,10 +1890,16 @@ EXPORT_SYMBOL_GPL(register_kretprobe);
> > 
> >  int register_kretprobes(struct kretprobe **rps, int num)
> >  {
> > -   int ret = 0, i;
> > +   int ret = 0, i, j;
> > 
> > if (num <= 0)
> > return -EINVAL;
> > +
> > +   for (i = 0; i < num-1; i++)
> > +   for (j = i+1; j < num; j++)
> > +   if (rps[i] == rps[j])
> > +   return -EINVAL;
> > +
> > for (i = 0; i < num; i++) {
> > ret = register_kretprobe(rps[i]);
> > if (ret < 0) {
> > --
> > 2.6.2
> > 
> > 
> > 
> > 
> > .
> > 
> 
> 


-- 
Masami Hiramatsu 


Re: [PATCH] kernel/kprobes: add check to avoid memory leaks

2017-10-29 Thread Bixuan Cui
On 2017/10/25 20:29, Bixuan Cui wrote:
And test again with this patch:

insmod testRegKretprobes_004.ko
[  163.853281] register_kretprobe failed, returned -22
insmod: can't insert 'testRegKretprobes_004.ko': Operation not permitted

Thanks,
Bixuan Cui
> The register_kretprobe(struct kretprobe *rp) creates and initializes
> a hash list for rp->free_instances when register kretprobe every time.
> Then malloc memory for it.
> 
> The test case:
> static struct kretprobe rp;
> struct  kretprobe *rps[2]={&rp, &rp};
> static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
> {
> printk(KERN_DEBUG "ret_handler\n");
> return 0;
> }
> static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
> {
> printk(KERN_DEBUG "entry_handler\n");
> return 0;
> }
> static int __init kretprobe_init(void)
> {
> int ret;
> rp.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("do_fork");
> rp.handler=ret_handler;
> rp.entry_handler=entry_handler;
> rp.maxactive = 3;
> 
> ret = register_kretprobes(rps,2);
> 
> Result:
> unreferenced object 0x8010b12ad980 (size 64):
> comm "insmod", pid 17352, jiffies 4298977824 (age 63065.756s)
> hex dump (first 32 bytes):
> 00 00 00 00 00 00 00 00 d8 84 12 fc ff 7f ff ff 
> 74 65 73 74 52 65 67 4b 72 65 74 70 72 6f 62 65 testRegKretprobe
> backtrace:
> [] create_object+0x1e0/0x3f0
> [] kmemleak_alloc+0x6c/0xf0
> [] __kmalloc+0x23c/0x2e0
> [] register_kretprobe+0x12c/0x350
> 
> When call register_kretprobes(struct kretprobe **rps, int num) with the
> same rps(num>=2).
> The first time,call INIT_HLIST_HEAD() and kmalloc() to malloc memory for the
> hash list,then save into rp->free_instances.
> The second time,call INIT_HLIST_HEAD() and kmalloc() then create a new
> hash list into rp->free_instances and lost the first rp->free_instances.
> So add check to avoid it.
> 
> Reported-and-tested-by: kangwen 
> Signed-off-by: Bixuan Cui 
> ---
>  kernel/kprobes.c | 8 +++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/kprobes.c b/kernel/kprobes.c
> index 6301dae..f19f191 100644
> --- a/kernel/kprobes.c
> +++ b/kernel/kprobes.c
> @@ -1890,10 +1890,16 @@ EXPORT_SYMBOL_GPL(register_kretprobe);
> 
>  int register_kretprobes(struct kretprobe **rps, int num)
>  {
> - int ret = 0, i;
> + int ret = 0, i, j;
> 
>   if (num <= 0)
>   return -EINVAL;
> +
> + for (i = 0; i < num-1; i++)
> + for (j = i+1; j < num; j++)
> + if (rps[i] == rps[j])
> + return -EINVAL;
> +
>   for (i = 0; i < num; i++) {
>   ret = register_kretprobe(rps[i]);
>   if (ret < 0) {
> --
> 2.6.2
> 
> 
> 
> 
> .
> 




[PATCH] kernel/kprobes: add check to avoid memory leaks

2017-10-25 Thread Bixuan Cui
The register_kretprobe(struct kretprobe *rp) creates and initializes
a hash list for rp->free_instances when register kretprobe every time.
Then malloc memory for it.

The test case:
static struct kretprobe rp;
struct  kretprobe *rps[2]={&rp, &rp};
static int ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk(KERN_DEBUG "ret_handler\n");
return 0;
}
static int entry_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
{
printk(KERN_DEBUG "entry_handler\n");
return 0;
}
static int __init kretprobe_init(void)
{
int ret;
rp.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("do_fork");
rp.handler=ret_handler;
rp.entry_handler=entry_handler;
rp.maxactive = 3;

ret = register_kretprobes(rps,2);

Result:
unreferenced object 0x8010b12ad980 (size 64):
comm "insmod", pid 17352, jiffies 4298977824 (age 63065.756s)
hex dump (first 32 bytes):
00 00 00 00 00 00 00 00 d8 84 12 fc ff 7f ff ff 
74 65 73 74 52 65 67 4b 72 65 74 70 72 6f 62 65 testRegKretprobe
backtrace:
[] create_object+0x1e0/0x3f0
[] kmemleak_alloc+0x6c/0xf0
[] __kmalloc+0x23c/0x2e0
[] register_kretprobe+0x12c/0x350

When call register_kretprobes(struct kretprobe **rps, int num) with the
same rps(num>=2).
The first time,call INIT_HLIST_HEAD() and kmalloc() to malloc memory for the
hash list,then save into rp->free_instances.
The second time,call INIT_HLIST_HEAD() and kmalloc() then create a new
hash list into rp->free_instances and lost the first rp->free_instances.
So add check to avoid it.

Reported-and-tested-by: kangwen 
Signed-off-by: Bixuan Cui 
---
 kernel/kprobes.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 6301dae..f19f191 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1890,10 +1890,16 @@ EXPORT_SYMBOL_GPL(register_kretprobe);

 int register_kretprobes(struct kretprobe **rps, int num)
 {
-   int ret = 0, i;
+   int ret = 0, i, j;

if (num <= 0)
return -EINVAL;
+
+   for (i = 0; i < num-1; i++)
+   for (j = i+1; j < num; j++)
+   if (rps[i] == rps[j])
+   return -EINVAL;
+
for (i = 0; i < num; i++) {
ret = register_kretprobe(rps[i]);
if (ret < 0) {
--
2.6.2