|
@@ -16,12 +16,6 @@ static bool should_merge(struct fsnotify_event *old_fsn,
|
|
|
{
|
|
{
|
|
|
struct fanotify_event_info *old, *new;
|
|
struct fanotify_event_info *old, *new;
|
|
|
|
|
|
|
|
-#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
|
|
|
- /* dont merge two permission events */
|
|
|
|
|
- if ((old_fsn->mask & FAN_ALL_PERM_EVENTS) &&
|
|
|
|
|
- (new_fsn->mask & FAN_ALL_PERM_EVENTS))
|
|
|
|
|
- return false;
|
|
|
|
|
-#endif
|
|
|
|
|
pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
|
|
pr_debug("%s: old=%p new=%p\n", __func__, old_fsn, new_fsn);
|
|
|
old = FANOTIFY_E(old_fsn);
|
|
old = FANOTIFY_E(old_fsn);
|
|
|
new = FANOTIFY_E(new_fsn);
|
|
new = FANOTIFY_E(new_fsn);
|
|
@@ -34,14 +28,23 @@ static bool should_merge(struct fsnotify_event *old_fsn,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* and the list better be locked by something too! */
|
|
/* and the list better be locked by something too! */
|
|
|
-static struct fsnotify_event *fanotify_merge(struct list_head *list,
|
|
|
|
|
- struct fsnotify_event *event)
|
|
|
|
|
|
|
+static int fanotify_merge(struct list_head *list, struct fsnotify_event *event)
|
|
|
{
|
|
{
|
|
|
struct fsnotify_event *test_event;
|
|
struct fsnotify_event *test_event;
|
|
|
bool do_merge = false;
|
|
bool do_merge = false;
|
|
|
|
|
|
|
|
pr_debug("%s: list=%p event=%p\n", __func__, list, event);
|
|
pr_debug("%s: list=%p event=%p\n", __func__, list, event);
|
|
|
|
|
|
|
|
|
|
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
|
|
|
+ /*
|
|
|
|
|
+ * Don't merge a permission event with any other event so that we know
|
|
|
|
|
+ * the event structure we have created in fanotify_handle_event() is the
|
|
|
|
|
+ * one we should check for permission response.
|
|
|
|
|
+ */
|
|
|
|
|
+ if (event->mask & FAN_ALL_PERM_EVENTS)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
list_for_each_entry_reverse(test_event, list, list) {
|
|
list_for_each_entry_reverse(test_event, list, list) {
|
|
|
if (should_merge(test_event, event)) {
|
|
if (should_merge(test_event, event)) {
|
|
|
do_merge = true;
|
|
do_merge = true;
|
|
@@ -50,10 +53,10 @@ static struct fsnotify_event *fanotify_merge(struct list_head *list,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!do_merge)
|
|
if (!do_merge)
|
|
|
- return NULL;
|
|
|
|
|
|
|
+ return 0;
|
|
|
|
|
|
|
|
test_event->mask |= event->mask;
|
|
test_event->mask |= event->mask;
|
|
|
- return test_event;
|
|
|
|
|
|
|
+ return 1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
@@ -149,7 +152,6 @@ static int fanotify_handle_event(struct fsnotify_group *group,
|
|
|
int ret = 0;
|
|
int ret = 0;
|
|
|
struct fanotify_event_info *event;
|
|
struct fanotify_event_info *event;
|
|
|
struct fsnotify_event *fsn_event;
|
|
struct fsnotify_event *fsn_event;
|
|
|
- struct fsnotify_event *notify_fsn_event;
|
|
|
|
|
|
|
|
|
|
BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
|
|
BUILD_BUG_ON(FAN_ACCESS != FS_ACCESS);
|
|
|
BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
|
|
BUILD_BUG_ON(FAN_MODIFY != FS_MODIFY);
|
|
@@ -188,21 +190,19 @@ static int fanotify_handle_event(struct fsnotify_group *group,
|
|
|
event->response = 0;
|
|
event->response = 0;
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
- notify_fsn_event = fsnotify_add_notify_event(group, fsn_event,
|
|
|
|
|
- fanotify_merge);
|
|
|
|
|
- if (notify_fsn_event) {
|
|
|
|
|
|
|
+ ret = fsnotify_add_notify_event(group, fsn_event, fanotify_merge);
|
|
|
|
|
+ if (ret) {
|
|
|
|
|
+ BUG_ON(mask & FAN_ALL_PERM_EVENTS);
|
|
|
/* Our event wasn't used in the end. Free it. */
|
|
/* Our event wasn't used in the end. Free it. */
|
|
|
fsnotify_destroy_event(group, fsn_event);
|
|
fsnotify_destroy_event(group, fsn_event);
|
|
|
- if (IS_ERR(notify_fsn_event))
|
|
|
|
|
- return PTR_ERR(notify_fsn_event);
|
|
|
|
|
- /* We need to ask about a different events after a merge... */
|
|
|
|
|
- event = FANOTIFY_E(notify_fsn_event);
|
|
|
|
|
- fsn_event = notify_fsn_event;
|
|
|
|
|
|
|
+ ret = 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
|
|
|
- if (fsn_event->mask & FAN_ALL_PERM_EVENTS)
|
|
|
|
|
|
|
+ if (mask & FAN_ALL_PERM_EVENTS) {
|
|
|
ret = fanotify_get_response_from_access(group, event);
|
|
ret = fanotify_get_response_from_access(group, event);
|
|
|
|
|
+ fsnotify_destroy_event(group, fsn_event);
|
|
|
|
|
+ }
|
|
|
#endif
|
|
#endif
|
|
|
return ret;
|
|
return ret;
|
|
|
}
|
|
}
|