On Wed, Feb 3, 2016 at 8:11 PM, Paul Bolle <pebo...@tiscali.nl> wrote: > Hi Dmitry, > > On wo, 2016-02-03 at 17:16 +0100, Paul Bolle wrote: >> The above should provide me with enough information to figure out >> what's going on here. > > I've instrumented ser_gigaset with some printk's. Basically I added the > stuff pasted at the end of this message. In 10.000 runs of the program > syzkaller generated the added printk's suggest that struct ser_cardstate > is freed every time. > > (Note that this was done on a machine that, probably like the VM > syzkaller was running in, doesn't have the clunky hardware that this > driver manages attached.) > > Before I dive deeper into this: can you reproduce this leak? Is it > perhaps a one in gazillion runs thing? Do you have the logs of a run > that warned about this leak at hand? > > Thanks, > > > Paul Bolle > > @@ -375,9 +377,12 @@ static void gigaset_device_release(struct device *dev) > { > struct cardstate *cs = dev_get_drvdata(dev); > > - if (!cs) > + if (!cs) { > + pr_info("%s: no cardstate", __func__); > return; > + } > dev_set_drvdata(dev, NULL); > + pr_info("%s: kfree(%p)", __func__, cs->hw.ser); > kfree(cs->hw.ser); > cs->hw.ser = NULL; > } > @@ -392,6 +397,7 @@ static int gigaset_initcshw(struct cardstate *cs) > struct ser_cardstate *scs; > > scs = kzalloc(sizeof(struct ser_cardstate), GFP_KERNEL); > + pr_info("%s: scs = %p", __func__, scs); > if (!scs) { > pr_err("out of memory\n"); > return -ENOMEM;
Forgot to mention that you need to run it in a parallel loop, sorry. This one should do: // autogenerated by syzkaller (http://github.com/google/syzkaller) #include <pthread.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <sys/syscall.h> #include <unistd.h> #include <sys/types.h> #include <sys/wait.h> void work() { long r[7]; memset(r, -1, sizeof(r)); r[0] = syscall(SYS_mmap, 0x20000000ul, 0x10000ul, 0x3ul, 0x32ul, 0xfffffffffffffffful, 0x0ul); r[2] = syscall(SYS_open, "/dev/ptmx", 0x8002ul, 0x0ul, 0, 0, 0); *(uint32_t*)0x20002b1e = (uint32_t)0x10; r[4] = syscall(SYS_ioctl, r[2], 0x5423ul, 0x20002b1eul, 0, 0, 0); *(uint32_t*)0x20009000 = (uint32_t)0x7; r[6] = syscall(SYS_ioctl, r[2], 0x5423ul, 0x20009000ul, 0, 0, 0); } int main() { int running, status; for (;;) { while (running < 32) { if (fork() == 0) { work(); exit(0); } running++; } if (wait(&status) > 0) running--; } } While running it, sample/proc/slabinfo with: # cat /proc/slabinfo | egrep "^kmalloc-2048" It constantly grows.