• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: MIT */
2 /*
3  * Description: test fsnotify access off O_DIRECT read
4  */
5 
6 #include "helpers.h"
7 
8 #ifdef CONFIG_HAVE_FANOTIFY
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <fcntl.h>
13 #include <sys/fanotify.h>
14 #include <sys/stat.h>
15 #include <sys/wait.h>
16 
17 #include "liburing.h"
18 
main(int argc,char * argv[])19 int main(int argc, char *argv[])
20 {
21 	struct io_uring_sqe *sqe;
22 	struct io_uring_cqe *cqe;
23 	struct io_uring ring;
24 	int fan, ret, fd, err;
25 	char fname[64], *f;
26 	struct stat sb;
27 	void *buf;
28 
29 	fan = fanotify_init(FAN_CLASS_NOTIF|FAN_CLASS_CONTENT, 0);
30 	if (fan < 0) {
31 		if (errno == ENOSYS)
32 			return T_EXIT_SKIP;
33 		if (geteuid())
34 			return T_EXIT_SKIP;
35 		perror("fanotify_init");
36 		return T_EXIT_FAIL;
37 	}
38 
39 	err = T_EXIT_FAIL;
40 	if (argc > 1) {
41 		f = argv[1];
42 		fd = open(argv[1], O_RDONLY | O_DIRECT);
43 		if (fd < 0 && errno == EINVAL)
44 			return T_EXIT_SKIP;
45 	} else {
46 		sprintf(fname, ".fsnotify.%d", getpid());
47 		f = fname;
48 		t_create_file(fname, 8192);
49 		fd = open(fname, O_RDONLY | O_DIRECT);
50 		if (fd < 0 && errno == EINVAL) {
51 			unlink(fname);
52 			return T_EXIT_SKIP;
53 		}
54 	}
55 	if (fd < 0) {
56 		perror("open");
57 		goto out;
58 	}
59 
60 	if (fstat(fd, &sb) < 0) {
61 		perror("fstat");
62 		goto out;
63 	}
64 	if ((sb.st_mode & S_IFMT) != S_IFREG) {
65 		err = T_EXIT_SKIP;
66 		close(fd);
67 		goto out;
68 	}
69 
70 	ret = fanotify_mark(fan, FAN_MARK_ADD, FAN_ACCESS|FAN_MODIFY, fd, NULL);
71 	if (ret < 0) {
72 		perror("fanotify_mark");
73 		goto out;
74 	}
75 
76 	if (fork()) {
77 		int wstat;
78 
79 		io_uring_queue_init(1, &ring, 0);
80 		if (posix_memalign(&buf, 4096, 4096))
81 			goto out;
82 		sqe = io_uring_get_sqe(&ring);
83 		io_uring_prep_read(sqe, fd, buf, 4096, 0);
84 		io_uring_submit(&ring);
85 		ret = io_uring_wait_cqe(&ring, &cqe);
86 		if (ret) {
87 			fprintf(stderr, "wait_ret=%d\n", ret);
88 			goto out;
89 		}
90 		wait(&wstat);
91 		if (!WEXITSTATUS(wstat))
92 			err = T_EXIT_PASS;
93 		free(buf);
94 	} else {
95 		struct fanotify_event_metadata m;
96 		int fret;
97 
98 		fret = read(fan, &m, sizeof(m));
99 		if (fret < 0)
100 			perror("fanotify read");
101 		/* fail if mask isn't right or pid indicates non-task context */
102 		else if (!(m.mask & 1) || !m.pid)
103 			exit(1);
104 		exit(0);
105 	}
106 
107 out:
108 	if (f == fname)
109 		unlink(fname);
110 	return err;
111 }
112 
113 #else /* #ifdef CONFIG_HAVE_FANOTIFY */
114 
main(void)115 int main(void)
116 {
117 	return T_EXIT_SKIP;
118 }
119 #endif /* #ifdef CONFIG_HAVE_FANOTIFY */
120