Commit 2492218c63dca0fb4f041bdc366d243ae3426b40
Committed by
David S. Miller
1 parent
5edddaab1d
Exists in
master
and in
7 other branches
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 |