1 /* -*- mode: c; c-file-style: "openbsd" -*- */
3 * Copyright (c) 2008 Vincent Bernat <bernat@luffy.cx>
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 #include "syscall-names.h"
28 # define SYS_SECCOMP 1
32 # define REG_SYSCALL REG_EAX
33 # define ARCH_NR AUDIT_ARCH_I386
34 #elif defined(__x86_64__)
35 # define REG_SYSCALL REG_RAX
36 # define ARCH_NR AUDIT_ARCH_X86_64
38 # error "Platform does not support seccomp filter yet"
39 # define REG_SYSCALL 0
43 /* If there is no privilege separation, seccomp is currently useless */
45 static int monitored
= -1;
46 static int trapped
= 0;
48 * SIGSYS signal handler
49 * @param nr the signal number
50 * @param info siginfo_t pointer
51 * @param void_context handler context
53 * Simple signal handler for SIGSYS displaying the error, killing the child and
58 priv_seccomp_trap_handler(int signal
, siginfo_t
*info
, void *vctx
)
60 ucontext_t
*ctx
= (ucontext_t
*)(vctx
);
64 _exit(161); /* Avoid loops */
67 if (info
->si_code
!= SYS_SECCOMP
)
71 syscall
= ctx
->uc_mcontext
.gregs
[REG_SYSCALL
];
74 /* Log them. Technically, `log_warnx()` is not signal safe, but we are
75 * unlikely to reenter here. */
76 log_warnx("seccomp", "invalid syscall attempted: %s(%d)",
77 (syscall
< sizeof(syscall_names
))?syscall_names
[syscall
]:"unknown",
80 /* Kill children and exit */
81 kill(monitored
, SIGTERM
);
82 fatalx("seccomp", "invalid syscall not allowed: stop here");
87 * Install a TRAP action signal handler
89 * This function installs the TRAP action signal handler and is based on
90 * examples from Will Drewry and Kees Cook. Returns zero on success, negative
95 priv_seccomp_trap_install()
97 struct sigaction signal_handler
= {};
100 sigemptyset(&signal_mask
);
101 sigaddset(&signal_mask
, SIGSYS
);
103 signal_handler
.sa_sigaction
= &priv_seccomp_trap_handler
;
104 signal_handler
.sa_flags
= SA_SIGINFO
;
105 if (sigaction(SIGSYS
, &signal_handler
, NULL
) < 0)
107 if (sigprocmask(SIG_UNBLOCK
, &signal_mask
, NULL
))
114 * Initialize seccomp.
116 * @param remote file descriptor to talk with the unprivileged process
117 * @param monitored monitored child
118 * @return negative on failures or 0 if everything was setup
121 priv_seccomp_init(int remote
, int child
)
124 scmp_filter_ctx ctx
= NULL
;
126 log_debug("seccomp", "initialize libseccomp filter");
128 if (priv_seccomp_trap_install() < 0) {
129 log_warn("seccomp", "unable to install SIGSYS handler");
133 if ((ctx
= seccomp_init(SCMP_ACT_TRAP
)) == NULL
) {
134 log_warnx("seccomp", "unable to initialize libseccomp subsystem");
138 if ((rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
,
139 SCMP_SYS(read
), 1, SCMP_CMP(0, SCMP_CMP_EQ
, remote
))) < 0 ||
140 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
,
141 SCMP_SYS(write
), 1, SCMP_CMP(0, SCMP_CMP_EQ
, remote
))) < 0) {
143 log_warn("seccomp", "unable to allow read/write on remote socket");
147 /* We are far more generic from here. */
148 if ((rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(read
), 0)) < 0 ||
149 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(write
), 0)) < 0 || /* write needed for */
150 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(open
), 0)) < 0 ||
151 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fcntl
), 0)) < 0 ||
152 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(kill
), 0)) < 0 ||
153 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(socket
), 0)) < 0 ||
154 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(bind
), 0)) < 0 ||
155 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(setsockopt
), 0)) < 0 ||
156 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getsockname
), 0)) < 0 ||
157 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(uname
), 0)) < 0 ||
158 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(unlink
), 0)) < 0 ||
159 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(ioctl
), 0)) < 0 ||
160 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(sendmsg
), 0)) < 0 ||
161 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(sendmmsg
), 0)) < 0 ||
162 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(wait4
), 0)) < 0 ||
163 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(stat
), 0)) < 0 ||
164 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(getpid
), 0)) < 0 ||
165 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(rt_sigreturn
), 0)) < 0 ||
166 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(close
), 0)) < 0 ||
167 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(sendto
), 0)) < 0 ||
168 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(poll
), 0)) < 0 ||
169 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(recvmsg
), 0)) < 0 ||
170 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(recvfrom
), 0)) < 0 ||
171 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(readv
), 0)) < 0 ||
172 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mprotect
), 0)) < 0 ||
173 /* The following are for resolving addresses */
174 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(mmap
), 0)) < 0 ||
175 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(munmap
), 0)) < 0 ||
176 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(fstat
), 0)) < 0 ||
177 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(connect
), 0)) < 0 ||
178 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(futex
), 0)) < 0 ||
180 (rc
= seccomp_rule_add(ctx
, SCMP_ACT_ALLOW
, SCMP_SYS(exit_group
), 0)) < 0) {
182 log_warn("seccomp", "unable to build seccomp rules");
186 if ((rc
= seccomp_load(ctx
)) < 0) {
188 log_warn("seccomp", "unable to load libseccomp filter");
193 seccomp_release(ctx
);