]>
git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/seccomp.c
2 * lxc: linux Container library
4 * (C) Copyright Canonical, Inc. 2012
7 * Serge Hallyn <serge.hallyn@canonical.com>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
32 #include "lxcseccomp.h"
35 lxc_log_define(lxc_seccomp
, lxc
);
37 static int parse_config_v1(FILE *f
, struct lxc_conf
*conf
)
42 while (fgets(line
, 1024, f
)) {
44 ret
= sscanf(line
, "%d", &nr
);
47 ret
= seccomp_rule_add(
48 #if HAVE_SCMP_FILTER_CTX
51 SCMP_ACT_ALLOW
, nr
, 0);
53 ERROR("failed loading allow rule for %d", nr
);
60 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
61 static void remove_trailing_newlines(char *l
)
67 while (--p
>= l
&& *p
== '\n')
71 static uint32_t get_v2_default_action(char *line
)
73 uint32_t ret_action
= -1;
75 while (*line
== ' ') line
++;
76 // after 'whitelist' or 'blacklist' comes default behavior
77 if (strncmp(line
, "kill", 4) == 0)
78 ret_action
= SCMP_ACT_KILL
;
79 else if (strncmp(line
, "errno", 5) == 0) {
81 if (sscanf(line
+5, "%d", &e
) != 1) {
82 ERROR("Bad errno value in %s", line
);
85 ret_action
= SCMP_ACT_ERRNO(e
);
86 } else if (strncmp(line
, "allow", 5) == 0)
87 ret_action
= SCMP_ACT_ALLOW
;
88 else if (strncmp(line
, "trap", 4) == 0)
89 ret_action
= SCMP_ACT_TRAP
;
93 static uint32_t get_and_clear_v2_action(char *line
, uint32_t def_action
)
95 char *p
= strchr(line
, ' ');
104 if (!*p
|| *p
== '#')
106 ret
= get_v2_default_action(p
);
109 case -1: return def_action
;
129 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
131 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
134 scmp_filter_ctx
*ctx
= NULL
;
135 bool blacklist
= false;
136 uint32_t default_policy_action
= -1, default_rule_action
= -1, action
;
137 uint32_t arch
= SCMP_ARCH_NATIVE
;
139 if (strncmp(line
, "blacklist", 9) == 0)
141 else if (strncmp(line
, "whitelist", 9) != 0) {
142 ERROR("Bad seccomp policy style: %s", line
);
146 if ((p
= strchr(line
, ' '))) {
147 default_policy_action
= get_v2_default_action(p
+1);
148 if (default_policy_action
== -2)
152 /* for blacklist, allow any syscall which has no rule */
154 if (default_policy_action
== -1)
155 default_policy_action
= SCMP_ACT_ALLOW
;
156 if (default_rule_action
== -1)
157 default_rule_action
= SCMP_ACT_KILL
;
159 if (default_policy_action
== -1)
160 default_policy_action
= SCMP_ACT_KILL
;
161 if (default_rule_action
== -1)
162 default_rule_action
= SCMP_ACT_ALLOW
;
165 if (default_policy_action
!= SCMP_ACT_KILL
) {
166 ret
= seccomp_reset(conf
->seccomp_ctx
, default_policy_action
);
168 ERROR("Error re-initializing seccomp");
171 if (seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0)) {
172 ERROR("failed to turn off n-new-privs");
177 while (fgets(line
, 1024, f
)) {
182 if (strlen(line
) == 0)
184 remove_trailing_newlines(line
);
185 INFO("processing: .%s.", line
);
186 if (line
[0] == '[') {
187 // read the architecture for next set of rules
188 if (strcmp(line
, "[x86]") == 0 ||
189 strcmp(line
, "[X86]") == 0)
190 arch
= SCMP_ARCH_X86
;
191 else if (strcmp(line
, "[X86_64]") == 0 ||
192 strcmp(line
, "[x86_64]") == 0)
193 arch
= SCMP_ARCH_X86_64
;
195 else if (strcmp(line
, "[arm]") == 0 ||
196 strcmp(line
, "[ARM]") == 0)
197 arch
= SCMP_ARCH_ARM
;
202 ERROR("Only two arch sections per policy supported");
205 if ((ctx
= seccomp_init(default_policy_action
)) == NULL
) {
206 ERROR("Error initializing seccomp context");
209 if (seccomp_attr_set(ctx
, SCMP_FLTATR_CTL_NNP
, 0)) {
210 ERROR("failed to turn off n-new-privs");
211 seccomp_release(ctx
);
214 ret
= seccomp_arch_add(ctx
, arch
);
215 if (ret
== -EEXIST
) {
216 seccomp_release(ctx
);
221 ERROR("Error %d adding arch: %s", ret
, line
);
224 if (seccomp_arch_remove(ctx
, SCMP_ARCH_NATIVE
) != 0) {
225 ERROR("Error removing native arch from %s", line
);
231 action
= get_and_clear_v2_action(line
, default_rule_action
);
233 ERROR("Failed to interpret action");
236 nr
= seccomp_syscall_resolve_name_arch(arch
, line
);
238 WARN("Seccomp: failed to resolve syscall: %s (returned %d)",
240 WARN("This syscall will NOT be blacklisted");
243 ret
= seccomp_rule_add(ctx
? ctx
: conf
->seccomp_ctx
,
246 ERROR("failed (%d) loading rule for %s", ret
, line
);
251 if (seccomp_merge(conf
->seccomp_ctx
, ctx
) != 0) {
252 seccomp_release(ctx
);
253 ERROR("Error merging seccomp contexts");
260 ERROR("Unsupported arch: %s", line
);
263 seccomp_release(ctx
);
271 * The first line of the config file has a policy language version
272 * the second line has some directives
273 * then comes policy subject to the directives
274 * right now version must be '1'
275 * the directives must include 'whitelist' (only type of policy currently
276 * supported) and can include 'debug' (though debug is not yet supported).
278 static int parse_config(FILE *f
, struct lxc_conf
*conf
)
283 ret
= fscanf(f
, "%d\n", &version
);
284 if (ret
!= 1 || (version
!= 1 && version
!= 2)) {
285 ERROR("invalid version");
288 if (!fgets(line
, 1024, f
)) {
289 ERROR("invalid config file");
292 if (version
== 1 && !strstr(line
, "whitelist")) {
293 ERROR("only whitelist policy is supported");
297 if (strstr(line
, "debug")) {
298 ERROR("debug not yet implemented");
303 return parse_config_v1(f
, conf
);
304 return parse_config_v2(f
, line
, conf
);
307 int lxc_read_seccomp_config(struct lxc_conf
*conf
)
315 #if HAVE_SCMP_FILTER_CTX
316 /* XXX for debug, pass in SCMP_ACT_TRAP */
317 conf
->seccomp_ctx
= seccomp_init(SCMP_ACT_KILL
);
318 ret
= !conf
->seccomp_ctx
;
320 ret
= seccomp_init(SCMP_ACT_KILL
) < 0;
323 ERROR("failed initializing seccomp");
327 /* turn of no-new-privs. We don't want it in lxc, and it breaks
329 if (seccomp_attr_set(
330 #if HAVE_SCMP_FILTER_CTX
333 SCMP_FLTATR_CTL_NNP
, 0)) {
334 ERROR("failed to turn off n-new-privs");
338 f
= fopen(conf
->seccomp
, "r");
340 SYSERROR("failed to open seccomp policy file %s", conf
->seccomp
);
343 ret
= parse_config(f
, conf
);
348 int lxc_seccomp_load(struct lxc_conf
*conf
)
354 #if HAVE_SCMP_FILTER_CTX
359 ERROR("Error loading the seccomp policy");
365 void lxc_seccomp_free(struct lxc_conf
*conf
) {
368 conf
->seccomp
= NULL
;
370 #if HAVE_SCMP_FILTER_CTX
371 if (conf
->seccomp_ctx
) {
372 seccomp_release(conf
->seccomp_ctx
);
373 conf
->seccomp_ctx
= NULL
;