Linux 커널 3.2.x에 특정 새 시스템 호출을 추가하고 싶지만 로드 가능한 커널 모듈로 추가하고 싶습니다(커널을 계속해서 다시 컴파일하고 싶지 않기 때문입니다).
나는 인터넷과 SO에서 많은 게시물을 읽었으며 어떤 곳에서는 시스템 호출을 로드 가능한 모듈로 구현하는 것이 불가능하다고 주장하는 반면 다른 곳에서는 가능하다고 말합니다.
어떤거야? 가능하다면 어떻게 달성할 수 있나요?
답변1
시스템 호출 테이블(시스템 호출 테이블이라고 함 sys_call_table
)이 정적으로 크기가 지정된 배열이기 때문에 이는 불가능합니다. 크기는 등록된 시스템 호출 수에 따라 컴파일 타임에 결정됩니다. 이는 다른 사람을 위한 공간이 없다는 것을 의미합니다.
arch/x86/kernel/syscall_64.c
sys_call_table
파일에 정의된 x86 아키텍처의 구현을 확인할 수 있습니다 . 그 크기는 정확히 다음 과 같이 __NR_syscall_max+1
정의됩니다 ( 마지막 시스템 호출의 번호). 여기서 모든 시스템 호출을 포함하는 테이블이 있습니다.__NR_syscall_max
arch/x86/kernel/asm-offsets_64.c
sizeof(syscalls) - 1
syscall
sys_setaltroot
한 가지 가능한 해결책은 일부 기존(또는 더 이상 사용되지 않는 syscall 번호, 아키텍처에 있는 경우 예 참조) syscall 번호를 재사용하는 것입니다. 이렇게 하면 더 많은 메모리 공간이 필요하지 않습니다. 또한 일부 아키텍처(예: x86의 64비트 버전)의 시스템 호출 테이블에 취약점이 있을 수 있으므로 이를 사용할 수도 있습니다.
새로운 시스템 호출을 개발 중이고 실험 중에 다시 시작하지 않으려는 경우 이 기술을 사용할 수 있습니다. 새로운 시스템 호출을 정의하고, 시스템 호출 테이블에서 기존 항목을 찾아 모듈에서 교체해야 합니다.
버전 2.6부터 커널이 모듈로 내보내지지 않기 때문에 커널 모듈에서 이 작업을 수행하는 것은 쉽지 않습니다 sys_call_table
(이 기호를 내보내는 마지막 커널 버전은 2.5.41
).
이 문제를 해결하는 한 가지 방법은 기호를 모듈로 내보내도록 커널을 변경하는 것입니다 sys_call_table
. 이렇게 하려면 다음 두 줄을 kernel/kallsyms.c
(프로덕션 머신에서는 이 작업을 수행하지 마세요.):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
또 다른 기술은 시스템 호출 테이블을 동적으로 조회하는 것입니다. 커널 메모리를 살펴보며 각 단어를 알려진 시스템 호출 함수에 대한 포인터와 비교합니다. 이 시스템 호출에 대한 테이블의 오프셋을 알고 있으므로 테이블의 시작 주소를 계산할 수 있습니다.
답변2
안타깝게도 시스템 호출을 커널에 로드 가능한 모듈로 추가할 수 없습니다. 새로운 시스템 호출을 추가할 때마다 커널을 컴파일하는 고통을 견뎌야 합니다.