Commit 9ecc6ea4 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull seccomp updates from Kees Cook:
 "There are a bunch of clean ups and selftest improvements along with
  two major updates to the SECCOMP_RET_USER_NOTIF filter return:
  EPOLLHUP support to more easily detect the death of a monitored
  process, and being able to inject fds when intercepting syscalls that
  expect an fd-opening side-effect (needed by both container folks and
  Chrome). The latter continued the refactoring of __scm_install_fd()
  started by Christoph, and in the process found and fixed a handful of
  bugs in various callers.

   - Improved selftest coverage, timeouts, and reporting

   - Add EPOLLHUP support for SECCOMP_RET_USER_NOTIF (Christian Brauner)

   - Refactor __scm_install_fd() into __receive_fd() and fix buggy
     callers

   - Introduce 'addfd' command for SECCOMP_RET_USER_NOTIF (Sargun
     Dhillon)"

* tag 'seccomp-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: (30 commits)
  selftests/seccomp: Test SECCOMP_IOCTL_NOTIF_ADDFD
  seccomp: Introduce addfd ioctl to seccomp user notifier
  fs: Expand __receive_fd() to accept existing fd
  pidfd: Replace open-coded receive_fd()
  fs: Add receive_fd() wrapper for __receive_fd()
  fs: Move __scm_install_fd() to __receive_fd()
  net/scm: Regularize compat handling of scm_detach_fds()
  pidfd: Add missing sock updates for pidfd_getfd()
  net/compat: Add missing sock updates for SCM_RIGHTS
  selftests/seccomp: Check ENOSYS under tracing
  selftests/seccomp: Refactor to use fixture variants
  selftests/harness: Clean up kern-doc for fixtures
  seccomp: Use -1 marker for end of mode 1 syscall list
  seccomp: Fix ioctl number for SECCOMP_IOCTL_NOTIF_ID_VALID
  selftests/seccomp: Rename user_trap_syscall() to user_notif_syscall()
  selftests/seccomp: Make kcmp() less required
  seccomp: Use pr_fmt
  selftests/seccomp: Improve calibration loop
  selftests/seccomp: use 90s as timeout
  selftests/seccomp: Expand benchmark to per-filter measurements
  ...
parents 99ea1521 c97aedc5
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -9,12 +9,12 @@ static inline const int *get_compat_mode1_syscalls(void)
	static const int syscalls_O32[] = {
		__NR_O32_Linux + 3, __NR_O32_Linux + 4,
		__NR_O32_Linux + 1, __NR_O32_Linux + 193,
		0, /* null terminated */
		-1, /* negative terminated */
	};
	static const int syscalls_N32[] = {
		__NR_N32_Linux + 0, __NR_N32_Linux + 1,
		__NR_N32_Linux + 58, __NR_N32_Linux + 211,
		0, /* null terminated */
		-1, /* negative terminated */
	};

	if (IS_ENABLED(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))
+61 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@
#include <linux/bitops.h>
#include <linux/spinlock.h>
#include <linux/rcupdate.h>
#include <net/sock.h>

unsigned int sysctl_nr_open __read_mostly = 1024*1024;
unsigned int sysctl_nr_open_min = BITS_PER_LONG;
@@ -613,6 +614,10 @@ void __fd_install(struct files_struct *files, unsigned int fd,
	rcu_read_unlock_sched();
}

/*
 * This consumes the "file" refcount, so callers should treat it
 * as if they had called fput(file).
 */
void fd_install(unsigned int fd, struct file *file)
{
	__fd_install(current->files, fd, file);
@@ -931,6 +936,62 @@ out_unlock:
	return err;
}

/**
 * __receive_fd() - Install received file into file descriptor table
 *
 * @fd: fd to install into (if negative, a new fd will be allocated)
 * @file: struct file that was received from another process
 * @ufd: __user pointer to write new fd number to
 * @o_flags: the O_* flags to apply to the new fd entry
 *
 * Installs a received file into the file descriptor table, with appropriate
 * checks and count updates. Optionally writes the fd number to userspace, if
 * @ufd is non-NULL.
 *
 * This helper handles its own reference counting of the incoming
 * struct file.
 *
 * Returns newly install fd or -ve on error.
 */
int __receive_fd(int fd, struct file *file, int __user *ufd, unsigned int o_flags)
{
	int new_fd;
	int error;

	error = security_file_receive(file);
	if (error)
		return error;

	if (fd < 0) {
		new_fd = get_unused_fd_flags(o_flags);
		if (new_fd < 0)
			return new_fd;
	} else {
		new_fd = fd;
	}

	if (ufd) {
		error = put_user(new_fd, ufd);
		if (error) {
			if (fd < 0)
				put_unused_fd(new_fd);
			return error;
		}
	}

	if (fd < 0) {
		fd_install(new_fd, get_file(file));
	} else {
		error = replace_fd(new_fd, file, o_flags);
		if (error)
			return error;
	}

	/* Bump the sock usage counts, if any. */
	__receive_sock(file);
	return new_fd;
}

static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
{
	int err = -EBADF;
+2 −0
Original line number Diff line number Diff line
@@ -341,6 +341,8 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
	seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
#ifdef CONFIG_SECCOMP
	seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
	seq_put_decimal_ull(m, "\nSeccomp_filters:\t",
			    atomic_read(&p->seccomp.filter_count));
#endif
	seq_puts(m, "\nSpeculation_Store_Bypass:\t");
	switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {
+1 −1
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ static inline const int *get_compat_mode1_syscalls(void)
	static const int mode1_syscalls_32[] = {
		__NR_seccomp_read_32, __NR_seccomp_write_32,
		__NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
		0, /* null terminated */
		-1, /* negative terminated */
	};
	return mode1_syscalls_32;
}
+19 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/compiler.h>
#include <linux/types.h>
#include <linux/posix_types.h>
#include <linux/errno.h>

struct file;

@@ -91,6 +92,24 @@ extern void put_unused_fd(unsigned int fd);

extern void fd_install(unsigned int fd, struct file *file);

extern int __receive_fd(int fd, struct file *file, int __user *ufd,
			unsigned int o_flags);
static inline int receive_fd_user(struct file *file, int __user *ufd,
				  unsigned int o_flags)
{
	if (ufd == NULL)
		return -EFAULT;
	return __receive_fd(-1, file, ufd, o_flags);
}
static inline int receive_fd(struct file *file, unsigned int o_flags)
{
	return __receive_fd(-1, file, NULL, o_flags);
}
static inline int receive_fd_replace(int fd, struct file *file, unsigned int o_flags)
{
	return __receive_fd(fd, file, NULL, o_flags);
}

extern void flush_delayed_fput(void);
extern void __fput_sync(struct file *);

Loading