diff options
author | Kees Cook <keescook@chromium.org> | 2014-03-10 16:42:48 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-24 13:18:26 -0400 |
commit | 9dd721c6dbfc310f94306902611f86dda87a45fa (patch) | |
tree | 56dbfcb8ae3c05f26be75dba824c5fb18b1ac25f | |
parent | e2b32e6785138d92d2a40e0d0473575c8c7310a2 (diff) |
x86, kaslr: fix module lock ordering problem
There was a potential lock ordering problem with the module kASLR patch
("x86, kaslr: randomize module base load address"). This patch removes
the usage of the module_mutex and creates a new mutex to protect the
module base address offset value.
Chain exists of:
text_mutex --> kprobe_insn_slots.mutex --> module_mutex
[ 0.515561] Possible unsafe locking scenario:
[ 0.515561]
[ 0.515561] CPU0 CPU1
[ 0.515561] ---- ----
[ 0.515561] lock(module_mutex);
[ 0.515561] lock(kprobe_insn_slots.mutex);
[ 0.515561] lock(module_mutex);
[ 0.515561] lock(text_mutex);
[ 0.515561]
[ 0.515561] *** DEADLOCK ***
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Andy Honig <ahonig@google.com>
Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r-- | arch/x86/kernel/module.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/arch/x86/kernel/module.c b/arch/x86/kernel/module.c index 49483137371f..e69f9882bf95 100644 --- a/arch/x86/kernel/module.c +++ b/arch/x86/kernel/module.c | |||
@@ -48,6 +48,9 @@ do { \ | |||
48 | static unsigned long module_load_offset; | 48 | static unsigned long module_load_offset; |
49 | static int randomize_modules = 1; | 49 | static int randomize_modules = 1; |
50 | 50 | ||
51 | /* Mutex protects the module_load_offset. */ | ||
52 | static DEFINE_MUTEX(module_kaslr_mutex); | ||
53 | |||
51 | static int __init parse_nokaslr(char *p) | 54 | static int __init parse_nokaslr(char *p) |
52 | { | 55 | { |
53 | randomize_modules = 0; | 56 | randomize_modules = 0; |
@@ -58,7 +61,7 @@ early_param("nokaslr", parse_nokaslr); | |||
58 | static unsigned long int get_module_load_offset(void) | 61 | static unsigned long int get_module_load_offset(void) |
59 | { | 62 | { |
60 | if (randomize_modules) { | 63 | if (randomize_modules) { |
61 | mutex_lock(&module_mutex); | 64 | mutex_lock(&module_kaslr_mutex); |
62 | /* | 65 | /* |
63 | * Calculate the module_load_offset the first time this | 66 | * Calculate the module_load_offset the first time this |
64 | * code is called. Once calculated it stays the same until | 67 | * code is called. Once calculated it stays the same until |
@@ -67,7 +70,7 @@ static unsigned long int get_module_load_offset(void) | |||
67 | if (module_load_offset == 0) | 70 | if (module_load_offset == 0) |
68 | module_load_offset = | 71 | module_load_offset = |
69 | (get_random_int() % 1024 + 1) * PAGE_SIZE; | 72 | (get_random_int() % 1024 + 1) * PAGE_SIZE; |
70 | mutex_unlock(&module_mutex); | 73 | mutex_unlock(&module_kaslr_mutex); |
71 | } | 74 | } |
72 | return module_load_offset; | 75 | return module_load_offset; |
73 | } | 76 | } |