xref: /openbmc/linux/fs/notify/fanotify/fanotify.h (revision 3dc4b6fb)
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_event_cachep;
9 extern struct kmem_cache *fanotify_perm_event_cachep;
10 
11 /* Possible states of the permission event */
12 enum {
13 	FAN_EVENT_INIT,
14 	FAN_EVENT_REPORTED,
15 	FAN_EVENT_ANSWERED,
16 	FAN_EVENT_CANCELED,
17 };
18 
19 /*
20  * 3 dwords are sufficient for most local fs (64bit ino, 32bit generation).
21  * For 32bit arch, fid increases the size of fanotify_event by 12 bytes and
22  * fh_* fields increase the size of fanotify_event by another 4 bytes.
23  * For 64bit arch, fid increases the size of fanotify_fid by 8 bytes and
24  * fh_* fields are packed in a hole after mask.
25  */
26 #if BITS_PER_LONG == 32
27 #define FANOTIFY_INLINE_FH_LEN	(3 << 2)
28 #else
29 #define FANOTIFY_INLINE_FH_LEN	(4 << 2)
30 #endif
31 
32 struct fanotify_fid {
33 	__kernel_fsid_t fsid;
34 	union {
35 		unsigned char fh[FANOTIFY_INLINE_FH_LEN];
36 		unsigned char *ext_fh;
37 	};
38 };
39 
40 static inline void *fanotify_fid_fh(struct fanotify_fid *fid,
41 				    unsigned int fh_len)
42 {
43 	return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid->fh : fid->ext_fh;
44 }
45 
46 static inline bool fanotify_fid_equal(struct fanotify_fid *fid1,
47 				      struct fanotify_fid *fid2,
48 				      unsigned int fh_len)
49 {
50 	return fid1->fsid.val[0] == fid2->fsid.val[0] &&
51 		fid1->fsid.val[1] == fid2->fsid.val[1] &&
52 		!memcmp(fanotify_fid_fh(fid1, fh_len),
53 			fanotify_fid_fh(fid2, fh_len), fh_len);
54 }
55 
56 /*
57  * Structure for normal fanotify events. It gets allocated in
58  * fanotify_handle_event() and freed when the information is retrieved by
59  * userspace
60  */
61 struct fanotify_event {
62 	struct fsnotify_event fse;
63 	u32 mask;
64 	/*
65 	 * Those fields are outside fanotify_fid to pack fanotify_event nicely
66 	 * on 64bit arch and to use fh_type as an indication of whether path
67 	 * or fid are used in the union:
68 	 * FILEID_ROOT (0) for path, > 0 for fid, FILEID_INVALID for neither.
69 	 */
70 	u8 fh_type;
71 	u8 fh_len;
72 	u16 pad;
73 	union {
74 		/*
75 		 * We hold ref to this path so it may be dereferenced at any
76 		 * point during this object's lifetime
77 		 */
78 		struct path path;
79 		/*
80 		 * With FAN_REPORT_FID, we do not hold any reference on the
81 		 * victim object. Instead we store its NFS file handle and its
82 		 * filesystem's fsid as a unique identifier.
83 		 */
84 		struct fanotify_fid fid;
85 	};
86 	struct pid *pid;
87 };
88 
89 static inline bool fanotify_event_has_path(struct fanotify_event *event)
90 {
91 	return event->fh_type == FILEID_ROOT;
92 }
93 
94 static inline bool fanotify_event_has_fid(struct fanotify_event *event)
95 {
96 	return event->fh_type != FILEID_ROOT &&
97 		event->fh_type != FILEID_INVALID;
98 }
99 
100 static inline bool fanotify_event_has_ext_fh(struct fanotify_event *event)
101 {
102 	return fanotify_event_has_fid(event) &&
103 		event->fh_len > FANOTIFY_INLINE_FH_LEN;
104 }
105 
106 static inline void *fanotify_event_fh(struct fanotify_event *event)
107 {
108 	return fanotify_fid_fh(&event->fid, event->fh_len);
109 }
110 
111 /*
112  * Structure for permission fanotify events. It gets allocated and freed in
113  * fanotify_handle_event() since we wait there for user response. When the
114  * information is retrieved by userspace the structure is moved from
115  * group->notification_list to group->fanotify_data.access_list to wait for
116  * user response.
117  */
118 struct fanotify_perm_event {
119 	struct fanotify_event fae;
120 	unsigned short response;	/* userspace answer to the event */
121 	unsigned short state;		/* state of the event */
122 	int fd;		/* fd we passed to userspace for this event */
123 };
124 
125 static inline struct fanotify_perm_event *
126 FANOTIFY_PE(struct fsnotify_event *fse)
127 {
128 	return container_of(fse, struct fanotify_perm_event, fae.fse);
129 }
130 
131 static inline bool fanotify_is_perm_event(u32 mask)
132 {
133 	return IS_ENABLED(CONFIG_FANOTIFY_ACCESS_PERMISSIONS) &&
134 		mask & FANOTIFY_PERM_EVENTS;
135 }
136 
137 static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
138 {
139 	return container_of(fse, struct fanotify_event, fse);
140 }
141 
142 struct fanotify_event *fanotify_alloc_event(struct fsnotify_group *group,
143 					    struct inode *inode, u32 mask,
144 					    const void *data, int data_type,
145 					    __kernel_fsid_t *fsid);
146