Bundle libseccomp 2.3.1
[linux-seccomp.git] / libseccomp / src / system.c
CommitLineData
8befd5cc
MG
1/**
2 * Seccomp System Interfaces
3 *
4 * Copyright (c) 2014 Red Hat <pmoore@redhat.com>
5 * Author: Paul Moore <paul@paul-moore.com>
6 */
7
8/*
9 * This library is free software; you can redistribute it and/or modify it
10 * under the terms of version 2.1 of the GNU Lesser General Public License as
11 * published by the Free Software Foundation.
12 *
13 * This library is distributed in the hope that it will be useful, but WITHOUT
14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
16 * for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this library; if not, see <http://www.gnu.org/licenses>.
20 */
21
22#include <stdlib.h>
23#include <errno.h>
24#include <sys/prctl.h>
25
26#define _GNU_SOURCE
27#include <unistd.h>
28
29#include <seccomp.h>
30
31#include "arch.h"
32#include "db.h"
33#include "gen_bpf.h"
34#include "system.h"
35
36/* NOTE: the seccomp syscall whitelist is currently disabled for testing
37 * purposes, but unless we can verify all of the supported ABIs before
38 * our next release we may have to enable the whitelist */
39#define SYSCALL_WHITELIST_ENABLE 0
40
41static int _nr_seccomp = -1;
42static int _support_seccomp_syscall = -1;
43
44/**
45 * Check to see if the seccomp() syscall is supported
46 *
47 * This function attempts to see if the system supports the seccomp() syscall.
48 * Unfortunately, there are a few reasons why this check may fail, including
49 * a previously loaded seccomp filter, so it is hard to say for certain.
50 * Return one if the syscall is supported, zero otherwise.
51 *
52 */
53int sys_chk_seccomp_syscall(void)
54{
55 int rc;
56 int nr_seccomp;
57
58 /* NOTE: it is reasonably safe to assume that we should be able to call
59 * seccomp() when the caller first starts, but we can't rely on
60 * it later so we need to cache our findings for use later */
61 if (_support_seccomp_syscall >= 0)
62 return _support_seccomp_syscall;
63
64#if SYSCALL_WHITELIST_ENABLE
65 /* architecture whitelist */
66 switch (arch_def_native->token) {
67 case SCMP_ARCH_X86_64:
68 case SCMP_ARCH_ARM:
69 case SCMP_ARCH_AARCH64:
70 case SCMP_ARCH_PPC64:
71 case SCMP_ARCH_PPC64LE:
72 case SCMP_ARCH_S390:
73 case SCMP_ARCH_S390X:
74 break;
75 default:
76 goto unsupported;
77 }
78#endif
79
80 nr_seccomp = arch_syscall_resolve_name(arch_def_native, "seccomp");
81 if (nr_seccomp < 0)
82 goto unsupported;
83
84 /* this is an invalid call because the second argument is non-zero, but
85 * depending on the errno value of ENOSYS or EINVAL we can guess if the
86 * seccomp() syscal is supported or not */
87 rc = syscall(nr_seccomp, SECCOMP_SET_MODE_STRICT, 1, NULL);
88 if (rc < 0 && errno == EINVAL)
89 goto supported;
90
91unsupported:
92 _support_seccomp_syscall = 0;
93 return 0;
94supported:
95 _nr_seccomp = nr_seccomp;
96 _support_seccomp_syscall = 1;
97 return 1;
98}
99
100/**
101 * Check to see if a seccomp() flag is supported
102 * @param flag the seccomp() flag
103 *
104 * This function checks to see if a seccomp() flag is supported by the system.
105 * If the flag is supported one is returned, zero if unsupported, negative
106 * values on error.
107 *
108 */
109int sys_chk_seccomp_flag(int flag)
110{
111 switch (flag) {
112 case SECCOMP_FILTER_FLAG_TSYNC:
113 return sys_chk_seccomp_syscall();
114 }
115
116 return -EOPNOTSUPP;
117}
118
119/**
120 * Loads the filter into the kernel
121 * @param col the filter collection
122 *
123 * This function loads the given seccomp filter context into the kernel. If
124 * the filter was loaded correctly, the kernel will be enforcing the filter
125 * when this function returns. Returns zero on success, negative values on
126 * error.
127 *
128 */
129int sys_filter_load(const struct db_filter_col *col)
130{
131 int rc;
132 struct bpf_program *prgm = NULL;
133
134 prgm = gen_bpf_generate(col);
135 if (prgm == NULL)
136 return -ENOMEM;
137
138 /* attempt to set NO_NEW_PRIVS */
139 if (col->attr.nnp_enable) {
140 rc = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
141 if (rc < 0)
142 goto filter_load_out;
143 }
144
145 /* load the filter into the kernel */
146 if (sys_chk_seccomp_syscall() == 1) {
147 int flgs = 0;
148 if (col->attr.tsync_enable)
149 flgs = SECCOMP_FILTER_FLAG_TSYNC;
150 rc = syscall(_nr_seccomp, SECCOMP_SET_MODE_FILTER, flgs, prgm);
151 if (rc > 0 && col->attr.tsync_enable)
152 /* always return -ESRCH if we fail to sync threads */
153 errno = ESRCH;
154 } else
155 rc = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prgm);
156
157filter_load_out:
158 /* cleanup and return */
159 gen_bpf_release(prgm);
160 if (rc < 0)
161 return -errno;
162 return 0;
163}
This page took 0.017602 seconds and 4 git commands to generate.