diff options
author | Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> | 2015-11-05 21:50:51 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-05 22:34:48 -0500 |
commit | fc5aeeaf593278f07ffa4d97296e27423ecae867 (patch) | |
tree | 17b6521e9f9ba2d43d6d0b4d416d5a599e561980 /mm | |
parent | f2377d4eaab2aabe1938b3974b5b94f5ba4c7ead (diff) |
mm/kasan: prevent deadlock in kasan reporting
When we end up calling kasan_report in real mode, our shadow mapping for
the spinlock variable will show poisoned. This will result in us calling
kasan_report_error with lock_report spin lock held. To prevent this
disable kasan reporting when we are priting error w.r.t kasan.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Reviewed-by: Andrey Ryabinin <ryabinin.a.a@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/kasan/report.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/mm/kasan/report.c b/mm/kasan/report.c index c5367089703c..7833f074ede8 100644 --- a/mm/kasan/report.c +++ b/mm/kasan/report.c | |||
@@ -173,12 +173,10 @@ static void print_shadow_for_address(const void *addr) | |||
173 | * function, because generic functions may try to | 173 | * function, because generic functions may try to |
174 | * access kasan mapping for the passed address. | 174 | * access kasan mapping for the passed address. |
175 | */ | 175 | */ |
176 | kasan_disable_current(); | ||
177 | memcpy(shadow_buf, shadow_row, SHADOW_BYTES_PER_ROW); | 176 | memcpy(shadow_buf, shadow_row, SHADOW_BYTES_PER_ROW); |
178 | print_hex_dump(KERN_ERR, buffer, | 177 | print_hex_dump(KERN_ERR, buffer, |
179 | DUMP_PREFIX_NONE, SHADOW_BYTES_PER_ROW, 1, | 178 | DUMP_PREFIX_NONE, SHADOW_BYTES_PER_ROW, 1, |
180 | shadow_buf, SHADOW_BYTES_PER_ROW, 0); | 179 | shadow_buf, SHADOW_BYTES_PER_ROW, 0); |
181 | kasan_enable_current(); | ||
182 | 180 | ||
183 | if (row_is_guilty(shadow_row, shadow)) | 181 | if (row_is_guilty(shadow_row, shadow)) |
184 | pr_err("%*c\n", | 182 | pr_err("%*c\n", |
@@ -195,6 +193,10 @@ void kasan_report_error(struct kasan_access_info *info) | |||
195 | { | 193 | { |
196 | unsigned long flags; | 194 | unsigned long flags; |
197 | 195 | ||
196 | /* | ||
197 | * Make sure we don't end up in loop. | ||
198 | */ | ||
199 | kasan_disable_current(); | ||
198 | spin_lock_irqsave(&report_lock, flags); | 200 | spin_lock_irqsave(&report_lock, flags); |
199 | pr_err("=================================" | 201 | pr_err("=================================" |
200 | "=================================\n"); | 202 | "=================================\n"); |
@@ -204,12 +206,17 @@ void kasan_report_error(struct kasan_access_info *info) | |||
204 | pr_err("=================================" | 206 | pr_err("=================================" |
205 | "=================================\n"); | 207 | "=================================\n"); |
206 | spin_unlock_irqrestore(&report_lock, flags); | 208 | spin_unlock_irqrestore(&report_lock, flags); |
209 | kasan_enable_current(); | ||
207 | } | 210 | } |
208 | 211 | ||
209 | void kasan_report_user_access(struct kasan_access_info *info) | 212 | void kasan_report_user_access(struct kasan_access_info *info) |
210 | { | 213 | { |
211 | unsigned long flags; | 214 | unsigned long flags; |
212 | 215 | ||
216 | /* | ||
217 | * Make sure we don't end up in loop. | ||
218 | */ | ||
219 | kasan_disable_current(); | ||
213 | spin_lock_irqsave(&report_lock, flags); | 220 | spin_lock_irqsave(&report_lock, flags); |
214 | pr_err("=================================" | 221 | pr_err("=================================" |
215 | "=================================\n"); | 222 | "=================================\n"); |
@@ -222,6 +229,7 @@ void kasan_report_user_access(struct kasan_access_info *info) | |||
222 | pr_err("=================================" | 229 | pr_err("=================================" |
223 | "=================================\n"); | 230 | "=================================\n"); |
224 | spin_unlock_irqrestore(&report_lock, flags); | 231 | spin_unlock_irqrestore(&report_lock, flags); |
232 | kasan_enable_current(); | ||
225 | } | 233 | } |
226 | 234 | ||
227 | void kasan_report(unsigned long addr, size_t size, | 235 | void kasan_report(unsigned long addr, size_t size, |