From: Eric Paris <eparis@redhat.com>
To: linux-kernel@vger.kernel.org
Subject: [PATCH 5/5] fanotify: flush outstanding perm requests on group destroy
Date: Wed, 18 Aug 2010 12:30:17 -0400 [thread overview]
Message-ID: <20100818163016.1080.18246.stgit@paris.rdu.redhat.com> (raw)
In-Reply-To: <20100818162954.1080.48055.stgit@paris.rdu.redhat.com>
fanotify should flush (and allow) all outstanding permission requests when
the group is being torn down. The most logical place for this flushing
was the fsnotify free_group_priv hook but that hook can't work. When fanotify
is waiting on a permission response from userspace it is holding the
fsnotify mark srcu lock. Group tear down to get to the free_group_priv hook
requires syncronizing the srcu lock.
The solution entered here is to add an atomic which is set on fanotify_release
which will prevent any further permissions actions from being taken. We then
flush all outstanding permission events, which will cause the original side to
release the srcu lock. The group destruction code then proceeds to sync the
srcu lock and finish cleaning up normally.
Signed-off-by: Eric Paris <eparis@redhat.com>
---
fs/notify/fanotify/fanotify.c | 3 +++
fs/notify/fanotify/fanotify_user.c | 21 +++++++++++++++++++++
include/linux/fanotify.h | 7 -------
include/linux/fsnotify_backend.h | 1 +
4 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 756566f..fe7845e 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -92,6 +92,9 @@ static int fanotify_get_response_from_access(struct fsnotify_group *group,
pr_debug("%s: group=%p event=%p\n", __func__, group, event);
+ if (unlikely(atomic_read(&group->fanotify_data.bypass_perm)))
+ return 0;
+
wait_event(group->fanotify_data.access_waitq, event->response);
/* userspace responded, convert to something usable */
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index 032b837..425ec89 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -187,6 +187,9 @@ static int prepare_for_access_response(struct fsnotify_group *group,
if (!(event->mask & FAN_ALL_PERM_EVENTS))
return 0;
+ if (unlikely(atomic_read(&group->fanotify_data.bypass_perm)))
+ return 0;
+
re = kmem_cache_alloc(fanotify_response_event_cache, GFP_KERNEL);
if (!re)
return -ENOMEM;
@@ -364,9 +367,27 @@ static ssize_t fanotify_write(struct file *file, const char __user *buf, size_t
static int fanotify_release(struct inode *ignored, struct file *file)
{
struct fsnotify_group *group = file->private_data;
+ struct fanotify_response_event *re, *lre;
pr_debug("%s: file=%p group=%p\n", __func__, file, group);
+#ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
+ atomic_inc(&group->fanotify_data.bypass_perm);
+
+ mutex_lock(&group->fanotify_data.access_mutex);
+ list_for_each_entry_safe(re, lre, &group->fanotify_data.access_list, list) {
+ pr_debug("%s: found group=%p re=%p event=%p\n", __func__, group,
+ re, re->event);
+
+ list_del_init(&re->list);
+ re->event->response = FAN_ALLOW;
+
+ kmem_cache_free(fanotify_response_event_cache, re);
+ }
+ mutex_unlock(&group->fanotify_data.access_mutex);
+
+ wake_up(&group->fanotify_data.access_waitq);
+#endif
/* matches the fanotify_init->fsnotify_alloc_group */
fsnotify_put_group(group);
diff --git a/include/linux/fanotify.h b/include/linux/fanotify.h
index f0949a5..9854356 100644
--- a/include/linux/fanotify.h
+++ b/include/linux/fanotify.h
@@ -95,11 +95,4 @@ struct fanotify_response {
(long)(meta)->event_len >= (long)FAN_EVENT_METADATA_LEN && \
(long)(meta)->event_len <= (long)(len))
-#ifdef __KERNEL__
-
-struct fanotify_wait {
- struct fsnotify_event *event;
- __s32 fd;
-};
-#endif /* __KERNEL__ */
#endif /* _LINUX_FANOTIFY_H */
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index ed36fb5..3d5b07c 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -156,6 +156,7 @@ struct fsnotify_group {
struct mutex access_mutex;
struct list_head access_list;
wait_queue_head_t access_waitq;
+ atomic_t bypass_perm;
#endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
int f_flags;
} fanotify_data;
next prev parent reply other threads:[~2010-08-18 16:30 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-08-18 16:29 [PATCH 1/5] fanotify: do not dereference inode_mark when it is unset Eric Paris
2010-08-18 16:29 ` [PATCH 2/5] fsnotify: reset used_inode and used_vfsmount on each pass Eric Paris
2010-08-18 16:30 ` [PATCH 3/5] fanotify: add MAINTAINERS entry Eric Paris
2010-08-18 16:30 ` [PATCH 4/5] fsnotify: fix ignored mask handling between inode and vfsmount marks Eric Paris
2010-08-18 16:30 ` Eric Paris [this message]
2010-08-19 14:07 ` [PATCH 5/5] fanotify: flush outstanding perm requests on group destroy Eric Paris
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20100818163016.1080.18246.stgit@paris.rdu.redhat.com \
--to=eparis@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®