Skip to content

Commit eef8cff

Browse files
committed
Merge tag 'seccomp-v5.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux
Pull seccomp fixes from Kees Cook: "This fixes a corner case of fatal SIGSYS being ignored since v5.15. Along with the signal fix is a change to seccomp so that seeing another syscall after a fatal filter result will cause seccomp to kill the process harder. Summary: - Force HANDLER_EXIT even for SIGNAL_UNKILLABLE - Make seccomp self-destruct after fatal filter results - Update seccomp samples for easier behavioral demonstration" * tag 'seccomp-v5.17-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux: samples/seccomp: Adjust sample to also provide kill option seccomp: Invalidate seccomp mode to catch death failures signal: HANDLER_EXIT should clear SIGNAL_UNKILLABLE
2 parents 9917ff5 + eed09ad commit eef8cff

File tree

3 files changed

+20
-4
lines changed

3 files changed

+20
-4
lines changed

kernel/seccomp.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#include <linux/syscalls.h>
3030
#include <linux/sysctl.h>
3131

32+
/* Not exposed in headers: strictly internal use only. */
33+
#define SECCOMP_MODE_DEAD (SECCOMP_MODE_FILTER + 1)
34+
3235
#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
3336
#include <asm/syscall.h>
3437
#endif
@@ -1010,6 +1013,7 @@ static void __secure_computing_strict(int this_syscall)
10101013
#ifdef SECCOMP_DEBUG
10111014
dump_stack();
10121015
#endif
1016+
current->seccomp.mode = SECCOMP_MODE_DEAD;
10131017
seccomp_log(this_syscall, SIGKILL, SECCOMP_RET_KILL_THREAD, true);
10141018
do_exit(SIGKILL);
10151019
}
@@ -1261,6 +1265,7 @@ static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd,
12611265
case SECCOMP_RET_KILL_THREAD:
12621266
case SECCOMP_RET_KILL_PROCESS:
12631267
default:
1268+
current->seccomp.mode = SECCOMP_MODE_DEAD;
12641269
seccomp_log(this_syscall, SIGSYS, action, true);
12651270
/* Dump core only if this is the last remaining thread. */
12661271
if (action != SECCOMP_RET_KILL_THREAD ||
@@ -1309,6 +1314,11 @@ int __secure_computing(const struct seccomp_data *sd)
13091314
return 0;
13101315
case SECCOMP_MODE_FILTER:
13111316
return __seccomp_filter(this_syscall, sd, false);
1317+
/* Surviving SECCOMP_RET_KILL_* must be proactively impossible. */
1318+
case SECCOMP_MODE_DEAD:
1319+
WARN_ON_ONCE(1);
1320+
do_exit(SIGKILL);
1321+
return -1;
13121322
default:
13131323
BUG();
13141324
}

kernel/signal.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,9 +1342,10 @@ force_sig_info_to_task(struct kernel_siginfo *info, struct task_struct *t,
13421342
}
13431343
/*
13441344
* Don't clear SIGNAL_UNKILLABLE for traced tasks, users won't expect
1345-
* debugging to leave init killable.
1345+
* debugging to leave init killable. But HANDLER_EXIT is always fatal.
13461346
*/
1347-
if (action->sa.sa_handler == SIG_DFL && !t->ptrace)
1347+
if (action->sa.sa_handler == SIG_DFL &&
1348+
(!t->ptrace || (handler == HANDLER_EXIT)))
13481349
t->signal->flags &= ~SIGNAL_UNKILLABLE;
13491350
ret = send_signal(sig, info, t, PIDTYPE_PID);
13501351
spin_unlock_irqrestore(&t->sighand->siglock, flags);

samples/seccomp/dropper.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
#include <sys/prctl.h>
2626
#include <unistd.h>
2727

28-
static int install_filter(int nr, int arch, int error)
28+
static int install_filter(int arch, int nr, int error)
2929
{
3030
struct sock_filter filter[] = {
3131
BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
@@ -42,6 +42,10 @@ static int install_filter(int nr, int arch, int error)
4242
.len = (unsigned short)(sizeof(filter)/sizeof(filter[0])),
4343
.filter = filter,
4444
};
45+
if (error == -1) {
46+
struct sock_filter kill = BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL);
47+
filter[4] = kill;
48+
}
4549
if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
4650
perror("prctl(NO_NEW_PRIVS)");
4751
return 1;
@@ -57,9 +61,10 @@ int main(int argc, char **argv)
5761
{
5862
if (argc < 5) {
5963
fprintf(stderr, "Usage:\n"
60-
"dropper <syscall_nr> <arch> <errno> <prog> [<args>]\n"
64+
"dropper <arch> <syscall_nr> <errno> <prog> [<args>]\n"
6165
"Hint: AUDIT_ARCH_I386: 0x%X\n"
6266
" AUDIT_ARCH_X86_64: 0x%X\n"
67+
" errno == -1 means SECCOMP_RET_KILL\n"
6368
"\n", AUDIT_ARCH_I386, AUDIT_ARCH_X86_64);
6469
return 1;
6570
}

0 commit comments

Comments
 (0)