aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/notify/fanotify/fanotify.c19
-rw-r--r--fs/notify/fanotify/fanotify.h3
-rw-r--r--fs/notify/fanotify/fanotify_user.c2
3 files changed, 17 insertions, 7 deletions
diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c
index 6702a6a0bbb5..928f2a5eedb7 100644
--- a/fs/notify/fanotify/fanotify.c
+++ b/fs/notify/fanotify/fanotify.c
@@ -139,23 +139,32 @@ static bool fanotify_should_send_event(struct fsnotify_mark *inode_mark,
139 return false; 139 return false;
140} 140}
141 141
142struct fanotify_event_info *fanotify_alloc_event(struct inode *inode, u32 mask, 142struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
143 struct inode *inode, u32 mask,
143 const struct path *path) 144 const struct path *path)
144{ 145{
145 struct fanotify_event_info *event; 146 struct fanotify_event_info *event;
147 gfp_t gfp = GFP_KERNEL;
148
149 /*
150 * For queues with unlimited length lost events are not expected and
151 * can possibly have security implications. Avoid losing events when
152 * memory is short.
153 */
154 if (group->max_events == UINT_MAX)
155 gfp |= __GFP_NOFAIL;
146 156
147 if (fanotify_is_perm_event(mask)) { 157 if (fanotify_is_perm_event(mask)) {
148 struct fanotify_perm_event_info *pevent; 158 struct fanotify_perm_event_info *pevent;
149 159
150 pevent = kmem_cache_alloc(fanotify_perm_event_cachep, 160 pevent = kmem_cache_alloc(fanotify_perm_event_cachep, gfp);
151 GFP_KERNEL);
152 if (!pevent) 161 if (!pevent)
153 return NULL; 162 return NULL;
154 event = &pevent->fae; 163 event = &pevent->fae;
155 pevent->response = 0; 164 pevent->response = 0;
156 goto init; 165 goto init;
157 } 166 }
158 event = kmem_cache_alloc(fanotify_event_cachep, GFP_KERNEL); 167 event = kmem_cache_alloc(fanotify_event_cachep, gfp);
159 if (!event) 168 if (!event)
160 return NULL; 169 return NULL;
161init: __maybe_unused 170init: __maybe_unused
@@ -210,7 +219,7 @@ static int fanotify_handle_event(struct fsnotify_group *group,
210 return 0; 219 return 0;
211 } 220 }
212 221
213 event = fanotify_alloc_event(inode, mask, data); 222 event = fanotify_alloc_event(group, inode, mask, data);
214 ret = -ENOMEM; 223 ret = -ENOMEM;
215 if (unlikely(!event)) 224 if (unlikely(!event))
216 goto finish; 225 goto finish;
diff --git a/fs/notify/fanotify/fanotify.h b/fs/notify/fanotify/fanotify.h
index 256d9d1ddea9..8609ba06f474 100644
--- a/fs/notify/fanotify/fanotify.h
+++ b/fs/notify/fanotify/fanotify.h
@@ -52,5 +52,6 @@ static inline struct fanotify_event_info *FANOTIFY_E(struct fsnotify_event *fse)
52 return container_of(fse, struct fanotify_event_info, fse); 52 return container_of(fse, struct fanotify_event_info, fse);
53} 53}
54 54
55struct fanotify_event_info *fanotify_alloc_event(struct inode *inode, u32 mask, 55struct fanotify_event_info *fanotify_alloc_event(struct fsnotify_group *group,
56 struct inode *inode, u32 mask,
56 const struct path *path); 57 const struct path *path);
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index c07eb3d655ea..72e367822efb 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -757,7 +757,7 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
757 group->fanotify_data.user = user; 757 group->fanotify_data.user = user;
758 atomic_inc(&user->fanotify_listeners); 758 atomic_inc(&user->fanotify_listeners);
759 759
760 oevent = fanotify_alloc_event(NULL, FS_Q_OVERFLOW, NULL); 760 oevent = fanotify_alloc_event(group, NULL, FS_Q_OVERFLOW, NULL);
761 if (unlikely(!oevent)) { 761 if (unlikely(!oevent)) {
762 fd = -ENOMEM; 762 fd = -ENOMEM;
763 goto out_destroy_group; 763 goto out_destroy_group;