/* * Copyright (c) 2011, 2012, 2013, 2014, 2015 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * x86/syscall.S * An assembly stub that acts as glue for system calls. */ #include .global syscall_handler .section .text .type syscall_handler, @function syscall_handler: /* -- stack is 12 bytes from being 16-byte aligned -- */ cld movl $0, errno pushl %ebp /* -- stack is 8 bytes from being 16-byte aligned -- */ # Grant ourselves kernel permissions to the data segment. movl %ds, %ebp pushl %ebp /* -- stack is 4 bytes from being 16-byte aligned -- */ movw $0x10, %bp movl %ebp, %ds movl %ebp, %es # Make sure the requested system call is valid. cmp $SYSCALL_MAX_NUM, %eax jae 3f 1: # Read a system call function pointer. xorl %ebp, %ebp movl syscall_list(%ebp,%eax,4), %eax # Point the %ebp register to the pushed user-space %ebp above. movl %esp, %ebp addl $4, %ebp # Call the system call. pushl %esi /* -- stack is 16-byte aligned -- */ pushl %edi pushl %edx pushl %ecx pushl %ebx /* -- stack is 16-byte aligned -- */ calll *%eax addl $20, %esp # Restore the previous permissions to data segment. popl %ebp movl %ebp, %ds movl %ebp, %es # Return to user-space, system call result in %eax:%edx, errno in %ecx. popl %ebp movl errno, %ecx # Zero registers to avoid information leaks. # eax is the return value. # ecx is errno. # edx is the return value (MIGHT NOT BE INITIALIZED, CAN LEAK!). # ebx is set in a moment. xor %esi, %esi xor %edi, %edi # If any signals are pending, fire them now. movl asm_signal_is_pending, %ebx testl %ebx, %ebx jnz 4f # ebx is zero in this branch. 2: iretl 3: # Call the null system call instead. xorl %eax, %eax jmp 1b 4: # We can't return to this location after the signal, since if any system # call is made this stack will get reused and all our nice temporaries wil # be garbage. We therefore pass the kernel the state to return to and it'll # handle it for us when the signal is over. movl %esp, %ebx int $130 # Deliver pending signals. # If we end up here, it means that the signal didn't override anything and # that we should just go ahead and return to userspace ourselves. xor %ebx, %ebx jmp 2b .size syscall_handler, .-syscall_handler