blob: 7299b89d9284911c42f6b941ae23290b2772c60e [file] [log] [blame]
/*
* seccomp_profile.c -- seccomp profile support
*
* (c) Copyright IBM Corporation 2019.
*
* Author: Stefan Berger <stefanb@us.ibm.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the names of the IBM Corporation nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdbool.h>
#include <string.h>
#ifdef WITH_SECCOMP
# include <seccomp.h>
#endif
#include "logging.h"
#include "utils.h"
#include "seccomp_profile.h"
#include "swtpm_utils.h"
#ifdef WITH_SECCOMP
static int create_seccomp_profile_add_rules(scmp_filter_ctx ctx,
int *syscalls, size_t syscalls_len,
unsigned int action)
{
int ret = 0;
unsigned i = 0;
uint32_t act = SCMP_ACT_KILL;
#ifdef SCMP_ACT_LOG
if (action == SWTPM_SECCOMP_ACTION_LOG)
act = SCMP_ACT_LOG;
#endif
for (i = 0; i < syscalls_len; i++) {
ret = seccomp_rule_add(ctx, act, syscalls[i], 0);
if (ret < 0) {
logprintf(STDERR_FILENO,
"seccomp_rule_add failed with errno %d: %s\n",
-ret, strerror(-ret));
break;
}
}
return ret;
}
/*
* create_seccomp_profile: Build a blacklist of syscalls
*
* cusetpm: whether to build for the CUSE tpm
* action: the seccomp action
*/
int create_seccomp_profile(bool cusetpm, unsigned int action)
{
int blacklist[] = {
/* high concern */
SCMP_SYS(capset),
SCMP_SYS(pivot_root),
SCMP_SYS(chroot),
SCMP_SYS(settimeofday),
SCMP_SYS(clock_adjtime),
SCMP_SYS(clock_settime),
#ifdef __SNR_clock_settime64
SCMP_SYS(clock_settime64),
#endif
SCMP_SYS(adjtimex),
#ifdef __SNR_fsopen
SCMP_SYS(fsopen),
#endif
#ifdef __SNR_fsconfig
SCMP_SYS(fsconfig),
#endif
#ifdef __SNR_fsmount
SCMP_SYS(fsmount),
#endif
#ifdef __SNR_fspick
SCMP_SYS(fspick),
#endif
SCMP_SYS(mount),
#ifdef __SNR_move_mount
SCMP_SYS(move_mount),
#endif
#if defined(__SNR_mount_setattr) && defined(__NR_mount_setattr)
SCMP_SYS(mount_setattr),
#endif
SCMP_SYS(umount2),
#ifdef __SNR_open_tree
SCMP_SYS(open_tree),
#endif
SCMP_SYS(swapon),
SCMP_SYS(swapoff),
SCMP_SYS(reboot),
SCMP_SYS(tgkill),
SCMP_SYS(kexec_load),
SCMP_SYS(unshare),
SCMP_SYS(setns),
SCMP_SYS(kcmp),
SCMP_SYS(init_module),
SCMP_SYS(finit_module),
SCMP_SYS(delete_module),
SCMP_SYS(seccomp),
SCMP_SYS(kexec_file_load),
#ifdef __SNR_sysctl
SCMP_SYS(sysctl),
#endif
/* semaphores and messages queues */
SCMP_SYS(semget),
SCMP_SYS(semop),
SCMP_SYS(shmget),
SCMP_SYS(shmat),
SCMP_SYS(shmctl),
SCMP_SYS(shmdt),
SCMP_SYS(msgget),
SCMP_SYS(msgsnd),
SCMP_SYS(msgrcv),
SCMP_SYS(msgctl),
SCMP_SYS(mq_open),
SCMP_SYS(mq_unlink),
SCMP_SYS(mq_timedsend),
SCMP_SYS(mq_timedreceive),
SCMP_SYS(mq_notify),
SCMP_SYS(mq_getsetattr),
/* misc */
SCMP_SYS(ptrace),
SCMP_SYS(syslog),
SCMP_SYS(capget),
SCMP_SYS(capset),
SCMP_SYS(sigaltstack),
SCMP_SYS(personality),
SCMP_SYS(sysfs),
SCMP_SYS(getpriority),
SCMP_SYS(setpriority),
SCMP_SYS(sched_setparam),
SCMP_SYS(sched_setscheduler),
SCMP_SYS(sched_setaffinity),
SCMP_SYS(vhangup),
SCMP_SYS(sethostname),
SCMP_SYS(setdomainname),
SCMP_SYS(quotactl),
#if defined(__SNR_quotactl_fd) && defined(__NR_quotactl_fd)
SCMP_SYS(quotactl_fd),
#endif
SCMP_SYS(readahead),
SCMP_SYS(lookup_dcookie),
SCMP_SYS(add_key),
SCMP_SYS(request_key),
SCMP_SYS(keyctl),
SCMP_SYS(inotify_init),
SCMP_SYS(inotify_init1),
SCMP_SYS(inotify_add_watch),
SCMP_SYS(inotify_rm_watch),
SCMP_SYS(splice),
SCMP_SYS(tee),
SCMP_SYS(vmsplice),
SCMP_SYS(signalfd),
SCMP_SYS(eventfd),
SCMP_SYS(timerfd_settime),
#ifdef __SNR_timer_settime64
SCMP_SYS(timer_settime64),
#endif
#ifdef __SNR_timerfd_settime64
SCMP_SYS(timerfd_settime64),
#endif
SCMP_SYS(timerfd_gettime),
SCMP_SYS(signalfd4),
SCMP_SYS(eventfd2),
SCMP_SYS(fanotify_init),
SCMP_SYS(fanotify_mark),
SCMP_SYS(mknod),
SCMP_SYS(mknodat),
SCMP_SYS(acct),
SCMP_SYS(prlimit64),
SCMP_SYS(setrlimit),
#ifdef __SNR_bpf
SCMP_SYS(bpf),
#endif
#ifdef __SNR_copy_filerange
SCMP_SYS(copy_filerange),
#endif
/* xattrs */
SCMP_SYS(setxattr),
SCMP_SYS(lsetxattr),
SCMP_SYS(fsetxattr),
SCMP_SYS(getxattr),
SCMP_SYS(lgetxattr),
SCMP_SYS(fgetxattr),
SCMP_SYS(listxattr),
SCMP_SYS(llistxattr),
SCMP_SYS(flistxattr),
SCMP_SYS(removexattr),
SCMP_SYS(lremovexattr),
SCMP_SYS(fremovexattr),
/* processs forking */
SCMP_SYS(execve),
/* io */
SCMP_SYS(iopl),
SCMP_SYS(ioperm),
SCMP_SYS(io_setup),
SCMP_SYS(io_destroy),
SCMP_SYS(io_getevents),
SCMP_SYS(io_submit),
SCMP_SYS(io_cancel),
SCMP_SYS(ioprio_set),
SCMP_SYS(ioprio_get),
/* not implemented, removed */
SCMP_SYS(create_module),
SCMP_SYS(get_kernel_syms),
SCMP_SYS(query_module),
SCMP_SYS(uselib),
SCMP_SYS(nfsservctl),
SCMP_SYS(getpmsg),
SCMP_SYS(putpmsg),
SCMP_SYS(afs_syscall),
SCMP_SYS(tuxcall),
SCMP_SYS(security),
SCMP_SYS(set_thread_area),
SCMP_SYS(get_thread_area),
SCMP_SYS(epoll_ctl_old),
SCMP_SYS(epoll_wait_old),
SCMP_SYS(vserver),
/* privileged */
SCMP_SYS(setuid),
SCMP_SYS(setgid),
SCMP_SYS(setpgid),
SCMP_SYS(setsid),
SCMP_SYS(setreuid),
SCMP_SYS(setregid),
SCMP_SYS(setgroups),
SCMP_SYS(setresuid),
SCMP_SYS(setresgid),
SCMP_SYS(setfsuid),
SCMP_SYS(setfsgid)
};
/* CUSE TPM needs to clone or fork */
int blacklist_noncuse[] = {
SCMP_SYS(clone),
SCMP_SYS(fork),
SCMP_SYS(vfork),
SCMP_SYS(prctl),
#ifdef __SNR_clone3
SCMP_SYS(clone3),
#endif
/* misc */
SCMP_SYS(sched_setattr), /* caller: g_thread_pool_new() glib v2.68 */
};
scmp_filter_ctx ctx;
int ret;
if (action == SWTPM_SECCOMP_ACTION_NONE)
return 0;
ctx = seccomp_init(SCMP_ACT_ALLOW);
if (!ctx) {
logprintf(STDERR_FILENO, "seccomp_init failed\n");
return -1;
}
if ((ret = create_seccomp_profile_add_rules(ctx, blacklist,
ARRAY_LEN(blacklist),
action)) < 0)
goto error_seccomp_rule_add;
if (!cusetpm &&
(ret = create_seccomp_profile_add_rules(ctx, blacklist_noncuse,
ARRAY_LEN(blacklist_noncuse),
action)) < 0)
goto error_seccomp_rule_add;
if ((ret = seccomp_load(ctx)) < 0)
logprintf(STDERR_FILENO, "seccomp_load failed with errno %d: %s\n",
-ret, strerror(-ret));
error_seccomp_rule_add:
seccomp_release(ctx);
return ret;
}
#endif