This flag prevents an fd from being passed via unix socket, and makes it to be always closed on exec(). It is needed for the subsequent OA2_CRED_INHERIT addition, to work as an "opt-in" for the new cred-inherit functionality. Without using O_CRED_ALLOW when opening dir fd, it won't be possible to use OA2_CRED_INHERIT on that dir fd. Signed-off-by: Stas Sergeev <stsp2@xxxxxxxxx> CC: Eric Biederman <ebiederm@xxxxxxxxxxxx> CC: Alexander Viro <viro@xxxxxxxxxxxxxxxxxx> CC: Christian Brauner <brauner@xxxxxxxxxx> CC: Jan Kara <jack@xxxxxxx> CC: Andy Lutomirski <luto@xxxxxxxxxx> CC: David Laight <David.Laight@xxxxxxxxxx> CC: Arnd Bergmann <arnd@xxxxxxxx> CC: "David S. Miller" <davem@xxxxxxxxxxxxx> CC: Eric Dumazet <edumazet@xxxxxxxxxx> CC: Jakub Kicinski <kuba@xxxxxxxxxx> CC: Paolo Abeni <pabeni@xxxxxxxxxx> CC: Jens Axboe <axboe@xxxxxxxxx> CC: Kuniyuki Iwashima <kuniyu@xxxxxxxxxx> CC: Pavel Begunkov <asml.silence@xxxxxxxxx> CC: linux-arch@xxxxxxxxxxxxxxx CC: netdev@xxxxxxxxxxxxxxx CC: linux-fsdevel@xxxxxxxxxxxxxxx CC: linux-kernel@xxxxxxxxxxxxxxx CC: linux-api@xxxxxxxxxxxxxxx --- fs/fcntl.c | 2 +- fs/file.c | 15 ++++++++------- include/linux/fcntl.h | 2 +- include/uapi/asm-generic/fcntl.h | 4 ++++ net/core/scm.c | 5 +++++ 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/fs/fcntl.c b/fs/fcntl.c index 54cc85d3338e..78c96b1293c2 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -1039,7 +1039,7 @@ static int __init fcntl_init(void) * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY * is defined as O_NONBLOCK on some platforms and not on others. */ - BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != + BUILD_BUG_ON(22 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) | __FMODE_EXEC | __FMODE_NONOTIFY)); diff --git a/fs/file.c b/fs/file.c index 3b683b9101d8..2a09d5276676 100644 --- a/fs/file.c +++ b/fs/file.c @@ -827,22 +827,23 @@ void do_close_on_exec(struct files_struct *files) /* exec unshares first */ spin_lock(&files->file_lock); for (i = 0; ; i++) { + int j; unsigned long set; unsigned fd = i * BITS_PER_LONG; fdt = files_fdtable(files); if (fd >= fdt->max_fds) break; set = fdt->close_on_exec[i]; - if (!set) - continue; fdt->close_on_exec[i] = 0; - for ( ; set ; fd++, set >>= 1) { - struct file *file; - if (!(set & 1)) - continue; - file = fdt->fd[fd]; + for (j = 0; j < BITS_PER_LONG; j++, fd++, set >>= 1) { + struct file *file = fdt->fd[fd]; if (!file) continue; + /* Close all cred-allow files. */ + if (file->f_flags & O_CRED_ALLOW) + set |= 1; + if (!(set & 1)) + continue; rcu_assign_pointer(fdt->fd[fd], NULL); __put_unused_fd(files, fd); spin_unlock(&files->file_lock); diff --git a/include/linux/fcntl.h b/include/linux/fcntl.h index a332e79b3207..e074ee9c1e36 100644 --- a/include/linux/fcntl.h +++ b/include/linux/fcntl.h @@ -10,7 +10,7 @@ (O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \ O_APPEND | O_NDELAY | O_NONBLOCK | __O_SYNC | O_DSYNC | \ FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \ - O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE) + O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE | O_CRED_ALLOW) /* List of all valid flags for the how->resolve argument: */ #define VALID_RESOLVE_FLAGS \ diff --git a/include/uapi/asm-generic/fcntl.h b/include/uapi/asm-generic/fcntl.h index 80f37a0d40d7..ee8c2267c516 100644 --- a/include/uapi/asm-generic/fcntl.h +++ b/include/uapi/asm-generic/fcntl.h @@ -89,6 +89,10 @@ #define __O_TMPFILE 020000000 #endif +#ifndef O_CRED_ALLOW +#define O_CRED_ALLOW 040000000 +#endif + /* a horrid kludge trying to make sure that this will fail on old kernels */ #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY) diff --git a/net/core/scm.c b/net/core/scm.c index 9cd4b0a01cd6..f54fb0ee9727 100644 --- a/net/core/scm.c +++ b/net/core/scm.c @@ -111,6 +111,11 @@ static int scm_fp_copy(struct cmsghdr *cmsg, struct scm_fp_list **fplp) fput(file); return -EINVAL; } + /* don't allow files with creds */ + if (file->f_flags & O_CRED_ALLOW) { + fput(file); + return -EPERM; + } if (unix_get_socket(file)) fpl->count_unix++; -- 2.44.0