diff options
| author | Eric Paris <eparis@redhat.com> | 2010-10-28 17:21:58 -0400 |
|---|---|---|
| committer | Eric Paris <eparis@redhat.com> | 2010-10-28 17:22:15 -0400 |
| commit | 4afeff8505cb8a38e36c1ef2bd3447c4b8f87367 (patch) | |
| tree | 50a80d8773698813e4e9d9f9112079c09d493c48 | |
| parent | ac7e22dcfafd04c842a02057afd6541c1d613ef9 (diff) | |
fanotify: limit number of listeners per user
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>
| -rw-r--r-- | fs/notify/fanotify/fanotify.c | 11 | ||||
| -rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 11 | ||||
| -rw-r--r-- | include/linux/fsnotify_backend.h | 1 | ||||
| -rw-r--r-- | include/linux/sched.h | 3 |
4 files changed, 25 insertions, 1 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 85366c78cc37..60c11c306fd9 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c | |||
| @@ -200,10 +200,19 @@ static bool fanotify_should_send_event(struct fsnotify_group *group, | |||
| 200 | return false; | 200 | return false; |
| 201 | } | 201 | } |
| 202 | 202 | ||
| 203 | static void fanotify_free_group_priv(struct fsnotify_group *group) | ||
| 204 | { | ||
| 205 | struct user_struct *user; | ||
| 206 | |||
| 207 | user = group->fanotify_data.user; | ||
| 208 | atomic_dec(&user->fanotify_listeners); | ||
| 209 | free_uid(user); | ||
| 210 | } | ||
| 211 | |||
| 203 | const struct fsnotify_ops fanotify_fsnotify_ops = { | 212 | const struct fsnotify_ops fanotify_fsnotify_ops = { |
| 204 | .handle_event = fanotify_handle_event, | 213 | .handle_event = fanotify_handle_event, |
| 205 | .should_send_event = fanotify_should_send_event, | 214 | .should_send_event = fanotify_should_send_event, |
| 206 | .free_group_priv = NULL, | 215 | .free_group_priv = fanotify_free_group_priv, |
| 207 | .free_event_priv = NULL, | 216 | .free_event_priv = NULL, |
| 208 | .freeing_mark = NULL, | 217 | .freeing_mark = NULL, |
| 209 | }; | 218 | }; |
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index f9216102b426..a7d9369482d5 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 | 19 | #define FANOTIFY_DEFAULT_MAX_EVENTS 16384 |
| 20 | #define FANOTIFY_DEFAULT_MAX_MARKS 8192 | 20 | #define FANOTIFY_DEFAULT_MAX_MARKS 8192 |
| 21 | #define FANOTIFY_DEFAULT_MAX_LISTENERS 128 | ||
| 21 | 22 | ||
| 22 | extern const struct fsnotify_ops fanotify_fsnotify_ops; | 23 | extern const struct fsnotify_ops fanotify_fsnotify_ops; |
| 23 | 24 | ||
| @@ -656,6 +657,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
| 656 | { | 657 | { |
| 657 | struct fsnotify_group *group; | 658 | struct fsnotify_group *group; |
| 658 | int f_flags, fd; | 659 | int f_flags, fd; |
| 660 | struct user_struct *user; | ||
| 659 | 661 | ||
| 660 | pr_debug("%s: flags=%d event_f_flags=%d\n", | 662 | pr_debug("%s: flags=%d event_f_flags=%d\n", |
| 661 | __func__, flags, event_f_flags); | 663 | __func__, flags, event_f_flags); |
| @@ -666,6 +668,12 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
| 666 | if (flags & ~FAN_ALL_INIT_FLAGS) | 668 | if (flags & ~FAN_ALL_INIT_FLAGS) |
| 667 | return -EINVAL; | 669 | return -EINVAL; |
| 668 | 670 | ||
| 671 | user = get_current_user(); | ||
| 672 | if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) { | ||
| 673 | free_uid(user); | ||
| 674 | return -EMFILE; | ||
| 675 | } | ||
| 676 | |||
| 669 | f_flags = O_RDWR | FMODE_NONOTIFY; | 677 | f_flags = O_RDWR | FMODE_NONOTIFY; |
| 670 | if (flags & FAN_CLOEXEC) | 678 | if (flags & FAN_CLOEXEC) |
| 671 | f_flags |= O_CLOEXEC; | 679 | f_flags |= O_CLOEXEC; |
| @@ -677,6 +685,9 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) | |||
| 677 | if (IS_ERR(group)) | 685 | if (IS_ERR(group)) |
| 678 | return PTR_ERR(group); | 686 | return PTR_ERR(group); |
| 679 | 687 | ||
| 688 | group->fanotify_data.user = user; | ||
| 689 | atomic_inc(&user->fanotify_listeners); | ||
| 690 | |||
| 680 | group->fanotify_data.f_flags = event_f_flags; | 691 | group->fanotify_data.f_flags = event_f_flags; |
| 681 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS | 692 | #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS |
| 682 | mutex_init(&group->fanotify_data.access_mutex); | 693 | mutex_init(&group->fanotify_data.access_mutex); |
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h index 49ceed6e92b1..4366f458a86a 100644 --- a/include/linux/fsnotify_backend.h +++ b/include/linux/fsnotify_backend.h | |||
| @@ -170,6 +170,7 @@ struct fsnotify_group { | |||
| 170 | #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ | 170 | #endif /* CONFIG_FANOTIFY_ACCESS_PERMISSIONS */ |
| 171 | int f_flags; | 171 | int f_flags; |
| 172 | unsigned int max_marks; | 172 | unsigned int max_marks; |
| 173 | struct user_struct *user; | ||
| 173 | } fanotify_data; | 174 | } fanotify_data; |
| 174 | #endif /* CONFIG_FANOTIFY */ | 175 | #endif /* CONFIG_FANOTIFY */ |
| 175 | }; | 176 | }; |
diff --git a/include/linux/sched.h b/include/linux/sched.h index be7adb7588e5..6f420baf37ca 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -672,6 +672,9 @@ struct user_struct { | |||
| 672 | atomic_t inotify_watches; /* How many inotify watches does this user have? */ | 672 | atomic_t inotify_watches; /* How many inotify watches does this user have? */ |
| 673 | atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ | 673 | atomic_t inotify_devs; /* How many inotify devs does this user have opened? */ |
| 674 | #endif | 674 | #endif |
| 675 | #ifdef CONFIG_FANOTIFY | ||
| 676 | atomic_t fanotify_listeners; | ||
| 677 | #endif | ||
| 675 | #ifdef CONFIG_EPOLL | 678 | #ifdef CONFIG_EPOLL |
| 676 | atomic_t epoll_watches; /* The number of file descriptors currently watched */ | 679 | atomic_t epoll_watches; /* The number of file descriptors currently watched */ |
| 677 | #endif | 680 | #endif |
