5
5
#include <linux/exportfs.h>
6
6
7
7
extern struct kmem_cache * fanotify_mark_cache ;
8
- extern struct kmem_cache * fanotify_event_cachep ;
8
+ extern struct kmem_cache * fanotify_fid_event_cachep ;
9
+ extern struct kmem_cache * fanotify_path_event_cachep ;
9
10
extern struct kmem_cache * fanotify_perm_event_cachep ;
10
11
11
12
/* Possible states of the permission event */
@@ -18,94 +19,140 @@ enum {
18
19
19
20
/*
20
21
* 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.
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.
25
24
*/
26
- #if BITS_PER_LONG == 32
27
25
#define FANOTIFY_INLINE_FH_LEN (3 << 2)
28
- #else
29
- #define FANOTIFY_INLINE_FH_LEN (4 << 2)
30
- #endif
31
26
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
- };
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
+ }
39
44
40
- static inline void * fanotify_fid_fh (struct fanotify_fid * fid ,
41
- unsigned int fh_len )
45
+ static inline void * fanotify_fh_ext_buf (struct fanotify_fh * fh )
42
46
{
43
- return fh_len <= FANOTIFY_INLINE_FH_LEN ? fid -> fh : fid -> ext_fh ;
47
+ return * fanotify_fh_ext_buf_ptr ( fh ) ;
44
48
}
45
49
46
- static inline bool fanotify_fid_equal (struct fanotify_fid * fid1 ,
47
- struct fanotify_fid * fid2 ,
48
- unsigned int fh_len )
50
+ static inline void * fanotify_fh_buf (struct fanotify_fh * fh )
49
51
{
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 );
52
+ return fanotify_fh_has_ext_buf (fh ) ? fanotify_fh_ext_buf (fh ) : fh -> buf ;
54
53
}
55
54
56
55
/*
57
- * Structure for normal fanotify events. It gets allocated in
56
+ * Common structure for fanotify events. Concrete structs are allocated in
58
57
* fanotify_handle_event() and freed when the information is retrieved by
59
- * userspace
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
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
+
61
68
struct fanotify_event {
62
69
struct fsnotify_event fse ;
63
70
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
- };
71
+ enum fanotify_event_type type ;
86
72
struct pid * pid ;
87
73
};
88
74
89
- static inline bool fanotify_event_has_path (struct fanotify_event * event )
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 )
90
83
{
91
- return event -> fh_type == FILEID_ROOT ;
84
+ return container_of ( event , struct fanotify_fid_event , fae ) ;
92
85
}
93
86
94
- static inline bool fanotify_event_has_fid (struct fanotify_event * event )
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 [0 ];
93
+ };
94
+
95
+ static inline struct fanotify_name_event *
96
+ FANOTIFY_NE (struct fanotify_event * event )
95
97
{
96
- return event -> fh_type != FILEID_ROOT &&
97
- event -> fh_type != FILEID_INVALID ;
98
+ return container_of (event , struct fanotify_name_event , fae );
98
99
}
99
100
100
- static inline bool fanotify_event_has_ext_fh (struct fanotify_event * event )
101
+ static inline __kernel_fsid_t * fanotify_event_fsid (struct fanotify_event * event )
101
102
{
102
- return fanotify_event_has_fid (event ) &&
103
- event -> fh_len > FANOTIFY_INLINE_FH_LEN ;
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 ;
104
109
}
105
110
106
- static inline void * fanotify_event_fh (struct fanotify_event * event )
111
+ static inline struct fanotify_fh * fanotify_event_object_fh (
112
+ struct fanotify_event * event )
107
113
{
108
- return fanotify_fid_fh (& event -> fid , event -> fh_len );
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 );
109
156
}
110
157
111
158
/*
@@ -117,15 +164,16 @@ static inline void *fanotify_event_fh(struct fanotify_event *event)
117
164
*/
118
165
struct fanotify_perm_event {
119
166
struct fanotify_event fae ;
167
+ struct path path ;
120
168
unsigned short response ; /* userspace answer to the event */
121
169
unsigned short state ; /* state of the event */
122
170
int fd ; /* fd we passed to userspace for this event */
123
171
};
124
172
125
173
static inline struct fanotify_perm_event *
126
- FANOTIFY_PE (struct fsnotify_event * fse )
174
+ FANOTIFY_PERM (struct fanotify_event * event )
127
175
{
128
- return container_of (fse , struct fanotify_perm_event , fae . fse );
176
+ return container_of (event , struct fanotify_perm_event , fae );
129
177
}
130
178
131
179
static inline bool fanotify_is_perm_event (u32 mask )
@@ -139,7 +187,24 @@ static inline struct fanotify_event *FANOTIFY_E(struct fsnotify_event *fse)
139
187
return container_of (fse , struct fanotify_event , fse );
140
188
}
141
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
+
142
206
struct fanotify_event * fanotify_alloc_event (struct fsnotify_group * group ,
143
207
struct inode * inode , u32 mask ,
144
208
const void * data , int data_type ,
209
+ const struct qstr * file_name ,
145
210
__kernel_fsid_t * fsid );
0 commit comments