[PATCH v5 2/3] open: add O_CRED_ALLOW flag
From: Stas Sergeev <hidden>
Date: 2024-04-26 13:34:23
Also in:
linux-arch, linux-fsdevel, lkml, netdev
Subsystem:
file locking (flock() and fcntl()/lockf()), filesystems (vfs and infrastructure), generic include/asm header files, networking [general], networking [sockets], the rest · Maintainers:
Jeff Layton, Chuck Lever, Alexander Viro, Christian Brauner, Arnd Bergmann, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Kuniyuki Iwashima, Willem de Bruijn, Linus Torvalds
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 <redacted> CC: Eric Biederman <redacted> CC: Alexander Viro <viro@zeniv.linux.org.uk> CC: Christian Brauner <brauner@kernel.org> CC: Jan Kara <jack@suse.cz> CC: Andy Lutomirski <luto@kernel.org> CC: David Laight <redacted> CC: Arnd Bergmann <arnd@arndb.de> CC: "David S. Miller" <davem@davemloft.net> CC: Eric Dumazet <edumazet@google.com> CC: Jakub Kicinski <kuba@kernel.org> CC: Paolo Abeni <pabeni@redhat.com> CC: Jens Axboe <axboe@kernel.dk> CC: Kuniyuki Iwashima <redacted> CC: Pavel Begunkov <asml.silence@gmail.com> CC: linux-arch@vger.kernel.org CC: netdev@vger.kernel.org CC: linux-fsdevel@vger.kernel.org CC: linux-kernel@vger.kernel.org CC: linux-api@vger.kernel.org --- 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