재시작 명령이 재시작 시스템 호출을 호출하지 않습니까?

재시작 명령이 재시작 시스템 호출을 호출하지 않습니까?

운영체제는 데비안입니다.

내 질문에 따르면:

서버를 다시 시작하는 프로세스를 확인하는 방법이 있습니까?

시스템 호출 테이블을 수정하여 재시작 시스템 호출을 가로채는 커널 모듈을 작성했습니다.

기본적으로 다음을 통해 이전 함수 포인터를 저장하십시오.

old_reboot = (void *) *(sys_call_table + __NR_reboot);

그런 다음 쓰기 가능하게 만들고 sys_call_table다음을 수행합니다.

*(sys_call_table + __NR_reboot) = (unsigned long) my_reboot;

sys_call_table그런 다음 다시 읽기 전용으로 전환합니다 . 내 재시작 시스템 호출은 다음과 같습니다.

asmlinkage long my_reboot(int magic1, int magic2, unsigned int cmd, void __user *arg)
{
    printk(KERN_INFO "Intercepted sys_reboot\n");
    return old_reboot(magic1, magic2, cmd, arg);
}

그런 다음 bash에서 "reboot" 명령을 실행하여 코드를 테스트했습니다.

그러나 dmesg/syslog에 로깅되는 사용자 정의 다시 시작 기능은 표시되지 않지만 모듈이 로드되거나 언로드될 때 로깅이 표시되므로 최소한 해당 부분은 작동합니다.

open그래서 나는 syscall 대신 시스템 호출을 사용하여 똑같은 것을 시도했고 reboot제대로 작동했습니다. 따라서 공개 시스템 호출을 가로채서 호출하는 프로세스의 pid를 가져오고 해당 정보를 dmesg/syslog 등에 기록할 수 있습니다.

이 방법을 통해 개방형 시스템 호출을 가로챌 수 있지만 다시 시작 시스템 호출은 가로챌 수 없는 이유는 무엇입니까?

다시 시작하면 실제로 다시 시작 시스템 호출이 호출되나요? 아니면 내가 여기서 뭔가 잘못하고 있는 걸까요?

편집하다:

재시작 시스템 호출을 직접 호출하는 작은 프로그램을 작성했으며 작동합니다. (커널 모듈을 통해 재시작 시스템 호출을 가로챌 수 있습니다)

재시작_테스트.c:

#include <unistd.h>
#include <sys/reboot.h>

int main()
{
        sync();
        reboot(RB_AUTOBOOT);
        return 0;
}

그러나 재부팅 명령을 사용하여 재부팅을 시도하면 차단된 재부팅 시스템 호출이 기록되지 않습니다.

추가 테스트로 다음을 수행합니다.

strace -f reboot

재시작 시스템 호출을 표시하지 않지만 내 작은 C 프로그램을 사용하면 strace는 재시작 시스템 호출을 표시합니다. (다시 시작하기 전 마지막 줄)

  1. systemd가 재시작 시스템 호출을 사용하지 않는 이유는 무엇입니까?

  2. 모든 재시작이 재시작 시스템 호출을 사용하도록 시스템을 어떻게 구성합니까?

답변1

나는 이것이 완전한 대답이 아니라고 확신합니다. systemd 소스 코드를 검사해 보면 긴급 재부팅이 필요한 경우(아마도 "reboot -f" 명령으로 인해??) 재부팅(2)과 동일한 진입점에 직접 시스템 호출이 이루어지지만 이를 우회하는 것으로 보입니다. glibc, glibc 라이브러리에서 지원하지 않는 다섯 번째 매개변수를 추가합니다. 일반적인 재부팅이 호출되면 재부팅하기 전에 최소한 동기화하고 파일 시스템을 마운트 해제하는 /usr/lib/systemd/systemd-shutdown을 호출하는 것으로 보입니다. 그것나타나다재시작 시스템 호출을 수행하지만 논리가 상당히 복잡합니다.

관련 정보