C 언어에서 외부에서 받은 경로를 열 때 상위 디렉터리로 빠져나가거나 심볼릭 링크를 따라가는 것까지 제한하려면 openat2()를 볼 만하다.
작게 실행해 보기
#define _GNU_SOURCE
#include <fcntl.h>
#include <linux/openat2.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdio.h>
int main(void) {
struct open_how how = {0};
how.flags = O_RDONLY;
int fd = syscall(SYS_openat2, AT_FDCWD, "/dev/null", &how, sizeof(how));
if (fd < 0) {
perror("openat2");
return 1;
}
printf("fd=%d\n", fd);
close(fd);
return 0;
}최소 예제는 경로 제한 없이 읽기만 한다. how.resolve에 RESOLVE_* 조건을 추가하는 것이 일반 open()과 비교할 핵심 차이다. 오래된 커널이면 지원 오류가 난다.
반환값과 주의점
성공하면 파일 디스크립터, 실패하면 -1이고 errno가 설정된다. 오래된 커널에서는 ENOSYS로 실패할 수 있다.
open_how 구조체를 0으로 초기화하고 flags와 resolve를 채운다. 예를 들어 RESOLVE_BENEATH는 지정한 디렉터리 밖으로 벗어나는 경로 해석을 막는다. glibc 전용 함수가 없어 syscall()로 부른다.
예제 실행 방법
gcc -std=c11 -Wall -Wextra example.c -lm -o example
./example
답글 달기