Commit aeb398768345c74a9e4c01aa3ebf839e858312ec

Authored by David S. Miller
1 parent 40bdac7dbc

sparc64: Fix probe_kernel_{read,write}().

This is based upon a report from Chris Torek and his initial patch.
From Chris's report:

--------------------
This came up in testing kgdb, using the built-in tests -- turn
on CONFIG_KGDB_TESTS, then

    echo V1 > /sys/module/kgdbts/parameters/kgdbts

-- but it would affect using kgdb if you were debugging and looking
at bad pointers.
--------------------

When we get a copy_{from,to}_user() request and the %asi is set to
something other than ASI_AIUS (which is userspace) then we branch off
to a routine called memcpy_user_stub().  It just does a straight
memcpy since we are copying from kernel to kernel in this case.

The logic was that since source and destination are both kernel
pointers we don't need to have exception checks.

But for what probe_kernel_{read,write}() is trying to do, we have to
have the checks, otherwise things like kgdb bad kernel pointer
accesses don't do the right thing.

Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 10 changed files with 25 additions and 48 deletions Side-by-side Diff

arch/sparc/lib/GENcopy_from_user.S
... ... @@ -23,7 +23,7 @@
23 23 #define PREAMBLE \
24 24 rd %asi, %g1; \
25 25 cmp %g1, ASI_AIUS; \
26   - bne,pn %icc, memcpy_user_stub; \
  26 + bne,pn %icc, ___copy_in_user; \
27 27 nop
28 28 #endif
29 29  
arch/sparc/lib/GENcopy_to_user.S
... ... @@ -27,7 +27,7 @@
27 27 #define PREAMBLE \
28 28 rd %asi, %g1; \
29 29 cmp %g1, ASI_AIUS; \
30   - bne,pn %icc, memcpy_user_stub; \
  30 + bne,pn %icc, ___copy_in_user; \
31 31 nop
32 32 #endif
33 33  
arch/sparc/lib/NG2copy_from_user.S
... ... @@ -28,7 +28,7 @@
28 28 #define PREAMBLE \
29 29 rd %asi, %g1; \
30 30 cmp %g1, ASI_AIUS; \
31   - bne,pn %icc, memcpy_user_stub; \
  31 + bne,pn %icc, ___copy_in_user; \
32 32 nop
33 33 #endif
34 34  
arch/sparc/lib/NG2copy_to_user.S
... ... @@ -37,7 +37,7 @@
37 37 #define PREAMBLE \
38 38 rd %asi, %g1; \
39 39 cmp %g1, ASI_AIUS; \
40   - bne,pn %icc, memcpy_user_stub; \
  40 + bne,pn %icc, ___copy_in_user; \
41 41 nop
42 42 #endif
43 43  
arch/sparc/lib/NGcopy_from_user.S
... ... @@ -25,7 +25,7 @@
25 25 #define PREAMBLE \
26 26 rd %asi, %g1; \
27 27 cmp %g1, ASI_AIUS; \
28   - bne,pn %icc, memcpy_user_stub; \
  28 + bne,pn %icc, ___copy_in_user; \
29 29 nop
30 30 #endif
31 31  
arch/sparc/lib/NGcopy_to_user.S
... ... @@ -28,7 +28,7 @@
28 28 #define PREAMBLE \
29 29 rd %asi, %g1; \
30 30 cmp %g1, ASI_AIUS; \
31   - bne,pn %icc, memcpy_user_stub; \
  31 + bne,pn %icc, ___copy_in_user; \
32 32 nop
33 33 #endif
34 34  
arch/sparc/lib/U1copy_from_user.S
... ... @@ -23,7 +23,7 @@
23 23 #define PREAMBLE \
24 24 rd %asi, %g1; \
25 25 cmp %g1, ASI_AIUS; \
26   - bne,pn %icc, memcpy_user_stub; \
  26 + bne,pn %icc, ___copy_in_user; \
27 27 nop; \
28 28  
29 29 #include "U1memcpy.S"
arch/sparc/lib/U1copy_to_user.S
... ... @@ -23,7 +23,7 @@
23 23 #define PREAMBLE \
24 24 rd %asi, %g1; \
25 25 cmp %g1, ASI_AIUS; \
26   - bne,pn %icc, memcpy_user_stub; \
  26 + bne,pn %icc, ___copy_in_user; \
27 27 nop; \
28 28  
29 29 #include "U1memcpy.S"
arch/sparc/lib/U3copy_to_user.S
... ... @@ -23,7 +23,7 @@
23 23 #define PREAMBLE \
24 24 rd %asi, %g1; \
25 25 cmp %g1, ASI_AIUS; \
26   - bne,pn %icc, memcpy_user_stub; \
  26 + bne,pn %icc, ___copy_in_user; \
27 27 nop; \
28 28  
29 29 #include "U3memcpy.S"
arch/sparc/lib/copy_in_user.S
... ... @@ -3,6 +3,7 @@
3 3 * Copyright (C) 1999, 2000, 2004 David S. Miller (davem@redhat.com)
4 4 */
5 5  
  6 +#include <linux/linkage.h>
6 7 #include <asm/asi.h>
7 8  
8 9 #define XCC xcc
... ... @@ -27,18 +28,7 @@
27 28 * to copy register windows around during thread cloning.
28 29 */
29 30  
30   - .globl ___copy_in_user
31   - .type ___copy_in_user,#function
32   -___copy_in_user: /* %o0=dst, %o1=src, %o2=len */
33   - /* Writing to %asi is _expensive_ so we hardcode it.
34   - * Reading %asi to check for KERNEL_DS is comparatively
35   - * cheap.
36   - */
37   - rd %asi, %g1
38   - cmp %g1, ASI_AIUS
39   - bne,pn %icc, memcpy_user_stub
40   - nop
41   -
  31 +ENTRY(___copy_in_user) /* %o0=dst, %o1=src, %o2=len */
42 32 cmp %o2, 0
43 33 be,pn %XCC, 85f
44 34 or %o0, %o1, %o3
45 35  
46 36  
47 37  
48 38  
... ... @@ -49,22 +39,24 @@
49 39 /* 16 < len <= 64 */
50 40 andcc %o3, 0x7, %g0
51 41 bne,pn %XCC, 90f
52   - sub %o0, %o1, %o3
  42 + nop
53 43  
54 44 andn %o2, 0x7, %o4
55 45 and %o2, 0x7, %o2
56 46 1: subcc %o4, 0x8, %o4
57 47 EX(ldxa [%o1] %asi, %o5)
58   - EX(stxa %o5, [%o1 + %o3] ASI_AIUS)
  48 + EX(stxa %o5, [%o0] %asi)
  49 + add %o1, 0x8, %o1
59 50 bgu,pt %XCC, 1b
60   - add %o1, 0x8, %o1
  51 + add %o0, 0x8, %o0
61 52 andcc %o2, 0x4, %g0
62 53 be,pt %XCC, 1f
63 54 nop
64 55 sub %o2, 0x4, %o2
65 56 EX(lduwa [%o1] %asi, %o5)
66   - EX(stwa %o5, [%o1 + %o3] ASI_AIUS)
  57 + EX(stwa %o5, [%o0] %asi)
67 58 add %o1, 0x4, %o1
  59 + add %o0, 0x4, %o0
68 60 1: cmp %o2, 0
69 61 be,pt %XCC, 85f
70 62 nop
71 63  
72 64  
... ... @@ -74,14 +66,15 @@
74 66 80: /* 0 < len <= 16 */
75 67 andcc %o3, 0x3, %g0
76 68 bne,pn %XCC, 90f
77   - sub %o0, %o1, %o3
  69 + nop
78 70  
79 71 82:
80 72 subcc %o2, 4, %o2
81 73 EX(lduwa [%o1] %asi, %g1)
82   - EX(stwa %g1, [%o1 + %o3] ASI_AIUS)
  74 + EX(stwa %g1, [%o0] %asi)
  75 + add %o1, 4, %o1
83 76 bgu,pt %XCC, 82b
84   - add %o1, 4, %o1
  77 + add %o0, 4, %o0
85 78  
86 79 85: retl
87 80 clr %o0
88 81  
89 82  
... ... @@ -90,27 +83,11 @@
90 83 90:
91 84 subcc %o2, 1, %o2
92 85 EX(lduba [%o1] %asi, %g1)
93   - EX(stba %g1, [%o1 + %o3] ASI_AIUS)
  86 + EX(stba %g1, [%o0] %asi)
  87 + add %o1, 1, %o1
94 88 bgu,pt %XCC, 90b
95   - add %o1, 1, %o1
  89 + add %o0, 1, %o0
96 90 retl
97 91 clr %o0
98   -
99   - .size ___copy_in_user, .-___copy_in_user
100   -
101   - /* Act like copy_{to,in}_user(), ie. return zero instead
102   - * of original destination pointer. This is invoked when
103   - * copy_{to,in}_user() finds that %asi is kernel space.
104   - */
105   - .globl memcpy_user_stub
106   - .type memcpy_user_stub,#function
107   -memcpy_user_stub:
108   - save %sp, -192, %sp
109   - mov %i0, %o0
110   - mov %i1, %o1
111   - call memcpy
112   - mov %i2, %o2
113   - ret
114   - restore %g0, %g0, %o0
115   - .size memcpy_user_stub, .-memcpy_user_stub
  92 +ENDPROC(___copy_in_user)