diff options
Diffstat (limited to 'fs/notify/fanotify/fanotify.c')
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 27 |
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 | ||
209 | static 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 | |||
203 | const struct fsnotify_ops fanotify_fsnotify_ops = { | 218 | const 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 | }; |