Commit 8ebe7055 authored by Dale Farnsworth's avatar Dale Farnsworth Committed by Paul Mackerras

PPC32: Fix copy_from_user to copy as much as possible.

copy_from_user is supposed to transfer as much data as is
valid and then to return the number of bytes not tranferred.
That's how it works on x86.  On ppc it can be as much as 15
bytes short.

I initially saw the problem with the mount system call.

Note that the fifth argument to mount is an address 8 bytes from the end
of user data space.  There is a null byte at that address, since no mount
options are being passed.

In the kernel, sys_mount() allocates a page for the options and
does copy_from_user(new_page, 0x1005eff8, PAGE_SIZE).  copy_from_user
should copy 8 bytes and return (PAGE_SIZE-8).  Instead, on ppc it reads
8 bytes, faults, writes no bytes, and returns PAGE_SIZE, which causes the
EFAULT to be erroneously reported.
parent 1316513d
...@@ -507,18 +507,18 @@ _GLOBAL(__copy_tofrom_user) ...@@ -507,18 +507,18 @@ _GLOBAL(__copy_tofrom_user)
blr blr
/* read fault, initial single-byte copy */ /* read fault, initial single-byte copy */
100: li r4,0 100: li r9,0
b 90f b 90f
/* write fault, initial single-byte copy */ /* write fault, initial single-byte copy */
101: li r4,1 101: li r9,1
90: subf r5,r8,r5 90: subf r5,r8,r5
li r3,0 li r3,0
b 99f b 99f
/* read fault, initial word copy */ /* read fault, initial word copy */
102: li r4,0 102: li r9,0
b 91f b 91f
/* write fault, initial word copy */ /* write fault, initial word copy */
103: li r4,1 103: li r9,1
91: li r3,2 91: li r3,2
b 99f b 99f
...@@ -542,38 +542,47 @@ _GLOBAL(__copy_tofrom_user) ...@@ -542,38 +542,47 @@ _GLOBAL(__copy_tofrom_user)
#endif #endif
/* read fault in cacheline loop */ /* read fault in cacheline loop */
104: li r4,0 104: li r9,0
b 92f b 92f
/* fault on dcbz (effectively a write fault) */ /* fault on dcbz (effectively a write fault) */
/* or write fault in cacheline loop */ /* or write fault in cacheline loop */
105: li r4,1 105: li r9,1
92: li r3,LG_CACHELINE_BYTES 92: li r3,LG_CACHELINE_BYTES
b 99f b 99f
/* read fault in final word loop */ /* read fault in final word loop */
108: li r4,0 108: li r9,0
b 93f b 93f
/* write fault in final word loop */ /* write fault in final word loop */
109: li r4,1 109: li r9,1
93: andi. r5,r5,3 93: andi. r5,r5,3
li r3,2 li r3,2
b 99f b 99f
/* read fault in final byte loop */ /* read fault in final byte loop */
110: li r4,0 110: li r9,0
b 94f b 94f
/* write fault in final byte loop */ /* write fault in final byte loop */
111: li r4,1 111: li r9,1
94: li r5,0 94: li r5,0
li r3,0 li r3,0
/* /*
* At this stage the number of bytes not copied is * At this stage the number of bytes not copied is
* r5 + (ctr << r3), and r4 is 0 for read or 1 for write. * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
*/ */
99: mfctr r0 99: mfctr r0
slw r3,r0,r3 slw r3,r0,r3
add r3,r3,r5 add. r3,r3,r5
cmpwi 0,r4,0 beq 120f /* shouldn't happen */
cmpwi 0,r9,0
bne 120f bne 120f
/* for read fault, clear out the destination: r3 bytes starting at 4(r6) */ /* for a read fault, first try to continue the copy one byte at a time */
mtctr r3
130: lbz r0,4(r4)
131: stb r0,4(r6)
addi r4,r4,1
addi r6,r6,1
bdnz 130b
/* then clear out the destination: r3 bytes starting at 4(r6) */
132: mfctr r3
srwi. r0,r3,2 srwi. r0,r3,2
li r9,0 li r9,0
mtctr r0 mtctr r0
...@@ -594,6 +603,8 @@ _GLOBAL(__copy_tofrom_user) ...@@ -594,6 +603,8 @@ _GLOBAL(__copy_tofrom_user)
.long 31b,109b .long 31b,109b
.long 40b,110b .long 40b,110b
.long 41b,111b .long 41b,111b
.long 130b,132b
.long 131b,120b
.long 112b,120b .long 112b,120b
.long 114b,120b .long 114b,120b
.text .text
......
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