NAME
fanotify_init - fanotify 그룹 만들어서 초기화하기
SYNOPSIS
#include <fcntl.h>
#include <sys/fanotify.h>
int fanotify_init(unsigned int flags, unsigned int event_f_flags);
DESCRIPTION
fanotify API에 대한 소개는 fanotify(7)를 보라.
fanotify_init()
은 새 fanotify 그룹을 초기화하고 그룹에 연계된 이벤트 큐에 대한 파일 디스크립터를 반환한다.
그 파일 디스크립터를 fanotify_mark(2) 호출에 사용해서 fanotify 이벤트가 발생할 파일, 디렉터리, 마운트, 파일 시스템을 지정한다. 그리고 파일 디스크립터에 읽기를 해서 그 이벤트를 읽는다. 어떤 이벤트는 정보를 주기만 하며 파일에 접근이 이뤄졌음을 나타낸다. 다른 이벤트는 다른 응용이 파일이나 디렉터리에 접근할 수 있는지 결정하는 데 쓸 수 있다. 파일 디스크립터에 쓰기를 해서 그 파일 시스템 객체에 대한 접근을 인가한다.
여러 프로그램이 fanotify 인터페이스로 같은 파일을 동시에 감시할 수도 있다.
현재 구현에서 사용자별 fanotify 그룹 수는 128개로 제한돼 있다. 이 제한을 무시할 수 없다.
fanotify_init()
호출을 위해선 CAP_SYS_ADMIN
역능이 필요하다. API 향후 버전에서는 이 제약이 완화될 수도 있다. 그래서 아래에서 보이는 것처럼 어떤 역능 검사들이 추가로 구현돼 있다.
flags
인자는 청취 응용의 알림 등급을 지정하는 비트 필드와 파일 디스크립터의 동작 방식을 지정하는 비트 필드들을 담고 있다.
허가 이벤트를 듣는 청취자가 여럿 존재하는 경우 알림 등급을 이용해 이벤트를 수신하는 순서를 정한다.
flags
에 다음 알림 등급들 중 하나를 지정할 수 있다.
FAN_CLASS_PRE_CONTENT
- 이 값은 파일에 접근이 이뤄졌음을 알리는 이벤트와 파일에 접근할 수 있냐는 허가 결정 이벤트를 수신하도록 한다. 파일에 최종 내용물이 담기기 전에 접근해야 하는 청취자를 위한 것이다. 예를 들면 계층 저장소 관리자에서 이 알림 등급을 사용할 수 있을 것이다.
FAN_CLASS_CONTENT
- 이 값은 파일에 접근이 이뤄졌음을 알리는 이벤트와 파일에 접근할 수 있냐는 허가 결정 이벤트를 수신하도록 한다. 파일에 최종 내용물이 이미 담겨 있을 때 접근해야 하는 청취자를 위한 것이다. 예를 들어 멀웨어 탐지 프로그램에서 이 알림 등급을 사용할 수 있을 것이다.
FAN_CLASS_NOTIF
- 기본값이다. 따로 지정하지 않아도 된다. 이 값은 파일에 접근이 이뤄졌음을 알리는 이벤트만 수신하도록 한다. 파일 접근 전의 허가 결정은 불가능하다.
알림 등급이 다른 청취자들은 FAN_CLASS_PRE_CONTENT
, FAN_CLASS_CONTENT
, FAN_CLASS_NOTIF
순서로 이벤트를 받게 된다. 알림 등급이 같은 청취자들에 대한 알림 순서는 규정돼 있지 않다.
flags
에 추가로 다음 비트들을 설정할 수 있다.
FAN_CLOEXEC
- 새 파일 디스크립터에 exec에서 닫기 플래그(
FD_CLOEXEC
)를 설정한다. open(2)의O_CLOEXEC
플래그 설명을 보라. FAN_NONBLOCK
- 파일 디스크립터에 논블로킹 플래그(
O_NONBLOCK
)를 켠다. 파일 디스크립터에서 읽기가 블록하지 않게 된다. 읽을 수 있는 데이터가 없으면 대신 read(2)가EAGAIN
오류로 실패한다. FAN_UNLIMITED_QUEUE
- 이벤트 큐에서 16384개 이벤트 제한을 없앤다. 이 플래그를 사용하려면
CAP_SYS_ADMIN
역능이 필요하다. FAN_UNLIMITED_MARKS
- 8192개 표시 제한을 없앤다. 이 플래그를 사용하려면
CAP_SYS_ADMIN
역능이 필요하다. FAN_REPORT_TID
(리눅스 4.20부터)- read(2)가 내놓는
struct fanotify_event_metadata
(fanotify(7) 참고)의pid
필드로 프로세스 ID(PID) 대신 스레드 ID(TID)를 알려 준다. FAN_ENABLE_AUDIT
(리눅스 4.15부터)- 권한 이벤트로 수행하는 접근 조정에 대해 감사 로그 기록 생성 동작을 켠다. 권한 이벤트 응답에
FAN_AUDIT
표시를 해 주어야 감사 로그 기록이 생성된다. FAN_REPORT_FID
(리눅스 5.1부터)- 이 값은 이벤트와 연관된 하위 파일 시스템 객체에 대한 추가 정보를 담은 이벤트를 수신하도록 한다.
FAN_EVENT_INFO_TYPE_FID
타입의 또 다른 레코드가 객체에 대한 정보를 담고서 범용 이벤트 메타데이터 구조체와 함께 포함된다. 그리고 이벤트와 연관된 객체를 나타내는 데 쓰는 파일 디스크립터는 파일 핸들로 교체된다. 이는 파일 디스크립터 대신 파일 핸들을 쓰면 객체를 더 쉽게 식별할 수 있는 응용들을 위한 것이다. 또한 디렉터리 항목 변경 이벤트인FAN_CREATE
,FAN_DELETE
,FAN_MOVE
나FAN_ATTRIB
,FAN_DELETE_SELF
,FAN_MOVE_SELF
에 관심 있어서 디렉터리나 파일 시스템을 감시하는 응용들에서도 이용할 수 있다. 그 이벤트들 모두에는 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다. 디렉터리 항목 변경 이벤트에서 보고되는 파일 핸들은 생성/삭제/이동된 자식 객체가 아니라 변경된 디렉터리를 나타낸다는 점에 유의하라.FAN_CLASS_CONTENT
나FAN_CLASS_PRE_CONTENT
를 이 플래그와 함께 쓰지 못하며 그렇게 하면EINVAL
오류가 발생한다. 자세한 내용은 fanotify(7) 참고. FAN_REPORT_DIR_FID
(리눅스 5.9부터)- 이 플래그로 초기화한 fanotify 그룹의 이벤트에는 이벤트와 연관된 디렉터리 객체에 대한 추가 정보가 담기게 된다. (아래의 예외 설명 참고.)
FAN_EVENT_INFO_TYPE_DFID
타입의 또 다른 레코드가 디렉터리 객체에 대한 정보를 담고서 범용 이벤트 메타데이터 구조체와 함께 포함된다. 디렉터리 아닌 객체에서 일어난 이벤트에선 그 추가 구조체가 부모 디렉터리 파일 시스템 객체를 가리키는 파일 핸들을 담는다. 이벤트를 수신한 시점에 그 디렉터리 파일 시스템 객체가 그 파일 핸들 정보가 기술하는 위치에 있을 거라는 보장이 없다는 점에 유의하라.FAN_REPORT_FID
와 함께 쓰면 디렉터리 아닌 객체에 생기는 이벤트에 대해 레코드 두 개로 이벤트가 보고될 수 있다. 그 중 하나는 디렉터리 아닌 객체 자체를 나타내고 다른 하나는 부모 디렉터리 객체를 나타낸다. 그리고 어떤 경우에는 파일 시스템 객체에 부모가 없을 수 있는데, 예를 들어 링크 제거(unlink)되었지만 아직 열려 있는 파일에서 이벤트가 발생할 때 그렇다. 그 경우FAN_REPORT_FID
플래그를 쓰면 디렉터리 아닌 객체 자체를 나타내는 레코드로만 이벤트가 보고되는데, 그 이벤트와 연관된 디렉터리가 없기 때문이다.FAN_REPORT_FID
플래그를 쓰지 않으면 이벤트가 보고되지 않는다. 자세한 내용은 fanotify(7) 참고. FAN_REPORT_NAME
(리눅스 5.9부터)- 이 플래그로 초기화한 fanotify 그룹의 이벤트에는 이벤트와 연관된 디렉터리 항목의 이름에 대한 추가 정보가 담기게 된다. 이 플래그는
FAN_REPORT_DIR_FID
플래그와 함께 써야 한다.FAN_REPORT_DIR_FID
없이 이 플래그 값을 주면EINVAL
오류가 발생한다. 이 플래그를FAN_REPORT_FID
와 함께 쓸 수 있다.FAN_EVENT_INFO_TYPE_DFID_NAME
타입의 또 다른 레코드가 디렉터리 항목에 대한 정보를 담고서 범용 이벤트 메타데이터 구조체와 함께 포함되며FAN_EVENT_INFO_TYPE_DFID
타입의 추가 정보 레코드를 대체한다. 그 추가 레코드에는 디렉터리 파일 시스템 객체를 나타내는 파일 핸들과 그 디렉터리 내 항목을 나타내는 이름이 포함돼 있다. 디렉터리 항목 변경 이벤트인FAN_CREATE
,FAN_DELETE
,FAN_MOVE
에서 보고되는 이름은 생성/삭제/이동된 디렉터리 항목의 이름이다. 디렉터리 객체에서 생기는 다른 이벤트에서 보고되는 파일 핸들은 디렉터리 객체 자체의 것이고 보고되는 이름은 '.'이다. 디렉터리 아닌 객체에서 생기는 다른 이벤트에서 보고되는 파일 핸들은 부모 디렉터리 객체의 것이고 보고되는 이름은 이벤트 시점에 객체가 위치해 있던 디렉터리 항목의 이름이다. 이렇게 한 이유는 보고된 디렉터리 파일 핸들을 open_by_handle_at(2)에 줘서 열린 디렉터리 파일 디스크립터를 얻고, 그 파일 디스크립터를 보고된 이름과 함께 fstatat(2)에 쓸 수 있도록 하기 위해서다.FAN_EVENT_INFO_TYPE_DFID
타입 레코드에 적용되는 규칙이FAN_EVENT_INFO_TYPE_DFID_NAME
타입 레코드에도 적용된다. 즉, 디렉터리 아닌 객체에 부모가 없으면 이벤트가 보고되지 않거나 디렉터리 항목 정보 없이 보고된다. 이벤트를 수신한 시점에 그 디렉터리 파일 시스템 객체가 그 디렉터리 항목 정보가 기술하는 위치에 있을 거라는 보장이 없다는 점에 유의하라. 자세한 내용은 fanotify(7) 참고. FAN_REPORT_DFID_NAME
(FAN_REPORT_DIR_FID|FAN_REPORT_NAME)
와 같다.
event_f_flags
인자는 fanotify 이벤트에 대해 생성되는 열린 파일 기술 항목에 설정할 파일 상태 플래그를 지정한다. 이 플래그들에 대한 자세한 내용은 open(2)의 flags
값 설명을 보라. event_f_flags
에는 접근 모드를 위한 비트 필드가 포함된다. 그 필드에 다음 값이 들어갈 수 있다.
O_RDONLY
- 읽기 접근만 허용한다.
O_WRONLY
- 쓰기 접근만 허용한다.
O_RDWR
- 읽기 및 쓰기 접근을 허용한다.
event_f_flags
에 다른 비트들을 설정할 수 있다. 특히 유용한 값들은 다음과 같다.
O_LARGEFILE
- 2GB 초과 파일 지원을 켠다. 이 플래그를 설정하지 않으면 32비트 시스템에서 fanotify 그룹으로 감시하는 큰 파일을 열려고 할 때
EOVERFLOW
오류가 발생하게 된다. O_CLOEXEC
(리눅스 3.18부터)- 파일 디스크립터에 exec에서 닫기 플래그를 켠다. 이게 유용할 수 있는 이유에 대해선 open(2)의
O_CLOEXEC
플래그 설명을 보라.
O_APPEND
, O_DSYNC
, O_NOATIME
, O_NONBLOCK
, O_SYNC
도 사용 가능하다. event_f_flags
에 그 외 다른 플래그를 지정하면 EINVAL
오류가 생긴다. (하지만 BUGS 참고.)
RETURN VALUE
성공 시 fanotify_init()
은 새 파일 디스크립터를 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno
를 설정한다.
ERRORS
EINVAL
flags
나event_f_flags
에 유효하지 않은 값을 줬다.FAN_ALL_INIT_FLAGS
(리눅스 커널 버전 4.20부터 폐기 예정 상태)가flags
에 가능한 모든 비트들이다.EMFILE
- 이 사용자의 알림 그룹 수가 128개를 초과한다.
EMFILE
- 열린 파일 디스크립터 개수에 대한 프로세스별 제한에 도달했다.
ENOMEM
- 알림 그룹을 위한 메모리 할당에 실패했다.
ENOSYS
- 커널에서
fanotify_init()
을 구현하고 있지 않다. 커널을CONFIG_FANOTIFY
로 구성한 경우에만 fanotify API를 쓸 수 있다. EPERM
- 호출자에게
CAP_SYS_ADMIN
역능이 없어서 동작이 허가되지 않는다.
VERSIONS
리눅스 커널 버전 2.6.36에서 fanotify_init()
이 도입되었고 버전 2.6.37에서 활성화되었다.
CONFORMING TO
이 시스템 호출은 리눅스 전용이다.
BUGS
리눅스 커널 버전 3.18 전에 다음 버그가 있었다.
event_f_flags
에O_CLOEXEC
를 주면 무시한다.
리눅스 커널 버전 3.14 전에 다음 버그가 있었다.
event_f_flags
에 유효하지 않은 플래그가 있는지 검사하지 않는다.FMODE_EXEC
처럼 내부 용도로만 쓰는 플래그를 설정할 수 있으며, 그러면 fanotify 파일 디스크립터 읽기가 반환하는 파일 디스크립터에 설정이 된다.
SEE ALSO
2021-03-22