2011-02-10 4 views
3

Linux i386에서 int $0x80 syscall ABI를 사용하면 유효한 사용자 공간 스택 없이도 syscall을 쉽게 수행 할 수 있습니다. 반면에 vdso/vsyscall 인터페이스는 스택에 액세스해야합니다. 이와 관련하여 다른 Linux 포트, 특히 x86_64는 어떻게됩니까? 그들은 스택없이 syscalls를 만드는 방법이 있습니까? 각 아치에 대해 사용 가능한 syscall 메소드에 대한 참조가 있습니까?스택이없는 Linux에서 syscalls 만들기

답변

4

일반적으로 알 수 있습니다. i386에서도 6 번째 인수가 있으면 스택에 전달해야합니다 (예 : mmap). x86_64에 들어

특히 (주의 : 시스템 콜 번호는 32 비트들로 완전히 다르게 할당) %rax에서 콜 번호를 넣어 6 개 %rdi의 인수 %rsi, %rdx, %r10, %r8%r9까지 (어느 레지스터에 전달되는 매개 변수의 일반적인 ABI와 거의 비슷하지만 거의 동일하지 않습니다. %rcx 대신 %r10을 사용하십시오.) syscall 명령어를 사용하십시오. 결과는 %rax으로 반환되고 %rcx%r11은 clobbered됩니다.

86_64 ABI 정보는 http://www.x86-64.org/documentation/abi.pdf에 있습니다. Linux ABI는 부록에 설명되어 있습니다. (주변에 다른 곳에서 x86_64의 ABI의 정보를 찾고 있다면, 64 비트 Windows가 자신의 다른 ABI 사용에 유의하십시오.) 나는 syscall가 작동하려면 사용자 스택 프레임에 대한 모든 요구 사항이 믿지 않는


정확히. 시그널에 의해 인터럽트되는 경우, 핸들러에는 분명히 정상적인 스택이 필요합니다. 그러나 의도적으로 다른 신호 스택을 사용하여 다음과 같은 실험은 syscall 주위 %rsp이 나를 위해 잘 작동 삭제 한 사용자 :

$ cat syscall_sig.c 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#include <signal.h> 
#include <time.h> 
#include <unistd.h> 

#define __NR_nanosleep 35 

static sig_atomic_t alrm = 0; 

void handler(int sig) 
{ 
    if (sig == SIGALRM) 
     alrm = 1; 
} 

int main(void) 
{ 
    stack_t ss; 
    struct sigaction sa; 
    struct timespec req, rem; 
    long ret; 

    ss.ss_flags = 0; 
    ss.ss_size = SIGSTKSZ; 
    ss.ss_sp = malloc(ss.ss_size); 
    sigaltstack(&ss, NULL); 

    memset(&sa, 0, sizeof(sa)); 
    sa.sa_handler = handler; 
    sa.sa_flags = SA_ONSTACK; 
    sigaction(SIGALRM, &sa, NULL); 

    alarm(1); 

    req.tv_sec = 5; 
    req.tv_nsec = 0; 
    asm("xorq $0x12345678, %%rsp ; syscall ; xorq $0x12345678, %%rsp" 
     : "=a" (ret) 
     : "0" (__NR_nanosleep), "D" (&req), "S" (&rem) 
     : "rcx", "r11", "memory"); 

    printf("syscall return code %ld, alarm flag %d\n", ret, alrm); 

    return 0; 
} 

$ gcc -Wall -o syscall_sig syscall_sig.c 
$ ./syscall_sig 
syscall return code -4, alarm flag 1 
$ 
+0

이 내가 간접적으로 내가 직접 액세스 할 수 없기 때문에 다른 사람을 통해 (뭘하는지입니다 포팅을 위해 x86_64 시스템으로). 사실 지금은 스택이 있지만 나중에 알 수없는 상황을 처리해야하지만 이미 문제가 있습니다. 당신이 기술 한 방법은 시그널에 의해 syscall이 인터럽트되지 않는 한 작동하지만 인터럽트되어 재개하려고하면'syscall' 명령으로 segfault됩니다 ...'syscall'은 특정 스택 프레임이 얻어 지도록 설정해야합니까 중단/재개? –

+0

내가 아는 한 멀지 않았다. 편집을 참조하십시오 ... –

+0

시그널 핸들러에 섀도우 스택이 없다면, 메인 스택을 사용합니다. – Joshua

관련 문제