Skip to content

Commit 9ecc6ea

Browse files
committed
Merge tag 'seccomp-v5.9-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
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 ...
2 parents 99ea152 + c97aedc commit 9ecc6ea

File tree

21 files changed

+1061
-392
lines changed

21 files changed

+1061
-392
lines changed

arch/mips/include/asm/seccomp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ static inline const int *get_compat_mode1_syscalls(void)
99
static const int syscalls_O32[] = {
1010
__NR_O32_Linux + 3, __NR_O32_Linux + 4,
1111
__NR_O32_Linux + 1, __NR_O32_Linux + 193,
12-
0, /* null terminated */
12+
-1, /* negative terminated */
1313
};
1414
static const int syscalls_N32[] = {
1515
__NR_N32_Linux + 0, __NR_N32_Linux + 1,
1616
__NR_N32_Linux + 58, __NR_N32_Linux + 211,
17-
0, /* null terminated */
17+
-1, /* negative terminated */
1818
};
1919

2020
if (IS_ENABLED(CONFIG_MIPS32_O32) && test_thread_flag(TIF_32BIT_REGS))

fs/file.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/bitops.h>
1919
#include <linux/spinlock.h>
2020
#include <linux/rcupdate.h>
21+
#include <net/sock.h>
2122

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

617+
/*
618+
* This consumes the "file" refcount, so callers should treat it
619+
* as if they had called fput(file).
620+
*/
616621
void fd_install(unsigned int fd, struct file *file)
617622
{
618623
__fd_install(current->files, fd, file);
@@ -931,6 +936,62 @@ int replace_fd(unsigned fd, struct file *file, unsigned flags)
931936
return err;
932937
}
933938

939+
/**
940+
* __receive_fd() - Install received file into file descriptor table
941+
*
942+
* @fd: fd to install into (if negative, a new fd will be allocated)
943+
* @file: struct file that was received from another process
944+
* @ufd: __user pointer to write new fd number to
945+
* @o_flags: the O_* flags to apply to the new fd entry
946+
*
947+
* Installs a received file into the file descriptor table, with appropriate
948+
* checks and count updates. Optionally writes the fd number to userspace, if
949+
* @ufd is non-NULL.
950+
*
951+
* This helper handles its own reference counting of the incoming
952+
* struct file.
953+
*
954+
* Returns newly install fd or -ve on error.
955+
*/
956+
int __receive_fd(int fd, struct file *file, int __user *ufd, unsigned int o_flags)
957+
{
958+
int new_fd;
959+
int error;
960+
961+
error = security_file_receive(file);
962+
if (error)
963+
return error;
964+
965+
if (fd < 0) {
966+
new_fd = get_unused_fd_flags(o_flags);
967+
if (new_fd < 0)
968+
return new_fd;
969+
} else {
970+
new_fd = fd;
971+
}
972+
973+
if (ufd) {
974+
error = put_user(new_fd, ufd);
975+
if (error) {
976+
if (fd < 0)
977+
put_unused_fd(new_fd);
978+
return error;
979+
}
980+
}
981+
982+
if (fd < 0) {
983+
fd_install(new_fd, get_file(file));
984+
} else {
985+
error = replace_fd(new_fd, file, o_flags);
986+
if (error)
987+
return error;
988+
}
989+
990+
/* Bump the sock usage counts, if any. */
991+
__receive_sock(file);
992+
return new_fd;
993+
}
994+
934995
static int ksys_dup3(unsigned int oldfd, unsigned int newfd, int flags)
935996
{
936997
int err = -EBADF;

fs/proc/array.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ static inline void task_seccomp(struct seq_file *m, struct task_struct *p)
341341
seq_put_decimal_ull(m, "NoNewPrivs:\t", task_no_new_privs(p));
342342
#ifdef CONFIG_SECCOMP
343343
seq_put_decimal_ull(m, "\nSeccomp:\t", p->seccomp.mode);
344+
seq_put_decimal_ull(m, "\nSeccomp_filters:\t",
345+
atomic_read(&p->seccomp.filter_count));
344346
#endif
345347
seq_puts(m, "\nSpeculation_Store_Bypass:\t");
346348
switch (arch_prctl_spec_ctrl_get(p, PR_SPEC_STORE_BYPASS)) {

include/asm-generic/seccomp.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static inline const int *get_compat_mode1_syscalls(void)
3333
static const int mode1_syscalls_32[] = {
3434
__NR_seccomp_read_32, __NR_seccomp_write_32,
3535
__NR_seccomp_exit_32, __NR_seccomp_sigreturn_32,
36-
0, /* null terminated */
36+
-1, /* negative terminated */
3737
};
3838
return mode1_syscalls_32;
3939
}

include/linux/file.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <linux/compiler.h>
1010
#include <linux/types.h>
1111
#include <linux/posix_types.h>
12+
#include <linux/errno.h>
1213

1314
struct file;
1415

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

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

95+
extern int __receive_fd(int fd, struct file *file, int __user *ufd,
96+
unsigned int o_flags);
97+
static inline int receive_fd_user(struct file *file, int __user *ufd,
98+
unsigned int o_flags)
99+
{
100+
if (ufd == NULL)
101+
return -EFAULT;
102+
return __receive_fd(-1, file, ufd, o_flags);
103+
}
104+
static inline int receive_fd(struct file *file, unsigned int o_flags)
105+
{
106+
return __receive_fd(-1, file, NULL, o_flags);
107+
}
108+
static inline int receive_fd_replace(int fd, struct file *file, unsigned int o_flags)
109+
{
110+
return __receive_fd(fd, file, NULL, o_flags);
111+
}
112+
94113
extern void flush_delayed_fput(void);
95114
extern void __fput_sync(struct file *);
96115

include/linux/seccomp.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,14 @@
1010
SECCOMP_FILTER_FLAG_NEW_LISTENER | \
1111
SECCOMP_FILTER_FLAG_TSYNC_ESRCH)
1212

13+
/* sizeof() the first published struct seccomp_notif_addfd */
14+
#define SECCOMP_NOTIFY_ADDFD_SIZE_VER0 24
15+
#define SECCOMP_NOTIFY_ADDFD_SIZE_LATEST SECCOMP_NOTIFY_ADDFD_SIZE_VER0
16+
1317
#ifdef CONFIG_SECCOMP
1418

1519
#include <linux/thread_info.h>
20+
#include <linux/atomic.h>
1621
#include <asm/seccomp.h>
1722

1823
struct seccomp_filter;
@@ -29,6 +34,7 @@ struct seccomp_filter;
2934
*/
3035
struct seccomp {
3136
int mode;
37+
atomic_t filter_count;
3238
struct seccomp_filter *filter;
3339
};
3440

@@ -82,10 +88,10 @@ static inline int seccomp_mode(struct seccomp *s)
8288
#endif /* CONFIG_SECCOMP */
8389

8490
#ifdef CONFIG_SECCOMP_FILTER
85-
extern void put_seccomp_filter(struct task_struct *tsk);
91+
extern void seccomp_filter_release(struct task_struct *tsk);
8692
extern void get_seccomp_filter(struct task_struct *tsk);
8793
#else /* CONFIG_SECCOMP_FILTER */
88-
static inline void put_seccomp_filter(struct task_struct *tsk)
94+
static inline void seccomp_filter_release(struct task_struct *tsk)
8995
{
9096
return;
9197
}

include/net/sock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -891,13 +891,17 @@ static inline int sk_memalloc_socks(void)
891891
{
892892
return static_branch_unlikely(&memalloc_socks_key);
893893
}
894+
895+
void __receive_sock(struct file *file);
894896
#else
895897

896898
static inline int sk_memalloc_socks(void)
897899
{
898900
return 0;
899901
}
900902

903+
static inline void __receive_sock(struct file *file)
904+
{ }
901905
#endif
902906

903907
static inline gfp_t sk_gfp_mask(const struct sock *sk, gfp_t gfp_mask)

include/uapi/linux/seccomp.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,25 @@ struct seccomp_notif_resp {
113113
__u32 flags;
114114
};
115115

116+
/* valid flags for seccomp_notif_addfd */
117+
#define SECCOMP_ADDFD_FLAG_SETFD (1UL << 0) /* Specify remote fd */
118+
119+
/**
120+
* struct seccomp_notif_addfd
121+
* @id: The ID of the seccomp notification
122+
* @flags: SECCOMP_ADDFD_FLAG_*
123+
* @srcfd: The local fd number
124+
* @newfd: Optional remote FD number if SETFD option is set, otherwise 0.
125+
* @newfd_flags: The O_* flags the remote FD should have applied
126+
*/
127+
struct seccomp_notif_addfd {
128+
__u64 id;
129+
__u32 flags;
130+
__u32 srcfd;
131+
__u32 newfd;
132+
__u32 newfd_flags;
133+
};
134+
116135
#define SECCOMP_IOC_MAGIC '!'
117136
#define SECCOMP_IO(nr) _IO(SECCOMP_IOC_MAGIC, nr)
118137
#define SECCOMP_IOR(nr, type) _IOR(SECCOMP_IOC_MAGIC, nr, type)
@@ -123,5 +142,9 @@ struct seccomp_notif_resp {
123142
#define SECCOMP_IOCTL_NOTIF_RECV SECCOMP_IOWR(0, struct seccomp_notif)
124143
#define SECCOMP_IOCTL_NOTIF_SEND SECCOMP_IOWR(1, \
125144
struct seccomp_notif_resp)
126-
#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOR(2, __u64)
145+
#define SECCOMP_IOCTL_NOTIF_ID_VALID SECCOMP_IOW(2, __u64)
146+
/* On success, the return value is the remote process's added fd number */
147+
#define SECCOMP_IOCTL_NOTIF_ADDFD SECCOMP_IOW(3, \
148+
struct seccomp_notif_addfd)
149+
127150
#endif /* _UAPI_LINUX_SECCOMP_H */

init/init_task.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,9 @@ struct task_struct init_task
204204
#ifdef CONFIG_SECURITY
205205
.security = NULL,
206206
#endif
207+
#ifdef CONFIG_SECCOMP
208+
.seccomp = { .filter_count = ATOMIC_INIT(0) },
209+
#endif
207210
};
208211
EXPORT_SYMBOL(init_task);
209212

kernel/exit.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ void release_task(struct task_struct *p)
217217
}
218218

219219
write_unlock_irq(&tasklist_lock);
220+
seccomp_filter_release(p);
220221
proc_flush_pid(thread_pid);
221222
put_pid(thread_pid);
222223
release_thread(p);

0 commit comments

Comments
 (0)