로드 가능한 커널 모듈을 사용하여 Linux 3.2.x에 새 시스템 호출 추가 [닫기]

리눅스 커널 3.2.x에서 특정 새로운 시스템 호출을 추가하고 싶지만로드 가능한 커널 모듈 (커널을 다시 컴파일하고 싶지 않기 때문에)

인터넷과 SO에 대한 많은 게시물을 읽었으며 일부 장소에서는로드 할 수있는 모듈로 시스템 호출을 구현할 수 없지만 다른 곳에서는 가능하다고 주장합니다.

무엇 이니? 가능하다면 어떻게합니까?



답변

시스템 호출 테이블 ( sys_call_table)이 정적 크기 배열 이므로 불가능합니다 . 그리고 그 크기는 컴파일 타임에 등록 된 syscall 수에 의해 결정됩니다. 이것은 다른 공간이 없다는 것을 의미합니다.

정의 된 arch/x86/kernel/syscall_64.c파일의 x86 아키텍처에 대한 구현을 확인할 수 있습니다 sys_call_table. 크기는 정확히 __NR_syscall_max+1입니다. __NR_syscall_max로 정의 arch/x86/kernel/asm-offsets_64.c됩니다 sizeof(syscalls) - 1(마지막 syscall 수). 여기서 syscall모든 syscall이있는 테이블입니다.

하나의 가능한 해결책은 sys_setaltroot메모리에 더 많은 공간이 필요하지 않기 때문에 기존의 일부 syscall 번호 (예 : 아키텍처에 하나가 있으면 더 이상 사용되지 않는 것)를 재사용하는 것입니다. 일부 아키텍처에는 syscall 테이블 (예 : x86의 64 비트 버전)에 구멍이있을 수 있으므로이 아키텍처도 사용할 수 있습니다.

새로운 syscall을 개발 중이고 실험하는 동안 재부팅하지 않으려는 경우이 기술을 사용할 수 있습니다. 새 시스템 호출을 정의하고 syscall 테이블에서 기존 항목을 찾은 다음 모듈에서이를 교체해야합니다.

커널이 sys_call_table2.6 버전으로 모듈로 내보내지지 않기 때문에 커널 모듈에서이 작업을 수행하는 것은 쉬운 일이 아닙니다 (이 기호를 내 보낸 마지막 커널 버전은 2.5.41).

이 문제를 해결하는 한 가지 방법은 커널을 변경하여 sys_call_table심볼을 모듈 로 내보내는 것 입니다. 이렇게하려면 다음 두 줄을 추가 해야 합니다 kernel/kallsyms.c( 생산 시스템에서는이 작업을 수행하지 마십시오 ).

extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);

다른 기술은 syscall 테이블을 동적으로 찾는 것입니다. 알려진 시스템 호출 함수에 대한 포인터와 각 단어를 비교하여 커널 메모리를 반복합니다. 테이블에서이 알고있는 syscall의 오프셋을 알고 있으므로 테이블 시작 주소를 계산할 수 있습니다.


답변

불행히도 커널에 시스템 호출을로드 가능한 모듈로 추가 할 수 없습니다. 새로운 시스템 호출을 추가 할 때마다 커널을 컴파일하는 데 어려움을 겪어야합니다.