Commit 2492218c63dca0fb4f041bdc366d243ae3426b40

Authored by Daniel Hellstrom
Committed by David S. Miller
1 parent 5edddaab1d

sparc32: unaligned memory access (MNA) trap handler bug

Since commit f0e98c387e61de00646be31fab4c2fa0224e1efb ("[SPARC]: Fix
link errors with gcc-4.3") the MNA trap handler does not emulate
stores to unaligned addresses correctly. MNA operation from both
kernel and user space are affected.

A typical effect of this bug is nr_frags in skbs are overwritten
during buffer copying/checksum-calculation, or maximally 6 bytes
of data in the network buffer will be overwitten with garbage.

Signed-off-by: Daniel Hellstrom <daniel@gaisler.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 1 changed file with 2 additions and 2 deletions Inline Diff

arch/sparc/kernel/una_asm_32.S
1 /* una_asm.S: Kernel unaligned trap assembler helpers. 1 /* una_asm.S: Kernel unaligned trap assembler helpers.
2 * 2 *
3 * Copyright (C) 1996,2005,2008 David S. Miller (davem@davemloft.net) 3 * Copyright (C) 1996,2005,2008 David S. Miller (davem@davemloft.net)
4 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 4 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
5 */ 5 */
6 6
7 #include <linux/errno.h> 7 #include <linux/errno.h>
8 8
9 .text 9 .text
10 10
11 retl_efault: 11 retl_efault:
12 retl 12 retl
13 mov -EFAULT, %o0 13 mov -EFAULT, %o0
14 14
15 /* int __do_int_store(unsigned long *dst_addr, int size, 15 /* int __do_int_store(unsigned long *dst_addr, int size,
16 * unsigned long *src_val) 16 * unsigned long *src_val)
17 * 17 *
18 * %o0 = dest_addr 18 * %o0 = dest_addr
19 * %o1 = size 19 * %o1 = size
20 * %o2 = src_val 20 * %o2 = src_val
21 * 21 *
22 * Return '0' on success, -EFAULT on failure. 22 * Return '0' on success, -EFAULT on failure.
23 */ 23 */
24 .globl __do_int_store 24 .globl __do_int_store
25 __do_int_store: 25 __do_int_store:
26 ld [%o2], %g1 26 ld [%o2], %g1
27 cmp %1, 2 27 cmp %o1, 2
28 be 2f 28 be 2f
29 cmp %1, 4 29 cmp %o1, 4
30 be 1f 30 be 1f
31 srl %g1, 24, %g2 31 srl %g1, 24, %g2
32 srl %g1, 16, %g7 32 srl %g1, 16, %g7
33 4: stb %g2, [%o0] 33 4: stb %g2, [%o0]
34 srl %g1, 8, %g2 34 srl %g1, 8, %g2
35 5: stb %g7, [%o0 + 1] 35 5: stb %g7, [%o0 + 1]
36 ld [%o2 + 4], %g7 36 ld [%o2 + 4], %g7
37 6: stb %g2, [%o0 + 2] 37 6: stb %g2, [%o0 + 2]
38 srl %g7, 24, %g2 38 srl %g7, 24, %g2
39 7: stb %g1, [%o0 + 3] 39 7: stb %g1, [%o0 + 3]
40 srl %g7, 16, %g1 40 srl %g7, 16, %g1
41 8: stb %g2, [%o0 + 4] 41 8: stb %g2, [%o0 + 4]
42 srl %g7, 8, %g2 42 srl %g7, 8, %g2
43 9: stb %g1, [%o0 + 5] 43 9: stb %g1, [%o0 + 5]
44 10: stb %g2, [%o0 + 6] 44 10: stb %g2, [%o0 + 6]
45 b 0f 45 b 0f
46 11: stb %g7, [%o0 + 7] 46 11: stb %g7, [%o0 + 7]
47 1: srl %g1, 16, %g7 47 1: srl %g1, 16, %g7
48 12: stb %g2, [%o0] 48 12: stb %g2, [%o0]
49 srl %g1, 8, %g2 49 srl %g1, 8, %g2
50 13: stb %g7, [%o0 + 1] 50 13: stb %g7, [%o0 + 1]
51 14: stb %g2, [%o0 + 2] 51 14: stb %g2, [%o0 + 2]
52 b 0f 52 b 0f
53 15: stb %g1, [%o0 + 3] 53 15: stb %g1, [%o0 + 3]
54 2: srl %g1, 8, %g2 54 2: srl %g1, 8, %g2
55 16: stb %g2, [%o0] 55 16: stb %g2, [%o0]
56 17: stb %g1, [%o0 + 1] 56 17: stb %g1, [%o0 + 1]
57 0: retl 57 0: retl
58 mov 0, %o0 58 mov 0, %o0
59 59
60 .section __ex_table,#alloc 60 .section __ex_table,#alloc
61 .word 4b, retl_efault 61 .word 4b, retl_efault
62 .word 5b, retl_efault 62 .word 5b, retl_efault
63 .word 6b, retl_efault 63 .word 6b, retl_efault
64 .word 7b, retl_efault 64 .word 7b, retl_efault
65 .word 8b, retl_efault 65 .word 8b, retl_efault
66 .word 9b, retl_efault 66 .word 9b, retl_efault
67 .word 10b, retl_efault 67 .word 10b, retl_efault
68 .word 11b, retl_efault 68 .word 11b, retl_efault
69 .word 12b, retl_efault 69 .word 12b, retl_efault
70 .word 13b, retl_efault 70 .word 13b, retl_efault
71 .word 14b, retl_efault 71 .word 14b, retl_efault
72 .word 15b, retl_efault 72 .word 15b, retl_efault
73 .word 16b, retl_efault 73 .word 16b, retl_efault
74 .word 17b, retl_efault 74 .word 17b, retl_efault
75 .previous 75 .previous
76 76
77 /* int do_int_load(unsigned long *dest_reg, int size, 77 /* int do_int_load(unsigned long *dest_reg, int size,
78 * unsigned long *saddr, int is_signed) 78 * unsigned long *saddr, int is_signed)
79 * 79 *
80 * %o0 = dest_reg 80 * %o0 = dest_reg
81 * %o1 = size 81 * %o1 = size
82 * %o2 = saddr 82 * %o2 = saddr
83 * %o3 = is_signed 83 * %o3 = is_signed
84 * 84 *
85 * Return '0' on success, -EFAULT on failure. 85 * Return '0' on success, -EFAULT on failure.
86 */ 86 */
87 .globl do_int_load 87 .globl do_int_load
88 do_int_load: 88 do_int_load:
89 cmp %o1, 8 89 cmp %o1, 8
90 be 9f 90 be 9f
91 cmp %o1, 4 91 cmp %o1, 4
92 be 6f 92 be 6f
93 4: ldub [%o2], %g1 93 4: ldub [%o2], %g1
94 5: ldub [%o2 + 1], %g2 94 5: ldub [%o2 + 1], %g2
95 sll %g1, 8, %g1 95 sll %g1, 8, %g1
96 tst %o3 96 tst %o3
97 be 3f 97 be 3f
98 or %g1, %g2, %g1 98 or %g1, %g2, %g1
99 sll %g1, 16, %g1 99 sll %g1, 16, %g1
100 sra %g1, 16, %g1 100 sra %g1, 16, %g1
101 3: b 0f 101 3: b 0f
102 st %g1, [%o0] 102 st %g1, [%o0]
103 6: ldub [%o2 + 1], %g2 103 6: ldub [%o2 + 1], %g2
104 sll %g1, 24, %g1 104 sll %g1, 24, %g1
105 7: ldub [%o2 + 2], %g7 105 7: ldub [%o2 + 2], %g7
106 sll %g2, 16, %g2 106 sll %g2, 16, %g2
107 8: ldub [%o2 + 3], %g3 107 8: ldub [%o2 + 3], %g3
108 sll %g7, 8, %g7 108 sll %g7, 8, %g7
109 or %g3, %g2, %g3 109 or %g3, %g2, %g3
110 or %g7, %g3, %g7 110 or %g7, %g3, %g7
111 or %g1, %g7, %g1 111 or %g1, %g7, %g1
112 b 0f 112 b 0f
113 st %g1, [%o0] 113 st %g1, [%o0]
114 9: ldub [%o2], %g1 114 9: ldub [%o2], %g1
115 10: ldub [%o2 + 1], %g2 115 10: ldub [%o2 + 1], %g2
116 sll %g1, 24, %g1 116 sll %g1, 24, %g1
117 11: ldub [%o2 + 2], %g7 117 11: ldub [%o2 + 2], %g7
118 sll %g2, 16, %g2 118 sll %g2, 16, %g2
119 12: ldub [%o2 + 3], %g3 119 12: ldub [%o2 + 3], %g3
120 sll %g7, 8, %g7 120 sll %g7, 8, %g7
121 or %g1, %g2, %g1 121 or %g1, %g2, %g1
122 or %g7, %g3, %g7 122 or %g7, %g3, %g7
123 or %g1, %g7, %g7 123 or %g1, %g7, %g7
124 13: ldub [%o2 + 4], %g1 124 13: ldub [%o2 + 4], %g1
125 st %g7, [%o0] 125 st %g7, [%o0]
126 14: ldub [%o2 + 5], %g2 126 14: ldub [%o2 + 5], %g2
127 sll %g1, 24, %g1 127 sll %g1, 24, %g1
128 15: ldub [%o2 + 6], %g7 128 15: ldub [%o2 + 6], %g7
129 sll %g2, 16, %g2 129 sll %g2, 16, %g2
130 16: ldub [%o2 + 7], %g3 130 16: ldub [%o2 + 7], %g3
131 sll %g7, 8, %g7 131 sll %g7, 8, %g7
132 or %g1, %g2, %g1 132 or %g1, %g2, %g1
133 or %g7, %g3, %g7 133 or %g7, %g3, %g7
134 or %g1, %g7, %g7 134 or %g1, %g7, %g7
135 st %g7, [%o0 + 4] 135 st %g7, [%o0 + 4]
136 0: retl 136 0: retl
137 mov 0, %o0 137 mov 0, %o0
138 138
139 .section __ex_table,#alloc 139 .section __ex_table,#alloc
140 .word 4b, retl_efault 140 .word 4b, retl_efault
141 .word 5b, retl_efault 141 .word 5b, retl_efault
142 .word 6b, retl_efault 142 .word 6b, retl_efault
143 .word 7b, retl_efault 143 .word 7b, retl_efault
144 .word 8b, retl_efault 144 .word 8b, retl_efault
145 .word 9b, retl_efault 145 .word 9b, retl_efault
146 .word 10b, retl_efault 146 .word 10b, retl_efault
147 .word 11b, retl_efault 147 .word 11b, retl_efault
148 .word 12b, retl_efault 148 .word 12b, retl_efault
149 .word 13b, retl_efault 149 .word 13b, retl_efault
150 .word 14b, retl_efault 150 .word 14b, retl_efault
151 .word 15b, retl_efault 151 .word 15b, retl_efault
152 .word 16b, retl_efault 152 .word 16b, retl_efault
153 .previous 153 .previous
154 154