Re: [PATCHv8.1] fanotify: enable close-on-exec on events' fd when requested in fanotify_init()

4 messages, 3 authors, 2014-10-02 · open the first message on its own page

Re: [PATCHv8.1] fanotify: enable close-on-exec on events' fd when requested in fanotify_init()

From: Andrew Morton <hidden>
Date: 2014-10-01 22:36:21

On Mon, 29 Sep 2014 10:49:15 +0200 Yann Droneaud [off-list ref] wrote:
According to commit 80af258867648 ('fanotify: groups can specify
their f_flags for new fd'), file descriptors created as part of
file access notification events inherit flags from the
event_f_flags argument passed to syscall fanotify_init(2).

So while it is legal for userspace to call fanotify_init() with
O_CLOEXEC as part of its second argument, O_CLOEXEC is currently
silently ignored.

Indeed event_f_flags are only given to dentry_open(), which only
seems to care about O_ACCMODE and O_PATH in do_dentry_open(),
O_DIRECT in open_check_o_direct() and O_LARGEFILE in
generic_file_open().

But it seems logical to set close-on-exec flag on the file
descriptor if userspace is allowed to request it with O_CLOEXEC.

In fact, according to some lookup on http://codesearch.debian.net/
and various search engine, there's already some userspace code
requesting it:

- in systemd's readahead[2]:

    fanotify_fd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK, O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOATIME);

- in clsync[3]:

    #define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDONLY|O_CLOEXEC)

    int fanotify_d = fanotify_init(FANOTIFY_FLAGS, FANOTIFY_EVFLAGS);

- in examples [4] from "Filesystem monitoring in the Linux
  kernel" article[5] by Aleksander Morgado:

    if ((fanotify_fd = fanotify_init (FAN_CLOEXEC,
                                      O_RDONLY | O_CLOEXEC | O_LARGEFILE)) < 0)
So we have a number of apps which are setting O_CLOEXEC, but it doesn't
actually work.  With this change it *will* work, so the behaviour of
those apps might change, possibly breaking them?

Re: [PATCHv8.1] fanotify: enable close-on-exec on events' fd when requested in fanotify_init()

From: Yann Droneaud <hidden>
Date: 2014-10-02 06:20:55

Hi,

Le mercredi 01 octobre 2014 à 15:36 -0700, Andrew Morton a écrit :
On Mon, 29 Sep 2014 10:49:15 +0200 Yann Droneaud [off-list ref] wrote:
quoted
According to commit 80af258867648 ('fanotify: groups can specify
their f_flags for new fd'), file descriptors created as part of
file access notification events inherit flags from the
event_f_flags argument passed to syscall fanotify_init(2).

So while it is legal for userspace to call fanotify_init() with
O_CLOEXEC as part of its second argument, O_CLOEXEC is currently
silently ignored.

Indeed event_f_flags are only given to dentry_open(), which only
seems to care about O_ACCMODE and O_PATH in do_dentry_open(),
O_DIRECT in open_check_o_direct() and O_LARGEFILE in
generic_file_open().

But it seems logical to set close-on-exec flag on the file
descriptor if userspace is allowed to request it with O_CLOEXEC.

In fact, according to some lookup on http://codesearch.debian.net/
and various search engine, there's already some userspace code
requesting it:

- in systemd's readahead[2]:

    fanotify_fd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK, O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOATIME);

- in clsync[3]:

    #define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDONLY|O_CLOEXEC)

    int fanotify_d = fanotify_init(FANOTIFY_FLAGS, FANOTIFY_EVFLAGS);

- in examples [4] from "Filesystem monitoring in the Linux
  kernel" article[5] by Aleksander Morgado:

    if ((fanotify_fd = fanotify_init (FAN_CLOEXEC,
                                      O_RDONLY | O_CLOEXEC | O_LARGEFILE)) < 0)
So we have a number of apps which are setting O_CLOEXEC, but it doesn't
actually work.  With this change it *will* work, so the behaviour of
those apps might change, possibly breaking them?
In the other hand, not enabling close-on-exec might expose unwanted file
descriptor to childs, creating security issues. YMMV.

-- 
Yann Droneaud
OPTEYA

Re: [PATCHv8.1] fanotify: enable close-on-exec on events' fd when requested in fanotify_init()

From: Mihai Donțu <hidden>
Date: 2014-10-02 06:50:46

On Thu, 02 Oct 2014 08:20:55 +0200 Yann Droneaud wrote:
Hi,

Le mercredi 01 octobre 2014 à 15:36 -0700, Andrew Morton a écrit :
quoted
On Mon, 29 Sep 2014 10:49:15 +0200 Yann Droneaud [off-list ref] wrote:
quoted
According to commit 80af258867648 ('fanotify: groups can specify
their f_flags for new fd'), file descriptors created as part of
file access notification events inherit flags from the
event_f_flags argument passed to syscall fanotify_init(2).

So while it is legal for userspace to call fanotify_init() with
O_CLOEXEC as part of its second argument, O_CLOEXEC is currently
silently ignored.

Indeed event_f_flags are only given to dentry_open(), which only
seems to care about O_ACCMODE and O_PATH in do_dentry_open(),
O_DIRECT in open_check_o_direct() and O_LARGEFILE in
generic_file_open().

But it seems logical to set close-on-exec flag on the file
descriptor if userspace is allowed to request it with O_CLOEXEC.

In fact, according to some lookup on http://codesearch.debian.net/
and various search engine, there's already some userspace code
requesting it:

- in systemd's readahead[2]:

    fanotify_fd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK, O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOATIME);

- in clsync[3]:

    #define FANOTIFY_EVFLAGS (O_LARGEFILE|O_RDONLY|O_CLOEXEC)

    int fanotify_d = fanotify_init(FANOTIFY_FLAGS, FANOTIFY_EVFLAGS);

- in examples [4] from "Filesystem monitoring in the Linux
  kernel" article[5] by Aleksander Morgado:

    if ((fanotify_fd = fanotify_init (FAN_CLOEXEC,
                                      O_RDONLY | O_CLOEXEC | O_LARGEFILE)) < 0)
So we have a number of apps which are setting O_CLOEXEC, but it doesn't
actually work.  With this change it *will* work, so the behaviour of
those apps might change, possibly breaking them?
In the other hand, not enabling close-on-exec might expose unwanted file
descriptor to childs, creating security issues. YMMV.
As someone who uses fanotify for content introspection, I can say that
I am _explicitly_ marking the fd obtained via read() as O_CLOEXEC,
because I have encountered a situation where a child managed to create
a deadlock because it kept the fd open after the main application
responded with FAN_ALLOW.

-- 
Mihai Donțu

[PATCH] fanotify: add a flag to allow setting O_CLOEXEC on event fd

From: Yann Droneaud <hidden>
Date: 2014-10-02 07:52:29

In order to not potentially break applications which were
requesting O_CLOEXEC on event file descriptors but which
actually need it to be not effective as the kernel currently
ignore the flag, so the file descriptor is inherited accross
exec regardless of O_CLOEXEC (please forgive me for the
wording), this patch introduces FAN_FD_CLOEXEC flag to
fanotify_init() so that application can request O_CLOEXEC
to be effective.
Newer application would use FAN_FD_CLOEXEC flag along
O_CLOEXEC to enable close on exec on newly created
file descriptor:

  fd = fanotify_init(FAN_CLOEXEC|FAN_NONBLOCK|FAN_FD_CLOEXEC,
                     O_RDONLY|O_LARGEFILE|O_CLOEXEC|O_NOATIME);

Signed-off-by: Yann Droneaud <redacted>
---

Hi Andrew,

While I believe fanotify_init() must enable close-on-exec
when requested by userspace to prevent unwelcomed security
issue, I understand your concerns regarding the possible
breakage on userspace application requesting O_CLOEXEC
but relying on it not being enable on file descriptor
created for the events.

So with a new flag to fanotify_init(), we could allow
newer applications to really enable O_CLOEXEC.

But I feel bad to have to force application to specify
twice they want close on exec:
  - are you sure ?
  - are you really sure ?
  - is this your final answer ?
  ...

Regards.

Yann Droneaud
OPTEYA


 fs/notify/fanotify/fanotify_user.c | 6 +++++-
 include/uapi/linux/fanotify.h      | 5 ++++-
 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c
index c991616acca9..3c1fb1412f37 100644
--- a/fs/notify/fanotify/fanotify_user.c
+++ b/fs/notify/fanotify/fanotify_user.c
@@ -78,7 +78,7 @@ static int create_fd(struct fsnotify_group *group,
 
 	pr_debug("%s: group=%p event=%p\n", __func__, group, event);
 
-	client_fd = get_unused_fd_flags(group->fanotify_data.f_flags);
+	client_fd = get_unused_fd_flags(group->fanotify_data.f_flags & O_CLOEXEC);
 	if (client_fd < 0)
 		return client_fd;
 
@@ -706,6 +706,10 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags)
 		return -EINVAL;
 	}
 
+	if ((event_f_flags & O_CLOEXEC) &&
+	    !(flags & FAN_FD_CLOEXEC))
+		event_f_flags ^= O_CLOEXEC;
+
 	user = get_current_user();
 	if (atomic_read(&user->fanotify_listeners) > FANOTIFY_DEFAULT_MAX_LISTENERS) {
 		free_uid(user);
diff --git a/include/uapi/linux/fanotify.h b/include/uapi/linux/fanotify.h
index 030508d195d3..f2d517be3152 100644
--- a/include/uapi/linux/fanotify.h
+++ b/include/uapi/linux/fanotify.h
@@ -36,7 +36,10 @@
 #define FAN_UNLIMITED_QUEUE	0x00000010
 #define FAN_UNLIMITED_MARKS	0x00000020
 
-#define FAN_ALL_INIT_FLAGS	(FAN_CLOEXEC | FAN_NONBLOCK | \
+/* flags used for fanotify_init() too */
+#define FAN_FD_CLOEXEC		0x00000100
+
+#define FAN_ALL_INIT_FLAGS	(FAN_CLOEXEC | FAN_NONBLOCK | FAN_FD_CLOEXEC | \
 				 FAN_ALL_CLASS_BITS | FAN_UNLIMITED_QUEUE |\
 				 FAN_UNLIMITED_MARKS)
 
-- 
1.9.3
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help