--- kernel/softirq.c | 23 +++++++++++++++++++++++ mm/slab.c | 6 +++++- 2 files changed, 28 insertions(+), 1 deletion(-) --- wireless-dev.orig/kernel/softirq.c 2007-02-17 11:35:52.381777421 +0100 +++ wireless-dev/kernel/softirq.c 2007-02-17 11:59:54.431777421 +0100 @@ -353,6 +353,29 @@ void fastcall __tasklet_schedule(struct EXPORT_SYMBOL(__tasklet_schedule); +int fastcall __tasklet_free_check(char *from, unsigned long len) +{ + struct tasklet_struct *t; + unsigned long start = (unsigned long) from; + int ret = 0; + + /* really should check all CPUs but I only have one + * right now so I'm fine. hah! */ + t = __get_cpu_var(tasklet_vec).list; + while (t) { + unsigned long tul = (unsigned long)t; + if (tul >= start && tul < (start+len)) { + printk(KERN_ERR "attempt to free scheduled tasklet %p in object %p!\n", t, from); + printk(KERN_ERR "will leak memory instead!\n"); + dump_stack(); + ret = -EBUSY; + } + t = t->next; + } + + return ret; +} + void fastcall __tasklet_hi_schedule(struct tasklet_struct *t) { unsigned long flags; --- wireless-dev.orig/mm/slab.c 2007-02-17 11:36:56.181777421 +0100 +++ wireless-dev/mm/slab.c 2007-02-17 11:45:17.161777421 +0100 @@ -3747,6 +3747,9 @@ EXPORT_SYMBOL(kmem_cache_free); * Don't free memory not originally allocated by kmalloc() * or you will run into trouble. */ + +extern int fastcall __tasklet_free_check(char *from, unsigned long length); + void kfree(const void *objp) { struct kmem_cache *c; @@ -3758,7 +3761,8 @@ void kfree(const void *objp) kfree_debugcheck(objp); c = virt_to_cache(objp); debug_check_no_locks_freed(objp, obj_size(c)); - __cache_free(c, (void *)objp); + if (__tasklet_free_check(objp, obj_size(c)) == 0) + __cache_free(c, (void *)objp); local_irq_restore(flags); } EXPORT_SYMBOL(kfree);