]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/4.11.3/fanotify-don-t-expose-eopenstale-to-userspace.patch
Linux 4.4.177
[thirdparty/kernel/stable-queue.git] / releases / 4.11.3 / fanotify-don-t-expose-eopenstale-to-userspace.patch
1 From 4ff33aafd32e084f5ee7faa54ba06e95f8b1b8af Mon Sep 17 00:00:00 2001
2 From: Amir Goldstein <amir73il@gmail.com>
3 Date: Tue, 25 Apr 2017 14:29:35 +0300
4 Subject: fanotify: don't expose EOPENSTALE to userspace
5
6 From: Amir Goldstein <amir73il@gmail.com>
7
8 commit 4ff33aafd32e084f5ee7faa54ba06e95f8b1b8af upstream.
9
10 When delivering an event to userspace for a file on an NFS share,
11 if the file is deleted on server side before user reads the event,
12 user will not get the event.
13
14 If the event queue contained several events, the stale event is
15 quietly dropped and read() returns to user with events read so far
16 in the buffer.
17
18 If the event queue contains a single stale event or if the stale
19 event is a permission event, read() returns to user with the kernel
20 internal error code 518 (EOPENSTALE), which is not a POSIX error code.
21
22 Check the internal return value -EOPENSTALE in fanotify_read(), just
23 the same as it is checked in path_openat() and drop the event in the
24 cases that it is not already dropped.
25
26 This is a reproducer from Marko Rauhamaa:
27
28 Just take the example program listed under "man fanotify" ("fantest")
29 and 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
46 where NFS Client (1) and (2) are two terminal sessions on a single NFS
47 Client machine.
48
49 Reported-by: Marko Rauhamaa <marko.rauhamaa@f-secure.com>
50 Tested-by: Marko Rauhamaa <marko.rauhamaa@f-secure.com>
51 Cc: <linux-api@vger.kernel.org>
52 Signed-off-by: Amir Goldstein <amir73il@gmail.com>
53 Signed-off-by: Jan Kara <jack@suse.cz>
54 Signed-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 @@ -295,27 +295,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 }