source: mainline/kernel/arch/ia32/src/asm.S@ 0f718ab

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 0f718ab was e13daa5d, checked in by Jakub Jermar <jakub@…>, 17 years ago

Fortify ia32 and amd64 kernels against mallicious uspace applications that set
DF prior to entering the kernel. For AMD64 syscalls, we don't use the CLD
instruction, but make use of the SFMASK MSR instead. Simics works fine with
it, but QEMU seems to have a problem.

  • Property mode set to 100644
File size: 6.2 KB
Line 
1#
2# Copyright (c) 2001-2004 Jakub Jermar
3# All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions
7# are met:
8#
9# - Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# - Redistributions in binary form must reproduce the above copyright
12# notice, this list of conditions and the following disclaimer in the
13# documentation and/or other materials provided with the distribution.
14# - The name of the author may not be used to endorse or promote products
15# derived from this software without specific prior written permission.
16#
17# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27#
28
29## very low and hardware-level functions
30
31# Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error
32# word and 1 means interrupt with error word
33#define ERROR_WORD_INTERRUPT_LIST 0x00027d00
34
35.text
36
37.global paging_on
38.global enable_l_apic_in_msr
39.global interrupt_handlers
40.global memcpy
41.global memcpy_from_uspace
42.global memcpy_from_uspace_failover_address
43.global memcpy_to_uspace
44.global memcpy_to_uspace_failover_address
45
46
47#define MEMCPY_DST 4
48#define MEMCPY_SRC 8
49#define MEMCPY_SIZE 12
50
51/** Copy memory to/from userspace.
52 *
53 * This is almost conventional memcpy().
54 * The difference is that there is a failover part
55 * to where control is returned from a page fault
56 * if the page fault occurs during copy_from_uspace()
57 * or copy_to_uspace().
58 *
59 * @param MEMCPY_DST(%esp) Destination address.
60 * @param MEMCPY_SRC(%esp) Source address.
61 * @param MEMCPY_SIZE(%esp) Size.
62 *
63 * @return MEMCPY_SRC(%esp) on success and 0 on failure.
64 */
65memcpy:
66memcpy_from_uspace:
67memcpy_to_uspace:
68 movl %edi, %edx /* save %edi */
69 movl %esi, %eax /* save %esi */
70
71 movl MEMCPY_SIZE(%esp), %ecx
72 shrl $2, %ecx /* size / 4 */
73
74 movl MEMCPY_DST(%esp), %edi
75 movl MEMCPY_SRC(%esp), %esi
76
77 rep movsl /* copy whole words */
78
79 movl MEMCPY_SIZE(%esp), %ecx
80 andl $3, %ecx /* size % 4 */
81 jz 0f
82
83 rep movsb /* copy the rest byte by byte */
84
850:
86 movl %edx, %edi
87 movl %eax, %esi
88 movl MEMCPY_SRC(%esp), %eax /* MEMCPY_SRC(%esp), success */
89 ret
90
91/*
92 * We got here from as_page_fault() after the memory operations
93 * above had caused a page fault.
94 */
95memcpy_from_uspace_failover_address:
96memcpy_to_uspace_failover_address:
97 movl %edx, %edi
98 movl %eax, %esi
99 xorl %eax, %eax /* return 0, failure */
100 ret
101
102## Turn paging on
103#
104# Enable paging and write-back caching in CR0.
105#
106paging_on:
107 movl %cr0, %edx
108 orl $(1 << 31), %edx # paging on
109 # clear Cache Disable and not Write Though
110 andl $~((1 << 30) | (1 << 29)), %edx
111 movl %edx,%cr0
112 jmp 0f
1130:
114 ret
115
116
117## Enable local APIC
118#
119# Enable local APIC in MSR.
120#
121enable_l_apic_in_msr:
122 movl $0x1b, %ecx
123 rdmsr
124 orl $(1 << 11), %eax
125 orl $(0xfee00000), %eax
126 wrmsr
127 ret
128
129# Clear nested flag
130# overwrites %ecx
131.macro CLEAR_NT_FLAG
132 pushfl
133 pop %ecx
134 and $0xffffbfff, %ecx
135 push %ecx
136 popfl
137.endm
138
139## Declare interrupt handlers
140#
141# Declare interrupt handlers for n interrupt
142# vectors starting at vector i.
143#
144# The handlers setup data segment registers
145# and call exc_dispatch().
146#
147#define INTERRUPT_ALIGN 64
148.macro handler i n
149
150.ifeq \i - 0x30 # Syscall handler
151 pushl %ds
152 pushl %es
153 pushl %fs
154 pushl %gs
155
156 #
157 # Push syscall arguments onto the stack
158 #
159 # NOTE: The idea behind the order of arguments passed in registers is to
160 # use all scratch registers first and preserved registers next.
161 # An optimized libc syscall wrapper can make use of this setup.
162 #
163 pushl %eax
164 pushl %ebp
165 pushl %edi
166 pushl %esi
167 pushl %ebx
168 pushl %ecx
169 pushl %edx
170
171 # we must fill the data segment registers
172 movw $16, %ax
173 movw %ax, %ds
174 movw %ax, %es
175
176 cld
177 sti
178 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax)
179 call syscall_handler
180 cli
181 addl $28, %esp # clean-up of parameters
182
183 popl %gs
184 popl %fs
185 popl %es
186 popl %ds
187
188 CLEAR_NT_FLAG
189 iret
190.else
191 /*
192 * This macro distinguishes between two versions of ia32 exceptions.
193 * One version has error word and the other does not have it.
194 * The latter version fakes the error word on the stack so that the
195 * handlers and istate_t can be the same for both types.
196 */
197 .iflt \i - 32
198 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST
199 /*
200 * With error word, do nothing
201 */
202 .else
203 /*
204 * Version without error word,
205 */
206 subl $4, %esp
207 .endif
208 .else
209 /*
210 * Version without error word,
211 */
212 subl $4, %esp
213 .endif
214
215 pushl %ds
216 pushl %es
217 pushl %fs
218 pushl %gs
219
220#ifdef CONFIG_DEBUG_ALLREGS
221 pushl %ebx
222 pushl %ebp
223 pushl %edi
224 pushl %esi
225#else
226 subl $16, %esp
227#endif
228 pushl %edx
229 pushl %ecx
230 pushl %eax
231
232 # we must fill the data segment registers
233 movw $16, %ax
234 movw %ax, %ds
235 movw %ax, %es
236
237 cld
238
239 pushl %esp # *istate
240 pushl $(\i) # intnum
241 call exc_dispatch # excdispatch(intnum, *istate)
242 addl $8, %esp # Clear arguments from stack
243
244 CLEAR_NT_FLAG # Modifies %ecx
245
246 popl %eax
247 popl %ecx
248 popl %edx
249#ifdef CONFIG_DEBUG_ALLREGS
250 popl %esi
251 popl %edi
252 popl %ebp
253 popl %ebx
254#else
255 addl $16, %esp
256#endif
257
258 popl %gs
259 popl %fs
260 popl %es
261 popl %ds
262
263 addl $4, %esp # Skip error word, no matter whether real or fake.
264 iret
265.endif
266
267 .align INTERRUPT_ALIGN
268 .if (\n- \i) - 1
269 handler "(\i + 1)", \n
270 .endif
271.endm
272
273# keep in sync with pm.h !!!
274IDT_ITEMS = 64
275.align INTERRUPT_ALIGN
276interrupt_handlers:
277h_start:
278 handler 0 IDT_ITEMS
279h_end:
280
281.data
282.global interrupt_handler_size
283
284interrupt_handler_size: .long (h_end - h_start) / IDT_ITEMS
Note: See TracBrowser for help on using the repository browser.