* The 64-bit version of __access_ok is broken.
@ 2002-12-05 15:28 Carsten Langgaard
2002-12-09 4:18 ` Ralf Baechle
0 siblings, 1 reply; 10+ messages in thread
From: Carsten Langgaard @ 2002-12-05 15:28 UTC (permalink / raw)
To: Ralf Baechle, Dominic Sweetman, chris, kevink, linux-mips
[-- Attachment #1: Type: text/plain, Size: 1238 bytes --]
I have addressed this issue before, and I do it again, because we have a
potential kernel crash situation, if this isn't fixed.
The __access_ok macro in include/asm-mips64/uaccess.h and the check_axs
macro in arch/mips64/kernel/unaligned.c need to be changed in order to
work correctly, it's a copy from the 32-bit kernel. It's not good enough
to simply check for the "sign bit" of the address.
The area between USEG (XUSEG) and KSEG0 will in 64-bit addressing mode
generate an address error, if accessed.
The size of the area depend on the number of virtual addressing bits
implemented in the CPU.
Please take a look at the patch below.
I think Ralf had some objection the last time I send it, about the fix,
not being efficient enough (performance vice), but I think we need to
consider stability and functionality over performance. So until someone
comes up with a better solution, I think we need this fix.
/Carsten
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
[-- Attachment #2: access_ok.patch --]
[-- Type: text/plain, Size: 2305 bytes --]
Index: arch/mips64/kernel/unaligned.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/unaligned.c,v
retrieving revision 1.6.2.7
diff -u -r1.6.2.7 unaligned.c
--- arch/mips64/kernel/unaligned.c 5 Dec 2002 03:09:58 -0000 1.6.2.7
+++ arch/mips64/kernel/unaligned.c 5 Dec 2002 15:06:59 -0000
@@ -89,11 +89,14 @@
#define __STR(x) #x
/*
- * User code may only access USEG; kernel code may access the
- * entire address space.
+ * User code may only access USEG;
+ * Kernel code may access the entire address space, except the area between
+ * USEG (XUSEG) and KSEG0.
*/
-#define check_axs(pc,a,s) \
- if ((long)(~(pc) & ((a) | ((a)+(s)))) < 0) \
+#define check_axs(pc,a,s) \
+ if (((pc < KUSIZE) && (((a) | ((a)+(s))) >= KUSIZE)) || \
+ ((((a) | ((a)+(s))) < K0BASE) && \
+ (((a) | ((a)+(s))) >= KUSIZE))) \
goto sigbus;
static inline int emulate_load_store_insn(struct pt_regs *regs,
Index: include/asm-mips64/uaccess.h
===================================================================
RCS file: /home/cvs/linux/include/asm-mips64/uaccess.h,v
retrieving revision 1.13.2.1
diff -u -r1.13.2.1 uaccess.h
--- include/asm-mips64/uaccess.h 1 Jul 2002 15:27:31 -0000 1.13.2.1
+++ include/asm-mips64/uaccess.h 5 Dec 2002 15:07:11 -0000
@@ -40,16 +40,23 @@
* than tests.
*
* Address valid if:
- * - "addr" doesn't have any high-bits set
- * - AND "size" doesn't have any high-bits set
- * - AND "addr+size" doesn't have any high-bits set
- * - OR we are in kernel mode.
+ * - In user mode and "addr" and "addr+size" in USEG (or XUSEG).
+ * - OR we are in kernel mode and "addr" and "addr+size" isn't in the
+ * area between USEG (XUSEG) and KSEG0.
*/
#define __ua_size(size) \
(__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size))
-#define __access_ok(addr,size,mask) \
- (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0)
+static inline int
+__access_ok(unsigned long addr, unsigned long size, long mask)
+{
+ if (((mask) && ((addr | (addr+size)) >= KUSIZE)) ||
+ (((addr | (addr+size)) < K0BASE) &&
+ ((addr | (addr+size)) >= KUSIZE)))
+ return 0;
+ else
+ return 1;
+}
#define __access_mask ((long)(get_fs().seg))
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: The 64-bit version of __access_ok is broken. 2002-12-05 15:28 The 64-bit version of __access_ok is broken Carsten Langgaard @ 2002-12-09 4:18 ` Ralf Baechle 2002-12-09 9:30 ` Carsten Langgaard 0 siblings, 1 reply; 10+ messages in thread From: Ralf Baechle @ 2002-12-09 4:18 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Dominic Sweetman, chris, kevink, linux-mips On Thu, Dec 05, 2002 at 04:28:07PM +0100, Carsten Langgaard wrote: > I have addressed this issue before, and I do it again, because we have a > potential kernel crash situation, if this isn't fixed. > > The __access_ok macro in include/asm-mips64/uaccess.h and the check_axs > macro in arch/mips64/kernel/unaligned.c need to be changed in order to > work correctly, it's a copy from the 32-bit kernel. It's not good enough > to simply check for the "sign bit" of the address. > The area between USEG (XUSEG) and KSEG0 will in 64-bit addressing mode > generate an address error, if accessed. > The size of the area depend on the number of virtual addressing bits > implemented in the CPU. > > Please take a look at the patch below. > I think Ralf had some objection the last time I send it, about the fix, > not being efficient enough (performance vice), but I think we need to > consider stability and functionality over performance. So until someone > comes up with a better solution, I think we need this fix. Standard Linux approach - a bad solution is worse than no solution. Just to show the impact of your patch: text data bss dec hex filename 1817824 1079664 173664 3071152 2edcb0 vmlinux-cvs 1870752 1079664 173664 3124080 2fab70 vmlinux-carsten So that's 52928 bytes of bloat. __access_ok is one of those kernel functions that are inlined so often that each extra instruction needs a _very_ good justification. The patch below adds 32 bytes. It's still not the right thing though. It's not fixing all stuff in the assembler code. I have a better patch but it results in odd userspace behaviour. Smells like a compiler problem ... Ralf Index: arch/mips64/kernel/process.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/process.c,v retrieving revision 1.18.2.9 diff -u -r1.18.2.9 process.c --- arch/mips64/kernel/process.c 2 Dec 2002 00:24:52 -0000 1.18.2.9 +++ arch/mips64/kernel/process.c 7 Dec 2002 02:13:40 -0000 @@ -52,17 +52,19 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) { unsigned long status; + int compat32 = current->thread.mflags & MF_32BIT; /* New thread looses kernel privileges. */ status = regs->cp0_status & ~(ST0_CU0|ST0_FR|ST0_KSU); status |= KSU_USER; - status |= (current->thread.mflags & MF_32BIT) ? 0 : ST0_FR; + status |= compat32 ? 0 : ST0_FR; regs->cp0_status = status; current->used_math = 0; loose_fpu(); regs->cp0_epc = pc; regs->regs[29] = sp; current->thread.current_ds = USER_DS; + current->thread.user_ds.seg = - (compat32 ? 0x80000000UL : TASK_SIZE); } void exit_thread(void) Index: include/asm-mips64/processor.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips64/processor.h,v retrieving revision 1.32.2.9 diff -u -r1.32.2.9 processor.h --- include/asm-mips64/processor.h 4 Nov 2002 19:39:56 -0000 1.32.2.9 +++ include/asm-mips64/processor.h 7 Dec 2002 02:14:10 -0000 @@ -180,7 +180,7 @@ #define MF_LOGADE 2 /* Log address errors to syslog */ #define MF_32BIT 4 /* Process is in 32-bit compat mode */ unsigned long mflags; - mm_segment_t current_ds; + mm_segment_t current_ds, user_ds; unsigned long irix_trampoline; /* Wheee... */ unsigned long irix_oldctx; }; @@ -208,7 +208,7 @@ /* \ * For now the default is to fix address errors \ */ \ - MF_FIXADE, { 0 }, 0, 0 \ + MF_FIXADE, KERNEL_DS, { -TASK_SIZE }, 0, 0 \ } #ifdef __KERNEL__ Index: include/asm-mips64/uaccess.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips64/uaccess.h,v retrieving revision 1.13.2.1 diff -u -r1.13.2.1 uaccess.h --- include/asm-mips64/uaccess.h 1 Jul 2002 15:27:31 -0000 1.13.2.1 +++ include/asm-mips64/uaccess.h 7 Dec 2002 02:14:10 -0000 @@ -23,7 +23,7 @@ * For historical reasons, these macros are grossly misnamed. */ #define KERNEL_DS ((mm_segment_t) { (unsigned long) 0L }) -#define USER_DS ((mm_segment_t) { (unsigned long) -1L }) +#define USER_DS (current->thread.user_ds) #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -49,7 +49,7 @@ (__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size)) #define __access_ok(addr,size,mask) \ - (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0) + (((mask) & (addr | (addr + size) | __ua_size(size))) == 0) #define __access_mask ((long)(get_fs().seg)) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 4:18 ` Ralf Baechle @ 2002-12-09 9:30 ` Carsten Langgaard 2002-12-09 11:54 ` Dominic Sweetman 2002-12-09 16:36 ` Ralf Baechle 0 siblings, 2 replies; 10+ messages in thread From: Carsten Langgaard @ 2002-12-09 9:30 UTC (permalink / raw) To: Ralf Baechle; +Cc: Dominic Sweetman, chris, kevink, linux-mips Ralf Baechle wrote: > On Thu, Dec 05, 2002 at 04:28:07PM +0100, Carsten Langgaard wrote: > > > I have addressed this issue before, and I do it again, because we have a > > potential kernel crash situation, if this isn't fixed. > > > > The __access_ok macro in include/asm-mips64/uaccess.h and the check_axs > > macro in arch/mips64/kernel/unaligned.c need to be changed in order to > > work correctly, it's a copy from the 32-bit kernel. It's not good enough > > to simply check for the "sign bit" of the address. > > The area between USEG (XUSEG) and KSEG0 will in 64-bit addressing mode > > generate an address error, if accessed. > > The size of the area depend on the number of virtual addressing bits > > implemented in the CPU. > > > > Please take a look at the patch below. > > I think Ralf had some objection the last time I send it, about the fix, > > not being efficient enough (performance vice), but I think we need to > > consider stability and functionality over performance. So until someone > > comes up with a better solution, I think we need this fix. > > Standard Linux approach - a bad solution is worse than no solution. > > Just to show the impact of your patch: > text data bss dec hex filename > 1817824 1079664 173664 3071152 2edcb0 vmlinux-cvs > 1870752 1079664 173664 3124080 2fab70 vmlinux-carsten > > So that's 52928 bytes of bloat. > __access_ok is one of those kernel > functions that are inlined so often that each extra instruction needs a > _very_ good justification. I really disagree. My solution may impact the size of the kernel (the increase is less than 2 percent), but it prevent kernel crashes. Sure we may be able to find a better solution, but it has been almost 1/2 year ago, the last time I addressed this problem. I know at least one other on the list was hit by this problem. > > The patch below adds 32 bytes. It's still not the right thing though. It's > not fixing all stuff in the assembler code. I have a better patch but it > results in odd userspace behaviour. Smells like a compiler problem ... I tried you patch below, but then nothing seems to work. > > Ralf > > Index: arch/mips64/kernel/process.c > =================================================================== > RCS file: /home/cvs/linux/arch/mips64/kernel/process.c,v > retrieving revision 1.18.2.9 > diff -u -r1.18.2.9 process.c > --- arch/mips64/kernel/process.c 2 Dec 2002 00:24:52 -0000 1.18.2.9 > +++ arch/mips64/kernel/process.c 7 Dec 2002 02:13:40 -0000 > @@ -52,17 +52,19 @@ > void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp) > { > unsigned long status; > + int compat32 = current->thread.mflags & MF_32BIT; > > /* New thread looses kernel privileges. */ > status = regs->cp0_status & ~(ST0_CU0|ST0_FR|ST0_KSU); > status |= KSU_USER; > - status |= (current->thread.mflags & MF_32BIT) ? 0 : ST0_FR; > + status |= compat32 ? 0 : ST0_FR; > regs->cp0_status = status; > current->used_math = 0; > loose_fpu(); > regs->cp0_epc = pc; > regs->regs[29] = sp; > current->thread.current_ds = USER_DS; > + current->thread.user_ds.seg = - (compat32 ? 0x80000000UL : TASK_SIZE); > } > > void exit_thread(void) > Index: include/asm-mips64/processor.h > =================================================================== > RCS file: /home/cvs/linux/include/asm-mips64/processor.h,v > retrieving revision 1.32.2.9 > diff -u -r1.32.2.9 processor.h > --- include/asm-mips64/processor.h 4 Nov 2002 19:39:56 -0000 1.32.2.9 > +++ include/asm-mips64/processor.h 7 Dec 2002 02:14:10 -0000 > @@ -180,7 +180,7 @@ > #define MF_LOGADE 2 /* Log address errors to syslog */ > #define MF_32BIT 4 /* Process is in 32-bit compat mode */ > unsigned long mflags; > - mm_segment_t current_ds; > + mm_segment_t current_ds, user_ds; > unsigned long irix_trampoline; /* Wheee... */ > unsigned long irix_oldctx; > }; > @@ -208,7 +208,7 @@ > /* \ > * For now the default is to fix address errors \ > */ \ > - MF_FIXADE, { 0 }, 0, 0 \ > + MF_FIXADE, KERNEL_DS, { -TASK_SIZE }, 0, 0 \ > } > > #ifdef __KERNEL__ > Index: include/asm-mips64/uaccess.h > =================================================================== > RCS file: /home/cvs/linux/include/asm-mips64/uaccess.h,v > retrieving revision 1.13.2.1 > diff -u -r1.13.2.1 uaccess.h > --- include/asm-mips64/uaccess.h 1 Jul 2002 15:27:31 -0000 1.13.2.1 > +++ include/asm-mips64/uaccess.h 7 Dec 2002 02:14:10 -0000 > @@ -23,7 +23,7 @@ > * For historical reasons, these macros are grossly misnamed. > */ > #define KERNEL_DS ((mm_segment_t) { (unsigned long) 0L }) > -#define USER_DS ((mm_segment_t) { (unsigned long) -1L }) > +#define USER_DS (current->thread.user_ds) > > #define VERIFY_READ 0 > #define VERIFY_WRITE 1 > @@ -49,7 +49,7 @@ > (__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size)) > > #define __access_ok(addr,size,mask) \ > - (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0) > + (((mask) & (addr | (addr + size) | __ua_size(size))) == 0) > > #define __access_mask ((long)(get_fs().seg)) > -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 9:30 ` Carsten Langgaard @ 2002-12-09 11:54 ` Dominic Sweetman 2002-12-09 12:27 ` Carsten Langgaard 2002-12-09 18:38 ` Ralf Baechle 2002-12-09 16:36 ` Ralf Baechle 1 sibling, 2 replies; 10+ messages in thread From: Dominic Sweetman @ 2002-12-09 11:54 UTC (permalink / raw) To: Ralf Baechle Cc: Carsten Langgaard, Dominic Sweetman, chris, kevink, linux-mips > > > The __access_ok macro in include/asm-mips64/uaccess.h and the > > > check_axs macro in arch/mips64/kernel/unaligned.c ... is a copy > > > from the 32-bit kernel... > > > > > > The area between USEG (XUSEG) and KSEG0 will in 64-bit > > > addressing mode generate an address error, if accessed. I'd like to be clear about the consequences of this. Presumably the 'access_ok()' macro is used to check addresses which were (originally) provided by a user program's system call. Carsten, are you saying that if such an address is set to say 2**41 in a CPU supporting 40-bit user virtual addresses, that the kernel will crash? If so, that seems to require a fix, even if we don't know a very efficient one. But perhaps any problem is a bit more subtle than that? -- Dominic Sweetman MIPS Technologies The Fruit Farm, Ely Road, Chittering, CAMBS CB5 9PH, ENGLAND phone +44 1223 706205/fax +44 1223 706250/swbrd +44 1223 706200 http://www.algor.co.uk ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 11:54 ` Dominic Sweetman @ 2002-12-09 12:27 ` Carsten Langgaard 2002-12-09 18:38 ` Ralf Baechle 1 sibling, 0 replies; 10+ messages in thread From: Carsten Langgaard @ 2002-12-09 12:27 UTC (permalink / raw) To: Dominic Sweetman Cc: Ralf Baechle, Dominic Sweetman, chris, kevink, linux-mips Dominic Sweetman wrote: > > > > The __access_ok macro in include/asm-mips64/uaccess.h and the > > > > check_axs macro in arch/mips64/kernel/unaligned.c ... is a copy > > > > from the 32-bit kernel... > > > > > > > > The area between USEG (XUSEG) and KSEG0 will in 64-bit > > > > addressing mode generate an address error, if accessed. > > I'd like to be clear about the consequences of this. Presumably the > 'access_ok()' macro is used to check addresses which were (originally) > provided by a user program's system call. > > Carsten, are you saying that if such an address is set to say 2**41 in > a CPU supporting 40-bit user virtual addresses, that the kernel will > crash? Yes, that's the case. It's been a while since I fixed it locally, but if I ran something like crashme, I could end up, in a situation where the kernel tries (on the behalf of the user) to access an address like 2**41 in a CPU supporting 40-bit user virtual addresses, which generate an address error and because we are in kernel mode we die. > > If so, that seems to require a fix, even if we don't know a very > efficient one. But perhaps any problem is a bit more subtle than > that? > > -- > Dominic Sweetman > MIPS Technologies > The Fruit Farm, Ely Road, Chittering, CAMBS CB5 9PH, ENGLAND > phone +44 1223 706205/fax +44 1223 706250/swbrd +44 1223 706200 > http://www.algor.co.uk -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 11:54 ` Dominic Sweetman 2002-12-09 12:27 ` Carsten Langgaard @ 2002-12-09 18:38 ` Ralf Baechle 2002-12-10 7:50 ` Carsten Langgaard 1 sibling, 1 reply; 10+ messages in thread From: Ralf Baechle @ 2002-12-09 18:38 UTC (permalink / raw) To: Dominic Sweetman Cc: Carsten Langgaard, Dominic Sweetman, chris, kevink, linux-mips On Mon, Dec 09, 2002 at 11:54:20AM +0000, Dominic Sweetman wrote: > I'd like to be clear about the consequences of this. Presumably the > 'access_ok()' macro is used to check addresses which were (originally) > provided by a user program's system call. > > Carsten, are you saying that if such an address is set to say 2**41 in > a CPU supporting 40-bit user virtual addresses, that the kernel will > crash? That's correct. The problem which Carsten diagnosed correctly was the assumption which has been inherited from the 32-bit kernel that the sign- bit makes the difference between valid userspace and kernelspace addresses. Linux doesn't use the supervisor mode so basically that assumption is still true with the except of the area 2^PHYSBITS ... 2^63-1. > If so, that seems to require a fix, even if we don't know a very > efficient one. But perhaps any problem is a bit more subtle than > that? Access_ok is a macro which depending on kernel configuration is expanded hundreds, if not thousands of times throughout the kernel. So every single machine instruction in access_ok will make a size difference of several kB. Carsten's patch was performing pretty badly in that cathegory. If access_ok wasn't used that often the issue certainly wasn't worth the fuzz. Access_ok is of course only usable in C code. We also have a few piece of assembler code that access userspace and need to perform the same kind of address validation tests. Carsten's patch was missing these completly. As such it did only reduce the window of this bug from huge to "just" big. An efficient solution only requires fairly minor changes as you can see in the patch I just posted. It doesn't even require thinking, it can be obtained by cut'n'paste from the Alpha code. Alternatively the problem could also have been solved by forwarding address errors for the address range in question to the page fault handler which would have served the same purpose, maybe even a tad more efficient but ofuscated ... Ralf ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 18:38 ` Ralf Baechle @ 2002-12-10 7:50 ` Carsten Langgaard 2002-12-10 12:40 ` Ralf Baechle 0 siblings, 1 reply; 10+ messages in thread From: Carsten Langgaard @ 2002-12-10 7:50 UTC (permalink / raw) To: Ralf Baechle Cc: Dominic Sweetman, Dominic Sweetman, chris, kevink, linux-mips Ralf Baechle wrote: > On Mon, Dec 09, 2002 at 11:54:20AM +0000, Dominic Sweetman wrote: > > > I'd like to be clear about the consequences of this. Presumably the > > 'access_ok()' macro is used to check addresses which were (originally) > > provided by a user program's system call. > > > > Carsten, are you saying that if such an address is set to say 2**41 in > > a CPU supporting 40-bit user virtual addresses, that the kernel will > > crash? > > That's correct. The problem which Carsten diagnosed correctly was the > assumption which has been inherited from the 32-bit kernel that the sign- > bit makes the difference between valid userspace and kernelspace > addresses. > > Linux doesn't use the supervisor mode so basically that assumption is still > true with the except of the area 2^PHYSBITS ... 2^63-1. > > > If so, that seems to require a fix, even if we don't know a very > > efficient one. But perhaps any problem is a bit more subtle than > > that? > > Access_ok is a macro which depending on kernel configuration is expanded > hundreds, if not thousands of times throughout the kernel. So every single > machine instruction in access_ok will make a size difference of several > kB. Carsten's patch was performing pretty badly in that cathegory. If > access_ok wasn't used that often the issue certainly wasn't worth the fuzz. > > Access_ok is of course only usable in C code. We also have a few piece of > assembler code that access userspace and need to perform the same kind of > address validation tests. Carsten's patch was missing these completly. As > such it did only reduce the window of this bug from huge to "just" big. > At least I haven't hit those holes, the would have been fixed otherwise, too ;-) > > An efficient solution only requires fairly minor changes as you can see in > the patch I just posted. It doesn't even require thinking, it can be > obtained by cut'n'paste from the Alpha code. Alternatively the problem > could also have been solved by forwarding address errors for the address > range in question to the page fault handler which would have served the > same purpose, maybe even a tad more efficient but ofuscated ... > I absolutely agree that we should go for an optimized solution, but we discuss this issue 1/2 year ago, none of us, had the time to come up with a better fix than the one I send. I'm going through my to-do list and came across this issue again, and I just wanted to reopen the case again. This time it annoyed you enough, so you came up with a better solution and I achieved what I came for, so that's great ;-) Thanks a lot. I will try you patch right away. > > Ralf -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-10 7:50 ` Carsten Langgaard @ 2002-12-10 12:40 ` Ralf Baechle 0 siblings, 0 replies; 10+ messages in thread From: Ralf Baechle @ 2002-12-10 12:40 UTC (permalink / raw) To: Carsten Langgaard Cc: Dominic Sweetman, Dominic Sweetman, chris, kevink, linux-mips On Tue, Dec 10, 2002 at 08:50:55AM +0100, Carsten Langgaard wrote: > I absolutely agree that we should go for an optimized solution, but we discuss > this issue 1/2 year ago, none of us, had the time to come up with a better fix > than the one I send. I'm going through my to-do list and came across this > issue again, and I just wanted to reopen the case again. > This time it annoyed you enough, so you came up with a better solution and > I achieved what I came for, so that's great ;-) > Thanks a lot. I will try you patch right away. It's already in CVS. Btw, a missconfigured firewall turned linux-mips.org into a heating for the server room last night. This should be fixed now. The machine is now hosted at MIPS UK, formerly Algorithmics. There should be no user visible changes. Ralf ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 9:30 ` Carsten Langgaard 2002-12-09 11:54 ` Dominic Sweetman @ 2002-12-09 16:36 ` Ralf Baechle 2002-12-10 8:55 ` Carsten Langgaard 1 sibling, 1 reply; 10+ messages in thread From: Ralf Baechle @ 2002-12-09 16:36 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Dominic Sweetman, chris, kevink, linux-mips On Mon, Dec 09, 2002 at 10:30:03AM +0100, Carsten Langgaard wrote: > > The patch below adds 32 bytes. It's still not the right thing though. It's > > not fixing all stuff in the assembler code. I have a better patch but it > > results in odd userspace behaviour. Smells like a compiler problem ... > > I tried you patch below, but then nothing seems to work. The reason for this problem (and a few others is the broken call to __access_ok() in clear_user(). That should actually be access_ok(). Basically the kernel was only working so far because addresses were just right ... Below my working version. I still needs to make TASK_SIZE variable but with the clear_user thing fixed that should be easy. Ralf Index: arch/mips64/kernel/scall_o32.S =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/scall_o32.S,v retrieving revision 1.48.2.21 diff -u -r1.48.2.21 scall_o32.S --- arch/mips64/kernel/scall_o32.S 3 Dec 2002 14:23:05 -0000 1.48.2.21 +++ arch/mips64/kernel/scall_o32.S 8 Dec 2002 06:08:55 -0000 @@ -209,7 +209,7 @@ daddiu a0, a1, 4 or a0, a0, a1 and a0, a0, v1 - bltz a0, bad_address + bnez a0, bad_address /* Ok, this is the ll/sc case. World is sane :-) */ 1: ll v0, (a1) @@ -273,7 +273,7 @@ ld v1, THREAD_CURDS($28) or v0, v0, t1 and v1, v1, v0 - bltz v1, efault + bnez v1, efault move a0, a1 # shift argument registers move a1, a2 Index: arch/mips64/lib/strlen_user.S =================================================================== RCS file: /home/cvs/linux/arch/mips64/lib/strlen_user.S,v retrieving revision 1.4.2.1 diff -u -r1.4.2.1 strlen_user.S --- arch/mips64/lib/strlen_user.S 1 Jul 2002 15:27:29 -0000 1.4.2.1 +++ arch/mips64/lib/strlen_user.S 8 Dec 2002 06:08:55 -0000 @@ -25,7 +25,7 @@ LEAF(__strlen_user_asm) ld v0, THREAD_CURDS($28) # pointer ok? and v0, a0 - bltz v0, fault + bnez v0, fault FEXPORT(__strlen_user_nocheck_asm) move v0, a0 Index: arch/mips64/lib/strncpy_user.S =================================================================== RCS file: /home/cvs/linux/arch/mips64/lib/strncpy_user.S,v retrieving revision 1.4 diff -u -r1.4 strncpy_user.S --- arch/mips64/lib/strncpy_user.S 9 Jul 2001 00:25:37 -0000 1.4 +++ arch/mips64/lib/strncpy_user.S 8 Dec 2002 06:08:55 -0000 @@ -30,7 +30,7 @@ LEAF(__strncpy_from_user_asm) ld v0, THREAD_CURDS($28) # pointer ok? and v0, a1 - bltz v0, fault + bnez v0, fault FEXPORT(__strncpy_from_user_nocheck_asm) move v0, zero Index: arch/mips64/lib/strnlen_user.S =================================================================== RCS file: /home/cvs/linux/arch/mips64/lib/strnlen_user.S,v retrieving revision 1.2.2.2 diff -u -r1.2.2.2 strnlen_user.S --- arch/mips64/lib/strnlen_user.S 1 Jul 2002 15:27:29 -0000 1.2.2.2 +++ arch/mips64/lib/strnlen_user.S 8 Dec 2002 06:08:55 -0000 @@ -25,7 +25,7 @@ LEAF(__strnlen_user_asm) ld v0, THREAD_CURDS($28) # pointer ok? and v0, a0 - bltz v0, fault + bnez v0, fault FEXPORT(__strnlen_user_nocheck_asm) move v0, a0 Index: include/asm-mips64/processor.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips64/processor.h,v retrieving revision 1.32.2.9 diff -u -r1.32.2.9 processor.h --- include/asm-mips64/processor.h 4 Nov 2002 19:39:56 -0000 1.32.2.9 +++ include/asm-mips64/processor.h 8 Dec 2002 06:09:38 -0000 @@ -208,7 +208,7 @@ /* \ * For now the default is to fix address errors \ */ \ - MF_FIXADE, { 0 }, 0, 0 \ + MF_FIXADE, KERNEL_DS, 0, 0 \ } #ifdef __KERNEL__ Index: include/asm-mips64/uaccess.h =================================================================== RCS file: /home/cvs/linux/include/asm-mips64/uaccess.h,v retrieving revision 1.13.2.1 diff -u -r1.13.2.1 uaccess.h --- include/asm-mips64/uaccess.h 1 Jul 2002 15:27:31 -0000 1.13.2.1 +++ include/asm-mips64/uaccess.h 8 Dec 2002 06:09:39 -0000 @@ -22,8 +22,8 @@ * * For historical reasons, these macros are grossly misnamed. */ -#define KERNEL_DS ((mm_segment_t) { (unsigned long) 0L }) -#define USER_DS ((mm_segment_t) { (unsigned long) -1L }) +#define KERNEL_DS ((mm_segment_t) { 0UL }) +#define USER_DS ((mm_segment_t) { -TASK_SIZE }) #define VERIFY_READ 0 #define VERIFY_WRITE 1 @@ -46,19 +46,19 @@ * - OR we are in kernel mode. */ #define __ua_size(size) \ - (__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size)) + ((__builtin_constant_p(size) && (size)) > 0 ? 0 : (size)) -#define __access_ok(addr,size,mask) \ - (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0) +#define __access_ok(addr, size, mask) \ + (((mask) & ((addr) | ((addr) + (size)) | __ua_size(size))) == 0) -#define __access_mask ((long)(get_fs().seg)) +#define __access_mask get_fs().seg -#define access_ok(type,addr,size) \ - __access_ok(((unsigned long)(addr)),(size),__access_mask) +#define access_ok(type, addr, size) \ + __access_ok((unsigned long)(addr), (size), __access_mask) static inline int verify_area(int type, const void * addr, unsigned long size) { - return access_ok(type,addr,size) ? 0 : -EFAULT; + return access_ok(type, addr, size) ? 0 : -EFAULT; } /* @@ -340,8 +340,8 @@ ({ \ void * __cl_addr = (addr); \ unsigned long __cl_size = (n); \ - if (__cl_size && __access_ok(VERIFY_WRITE, \ - ((unsigned long)(__cl_addr)), __cl_size)) \ + if (__cl_size && access_ok(VERIFY_WRITE, \ + ((unsigned long)(__cl_addr)), __cl_size)) \ __cl_size = __clear_user(__cl_addr, __cl_size); \ __cl_size; \ }) ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: The 64-bit version of __access_ok is broken. 2002-12-09 16:36 ` Ralf Baechle @ 2002-12-10 8:55 ` Carsten Langgaard 0 siblings, 0 replies; 10+ messages in thread From: Carsten Langgaard @ 2002-12-10 8:55 UTC (permalink / raw) To: Ralf Baechle; +Cc: Dominic Sweetman, chris, kevink, linux-mips Your patch seems to do the job, thanks a lot. /Carsten Ralf Baechle wrote: > On Mon, Dec 09, 2002 at 10:30:03AM +0100, Carsten Langgaard wrote: > > > > The patch below adds 32 bytes. It's still not the right thing though. It's > > > not fixing all stuff in the assembler code. I have a better patch but it > > > results in odd userspace behaviour. Smells like a compiler problem ... > > > > I tried you patch below, but then nothing seems to work. > > The reason for this problem (and a few others is the broken call to > __access_ok() in clear_user(). That should actually be access_ok(). > Basically the kernel was only working so far because addresses were just > right ... > > Below my working version. I still needs to make TASK_SIZE variable but > with the clear_user thing fixed that should be easy. > > Ralf > > Index: arch/mips64/kernel/scall_o32.S > =================================================================== > RCS file: /home/cvs/linux/arch/mips64/kernel/scall_o32.S,v > retrieving revision 1.48.2.21 > diff -u -r1.48.2.21 scall_o32.S > --- arch/mips64/kernel/scall_o32.S 3 Dec 2002 14:23:05 -0000 1.48.2.21 > +++ arch/mips64/kernel/scall_o32.S 8 Dec 2002 06:08:55 -0000 > @@ -209,7 +209,7 @@ > daddiu a0, a1, 4 > or a0, a0, a1 > and a0, a0, v1 > - bltz a0, bad_address > + bnez a0, bad_address > > /* Ok, this is the ll/sc case. World is sane :-) */ > 1: ll v0, (a1) > @@ -273,7 +273,7 @@ > ld v1, THREAD_CURDS($28) > or v0, v0, t1 > and v1, v1, v0 > - bltz v1, efault > + bnez v1, efault > > move a0, a1 # shift argument registers > move a1, a2 > Index: arch/mips64/lib/strlen_user.S > =================================================================== > RCS file: /home/cvs/linux/arch/mips64/lib/strlen_user.S,v > retrieving revision 1.4.2.1 > diff -u -r1.4.2.1 strlen_user.S > --- arch/mips64/lib/strlen_user.S 1 Jul 2002 15:27:29 -0000 1.4.2.1 > +++ arch/mips64/lib/strlen_user.S 8 Dec 2002 06:08:55 -0000 > @@ -25,7 +25,7 @@ > LEAF(__strlen_user_asm) > ld v0, THREAD_CURDS($28) # pointer ok? > and v0, a0 > - bltz v0, fault > + bnez v0, fault > > FEXPORT(__strlen_user_nocheck_asm) > move v0, a0 > Index: arch/mips64/lib/strncpy_user.S > =================================================================== > RCS file: /home/cvs/linux/arch/mips64/lib/strncpy_user.S,v > retrieving revision 1.4 > diff -u -r1.4 strncpy_user.S > --- arch/mips64/lib/strncpy_user.S 9 Jul 2001 00:25:37 -0000 1.4 > +++ arch/mips64/lib/strncpy_user.S 8 Dec 2002 06:08:55 -0000 > @@ -30,7 +30,7 @@ > LEAF(__strncpy_from_user_asm) > ld v0, THREAD_CURDS($28) # pointer ok? > and v0, a1 > - bltz v0, fault > + bnez v0, fault > > FEXPORT(__strncpy_from_user_nocheck_asm) > move v0, zero > Index: arch/mips64/lib/strnlen_user.S > =================================================================== > RCS file: /home/cvs/linux/arch/mips64/lib/strnlen_user.S,v > retrieving revision 1.2.2.2 > diff -u -r1.2.2.2 strnlen_user.S > --- arch/mips64/lib/strnlen_user.S 1 Jul 2002 15:27:29 -0000 1.2.2.2 > +++ arch/mips64/lib/strnlen_user.S 8 Dec 2002 06:08:55 -0000 > @@ -25,7 +25,7 @@ > LEAF(__strnlen_user_asm) > ld v0, THREAD_CURDS($28) # pointer ok? > and v0, a0 > - bltz v0, fault > + bnez v0, fault > > FEXPORT(__strnlen_user_nocheck_asm) > move v0, a0 > Index: include/asm-mips64/processor.h > =================================================================== > RCS file: /home/cvs/linux/include/asm-mips64/processor.h,v > retrieving revision 1.32.2.9 > diff -u -r1.32.2.9 processor.h > --- include/asm-mips64/processor.h 4 Nov 2002 19:39:56 -0000 1.32.2.9 > +++ include/asm-mips64/processor.h 8 Dec 2002 06:09:38 -0000 > @@ -208,7 +208,7 @@ > /* \ > * For now the default is to fix address errors \ > */ \ > - MF_FIXADE, { 0 }, 0, 0 \ > + MF_FIXADE, KERNEL_DS, 0, 0 \ > } > > #ifdef __KERNEL__ > Index: include/asm-mips64/uaccess.h > =================================================================== > RCS file: /home/cvs/linux/include/asm-mips64/uaccess.h,v > retrieving revision 1.13.2.1 > diff -u -r1.13.2.1 uaccess.h > --- include/asm-mips64/uaccess.h 1 Jul 2002 15:27:31 -0000 1.13.2.1 > +++ include/asm-mips64/uaccess.h 8 Dec 2002 06:09:39 -0000 > @@ -22,8 +22,8 @@ > * > * For historical reasons, these macros are grossly misnamed. > */ > -#define KERNEL_DS ((mm_segment_t) { (unsigned long) 0L }) > -#define USER_DS ((mm_segment_t) { (unsigned long) -1L }) > +#define KERNEL_DS ((mm_segment_t) { 0UL }) > +#define USER_DS ((mm_segment_t) { -TASK_SIZE }) > > #define VERIFY_READ 0 > #define VERIFY_WRITE 1 > @@ -46,19 +46,19 @@ > * - OR we are in kernel mode. > */ > #define __ua_size(size) \ > - (__builtin_constant_p(size) && (signed long) (size) > 0 ? 0 : (size)) > + ((__builtin_constant_p(size) && (size)) > 0 ? 0 : (size)) > > -#define __access_ok(addr,size,mask) \ > - (((signed long)((mask)&(addr | (addr + size) | __ua_size(size)))) >= 0) > +#define __access_ok(addr, size, mask) \ > + (((mask) & ((addr) | ((addr) + (size)) | __ua_size(size))) == 0) > > -#define __access_mask ((long)(get_fs().seg)) > +#define __access_mask get_fs().seg > > -#define access_ok(type,addr,size) \ > - __access_ok(((unsigned long)(addr)),(size),__access_mask) > +#define access_ok(type, addr, size) \ > + __access_ok((unsigned long)(addr), (size), __access_mask) > > static inline int verify_area(int type, const void * addr, unsigned long size) > { > - return access_ok(type,addr,size) ? 0 : -EFAULT; > + return access_ok(type, addr, size) ? 0 : -EFAULT; > } > > /* > @@ -340,8 +340,8 @@ > ({ \ > void * __cl_addr = (addr); \ > unsigned long __cl_size = (n); \ > - if (__cl_size && __access_ok(VERIFY_WRITE, \ > - ((unsigned long)(__cl_addr)), __cl_size)) \ > + if (__cl_size && access_ok(VERIFY_WRITE, \ > + ((unsigned long)(__cl_addr)), __cl_size)) \ > __cl_size = __clear_user(__cl_addr, __cl_size); \ > __cl_size; \ > }) -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2002-12-16 9:39 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-12-05 15:28 The 64-bit version of __access_ok is broken Carsten Langgaard 2002-12-09 4:18 ` Ralf Baechle 2002-12-09 9:30 ` Carsten Langgaard 2002-12-09 11:54 ` Dominic Sweetman 2002-12-09 12:27 ` Carsten Langgaard 2002-12-09 18:38 ` Ralf Baechle 2002-12-10 7:50 ` Carsten Langgaard 2002-12-10 12:40 ` Ralf Baechle 2002-12-09 16:36 ` Ralf Baechle 2002-12-10 8:55 ` Carsten Langgaard
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.