2012-03-18 7 views
3

,이 코드가 :이 코드는 작동하지 않으며 시스템의 작동을 중지리눅스 시스템 호출 (이상한 오프셋) 나는 커널 모듈에서 시스템 콜을 호출하기 위해 노력하고있어

set_fs(get_ds()); // lets our module do the system-calls 


    // Save everything before systemcalling 

    asm ("  push %rax  "); 
    asm ("  push %rdi  "); 
    asm ("  push %rcx  "); 
    asm ("  push %rsi  "); 
    asm ("  push %rdx  "); 
    asm ("  push %r10  "); 
    asm ("  push %r8  "); 
    asm ("  push %r9  "); 
    asm ("  push %r11  "); 
    asm ("  push %r12  "); 
    asm ("  push %r15  "); 
    asm ("  push %rbp  "); 
    asm ("  push %rbx  "); 


    // Invoke the long sys_mknod(const char __user *filename, int mode, unsigned dev); 

    asm volatile ("  movq $133, %rax  "); // system call number 

    asm volatile (" lea path(%rip), %rdi  "); // path is char path[] = ".." 

    asm volatile ("  movq mode, %rsi  "); // mode is S_IFCHR | ... 

    asm volatile ("  movq dev, %rdx  "); // dev is 70 >> 8 

    asm volatile ("  syscall  "); 


     // POP EVERYTHING 

    asm ("  pop  %rbx  "); 
    asm ("  pop  %rbp  "); 
    asm ("  pop  %r15  "); 
    asm ("  pop  %r12  "); 
    asm ("  pop  %r11  "); 
    asm ("  pop  %r9  "); 
    asm ("  pop  %r8  "); 
    asm ("  pop  %r10  "); 
    asm ("  pop  %rdx  "); 
    asm ("  pop  %rsi  "); 
    asm ("  pop  %rcx  "); 
    asm ("  pop  %rdi  "); 
    asm ("  pop  %rax  "); 



    set_fs(savedFS); // restore the former address-limit value 

을 down (커널 모듈).

재배치 정보를 사용해, 코드의 조각의 덤프는 다음과 같습니다 R_X86_64_PC32의 경로를 0x4 :

내가 궁금하네요
2c: 50      push %rax 
    2d: 57      push %rdi 
    2e: 51      push %rcx 
    2f: 56      push %rsi 
    30: 52      push %rdx 
    31: 41 52     push %r10 
    33: 41 50     push %r8 
    35: 41 51     push %r9 
    37: 41 53     push %r11 
    39: 41 54     push %r12 
    3b: 41 57     push %r15 
    3d: 55      push %rbp 
    3e: 53      push %rbx 
    3f: 48 c7 c0 85 00 00 00  mov $0x85,%rax 
    46: 48 8d 3d 00 00 00 00  lea 0x0(%rip),%rdi  # 4d <init_module+0x4d> 
      49: R_X86_64_PC32 path-0x4 
    4d: 48 83 c7 04    add $0x4,%rdi 
    51: 48 8b 34 25 00 00 00  mov 0x0,%rsi 
    58: 00 
      55: R_X86_64_32S mode 
    59: 48 8b 14 25 00 00 00  mov 0x0,%rdx 
    60: 00 
      5d: R_X86_64_32S dev 
    61: 0f 05     syscall 
    63: 5b      pop %rbx 
    64: 5d      pop %rbp 
    65: 41 5f     pop %r15 
    67: 41 5c     pop %r12 
    69: 41 5b     pop %r11 
    6b: 41 59     pop %r9 
    6d: 41 58     pop %r8 
    6f: 41 5a     pop %r10 
    71: 5a      pop %rdx 
    72: 5e      pop %rsi 
    73: 59      pop %rcx 
    74: 5f      pop %rdi 
    75: 58      pop %rax 

.. 왜 49 오프셋 -0x4이있다?

의미 : 모드 및 dev는 문제없이 자동으로 해결되어야하지만 경로는 어떻게됩니까? 왜 -0x4 오프셋입니까?

나는

레아 0x0을 (% 립), %의 RDI에 "그것을 보상"을 시도 //이 어떻게 든 -0x4가 추가 $ 0x4를, %의 RDI ....

오프셋 추가 그러나 코드는 여전히 추락했습니다.

어디서 잘못 되었나요?

+4

커널 내부에서 시스템 호출을 호출 할 수 없습니다. 커널은 응용 프로그램에 시스템 호출을 제공합니다. 너 정말로하고 싶은게 뭐야? 커널 토지에서 일하는 것을 피할 수 없습니까? –

+0

그래서 set_fs (get_ds()); 시스템 호출을 호출 할 수있는 세그먼트 제한이 증가해야합니다. 시험을위한 연습 (http://cs.usfca.edu/~cruse/cs635/)이므로 amd64로 수행하는 방법을 알아야합니다. – paulAl

+0

'syscall' 호출 규칙에서'rcx return address for syscall/sysret, C arg3'을 실행하십시오. –

답변

0

내 생각에 스택 문제가있다. int $0x80과 달리 syscall 명령어는 커널 스택을 설정하지 않습니다. system_call:에서 실제 코드를 보면 SWAPGS_UNSAFE_STACK과 같은 것을 볼 수 있습니다. 이 매크로의 핵심은 SwapGS 명령어입니다 (15232 페이지 참조). here. 커널 모드가 시작되면, 커널은 데이터 구조에 대한 포인터를 가져 오는 방법을 필요로하며,이 명령은 정확하게 수행합니다. 사용자 %gs 레지스터를 모델 특정 레지스터에 저장된 값과 바꿔서 커널 모드 스택을 가져올 수 있습니다.

syscall 진입 점이 호출되면 이미 커널 모드에 있었기 때문에이 스왑은 잘못된 값을 생성하고 커널은 가짜 스택을 사용하기 시작합니다. SwapGS를 수동으로 호출하여 커널의 SwapGS 결과를 기대하는 결과를 내고 작동하는지 확인하십시오.

+0

세그멘테이션 오류입니다. 어쨌든 당신이 옳다고 생각합니다. 많은 일들이 일어나고 있고 무엇이 잘못되었는지를 파악하기 위해 모든 시스템 호출 루틴을 읽어야합니다. 참으로 많은 시간. – paulAl

+0

죄송합니다. 위의 잘못된 링크를 제공해 드렸습니다. 지금 고쳐야한다. 또한 342 페이지의 syscall 명령어 [여기] (http://lars.nocrew.org/computers/processors/x86-64/24594.pdf)에 대한 AMD 사양의 의사 코드를 살펴볼 것입니다. 이것은 리눅스가 system_call 루틴에서하는 일을 이해하는데 도움이 될 것입니다. btw, 정확히 말하자면 충돌이 일어났습니다. 그것은 기계가 멈추는 원인이 되었습니까? 커널 언젠가 인쇄 된거야? 기계를 걸면 안되면 dmesg를 실행하고 이상한 것을 찾아보십시오 – kch

+0

아니, 그냥 매달아 놓으십시오. – paulAl

0

그런 식으로는 할 수없는 것처럼 보입니다. 그래서

/* 
    * Register setup: 
    * rax system call number 
    * rdi arg0 
    * rcx return address for syscall/sysret, C arg3 
    * rsi arg1 
    * rdx arg2 
    * r10 arg3 (--> moved to rcx for C) 
    * r8 arg4 
    * r9 arg5 
    * r11 eflags for syscall/sysret, temporary for C 
    * r12-r15,rbp,rbx saved by C code, not touched. 
    * 
    * Interrupts are off on entry. 
    * Only called from user space. 
    * 
    * XXX if we had a free scratch register we could save the RSP into the stack frame 
    *  and report it properly in ps. Unfortunately we haven't. 
    * 
    * When user can change the frames always force IRET. That is because 
    * it deals with uncanonical addresses better. SYSRET has trouble 
    * with them due to bugs in both AMD and Intel CPUs. 
    */ 

, 커널에서 syscall를 호출 할 수 없습니다 : (가) commentsystem_call하기 전에를 참조하십시오. 그러나 그 목적으로 int $0x80을 사용할 수 있습니다. 내가 본대로 kernel_execve 그루터기는 그 것을 사용한다 trick

+0

64 비트 프로그램에서 int 0x80을 호출 할 수 있습니까? 작동할까요? 그리고 나는 32 비트 시스템 콜 인덱스를 렉스에 넣어야합니다. 그렇지 않습니까? – paulAl

+0

64 비트 커널 모듈에서 int 0x80을 사용할 수 없다는 것을 알게되었습니다. 어떤 종류의 VA-whence-protection 메커니즘이 있는지 궁금합니다. – paulAl

+0

왜 'syscall'을 만들어야합니까?'sys_mknod'를 직접 호출 할 수 있습니까? .. –