diff options
author | Arjan van de Ven <arjan@linux.intel.com> | 2008-01-24 01:00:45 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-01-24 11:01:09 -0500 |
commit | fabe874a48de45b137f99b4ed3641e0413f465ce (patch) | |
tree | 815204d845875bd14f5623766b2ec5bc6f1fe00c /kernel/lockdep.c | |
parent | 4784b11c4f49eb88f2dd74df6afc5170f193cedc (diff) |
lockdep: fix kernel crash on module unload
Michael Wu noticed in his lkml post at
http://marc.info/?l=linux-kernel&m=119396182726091&w=2
that certain wireless drivers ended up having their name in module
memory, which would then crash the kernel on module unload.
The patch he proposed was a bit clumsy in that it increased the size of
a lockdep entry significantly; the patch below tries another approach,
it checks, on module teardown, if the name of a class is in module space
and then zaps the class. This is very similar to what we already do
with keys that are in module space.
Signed-off-by: Arjan van de Ven <arjan@linux.intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/lockdep.c')
-rw-r--r-- | kernel/lockdep.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 4335f12a27c..e2c07ece367 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -2932,7 +2932,7 @@ static void zap_class(struct lock_class *class) | |||
2932 | 2932 | ||
2933 | } | 2933 | } |
2934 | 2934 | ||
2935 | static inline int within(void *addr, void *start, unsigned long size) | 2935 | static inline int within(const void *addr, void *start, unsigned long size) |
2936 | { | 2936 | { |
2937 | return addr >= start && addr < start + size; | 2937 | return addr >= start && addr < start + size; |
2938 | } | 2938 | } |
@@ -2955,9 +2955,12 @@ void lockdep_free_key_range(void *start, unsigned long size) | |||
2955 | head = classhash_table + i; | 2955 | head = classhash_table + i; |
2956 | if (list_empty(head)) | 2956 | if (list_empty(head)) |
2957 | continue; | 2957 | continue; |
2958 | list_for_each_entry_safe(class, next, head, hash_entry) | 2958 | list_for_each_entry_safe(class, next, head, hash_entry) { |
2959 | if (within(class->key, start, size)) | 2959 | if (within(class->key, start, size)) |
2960 | zap_class(class); | 2960 | zap_class(class); |
2961 | else if (within(class->name, start, size)) | ||
2962 | zap_class(class); | ||
2963 | } | ||
2961 | } | 2964 | } |
2962 | 2965 | ||
2963 | if (locked) | 2966 | if (locked) |