xref: /openbmc/linux/fs/notify/fanotify/fanotify.h (revision c8ed9fc9)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #include <linux/fsnotify_backend.h>
3 #include <linux/path.h>
4 #include <linux/slab.h>
5 #include <linux/exportfs.h>
6 
7 extern struct kmem_cache *fanotify_mark_cache;
8 extern struct kmem_cache *fanotify_fid_event_cachep;
9 extern struct kmem_cache *fanotify_path_event_cachep;
10 extern struct kmem_cache *fanotify_perm_event_cachep;
11 
12 /* Possible states of the permission event */
13 enum {
14 	FAN_EVENT_INIT,
15 	FAN_EVENT_REPORTED,
16 	FAN_EVENT_ANSWERED,
17 	FAN_EVENT_CANCELED,
18 };
19 
20 /*
21  * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation).
22  * fh buf should be dword aligned. On 64bit arch, the ext_buf pointer is
23  * stored in either the first or last 2 dwords.
24  */
25 #define FANOTIFY_INLINE_FH_LEN	(3 << 2)
26 
27 struct fanotify_fh {
28 	unsigned char buf[FANOTIFY_INLINE_FH_LEN];
29 	u8 type;
30 	u8 len;
31 } __aligned(4);
32 
33 static inline bool fanotify_fh_has_ext_buf(struct fanotify_fh *fh)
34 {
35 	return fh->len > FANOTIFY_INLINE_FH_LEN;
36 }
37 
38 static inline char **fanotify_fh_ext_buf_ptr(struct fanotify_fh *fh)
39 {
40 	BUILD_BUG_ON(__alignof__(char *) - 4 + sizeof(char *) >
41 		     FANOTIFY_INLINE_FH_LEN);
42 	return (char **)ALIGN((unsigned long)(fh->buf), __alignof__(char *));
43 }
44 
45 static inline void *fanotify_fh_ext_buf(struct fanotify_fh *fh)
46 {
47 	return *fanotify_fh_ext_buf_ptr(fh);
48 }
49 
50 static inline void *fanotify_fh_buf(struct fanotify_fh *fh)
51 {
52 	return fanotify_fh_has_ext_buf(fh) ? fanotify_fh_ext_buf(fh) : fh->buf;
53 }
54 
55 /*
56  * Common structure for fanotify events. Concrete structs are allocated in
57  * fanotify_handle_event() and freed when the information is retrieved by
58  * userspace. The type of event determines how it was allocated, how it will
59  * be freed and which concrete struct it may be cast to.
60  */
61 enum fanotify_event_type {
62 	FANOTIFY_EVENT_TYPE_FID, /* fixed length */
63 	FANOTIFY_EVENT_TYPE_FID_NAME, /* variable length */
64 	FANOTIFY_EVENT_TYPE_PATH,
65 	FANOTIFY_EVENT_TYPE_PATH_PERM,
66 };
67 
68 struct fanotify_event {
69 	struct fsnotify_event fse;
70 	u32 mask;
71 	enum fanotify_event_type type;
72 	struct pid *pid;
73 };
74 
75 struct fanotify_fid_event {
76 	struct fanotify_event fae;
77 	__kernel_fsid_t fsid;
78 	struct fanotify_fh object_fh;
79 };
80 
81 static inline struct fanotify_fid_event *
82 FANOTIFY_FE(struct fanotify_event *event)
83 {
84 	return container_of(event, struct fanotify_fid_event, fae);
85 }
86 
87 struct fanotify_name_event {
88 	struct fanotify_event fae;
89 	__kernel_fsid_t fsid;
90 	struct fanotify_fh dir_fh;
91 	u8 name_len;
92 	char name[];
93 };
94 
95 static inline struct fanotify_name_event *
96 FANOTIFY_NE(struct fanotify_event *event)
97 {
98 	return container_of(event, struct fanotify_name_event, fae);
99 }
100 
101 static inline __kernel_fsid_t *fanotify_event_fsid(struct fanotify_event *event)
102 {
103 	if (event->type == FANOTIFY_EVENT_TYPE_FID)
104 		return &FANOTIFY_FE(event)->fsid;
105 	else if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME)
106 		return &FANOTIFY_NE(event)->fsid;
107 	else
108 		return NULL;
109 }
110 
111 static inline struct fanotify_fh *fanotify_event_object_fh(
112 						struct fanotify_event *event)
113 {
114 	if (event->type == FANOTIFY_EVENT_TYPE_FID)
115 		return &FANOTIFY_FE(event)->object_fh;
116 	else
117 		return NULL;
118 }
119 
120 static inline struct fanotify_fh *fanotify_event_dir_fh(
121 						struct fanotify_event *event)
122 {
123 	if (event->type == FANOTIFY_EVENT_TYPE_FID_NAME)
124 		return &FANOTIFY_NE(event)->dir_fh;
125 	else
126 		return NULL;
127 }
128 
129 static inline int fanotify_event_object_fh_len(struct fanotify_event *event)
130 {
131 	struct fanotify_fh *fh = fanotify_event_object_fh(event);
132 
133 	return fh ? fh->len : 0;
134 }
135 
136 static inline bool fanotify_event_has_name(struct fanotify_event *event)
137 {
138 	return event->type == FANOTIFY_EVENT_TYPE_FID_NAME;
139 }
140 
141 static inline int fanotify_event_name_len(struct fanotify_event *event)
142 {
143 	return fanotify_event_has_name(event) ?
144 		FANOTIFY_NE(event)->name_len : 0;
145 }
146 
147 struct fanotify_path_event {
148 	struct fanotify_event fae;
149 	struct path path;
150 };
151 
152 static inline struct fanotify_path_event *
153 FANOTIFY_PE(struct fanotify_event *event)
154 {
155 	return container_of(event, struct fanotify_path_event, fae);
156 }
157 
158 /*
159  * Structure for permission fanotify events. It gets allocated and freed in
160  * fanotify_handle_event() since we wait there for user response. When the
161  * information is retrieved by userspace the structure is moved from
162  * group->notification_list to group->fanotify_data.access_list to wait for
163  * user response.
164  */
165 struct fanotify_perm_event {
166 	struct fanotify_event fae;
167 	struct path path;
168 	unsigned short response;	/* userspace answer to the event */
169 	unsigned short state;		/* state of the event */
170 	int fd;		/* fd we passed to userspace for this event */
171 };
172 
173 static inline struct fanotify_perm_event *
174 FANOTIFY_PERM(struct fanotify_event *event)
175 {
176 	return container_of(event, struct fanotify_perm_event, fae);
177 }
178 
179 static inline bool fanotify_is_perm_event(u32 mask)
180 {
181 	return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) &&
182 		mask & FANOTIFY_PERM_EVENTS;
183 }
184 
185 static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
186 {
187 	return container_of(fse, struct fanotify_event, fse);
188 }
189 
190 static inline bool fanotify_event_has_path(struct fanotify_event *event)
191 {
192 	return event->type == FANOTIFY_EVENT_TYPE_PATH ||
193 		event->type == FANOTIFY_EVENT_TYPE_PATH_PERM;
194 }
195 
196 static inline struct path *fanotify_event_path(struct fanotify_event *event)
197 {
198 	if (event->type == FANOTIFY_EVENT_TYPE_PATH)
199 		return &FANOTIFY_PE(event)->path;
200 	else if (event->type == FANOTIFY_EVENT_TYPE_PATH_PERM)
201 		return &FANOTIFY_PERM(event)->path;
202 	else
203 		return NULL;
204 }
205 
206 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
207 					    struct inode *inode, u32 mask,
208 					    const void *data, int data_type,
209 					    const struct qstr *file_name,
210 					    __kernel_fsid_t *fsid);
211