aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2008-09-10 07:37:17 -0400
committerIngo Molnar <mingo@elte.hu>2008-09-11 03:44:21 -0400
commit3ee1afa308f2a38e5d1e2ad3752ad7abcf480da1 (patch)
tree914e0f3bbd32a387cf6095c6955369fa8da7ebf6
parentc10d38dda1774ed4540380333cabd229eff37094 (diff)
x86: some lock annotations for user copy paths, v2
- introduce might_fault() - handle the atomic user copy paths correctly [ mingo@elte.hu: move might_sleep() outside of in_atomic(). ] Signed-off-by: Nick Piggin <npiggin@suse.de> Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/x86/lib/usercopy_32.c12
-rw-r--r--arch/x86/lib/usercopy_64.c8
-rw-r--r--include/asm-x86/uaccess.h18
-rw-r--r--include/asm-x86/uaccess_32.h12
-rw-r--r--include/asm-x86/uaccess_64.h12
-rw-r--r--include/linux/kernel.h9
-rw-r--r--mm/memory.c15
7 files changed, 39 insertions, 47 deletions
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index 8eedde2a9cac..7393152a252e 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -32,9 +32,7 @@ static inline int __movsl_is_ok(unsigned long a1, unsigned long a2, unsigned lon
32#define __do_strncpy_from_user(dst, src, count, res) \ 32#define __do_strncpy_from_user(dst, src, count, res) \
33do { \ 33do { \
34 int __d0, __d1, __d2; \ 34 int __d0, __d1, __d2; \
35 might_sleep(); \ 35 might_fault(); \
36 if (current->mm) \
37 might_lock_read(&current->mm->mmap_sem); \
38 __asm__ __volatile__( \ 36 __asm__ __volatile__( \
39 " testl %1,%1\n" \ 37 " testl %1,%1\n" \
40 " jz 2f\n" \ 38 " jz 2f\n" \
@@ -121,9 +119,7 @@ EXPORT_SYMBOL(strncpy_from_user);
121#define __do_clear_user(addr,size) \ 119#define __do_clear_user(addr,size) \
122do { \ 120do { \
123 int __d0; \ 121 int __d0; \
124 might_sleep(); \ 122 might_fault(); \
125 if (current->mm) \
126 might_lock_read(&current->mm->mmap_sem); \
127 __asm__ __volatile__( \ 123 __asm__ __volatile__( \
128 "0: rep; stosl\n" \ 124 "0: rep; stosl\n" \
129 " movl %2,%0\n" \ 125 " movl %2,%0\n" \
@@ -193,9 +189,7 @@ long strnlen_user(const char __user *s, long n)
193 unsigned long mask = -__addr_ok(s); 189 unsigned long mask = -__addr_ok(s);
194 unsigned long res, tmp; 190 unsigned long res, tmp;
195 191
196 might_sleep(); 192 might_fault();
197 if (current->mm)
198 might_lock_read(&current->mm->mmap_sem);
199 193
200 __asm__ __volatile__( 194 __asm__ __volatile__(
201 " testl %0, %0\n" 195 " testl %0, %0\n"
diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
index 847d12945998..64d6c84e6353 100644
--- a/arch/x86/lib/usercopy_64.c
+++ b/arch/x86/lib/usercopy_64.c
@@ -15,9 +15,7 @@
15#define __do_strncpy_from_user(dst,src,count,res) \ 15#define __do_strncpy_from_user(dst,src,count,res) \
16do { \ 16do { \
17 long __d0, __d1, __d2; \ 17 long __d0, __d1, __d2; \
18 might_sleep(); \ 18 might_fault(); \
19 if (current->mm) \
20 might_lock_read(&current->mm->mmap_sem); \
21 __asm__ __volatile__( \ 19 __asm__ __volatile__( \
22 " testq %1,%1\n" \ 20 " testq %1,%1\n" \
23 " jz 2f\n" \ 21 " jz 2f\n" \
@@ -66,9 +64,7 @@ EXPORT_SYMBOL(strncpy_from_user);
66unsigned long __clear_user(void __user *addr, unsigned long size) 64unsigned long __clear_user(void __user *addr, unsigned long size)
67{ 65{
68 long __d0; 66 long __d0;
69 might_sleep(); 67 might_fault();
70 if (current->mm)
71 might_lock_read(&current->mm->mmap_sem);
72 /* no memory constraint because it doesn't change any memory gcc knows 68 /* no memory constraint because it doesn't change any memory gcc knows
73 about */ 69 about */
74 asm volatile( 70 asm volatile(
diff --git a/include/asm-x86/uaccess.h b/include/asm-x86/uaccess.h
index ad29752a1713..39f8420c75d9 100644
--- a/include/asm-x86/uaccess.h
+++ b/include/asm-x86/uaccess.h
@@ -8,8 +8,6 @@
8#include <linux/thread_info.h> 8#include <linux/thread_info.h>
9#include <linux/prefetch.h> 9#include <linux/prefetch.h>
10#include <linux/string.h> 10#include <linux/string.h>
11#include <linux/lockdep.h>
12#include <linux/sched.h>
13#include <asm/asm.h> 11#include <asm/asm.h>
14#include <asm/page.h> 12#include <asm/page.h>
15 13
@@ -159,9 +157,7 @@ extern int __get_user_bad(void);
159 int __ret_gu; \ 157 int __ret_gu; \
160 unsigned long __val_gu; \ 158 unsigned long __val_gu; \
161 __chk_user_ptr(ptr); \ 159 __chk_user_ptr(ptr); \
162 might_sleep(); \ 160 might_fault(); \
163 if (current->mm) \
164 might_lock_read(&current->mm->mmap_sem); \
165 switch (sizeof(*(ptr))) { \ 161 switch (sizeof(*(ptr))) { \
166 case 1: \ 162 case 1: \
167 __get_user_x(1, __ret_gu, __val_gu, ptr); \ 163 __get_user_x(1, __ret_gu, __val_gu, ptr); \
@@ -246,9 +242,7 @@ extern void __put_user_8(void);
246 int __ret_pu; \ 242 int __ret_pu; \
247 __typeof__(*(ptr)) __pu_val; \ 243 __typeof__(*(ptr)) __pu_val; \
248 __chk_user_ptr(ptr); \ 244 __chk_user_ptr(ptr); \
249 might_sleep(); \ 245 might_fault(); \
250 if (current->mm) \
251 might_lock_read(&current->mm->mmap_sem); \
252 __pu_val = x; \ 246 __pu_val = x; \
253 switch (sizeof(*(ptr))) { \ 247 switch (sizeof(*(ptr))) { \
254 case 1: \ 248 case 1: \
@@ -273,9 +267,7 @@ extern void __put_user_8(void);
273#define __put_user_size(x, ptr, size, retval, errret) \ 267#define __put_user_size(x, ptr, size, retval, errret) \
274do { \ 268do { \
275 retval = 0; \ 269 retval = 0; \
276 might_sleep(); \ 270 might_fault(); \
277 if (current->mm) \
278 might_lock_read(&current->mm->mmap_sem); \
279 __chk_user_ptr(ptr); \ 271 __chk_user_ptr(ptr); \
280 switch (size) { \ 272 switch (size) { \
281 case 1: \ 273 case 1: \
@@ -328,9 +320,7 @@ do { \
328#define __get_user_size(x, ptr, size, retval, errret) \ 320#define __get_user_size(x, ptr, size, retval, errret) \
329do { \ 321do { \
330 retval = 0; \ 322 retval = 0; \
331 might_sleep(); \ 323 might_fault(); \
332 if (current->mm) \
333 might_lock_read(&current->mm->mmap_sem); \
334 __chk_user_ptr(ptr); \ 324 __chk_user_ptr(ptr); \
335 switch (size) { \ 325 switch (size) { \
336 case 1: \ 326 case 1: \
diff --git a/include/asm-x86/uaccess_32.h b/include/asm-x86/uaccess_32.h
index d725e2d703f7..d10e842ec3ee 100644
--- a/include/asm-x86/uaccess_32.h
+++ b/include/asm-x86/uaccess_32.h
@@ -82,9 +82,7 @@ __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n)
82static __always_inline unsigned long __must_check 82static __always_inline unsigned long __must_check
83__copy_to_user(void __user *to, const void *from, unsigned long n) 83__copy_to_user(void __user *to, const void *from, unsigned long n)
84{ 84{
85 might_sleep(); 85 might_fault();
86 if (current->mm)
87 might_lock_read(&current->mm->mmap_sem);
88 return __copy_to_user_inatomic(to, from, n); 86 return __copy_to_user_inatomic(to, from, n);
89} 87}
90 88
@@ -139,9 +137,7 @@ __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
139static __always_inline unsigned long 137static __always_inline unsigned long
140__copy_from_user(void *to, const void __user *from, unsigned long n) 138__copy_from_user(void *to, const void __user *from, unsigned long n)
141{ 139{
142 might_sleep(); 140 might_fault();
143 if (current->mm)
144 might_lock_read(&current->mm->mmap_sem);
145 if (__builtin_constant_p(n)) { 141 if (__builtin_constant_p(n)) {
146 unsigned long ret; 142 unsigned long ret;
147 143
@@ -163,9 +159,7 @@ __copy_from_user(void *to, const void __user *from, unsigned long n)
163static __always_inline unsigned long __copy_from_user_nocache(void *to, 159static __always_inline unsigned long __copy_from_user_nocache(void *to,
164 const void __user *from, unsigned long n) 160 const void __user *from, unsigned long n)
165{ 161{
166 might_sleep(); 162 might_fault();
167 if (current->mm)
168 might_lock_read(&current->mm->mmap_sem);
169 if (__builtin_constant_p(n)) { 163 if (__builtin_constant_p(n)) {
170 unsigned long ret; 164 unsigned long ret;
171 165
diff --git a/include/asm-x86/uaccess_64.h b/include/asm-x86/uaccess_64.h
index 40a7205fe576..13fd56fbc3ab 100644
--- a/include/asm-x86/uaccess_64.h
+++ b/include/asm-x86/uaccess_64.h
@@ -29,9 +29,7 @@ int __copy_from_user(void *dst, const void __user *src, unsigned size)
29{ 29{
30 int ret = 0; 30 int ret = 0;
31 31
32 might_sleep(); 32 might_fault();
33 if (current->mm)
34 might_lock_read(&current->mm->mmap_sem);
35 if (!__builtin_constant_p(size)) 33 if (!__builtin_constant_p(size))
36 return copy_user_generic(dst, (__force void *)src, size); 34 return copy_user_generic(dst, (__force void *)src, size);
37 switch (size) { 35 switch (size) {
@@ -75,9 +73,7 @@ int __copy_to_user(void __user *dst, const void *src, unsigned size)
75{ 73{
76 int ret = 0; 74 int ret = 0;
77 75
78 might_sleep(); 76 might_fault();
79 if (current->mm)
80 might_lock_read(&current->mm->mmap_sem);
81 if (!__builtin_constant_p(size)) 77 if (!__builtin_constant_p(size))
82 return copy_user_generic((__force void *)dst, src, size); 78 return copy_user_generic((__force void *)dst, src, size);
83 switch (size) { 79 switch (size) {
@@ -121,9 +117,7 @@ int __copy_in_user(void __user *dst, const void __user *src, unsigned size)
121{ 117{
122 int ret = 0; 118 int ret = 0;
123 119
124 might_sleep(); 120 might_fault();
125 if (current->mm)
126 might_lock_read(&current->mm->mmap_sem);
127 if (!__builtin_constant_p(size)) 121 if (!__builtin_constant_p(size))
128 return copy_user_generic((__force void *)dst, 122 return copy_user_generic((__force void *)dst,
129 (__force void *)src, size); 123 (__force void *)src, size);
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 2651f805ba6d..e580ec095765 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -140,6 +140,15 @@ extern int _cond_resched(void);
140 (__x < 0) ? -__x : __x; \ 140 (__x < 0) ? -__x : __x; \
141 }) 141 })
142 142
143#ifdef CONFIG_PROVE_LOCKING
144void might_fault(void);
145#else
146static inline void might_fault(void)
147{
148 might_sleep();
149}
150#endif
151
143extern struct atomic_notifier_head panic_notifier_list; 152extern struct atomic_notifier_head panic_notifier_list;
144extern long (*panic_blink)(long time); 153extern long (*panic_blink)(long time);
145NORET_TYPE void panic(const char * fmt, ...) 154NORET_TYPE void panic(const char * fmt, ...)
diff --git a/mm/memory.c b/mm/memory.c
index 1002f473f497..b8fdf4e5e65b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3016,3 +3016,18 @@ void print_vma_addr(char *prefix, unsigned long ip)
3016 } 3016 }
3017 up_read(&current->mm->mmap_sem); 3017 up_read(&current->mm->mmap_sem);
3018} 3018}
3019
3020#ifdef CONFIG_PROVE_LOCKING
3021void might_fault(void)
3022{
3023 might_sleep();
3024 /*
3025 * it would be nicer only to annotate paths which are not under
3026 * pagefault_disable, however that requires a larger audit and
3027 * providing helpers like get_user_atomic.
3028 */
3029 if (!in_atomic() && current->mm)
3030 might_lock_read(&current->mm->mmap_sem);
3031}
3032EXPORT_SYMBOL(might_fault);
3033#endif