Commit d3b904a2 authored by Martin Schwidefsky's avatar Martin Schwidefsky Committed by Linus Torvalds

[PATCH] s390: uaccess bug.

Don't rely on lowcore information in __copy_{from,to}_user_asm. Fix compile
for peculiar get_user() usage in drivers/scsi/scsi_ioctl.c
parent ca70cd21
/* /*
* arch/s390/lib/uaccess.S * arch/s390/lib/uaccess.S
* fixup routines for copy_{from|to}_user functions. * __copy_{from|to}_user functions.
* *
* s390 * s390
* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
* *
* These functions have standard call interface * These functions have standard call interface
...@@ -22,17 +22,23 @@ __copy_from_user_asm: ...@@ -22,17 +22,23 @@ __copy_from_user_asm:
1: sacf 0 1: sacf 0
lr %r2,%r5 lr %r2,%r5
br %r14 br %r14
2: sll %r4,1 2: lhi %r1,-4096
srl %r4,1 lr %r3,%r4
lhi %r3,-4096 slr %r3,%r1 # %r3 = %r4 + 4096
sll %r3,1 nr %r3,%r1 # %r3 = (%r4 + 4096) & -4096
srl %r3,1 slr %r3,%r4 # %r3 = #bytes to next user page boundary
n %r3,__LC_TRANS_EXC_ADDR clr %r5,%r3 # copy crosses next page boundary ?
sr %r3,%r4 jnh 1b # no, this page fauled
jm 1b # The page after the current user page might have faulted.
j 0b # We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r2,%r4,0
jo 3b
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.long 0b,2b .long 0b,2b
.long 3b,1b
.previous .previous
.align 4 .align 4
...@@ -46,17 +52,23 @@ __copy_to_user_asm: ...@@ -46,17 +52,23 @@ __copy_to_user_asm:
1: sacf 0 1: sacf 0
lr %r2,%r3 lr %r2,%r3
br %r14 br %r14
2: sll %r4,1 2: lhi %r1,-4096
srl %r4,1 lr %r5,%r4
lhi %r5,-4096 slr %r5,%r1 # %r5 = %r4 + 4096
sll %r5,1 nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096
srl %r5,1 slr %r5,%r4 # %r5 = #bytes to next user page boundary
n %r5,__LC_TRANS_EXC_ADDR clr %r3,%r5 # copy crosses next page boundary ?
sr %r5,%r4 jnh 1b # no, the current page fauled
jm 1b # The page after the current user page might have faulted.
j 0b # We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r4,%r2,0
jo 3b
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.long 0b,2b .long 0b,2b
.long 3b,1b
.previous .previous
.align 4 .align 4
...@@ -71,18 +83,26 @@ __clear_user_asm: ...@@ -71,18 +83,26 @@ __clear_user_asm:
0: mvcle %r4,%r2,0 0: mvcle %r4,%r2,0
jo 0b jo 0b
1: sacf 0 1: sacf 0
lr %r2,%r3
br %r14 br %r14
2: sll %r4,1 2: lr %r2,%r5
srl %r4,1 lhi %r1,-4096
lhi %r5,-4096 slr %r5,%r1 # %r5 = %r4 + 4096
sll %r5,1 nr %r5,%r1 # %r5 = (%r4 + 4096) & -4096
srl %r5,1 slr %r5,%r4 # %r5 = #bytes to next user page boundary
n %r5,__LC_TRANS_EXC_ADDR clr %r2,%r5 # copy crosses next page boundary ?
sr %r5,%r4 jnh 1b # no, the current page fauled
jm 1b # The page after the current user page might have faulted.
j 0b # We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
slr %r2,%r5
3: mvcle %r4,%r2,0
jo 3b
j 1b
4: alr %r2,%r5
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.long 0b,2b .long 0b,2b
.long 3b,4b
.previous .previous
/* /*
* arch/s390x/lib/uaccess.S * arch/s390x/lib/uaccess.S
* fixup routines for copy_{from|to}_user functions. * __copy_{from|to}_user functions.
* *
* S390 * s390
* Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation * Copyright (C) 2000,2002 IBM Deutschland Entwicklung GmbH, IBM Corporation
* Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com) * Authors(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
* *
* These functions have standard call interface * These functions have standard call interface
...@@ -22,14 +22,23 @@ __copy_from_user_asm: ...@@ -22,14 +22,23 @@ __copy_from_user_asm:
1: sacf 0 1: sacf 0
lgr %r2,%r5 lgr %r2,%r5
br %r14 br %r14
2: lghi %r3,-4096 2: lghi %r1,-4096
ng %r3,__LC_TRANS_EXC_ADDR lgr %r3,%r4
sgr %r3,%r4 slgr %r3,%r1 # %r3 = %r4 + 4096
jm 1b ngr %r3,%r1 # %r3 = (%r4 + 4096) & -4096
j 0b slgr %r3,%r4 # %r3 = #bytes to next user page boundary
clgr %r5,%r3 # copy crosses next page boundary ?
jnh 1b # no, this page fauled
# The page after the current user page might have faulted.
# We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r2,%r4,0
jo 3b
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.align 8
.quad 0b,2b .quad 0b,2b
.quad 3b,1b
.previous .previous
.align 4 .align 4
...@@ -43,14 +52,23 @@ __copy_to_user_asm: ...@@ -43,14 +52,23 @@ __copy_to_user_asm:
1: sacf 0 1: sacf 0
lgr %r2,%r3 lgr %r2,%r3
br %r14 br %r14
2: lghi %r5,-4096 2: lghi %r1,-4096
ng %r5,__LC_TRANS_EXC_ADDR lgr %r5,%r4
sgr %r5,%r4 slgr %r5,%r1 # %r5 = %r4 + 4096
jm 1b ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096
j 0b slgr %r5,%r4 # %r5 = #bytes to next user page boundary
clgr %r3,%r5 # copy crosses next page boundary ?
jnh 1b # no, the current page fauled
# The page after the current user page might have faulted.
# We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
3: mvcle %r4,%r2,0
jo 3b
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.align 8 .quad 0b,2b
.quad 0b,2b .quad 3b,1b
.previous .previous
.align 4 .align 4
...@@ -65,14 +83,25 @@ __clear_user_asm: ...@@ -65,14 +83,25 @@ __clear_user_asm:
0: mvcle %r4,%r2,0 0: mvcle %r4,%r2,0
jo 0b jo 0b
1: sacf 0 1: sacf 0
lgr %r2,%r5
br %r14 br %r14
2: lghi %r5,-4096 2: lgr %r2,%r5
ng %r5,__LC_TRANS_EXC_ADDR lghi %r1,-4096
sgr %r5,%r4 slgr %r5,%r1 # %r5 = %r4 + 4096
jm 1b ngr %r5,%r1 # %r5 = (%r4 + 4096) & -4096
j 0b slgr %r5,%r4 # %r5 = #bytes to next user page boundary
clgr %r2,%r5 # copy crosses next page boundary ?
jnh 1b # no, the current page fauled
# The page after the current user page might have faulted.
# We cant't find out which page because the program check handler
# might have callled schedule, destroying all lowcore information.
# We retry with the shortened length.
slgr %r2,%r5
3: mvcle %r4,%r2,0
jo 3b
j 1b
4: algr %r2,%r5
j 1b
.section __ex_table,"a" .section __ex_table,"a"
.align 8 .quad 0b,2b
.quad 0b,2b .quad 3b,4b
.previous .previous
...@@ -199,24 +199,23 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) ...@@ -199,24 +199,23 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
*/ */
#define __put_user(x, ptr) \ #define __put_user(x, ptr) \
({ \ ({ \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
__typeof__(*(ptr)) __x = (x); \ __typeof__(*(ptr)) __x = (x); \
int __pu_err; \ int __pu_err; \
switch (sizeof (*(ptr))) { \ switch (sizeof (*(ptr))) { \
case 1: \ case 1: \
__pu_err = __put_user_asm_1((__u8)(__u32) __x, \ __pu_err = __put_user_asm_1((__u8)(__u32) __x, \
__pu_addr); \ ptr); \
break; \ break; \
case 2: \ case 2: \
__pu_err = __put_user_asm_2((__u16)(__u32) __x, \ __pu_err = __put_user_asm_2((__u16)(__u32) __x, \
__pu_addr); \ ptr); \
break; \ break; \
case 4: \ case 4: \
__pu_err = __put_user_asm_4((__u32) __x, \ __pu_err = __put_user_asm_4((__u32) __x, \
__pu_addr); \ ptr); \
break; \ break; \
case 8: \ case 8: \
__pu_err = __put_user_asm_8(&__x, __pu_addr); \ __pu_err = __put_user_asm_8(&__x, ptr); \
break; \ break; \
default: \ default: \
__pu_err = __put_user_bad(); \ __pu_err = __put_user_bad(); \
...@@ -333,21 +332,20 @@ extern int __put_user_bad(void); ...@@ -333,21 +332,20 @@ extern int __put_user_bad(void);
#define __get_user(x, ptr) \ #define __get_user(x, ptr) \
({ \ ({ \
__typeof__(ptr) __gu_addr = (ptr); \
__typeof__(*(ptr)) __x; \ __typeof__(*(ptr)) __x; \
int __gu_err; \ int __gu_err; \
switch (sizeof(*(__gu_addr))) { \ switch (sizeof(*(ptr))) { \
case 1: \ case 1: \
__get_user_asm_1(__x, __gu_addr, __gu_err); \ __get_user_asm_1(__x, ptr, __gu_err); \
break; \ break; \
case 2: \ case 2: \
__get_user_asm_2(__x, __gu_addr, __gu_err); \ __get_user_asm_2(__x, ptr, __gu_err); \
break; \ break; \
case 4: \ case 4: \
__get_user_asm_4(__x, __gu_addr, __gu_err); \ __get_user_asm_4(__x, ptr, __gu_err); \
break; \ break; \
case 8: \ case 8: \
__get_user_asm_8(__x, __gu_addr, __gu_err); \ __get_user_asm_8(__x, ptr, __gu_err); \
break; \ break; \
default: \ default: \
__x = 0; \ __x = 0; \
......
...@@ -177,25 +177,24 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr) ...@@ -177,25 +177,24 @@ extern inline int __put_user_asm_1(__u8 x, void *ptr)
*/ */
#define __put_user(x, ptr) \ #define __put_user(x, ptr) \
({ \ ({ \
__typeof__(*(ptr)) *__pu_addr = (ptr); \
__typeof__(*(ptr)) __x = (x); \ __typeof__(*(ptr)) __x = (x); \
int __pu_err; \ int __pu_err; \
switch (sizeof (*(__pu_addr))) { \ switch (sizeof (*(ptr))) { \
case 1: \ case 1: \
__pu_err = __put_user_asm_1((__u8)(__u64)(__x), \ __pu_err = __put_user_asm_1((__u8)(__u64)(__x), \
__pu_addr); \ ptr); \
break; \ break; \
case 2: \ case 2: \
__pu_err = __put_user_asm_2((__u16)(__u64)(__x),\ __pu_err = __put_user_asm_2((__u16)(__u64)(__x),\
__pu_addr); \ ptr); \
break; \ break; \
case 4: \ case 4: \
__pu_err = __put_user_asm_4((__u32)(__u64)(__x),\ __pu_err = __put_user_asm_4((__u32)(__u64)(__x),\
__pu_addr); \ ptr); \
break; \ break; \
case 8: \ case 8: \
__pu_err = __put_user_asm_8((__u64)(__x), \ __pu_err = __put_user_asm_8((__u64)(__x), \
__pu_addr); \ ptr); \
break; \ break; \
default: \ default: \
__pu_err = __put_user_bad(); \ __pu_err = __put_user_bad(); \
...@@ -290,21 +289,20 @@ extern int __put_user_bad(void); ...@@ -290,21 +289,20 @@ extern int __put_user_bad(void);
#define __get_user(x, ptr) \ #define __get_user(x, ptr) \
({ \ ({ \
__typeof__(ptr) __gu_addr = (ptr); \
__typeof__(*(ptr)) __x; \ __typeof__(*(ptr)) __x; \
int __gu_err; \ int __gu_err; \
switch (sizeof(*(ptr))) { \ switch (sizeof(*(ptr))) { \
case 1: \ case 1: \
__get_user_asm_1(__x,__gu_addr,__gu_err); \ __get_user_asm_1(__x,ptr,__gu_err); \
break; \ break; \
case 2: \ case 2: \
__get_user_asm_2(__x,__gu_addr,__gu_err); \ __get_user_asm_2(__x,ptr,__gu_err); \
break; \ break; \
case 4: \ case 4: \
__get_user_asm_4(__x,__gu_addr,__gu_err); \ __get_user_asm_4(__x,ptr,__gu_err); \
break; \ break; \
case 8: \ case 8: \
__get_user_asm_8(__x,__gu_addr,__gu_err); \ __get_user_asm_8(__x,ptr,__gu_err); \
break; \ break; \
default: \ default: \
__x = 0; \ __x = 0; \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment