aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2018-02-21 08:10:59 -0500
committerJan Kara <jack@suse.cz>2018-02-27 04:25:33 -0500
commit1f5eaa90010ed7cf0ae90a526c48657d02c6086f (patch)
treeaccb9faea9a7b5160d5e35f320007938e2f76af9
parentf0c4a81711cb773b60cb8f90173e6491e67bf74f (diff)
fanotify: Avoid lost events due to ENOMEM for unlimited queues
Fanotify queues of unlimited length do not expect events can be lost. Since these queues are used for system auditing and other security related tasks, loosing events can even have security implications. Currently, since the allocation is small (32-bytes), it cannot fail however when we start accounting events in memcgs, allocation can start failing. So avoid loosing events due to failure to allocate memory by making event allocation use __GFP_NOFAIL. Reviewed-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Jan Kara <jack@suse.cz>
-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;