]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/4.9.30/fanotify-don-t-expose-eopenstale-to-userspace.patch
Linux 4.14.95
[thirdparty/kernel/stable-queue.git] / releases / 4.9.30 / fanotify-don-t-expose-eopenstale-to-userspace.patch
CommitLineData
208fc782
GKH
1From 4ff33aafd32e084f5ee7faa54ba06e95f8b1b8af Mon Sep 17 00:00:00 2001
2From: Amir Goldstein <amir73il@gmail.com>
3Date: Tue, 25 Apr 2017 14:29:35 +0300
4Subject: fanotify: don't expose EOPENSTALE to userspace
5
6From: Amir Goldstein <amir73il@gmail.com>
7
8commit 4ff33aafd32e084f5ee7faa54ba06e95f8b1b8af upstream.
9
10When delivering an event to userspace for a file on an NFS share,
11if the file is deleted on server side before user reads the event,
12user will not get the event.
13
14If the event queue contained several events, the stale event is
15quietly dropped and read() returns to user with events read so far
16in the buffer.
17
18If the event queue contains a single stale event or if the stale
19event is a permission event, read() returns to user with the kernel
20internal error code 518 (EOPENSTALE), which is not a POSIX error code.
21
22Check the internal return value -EOPENSTALE in fanotify_read(), just
23the same as it is checked in path_openat() and drop the event in the
24cases that it is not already dropped.
25
26This is a reproducer from Marko Rauhamaa:
27
28Just take the example program listed under "man fanotify" ("fantest")
29and follow these steps:
30
31 ==============================================================
32 NFS Server NFS Client(1) NFS Client(2)
33 ==============================================================
34 # echo foo >/nfsshare/bar.txt
35 # cat /nfsshare/bar.txt
36 foo
37 # ./fantest /nfsshare
38 Press enter key to terminate.
39 Listening for events.
40 # rm -f /nfsshare/bar.txt
41 # cat /nfsshare/bar.txt
42 read: Unknown error 518
43 cat: /nfsshare/bar.txt: Operation not permitted
44 ==============================================================
45
46where NFS Client (1) and (2) are two terminal sessions on a single NFS
47Client machine.
48
49Reported-by: Marko Rauhamaa <marko.rauhamaa@f-secure.com>
50Tested-by: Marko Rauhamaa <marko.rauhamaa@f-secure.com>
51Cc: <linux-api@vger.kernel.org>
52Signed-off-by: Amir Goldstein <amir73il@gmail.com>
53Signed-off-by: Jan Kara <jack@suse.cz>
54Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
55
56---
57 fs/notify/fanotify/fanotify_user.c | 26 ++++++++++++++++++--------
58 1 file changed, 18 insertions(+), 8 deletions(-)
59
60--- a/fs/notify/fanotify/fanotify_user.c
61+++ b/fs/notify/fanotify/fanotify_user.c
62@@ -294,27 +294,37 @@ static ssize_t fanotify_read(struct file
63 }
64
65 ret = copy_event_to_user(group, kevent, buf);
66+ if (unlikely(ret == -EOPENSTALE)) {
67+ /*
68+ * We cannot report events with stale fd so drop it.
69+ * Setting ret to 0 will continue the event loop and
70+ * do the right thing if there are no more events to
71+ * read (i.e. return bytes read, -EAGAIN or wait).
72+ */
73+ ret = 0;
74+ }
75+
76 /*
77 * Permission events get queued to wait for response. Other
78 * events can be destroyed now.
79 */
80 if (!(kevent->mask & FAN_ALL_PERM_EVENTS)) {
81 fsnotify_destroy_event(group, kevent);
82- if (ret < 0)
83- break;
84 } else {
85 #ifdef CONFIG_FANOTIFY_ACCESS_PERMISSIONS
86- if (ret < 0) {
87+ if (ret <= 0) {
88 FANOTIFY_PE(kevent)->response = FAN_DENY;
89 wake_up(&group->fanotify_data.access_waitq);
90- break;
91+ } else {
92+ spin_lock(&group->notification_lock);
93+ list_add_tail(&kevent->list,
94+ &group->fanotify_data.access_list);
95+ spin_unlock(&group->notification_lock);
96 }
97- spin_lock(&group->notification_lock);
98- list_add_tail(&kevent->list,
99- &group->fanotify_data.access_list);
100- spin_unlock(&group->notification_lock);
101 #endif
102 }
103+ if (ret < 0)
104+ break;
105 buf += ret;
106 count -= ret;
107 }