diff options
-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 |