NAME

fanotify_mark - 파일 시스템 객체에 대한 fanotify 표시 추가, 제거, 변경하기

SYNOPSIS

#include <sys/fanotify.h>

int fanotify_mark(int fanotify_fd, unsigned int flags,
                  uint64_t mask, int dirfd, const char *pathname);

DESCRIPTION

fanotify API에 대한 소개는 fanotify(7)를 보라.

fanotify_mark()는 파일 시스템 객체에 fanotify 표시를 추가하거나 제거하거나 변경한다. 표시를 하는 파일 시스템 객체에 대해 호출자가 읽기 권한을 가지고 있어야 한다.

fanotify_fd 인자는 fanotify_init(2)이 반환한 파일 디스크립터이다.

flags는 수행할 변경 동작을 기술하는 비트 마스크이다. 다음 값들 중 정확히 하나를 포함해야 한다.

FAN_MARK_ADD
표시 마스크에 (또는 무시 마스크에) mask의 이벤트들을 추가한다. mask가 비어 있지 않아야 하며, 안 그러면 EINVAL 오류가 발생한다.
FAN_MARK_REMOVE
표시 마스크에서 (또는 무시 마스크에서) mask 인자의 이벤트들을 제거한다. mask가 비어 있지 않아야 하며, 안 그러면 EINVAL 오류가 발생한다.
FAN_MARK_FLUSH
fanotify 그룹에서 모든 파일 시스템 표시, 또는 모든 마운트 표시, 또는 모든 디렉터리 및 파일 표시를 제거한다. flags에 FAN_MARK_MOUNT가 있으면 그룹에서 마운트에 대한 표시들을 모두 제거한다. flags에 FAN_MARK_FILESYSTEM이 있으면 그룹에서 파일 시스템에 대한 표시들을 모두 제거한다. 그렇지 않으면 디렉터리 및 파일에 대한 표시들을 모두 제거한다. FAN_MARK_MOUNT와 FAN_MARK_FILESYSTEM 외의 플래그나 두 플래그 모두를 FAN_MARK_FLUSH와 함께 사용할 수 없다. mask는 무시한다.

위 값들 중 아무것도 지정하지 않거나 여러 가지를 지정하면 호출이 EINVAL 오류로 실패한다.

추가로 flags에 다음 값들을 0개 이상 OR 할 수 있다.

FAN_MARK_DONT_FOLLOW
pathname이 심볼릭 링크면 가리키는 파일이 아니라 링크 자체에 표시를 한다. (기본적으로 fanotify_mark()는 pathname이 심볼릭 링크면 따라간다.)
FAN_MARK_ONLYDIR
표시할 파일 시스템 객체가 디렉터리가 아니면 ENOTDIR 오류를 제기한다.
FAN_MARK_MOUNT
pathname으로 지정한 마운트 지점에 표시를 한다. pathname 자체가 마운트 지점이 아니면 pathname을 담은 마운트 지점에 표시를 하게 된다. 마운트 지점의 모든 디렉터리와 서브디렉터리, 그리고 거기 담긴 파일들을 감시한다. flags에 FAN_MARK_MOUNT가 있을 때는 FAN_CREATE, FAN_ATTRIB, FAN_MOVE, FAN_DELETE_SELF처럼 파일 핸들로 파일 시스템 객체를 식별해야 하는 이벤트를 줄 수 없다. 그렇게 해서 시도하면 오류 EINVAL이 반환된다.
FAN_MARK_FILESYSTEM (리눅스 4.20부터)
pathname으로 지정한 파일 시스템에 표시를 한다. pathname을 담은 파일 시스템에 표시를 하게 된다. 마운트 지점이 어디든 그 파일 시스템에 담긴 모든 파일과 디렉터리를 감시한다.
FAN_MARK_IGNORED_MASK
무시 마스크에서 mask의 이벤트들을 추가하거나 제거한다.
FAN_MARK_IGNORED_SURV_MODIFY
무시 마스크가 변경 이벤트를 거치며 유지된다. 이 플래그가 설정돼 있지 않으면 무시하는 파일이나 디렉터리에 변경 이벤트가 발생할 때 그 무시 마스크를 없앤다.

mask는 어떤 이벤트를 청취할지 (또는 무시할지) 지정한다. 다음 값들로 이뤄진 비트 마스크이다.

FAN_ACCESS
파일이나 디렉터리에 (BUGS 참고) 접근(읽기)이 이뤄지면 이벤트 생성.
FAN_MODIFY
파일이 변경(쓰기)되면 이벤트 생성.
FAN_CLOSE_WRITE
쓰기 가능 파일이 닫히면 이벤트 생성.
FAN_CLOSE_NOWRITE
읽기 전용 파일이나 디렉터리가 닫히면 이벤트 생성.
FAN_OPEN
파일이나 디렉터리가 열리면 이벤트 생성.
FAN_OPEN_EXEC (리눅스 5.0부터)
파일이 실행하려는 의도로 열리면 이벤트 생성. NOTES의 추가 설명 참고.
FAN_ATTRIB (리눅스 5.1부터)
파일이나 디렉터리의 메타데이터가 바뀌었을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_CREATE (리눅스 5.1부터)
표시된 부모 디렉터리 내에서 파일이나 디렉터리가 생성됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_DELETE (리눅스 5.1부터)
표시된 부모 디렉터리 내에서 파일이나 디렉터리가 삭제됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_DELETE_SELF (리눅스 5.1부터)
표시된 파일이나 디렉터리 자체가 삭제됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_MOVED_FROM (리눅스 5.1부터)
표시된 부모 디렉터리에 있던 파일이나 디렉터리가 이동됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_MOVED_TO (리눅스 5.1부터)
표시된 부모 디렉터리로 파일이나 디렉터리가 이동됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_MOVE_SELF (리눅스 5.1부터)
표시된 파일이나 디렉터리 자체가 이동됐을 때 이벤트 생성. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹이 필요하다.
FAN_OPEN_PERM
파일이나 디렉터리 열기 요청이 있으면 이벤트 생성. FAN_CLASS_PRE_CONTENT나 FAN_CLASS_CONTENT로 생성한 fanotify 파일 디스크립터가 필요하다.
FAN_OPEN_EXEC_PERM (리눅스 5.0부터)
실행을 위한 파일 열기 요청이 있으면 이벤트 생성. FAN_CLASS_PRE_CONTENT나 FAN_CLASS_CONTENT로 생성한 fanotify 파일 디스크립터가 필요하다. NOTES의 추가 설명 참고.
FAN_ACCESS_PERM
파일이나 디렉터리 읽기 요청이 있으면 이벤트 생성. FAN_CLASS_PRE_CONTENT나 FAN_CLASS_CONTENT로 생성한 fanotify 파일 디스크립터가 필요하다.
FAN_ONDIR
디렉터리에 대해 (가령 opendir(3), readdir(3) (단 BUGS 참고), closedir(3)이 호출될 때) 이벤트 생성. 이 플래그가 없으면 파일에 대해서만 이벤트가 생긴다. FAN_CREATE, FAN_DELETE, FAN_MOVED_FROM, FAN_MOVED_TO 같은 디렉터리 항목 이벤트 맥락에서 서브디렉터리 항목들이 변경(즉 mkdir(2)/rmdir(2))될 때 이벤트가 생성되게 하려면 FAN_ONDIR 플래그를 지정해야 한다.
FAN_EVENT_ON_CHILD
표시한 디렉터리의 직접 자식들에 대한 이벤트를 생성한다. 마운트 및 파일 시스템에 표시할 때는 이 플래그에 아무 효과가 없다. 표시된 디렉터리의 서브디렉터리의 자식들에 대해 이벤트가 생성되지 않는다는 점에 유의하라. 구체적으로 표시된 디렉터리의 서브디렉터리 내에서 수행된 항목 변경에 대해 디렉터리 항목 변경 이벤트인 FAN_CREATE, FAN_DELETE, FAN_MOVED_FROM, FAN_MOVED_TO가 생성되지 않는다. 표시된 디렉터리의 자식들에 대해 FAN_DELETE_SELF 및 FAN_MOVE_SELF 이벤트가 생성되지 않는다는 점에 유의하라. 디렉터리 트리 전체를 감시하려면 적절한 마운트 내지 파일 시스템에 표시를 해야 한다.

다음 조합 값이 정의돼 있다.

FAN_CLOSE
파일이 닫혔음. (FAN_CLOSE_WRITE|FAN_CLOSE_NOWRITE)
FAN_MOVE
파일이나 디렉터리가 이동됐음. (FAN_MOVED_FROM|FAN_MOVED_TO)

파일 디스크립터 dirfd와 pathname에 지정한 경로명을 써서 표시를 할 파일 시스템 객체를 결정한다.

RETURN VALUE

성공 시 fanotify_mark()는 0을 반환한다. 오류 시 -1을 반환하며 오류를 나타내도록 errno를 설정한다.

ERRORS

EBADF
fanotify_fd로 유효하지 않은 파일 디스크립터를 줬다.
EINVAL
flags나 mask에 유효하지 않은 값을 줬다. 또는 fanotify_fd가 fanotify 파일 디스크립터가 아니다.
EINVAL
FAN_CLASS_NOTIF로, 또는 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹으로 fanotify 파일 디스크립터를 열였는데 mask에 허가 이벤트를 위한 플래그(FAN_OPEN_PERM이나 FAN_ACCESS_PERM)가 있다.
ENODEV
pathname이 가리키는 파일 시스템 객체가 fsid를 지원하는 파일 시스템에 연계돼 있지 않다. (예를 들면 tmpfs(5).) 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹에서만 이 오류가 반환될 수 있다.
ENOENT
dirfd와 pathname으로 나타낸 파일 시스템 객체가 존재하지 않는다. 표시 안 된 객체에서 표시를 제거하려 할 때도 이 오류가 생긴다.
ENOMEM
필요한 메모리를 할당할 수 없다.
ENOSPC
표시 개수가 제한값인 8192개를 초과했으며 fanotify_init(2)으로 fanotify 파일 디스크립터를 생성할 때 FAN_UNLIMITED_MARKS 플래그를 지정하지 않았다.
ENOSYS
커널에서 fanotify_mark()를 구현하고 있지 않다. 커널을 CONFIG_FANOTIFY로 구성한 경우에만 fanotify API를 쓸 수 있다.
ENOTDIR
flags에 FAN_MARK_ONLYDIR이 있는데 dirfd와 pathname이 디렉터리를 나타내지 않는다.
EOPNOTSUPP
pathname이 가리키는 객체가 파일 핸들 인코딩을 지원하지 않는 파일 시스템에 연계돼 있다. 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹에서만 이 오류가 반환될 수 있다.
EXDEV
pathname이 가리키는 파일 시스템 객체가 루트 수퍼블록과 다른 fsid를 쓰는 파일 시스템 서브볼륨에 위치해 있다. (예를 들면 btrfs(5).) 파일 핸들로 파일 시스템 객체를 식별하는 fanotify 그룹에서만 이 오류가 반환될 수 있다.

VERSIONS

리눅스 커널 버전 2.6.36에서 fanotify_mark()가 도입되었고 버전 2.6.37에서 활성화되었다.

CONFORMING TO

이 시스템 호출은 리눅스 전용이다.

NOTES

FAN_OPEN_EXEC와 FAN_OPEN_EXEC_PERM

mask에 FAN_OPEN_EXEC나 FAN_OPEN_EXEC_PERM를 사용 시에는 프로그램 직접 실행이 이뤄질 때만 그 이벤트들이 반환된다. 구체적으로 말해 execve(2)나 execveat(2), uselib(2)로 열리는 파일에 대해 그 이벤트들이 생성된다. 인터프리터가 파일을 전달받는 (또는 읽어 들이는) 경우에는 그 이벤트들이 생기지 않는다.

그리고 리눅스 동적 링커에도 표시가 돼 있다면 execve(2)나 execveat(2)을 이용해 성공적으로 ELF 오브젝트가 열릴 때도 이벤트를 받을 걸 예상해야 한다.

예를 들어 다음 ELF 바이너리를 호출하려 하고 /에 FAN_OPEN_EXEC 표시를 해 뒀다고 하자.

$ /bin/echo foo

이 경우 이벤트 수신 응용은 그 ELF 바이너리와 인터프리터 각각에 대해 FAN_OPEN_EXEC 이벤트를 받게 된다.

/bin/echo
/lib64/ld-linux-x86-64.so.2

BUGS

리눅스 커널 버전 3.16 전에 다음 버그들이 있었다.

SEE ALSO

fanotify_init(2), fanotify(7)


2021-03-22