ALT Linux Bugzilla
– Attachment 17165 Details for
Bug 52016
CIFS cannot gain access to a file when fanotify works with OPEN_PERM
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
fanotify.c
fanotify.c (text/x-csrc), 7.31 KB, created by
Evgeny Shesteperov
on 2024-11-11 20:28:35 MSK
(
hide
)
Description:
fanotify.c
Filename:
MIME Type:
Creator:
Evgeny Shesteperov
Created:
2024-11-11 20:28:35 MSK
Size:
7.31 KB
patch
obsolete
>#define _GNU_SOURCE /* Needed to get O_LARGEFILE definition */ >#include <errno.h> >#include <fcntl.h> >#include <limits.h> >#include <poll.h> >#include <stdio.h> >#include <stdlib.h> >#include <sys/fanotify.h> >#include <unistd.h> >#include <pthread.h> > >/* Read all available fanotify events from the file descriptor 'fd'. */ > >static void print_path(int fd, char* path, int len) >{ > ssize_t path_len; > char procfd_path[PATH_MAX]; > > /* Allow file to be opened. */ > snprintf(procfd_path, sizeof(procfd_path), "/proc/self/fd/%d", fd); > path_len = readlink(procfd_path, path, len - 1); > if (path_len == -1) > { > perror("readlink"); > } > else > { > path[path_len] = '\0'; > printf("File %s\n", path); > } >} > >static void read_file(int fd) >{ > while (fd >= 0) > { > char b[0x1000]; > int n = read(fd, b, sizeof(b)); > printf("[%d] read %d bytes from %d\n", gettid(), n, fd); > if (n <= 0) > break; > } > usleep(15000); >} > >static void* process_routine(void* arg) >{ > int* data = (int*)arg; > int fd = data[0]; > int mfd = data[1]; > int mask = data[2]; > struct fanotify_response response; > char path[PATH_MAX]; > > print_path(mfd, path, sizeof(path) - 1); > if (mask & FAN_CLOSE_WRITE) > { > printf("FAN_CLOSE_WRITE: "); > close(mfd); > mfd = open(path, O_RDONLY); > read_file(mfd); > close(mfd); > } > else if (mask & FAN_OPEN_PERM) > { > printf("FAN_OPEN_PERM: "); > read_file(mfd); > response.fd = mfd; > response.response = FAN_ALLOW; > write(fd, &response, sizeof(response)); > close(mfd); > } > > free(arg); > return NULL; >} > > >static void handle_events(int fd) >{ > struct fanotify_event_metadata* metadata; > struct fanotify_event_metadata buf[1]; > struct fanotify_response response; > ssize_t len; > > /* Loop while events can be read from fanotify file descriptor. */ > > for (;;) > { > /* Read some events. */ > len = TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))); > if (len == -1) > { > break; > } > > /* Check if end of available data reached. */ > > if (len <= 0) > break; > > /* Point to the first event in the buffer. */ > > metadata = buf; > > /* Loop over all events in the buffer. */ > > while (FAN_EVENT_OK(metadata, len)) > { > /* Check that run-time and compile-time structures match. */ > > if (metadata->vers != FANOTIFY_METADATA_VERSION) > { > fprintf(stderr, "Mismatch of fanotify metadata version.\n"); > exit(EXIT_FAILURE); > } > /* metadata->fd contains either FAN_NOFD, indicating a > queue overflow, or a file descriptor (a nonnegative > integer). Here, we simply ignore queue overflow. */ > > if (metadata->fd >= 0) > { > for (int mask = metadata->mask; mask;) > { > if (mask & FAN_OPEN_PERM) > { > mask &= ~FAN_OPEN_PERM; > // svacer_review: OVERFLOW_UNDER_CHECK r:False Positive|s:Unspecified|a:Undecided|c: 6370363 event points to correct > // place. > metadata->mask = FAN_OPEN_PERM; > } > else if (mask & FAN_CLOSE_WRITE) > { > mask &= ~FAN_CLOSE_WRITE; > // svacer_review: OVERFLOW_UNDER_CHECK r:False Positive|s:Unspecified|a:Undecided|c: 6370363 event points to correct > // place. > metadata->mask = FAN_CLOSE_WRITE; > } > > int dupFd = -1; > if (mask) > { > dupFd = dup(metadata->fd); > if (dupFd == -1) > { > perror("dup"); > } > } > > pthread_t tid; > int* data = calloc(3, sizeof(int)); > data[0] = fd; > data[1] = metadata->fd; > data[2] = metadata->mask; > if (pthread_create(&tid, NULL, process_routine, data)) > { > perror("pthread_create"); > exit(EXIT_FAILURE); > } > pthread_detach(tid); > > if (mask) > { > if (dupFd != -1) > { > metadata->fd = dupFd; > } > else > { > break; > } > } > } > } > > /* Advance to next event. */ > > metadata = FAN_EVENT_NEXT(metadata, len); > } > } >} > >pthread_mutex_t poll_mutex = PTHREAD_MUTEX_INITIALIZER; > >static void* fanotify_thread(void* arg) >{ > int fd = *((int*)arg); > nfds_t nfds = 2; > struct pollfd fds[2]; > > > fds[0].fd = STDIN_FILENO; /* Console input */ > fds[0].events = POLLIN; > > fds[1].fd = fd; /* Fanotify input */ > fds[1].events = POLLIN; > > printf("Listening for events.\n"); > > while (1) > { > int poll_num; > pthread_mutex_lock(&poll_mutex); > poll_num = poll(fds, nfds, -1); > pthread_mutex_unlock(&poll_mutex); > if (poll_num == -1) > { > if (errno == EINTR) /* Interrupted by a signal */ > continue; /* Restart poll() */ > > perror("poll"); /* Unexpected error */ > exit(EXIT_FAILURE); > } > > if (poll_num > 0) > { > if (fds[0].revents & POLLIN) > { > break; > } > > if (fds[1].revents & POLLIN) > { > /* Fanotify events are available. */ > > handle_events(fd); > } > } > } >} > >int main(int argc, char* argv[]) >{ > int fd; > > /* Check mount point is supplied. */ > > if (argc != 2) > { > fprintf(stderr, "Usage: %s MOUNT\n", argv[0]); > exit(EXIT_FAILURE); > } > > printf("Press enter key to terminate.\n"); > > /* Create the file descriptor for accessing the fanotify API. */ > > fd = fanotify_init(FAN_CLOEXEC | FAN_CLASS_CONTENT | FAN_NONBLOCK | FAN_UNLIMITED_QUEUE, O_RDONLY | O_NOATIME | O_LARGEFILE); > if (fd == -1) > { > perror("fanotify_init"); > exit(EXIT_FAILURE); > } > > /* Mark the mount for: > - permission events before opening files > - notification events after closing a write-enabled > file descriptor. */ > > if (fanotify_mark(fd, FAN_MARK_ADD | FAN_MARK_MOUNT, FAN_OPEN_PERM | FAN_CLOSE_WRITE, AT_FDCWD, argv[1]) == -1) > { > perror("fanotify_mark"); > exit(EXIT_FAILURE); > } > > /* Prepare for polling. */ > > pthread_t threads[5]; > for (int i = 0; i < sizeof(threads) / sizeof(threads[0]); i++) > { > if (pthread_create(&threads[i], NULL, fanotify_thread, &fd)) > { > perror("pthread_create"); > exit(EXIT_FAILURE); > } > } > > for (int i = 0; i < sizeof(threads) / sizeof(threads[0]); i++) > { > pthread_join(threads[i], NULL); > } > > printf("Listening for events stopped.\n"); > exit(EXIT_SUCCESS); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 52016
: 17165 |
17166