Skip to content
Snippets Groups Projects
Commit 6bfd93c3 authored by Paul Mackerras's avatar Paul Mackerras
Browse files

powerpc: Fix incorrect might_sleep in __get_user/__put_user on kernel addresses


We have a case where __get_user and __put_user can validly be used
on kernel addresses in interrupt context - namely, the alignment
exception handler, as our get/put_unaligned just do a single access
and rely on the alignment exception handler to fix things up in the
rare cases where the cpu can't handle it in hardware.  Thus we can
get alignment exceptions in the network stack at interrupt level.
The alignment exception handler does a __get_user to read the
instruction and blows up in might_sleep().

Since a __get_user on a kernel address won't actually ever sleep,
this makes the might_sleep conditional on the address being less
than PAGE_OFFSET.

Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent 6e197696
No related branches found
No related tags found
No related merge requests found
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <asm/processor.h> #include <asm/processor.h>
#include <asm/page.h>
#define VERIFY_READ 0 #define VERIFY_READ 0
#define VERIFY_WRITE 1 #define VERIFY_WRITE 1
...@@ -179,9 +180,11 @@ do { \ ...@@ -179,9 +180,11 @@ do { \
#define __put_user_nocheck(x, ptr, size) \ #define __put_user_nocheck(x, ptr, size) \
({ \ ({ \
long __pu_err; \ long __pu_err; \
might_sleep(); \ __typeof__(*(ptr)) __user *__pu_addr = (ptr); \
if (!is_kernel_addr((unsigned long)__pu_addr)) \
might_sleep(); \
__chk_user_ptr(ptr); \ __chk_user_ptr(ptr); \
__put_user_size((x), (ptr), (size), __pu_err); \ __put_user_size((x), __pu_addr, (size), __pu_err); \
__pu_err; \ __pu_err; \
}) })
...@@ -258,9 +261,11 @@ do { \ ...@@ -258,9 +261,11 @@ do { \
({ \ ({ \
long __gu_err; \ long __gu_err; \
unsigned long __gu_val; \ unsigned long __gu_val; \
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \ __chk_user_ptr(ptr); \
might_sleep(); \ if (!is_kernel_addr((unsigned long)__gu_addr)) \
__get_user_size(__gu_val, (ptr), (size), __gu_err); \ might_sleep(); \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \ (x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \ __gu_err; \
}) })
...@@ -270,9 +275,11 @@ do { \ ...@@ -270,9 +275,11 @@ do { \
({ \ ({ \
long __gu_err; \ long __gu_err; \
long long __gu_val; \ long long __gu_val; \
const __typeof__(*(ptr)) __user *__gu_addr = (ptr); \
__chk_user_ptr(ptr); \ __chk_user_ptr(ptr); \
might_sleep(); \ if (!is_kernel_addr((unsigned long)__gu_addr)) \
__get_user_size(__gu_val, (ptr), (size), __gu_err); \ might_sleep(); \
__get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
(x) = (__typeof__(*(ptr)))__gu_val; \ (x) = (__typeof__(*(ptr)))__gu_val; \
__gu_err; \ __gu_err; \
}) })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment