fanotify: limit number of listeners per user
authorEric Paris <eparis@redhat.com>
Thu, 28 Oct 2010 21:21:58 +0000 (17:21 -0400)
committerEric Paris <eparis@redhat.com>
Thu, 28 Oct 2010 21:22:15 +0000 (17:22 -0400)
fanotify currently has no limit on the number of listeners a given user can
have open.  This patch limits the total number of listeners per user to
128.  This is the same as the inotify default limit.

Signed-off-by: Eric Paris <eparis@redhat.com>
fs/notify/fanotify/fanotify.c
fs/notify/fanotify/fanotify_user.c
include/linux/fsnotify_backend.h
include/linux/sched.h

index 85366c78cc3759b1a0027e1a3d5d0598e2f2fdec..60c11c306fd91429c3637baa4530f547d3c6c324 100644 (file)
@@ -200,10 +200,19 @@ static bool fanotify_should_send_event(struct fsnotify_group *group,
        return false;
 }
 
+static void fanotify_free_group_priv(struct fsnotify_group *group)
+{
+       struct user_struct *user;
+
+       user = group->fanotify_data.user;
+       atomic_dec(&user->fanotify_listeners);
+       free_uid(user);
+}
+
 const struct fsnotify_ops fanotify_fsnotify_ops = {
        .handle_event = fanotify_handle_event,
        .should_send_event = fanotify_should_send_event,
-       .free_group_priv = NULL,
+       .free_group_priv = fanotify_free_group_priv,
        .free_event_priv = NULL,
        .freeing_mark = NULL,
 };
index f9216102b4261f997b6838be271110f4a3238a6e..a7d9369482d59a0ec38825c98f21ed9b80358e86 100644 (file)
@@ -18,6 +18,7 @@
 
 #define FANOTIFY_DEFAULT_MAX_EVENTS    16384
 #define FANOTIFY_DEFAULT_MAX_MARKS     8192
+#define FANOTIFY_DEFAULT_MAX_LISTENERS 128
 
 extern const struct fsnotify_ops fanotify_fsnotify_ops;
 
@@ -656,6 +657,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 {
        struct fsnotify_group *group;
        int f_flags, fd;
+       struct user_struct *user;
 
        pr_debug("%s: flags=%d event_f_flags=%d\n",
                __func__, flags, event_f_flags);
@@ -666,6 +668,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        if (flags & ~FAN_ALL_INIT_FLAGS)
                return -EINVAL;
 
+       user = get_current_user();
+       if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) {
+               free_uid(user);
+               return -EMFILE;
+       }
+
        f_flags = O_RDWR | FMODE_NONOTIFY;
        if (flags & FAN_CLOEXEC)
                f_flags |= O_CLOEXEC;
@@ -677,6 +685,9 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
        if (IS_ERR(group))
                return PTR_ERR(group);
 
+       group->fanotify_data.user = user;
+       atomic_inc(&user->fanotify_listeners);
+
        group->fanotify_data.f_flags = event_f_flags;
 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
        mutex_init(&group->fanotify_data.access_mutex);
index 49ceed6e92b1af41415a2ba8bf87038fed48de4d..4366f458a86af6da0d67a57109467885a72519ad 100644 (file)
@@ -170,6 +170,7 @@ struct fsnotify_group {
 #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */
                        int f_flags;
                        unsigned int max_marks;
+                       struct user_struct *user;
                } fanotify_data;
 #endif /* CONFIG_FANOTIFY */
        };
index be7adb7588e5e5519c45caff28534cb3e2476b72..6f420baf37ca05e7e8395eed236f0ba5f1a0fde7 100644 (file)
@@ -672,6 +672,9 @@ struct user_struct {
        atomic_t inotify_watches; /* How many inotify watches does this user have? */
        atomic_t inotify_devs;  /* How many inotify devs does this user have opened? */
 #endif
+#ifdef CONFIG_FANOTIFY
+       atomic_t fanotify_listeners;
+#endif
 #ifdef CONFIG_EPOLL
        atomic_t epoll_watches; /* The number of file descriptors currently watched */
 #endif