aboutsummaryrefslogtreecommitdiffstats
path: root/fs/notify/fanotify/fanotify.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/notify/fanotify/fanotify.c')
-rw-r--r--fs/notify/fanotify/fanotify.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 85366c78cc37..b04f88eed09e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -131,6 +131,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW); 131 BUILD_BUG_ON(FAN_Q_OVERFLOW != FS_Q_OVERFLOW);
132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM); 132 BUILD_BUG_ON(FAN_OPEN_PERM != FS_OPEN_PERM);
133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM); 133 BUILD_BUG_ON(FAN_ACCESS_PERM != FS_ACCESS_PERM);
134 BUILD_BUG_ON(FAN_ONDIR != FS_ISDIR);
134 135
135 pr_debug("%s: group=%p event=%p\n", __func__, group, event); 136 pr_debug("%s: group=%p event=%p\n", __func__, group, event);
136 137
@@ -160,20 +161,21 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
160 __u32 event_mask, void *data, int data_type) 161 __u32 event_mask, void *data, int data_type)
161{ 162{
162 __u32 marks_mask, marks_ignored_mask; 163 __u32 marks_mask, marks_ignored_mask;
164 struct path *path = data;
163 165
164 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p " 166 pr_debug("%s: group=%p to_tell=%p inode_mark=%p vfsmnt_mark=%p "
165 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell, 167 "mask=%x data=%p data_type=%d\n", __func__, group, to_tell,
166 inode_mark, vfsmnt_mark, event_mask, data, data_type); 168 inode_mark, vfsmnt_mark, event_mask, data, data_type);
167 169
168 /* sorry, fanotify only gives a damn about files and dirs */
169 if (!S_ISREG(to_tell->i_mode) &&
170 !S_ISDIR(to_tell->i_mode))
171 return false;
172
173 /* if we don't have enough info to send an event to userspace say no */ 170 /* if we don't have enough info to send an event to userspace say no */
174 if (data_type != FSNOTIFY_EVENT_PATH) 171 if (data_type != FSNOTIFY_EVENT_PATH)
175 return false; 172 return false;
176 173
174 /* sorry, fanotify only gives a damn about files and dirs */
175 if (!S_ISREG(path->dentry->d_inode->i_mode) &&
176 !S_ISDIR(path->dentry->d_inode->i_mode))
177 return false;
178
177 if (inode_mark && vfsmnt_mark) { 179 if (inode_mark && vfsmnt_mark) {
178 marks_mask = (vfsmnt_mark->mask | inode_mark->mask); 180 marks_mask = (vfsmnt_mark->mask | inode_mark->mask);
179 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask); 181 marks_ignored_mask = (vfsmnt_mark->ignored_mask | inode_mark->ignored_mask);
@@ -194,16 +196,29 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
194 BUG(); 196 BUG();
195 } 197 }
196 198
199 if (S_ISDIR(path->dentry->d_inode->i_mode) &&
200 (marks_ignored_mask & FS_ISDIR))
201 return false;
202
197 if (event_mask & marks_mask & ~marks_ignored_mask) 203 if (event_mask & marks_mask & ~marks_ignored_mask)
198 return true; 204 return true;
199 205
200 return false; 206 return false;
201} 207}
202 208
209static void fanotify_free_group_priv(struct fsnotify_group *group)
210{
211 struct user_struct *user;
212
213 user = group->fanotify_data.user;
214 atomic_dec(&user->fanotify_listeners);
215 free_uid(user);
216}
217
203const struct fsnotify_ops fanotify_fsnotify_ops = { 218const struct fsnotify_ops fanotify_fsnotify_ops = {
204 .handle_event = fanotify_handle_event, 219 .handle_event = fanotify_handle_event,
205 .should_send_event = fanotify_should_send_event, 220 .should_send_event = fanotify_should_send_event,
206 .free_group_priv = NULL, 221 .free_group_priv = fanotify_free_group_priv,
207 .free_event_priv = NULL, 222 .free_event_priv = NULL,
208 .freeing_mark = NULL, 223 .freeing_mark = NULL,
209}; 224};