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
29 #include <sys/mount.h>
30 #include <sys/utsname.h>
34 #include "lxcseccomp.h"
36 lxc_log_define(lxc_seccomp
, lxc
);
38 static int parse_config_v1(FILE *f
, struct lxc_conf
*conf
)
43 while (fgets(line
, 1024, f
)) {
45 ret
= sscanf(line
, "%d", &nr
);
48 ret
= seccomp_rule_add(
49 #if HAVE_SCMP_FILTER_CTX
52 SCMP_ACT_ALLOW
, nr
, 0);
54 ERROR("Failed loading allow rule for %d.", nr
);
61 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
62 static void remove_trailing_newlines(char *l
)
68 while (--p
>= l
&& *p
== '\n')
72 static uint32_t get_v2_default_action(char *line
)
74 uint32_t ret_action
= -1;
78 // after 'whitelist' or 'blacklist' comes default behavior
79 if (strncmp(line
, "kill", 4) == 0)
80 ret_action
= SCMP_ACT_KILL
;
81 else if (strncmp(line
, "errno", 5) == 0) {
83 if (sscanf(line
+ 5, "%d", &e
) != 1) {
84 ERROR("Bad errno value in %s.", line
);
87 ret_action
= SCMP_ACT_ERRNO(e
);
88 } else if (strncmp(line
, "allow", 5) == 0)
89 ret_action
= SCMP_ACT_ALLOW
;
90 else if (strncmp(line
, "trap", 4) == 0)
91 ret_action
= SCMP_ACT_TRAP
;
95 static const char *get_action_name(uint32_t action
)
97 // The upper 16 bits indicate the type of the seccomp action
98 switch(action
& 0xffff0000){
105 case SCMP_ACT_ERRNO(0):
108 return "invalid action";
112 static uint32_t get_and_clear_v2_action(char *line
, uint32_t def_action
)
114 char *p
= strchr(line
, ' ');
123 if (!*p
|| *p
== '#')
125 ret
= get_v2_default_action(p
);
128 case -1: return def_action
;
134 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
135 enum lxc_hostarch_t
{
136 lxc_seccomp_arch_all
= 0,
137 lxc_seccomp_arch_native
,
138 lxc_seccomp_arch_i386
,
139 lxc_seccomp_arch_x32
,
140 lxc_seccomp_arch_amd64
,
141 lxc_seccomp_arch_arm
,
142 lxc_seccomp_arch_arm64
,
143 lxc_seccomp_arch_ppc64
,
144 lxc_seccomp_arch_ppc64le
,
145 lxc_seccomp_arch_ppc
,
146 lxc_seccomp_arch_mips
,
147 lxc_seccomp_arch_mips64
,
148 lxc_seccomp_arch_mips64n32
,
149 lxc_seccomp_arch_mipsel
,
150 lxc_seccomp_arch_mipsel64
,
151 lxc_seccomp_arch_mipsel64n32
,
152 lxc_seccomp_arch_s390x
,
153 lxc_seccomp_arch_unknown
= 999,
157 # define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel
158 # define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64
160 # define MIPS_ARCH_O32 lxc_seccomp_arch_mips
161 # define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
164 int get_hostarch(void)
167 if (uname(&uts
) < 0) {
168 SYSERROR("Failed to read host arch.");
171 if (strcmp(uts
.machine
, "i686") == 0)
172 return lxc_seccomp_arch_i386
;
174 else if (strcmp(uts
.machine
, "x86_64") == 0)
175 return lxc_seccomp_arch_amd64
;
176 else if (strncmp(uts
.machine
, "armv7", 5) == 0)
177 return lxc_seccomp_arch_arm
;
178 else if (strncmp(uts
.machine
, "aarch64", 7) == 0)
179 return lxc_seccomp_arch_arm64
;
180 else if (strncmp(uts
.machine
, "ppc64le", 7) == 0)
181 return lxc_seccomp_arch_ppc64le
;
182 else if (strncmp(uts
.machine
, "ppc64", 5) == 0)
183 return lxc_seccomp_arch_ppc64
;
184 else if (strncmp(uts
.machine
, "ppc", 3) == 0)
185 return lxc_seccomp_arch_ppc
;
186 else if (strncmp(uts
.machine
, "mips64", 6) == 0)
187 return MIPS_ARCH_N64
;
188 else if (strncmp(uts
.machine
, "mips", 4) == 0)
189 return MIPS_ARCH_O32
;
190 else if (strncmp(uts
.machine
, "s390x", 5) == 0)
191 return lxc_seccomp_arch_s390x
;
192 return lxc_seccomp_arch_unknown
;
195 scmp_filter_ctx
get_new_ctx(enum lxc_hostarch_t n_arch
, uint32_t default_policy_action
)
202 case lxc_seccomp_arch_i386
: arch
= SCMP_ARCH_X86
; break;
203 case lxc_seccomp_arch_x32
: arch
= SCMP_ARCH_X32
; break;
204 case lxc_seccomp_arch_amd64
: arch
= SCMP_ARCH_X86_64
; break;
205 case lxc_seccomp_arch_arm
: arch
= SCMP_ARCH_ARM
; break;
206 #ifdef SCMP_ARCH_AARCH64
207 case lxc_seccomp_arch_arm64
: arch
= SCMP_ARCH_AARCH64
; break;
209 #ifdef SCMP_ARCH_PPC64LE
210 case lxc_seccomp_arch_ppc64le
: arch
= SCMP_ARCH_PPC64LE
; break;
212 #ifdef SCMP_ARCH_PPC64
213 case lxc_seccomp_arch_ppc64
: arch
= SCMP_ARCH_PPC64
; break;
216 case lxc_seccomp_arch_ppc
: arch
= SCMP_ARCH_PPC
; break;
218 #ifdef SCMP_ARCH_MIPS
219 case lxc_seccomp_arch_mips
: arch
= SCMP_ARCH_MIPS
; break;
220 case lxc_seccomp_arch_mips64
: arch
= SCMP_ARCH_MIPS64
; break;
221 case lxc_seccomp_arch_mips64n32
: arch
= SCMP_ARCH_MIPS64N32
; break;
222 case lxc_seccomp_arch_mipsel
: arch
= SCMP_ARCH_MIPSEL
; break;
223 case lxc_seccomp_arch_mipsel64
: arch
= SCMP_ARCH_MIPSEL64
; break;
224 case lxc_seccomp_arch_mipsel64n32
: arch
= SCMP_ARCH_MIPSEL64N32
; break;
226 #ifdef SCMP_ARCH_S390X
227 case lxc_seccomp_arch_s390x
: arch
= SCMP_ARCH_S390X
; break;
229 default: return NULL
;
232 if ((ctx
= seccomp_init(default_policy_action
)) == NULL
) {
233 ERROR("Error initializing seccomp context.");
236 if (seccomp_attr_set(ctx
, SCMP_FLTATR_CTL_NNP
, 0)) {
237 ERROR("Failed to turn off no-new-privs.");
238 seccomp_release(ctx
);
241 #ifdef SCMP_FLTATR_ATL_TSKIP
242 if (seccomp_attr_set(ctx
, SCMP_FLTATR_ATL_TSKIP
, 1)) {
243 WARN("Failed to turn on seccomp nop-skip, continuing");
246 ret
= seccomp_arch_add(ctx
, arch
);
248 ERROR("Seccomp error %d (%s) adding arch: %d", ret
,
249 strerror(-ret
), (int)n_arch
);
250 seccomp_release(ctx
);
253 if (seccomp_arch_remove(ctx
, SCMP_ARCH_NATIVE
) != 0) {
254 ERROR("Seccomp error removing native arch");
255 seccomp_release(ctx
);
262 bool do_resolve_add_rule(uint32_t arch
, char *line
, scmp_filter_ctx ctx
,
267 ret
= seccomp_arch_exist(ctx
, arch
);
268 if (arch
&& ret
!= 0) {
269 ERROR("BUG: Seccomp: rule and context arch do not match (arch "
271 arch
, strerror(-ret
));
275 if (strncmp(line
, "reject_force_umount", 19) == 0) {
276 INFO("Setting Seccomp rule to reject force umounts.");
277 ret
= seccomp_rule_add_exact(ctx
, SCMP_ACT_ERRNO(EACCES
), SCMP_SYS(umount2
),
278 1, SCMP_A1(SCMP_CMP_MASKED_EQ
, MNT_FORCE
, MNT_FORCE
));
280 ERROR("Failed (%d) loading rule to reject force "
282 ret
, strerror(-ret
));
288 nr
= seccomp_syscall_resolve_name(line
);
289 if (nr
== __NR_SCMP_ERROR
) {
290 WARN("Seccomp: failed to resolve syscall: %s.", line
);
291 WARN("This syscall will NOT be blacklisted.");
295 WARN("Seccomp: got negative for syscall: %d: %s.", nr
, line
);
296 WARN("This syscall will NOT be blacklisted.");
299 ret
= seccomp_rule_add_exact(ctx
, action
, nr
, 0);
301 ERROR("Failed (%d) loading rule for %s (nr %d action %d(%s)): %s.",
302 ret
, line
, nr
, action
, get_action_name(action
), strerror(-ret
));
322 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
326 scmp_filter_ctx compat_ctx
[2] = {NULL
, NULL
};
327 bool blacklist
= false;
328 uint32_t default_policy_action
= -1, default_rule_action
= -1, action
;
329 enum lxc_hostarch_t native_arch
= get_hostarch(),
330 cur_rule_arch
= native_arch
;
331 uint32_t compat_arch
[2] = {SCMP_ARCH_NATIVE
, SCMP_ARCH_NATIVE
};
333 if (strncmp(line
, "blacklist", 9) == 0)
335 else if (strncmp(line
, "whitelist", 9) != 0) {
336 ERROR("Bad seccomp policy style: %s.", line
);
340 if ((p
= strchr(line
, ' '))) {
341 default_policy_action
= get_v2_default_action(p
+ 1);
342 if (default_policy_action
== -2)
346 /* for blacklist, allow any syscall which has no rule */
348 if (default_policy_action
== -1)
349 default_policy_action
= SCMP_ACT_ALLOW
;
350 if (default_rule_action
== -1)
351 default_rule_action
= SCMP_ACT_KILL
;
353 if (default_policy_action
== -1)
354 default_policy_action
= SCMP_ACT_KILL
;
355 if (default_rule_action
== -1)
356 default_rule_action
= SCMP_ACT_ALLOW
;
359 if (native_arch
== lxc_seccomp_arch_amd64
) {
360 cur_rule_arch
= lxc_seccomp_arch_all
;
361 compat_arch
[0] = SCMP_ARCH_X86
;
362 compat_ctx
[0] = get_new_ctx(lxc_seccomp_arch_i386
,
363 default_policy_action
);
364 compat_arch
[1] = SCMP_ARCH_X32
;
365 compat_ctx
[1] = get_new_ctx(lxc_seccomp_arch_x32
,
366 default_policy_action
);
367 if (!compat_ctx
[0] || !compat_ctx
[1])
370 } else if (native_arch
== lxc_seccomp_arch_ppc64
) {
371 cur_rule_arch
= lxc_seccomp_arch_all
;
372 compat_arch
[0] = SCMP_ARCH_PPC
;
373 compat_ctx
[0] = get_new_ctx(lxc_seccomp_arch_ppc
,
374 default_policy_action
);
379 } else if (native_arch
== lxc_seccomp_arch_arm64
) {
380 cur_rule_arch
= lxc_seccomp_arch_all
;
381 compat_arch
[0] = SCMP_ARCH_ARM
;
382 compat_ctx
[0] = get_new_ctx(lxc_seccomp_arch_arm
,
383 default_policy_action
);
387 #ifdef SCMP_ARCH_MIPS
388 } else if (native_arch
== lxc_seccomp_arch_mips64
) {
389 cur_rule_arch
= lxc_seccomp_arch_all
;
390 compat_arch
[0] = SCMP_ARCH_MIPS
;
391 compat_arch
[1] = SCMP_ARCH_MIPS64N32
;
392 compat_ctx
[0] = get_new_ctx(lxc_seccomp_arch_mips
,
393 default_policy_action
);
394 compat_ctx
[1] = get_new_ctx(lxc_seccomp_arch_mips64n32
,
395 default_policy_action
);
396 if (!compat_ctx
[0] || !compat_ctx
[1])
398 } else if (native_arch
== lxc_seccomp_arch_mipsel64
) {
399 cur_rule_arch
= lxc_seccomp_arch_all
;
400 compat_arch
[0] = SCMP_ARCH_MIPSEL
;
401 compat_arch
[1] = SCMP_ARCH_MIPSEL64N32
;
402 compat_ctx
[0] = get_new_ctx(lxc_seccomp_arch_mipsel
,
403 default_policy_action
);
404 compat_ctx
[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32
,
405 default_policy_action
);
406 if (!compat_ctx
[0] || !compat_ctx
[1])
411 if (default_policy_action
!= SCMP_ACT_KILL
) {
412 ret
= seccomp_reset(conf
->seccomp_ctx
, default_policy_action
);
414 ERROR("Error re-initializing Seccomp.");
417 if (seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0)) {
418 ERROR("Failed to turn off no-new-privs.");
421 #ifdef SCMP_FLTATR_ATL_TSKIP
422 if (seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1)) {
423 WARN("Failed to turn on seccomp nop-skip, continuing");
428 while (fgets(line
, 1024, f
)) {
432 if (strlen(line
) == 0)
434 remove_trailing_newlines(line
);
435 INFO("processing: .%s.", line
);
436 if (line
[0] == '[') {
437 // read the architecture for next set of rules
438 if (strcmp(line
, "[x86]") == 0 ||
439 strcmp(line
, "[X86]") == 0) {
440 if (native_arch
!= lxc_seccomp_arch_i386
&&
441 native_arch
!= lxc_seccomp_arch_amd64
) {
442 cur_rule_arch
= lxc_seccomp_arch_unknown
;
445 cur_rule_arch
= lxc_seccomp_arch_i386
;
446 } else if (strcmp(line
, "[x32]") == 0 ||
447 strcmp(line
, "[X32]") == 0) {
448 if (native_arch
!= lxc_seccomp_arch_amd64
) {
449 cur_rule_arch
= lxc_seccomp_arch_unknown
;
452 cur_rule_arch
= lxc_seccomp_arch_x32
;
453 } else if (strcmp(line
, "[X86_64]") == 0 ||
454 strcmp(line
, "[x86_64]") == 0) {
455 if (native_arch
!= lxc_seccomp_arch_amd64
) {
456 cur_rule_arch
= lxc_seccomp_arch_unknown
;
459 cur_rule_arch
= lxc_seccomp_arch_amd64
;
460 } else if (strcmp(line
, "[all]") == 0 ||
461 strcmp(line
, "[ALL]") == 0) {
462 cur_rule_arch
= lxc_seccomp_arch_all
;
465 else if (strcmp(line
, "[arm]") == 0 ||
466 strcmp(line
, "[ARM]") == 0) {
467 if (native_arch
!= lxc_seccomp_arch_arm
&&
468 native_arch
!= lxc_seccomp_arch_arm64
) {
469 cur_rule_arch
= lxc_seccomp_arch_unknown
;
472 cur_rule_arch
= lxc_seccomp_arch_arm
;
475 #ifdef SCMP_ARCH_AARCH64
476 else if (strcmp(line
, "[arm64]") == 0 ||
477 strcmp(line
, "[ARM64]") == 0) {
478 if (native_arch
!= lxc_seccomp_arch_arm64
) {
479 cur_rule_arch
= lxc_seccomp_arch_unknown
;
482 cur_rule_arch
= lxc_seccomp_arch_arm64
;
485 #ifdef SCMP_ARCH_PPC64LE
486 else if (strcmp(line
, "[ppc64le]") == 0 ||
487 strcmp(line
, "[PPC64LE]") == 0) {
488 if (native_arch
!= lxc_seccomp_arch_ppc64le
) {
489 cur_rule_arch
= lxc_seccomp_arch_unknown
;
492 cur_rule_arch
= lxc_seccomp_arch_ppc64le
;
495 #ifdef SCMP_ARCH_PPC64
496 else if (strcmp(line
, "[ppc64]") == 0 ||
497 strcmp(line
, "[PPC64]") == 0) {
498 if (native_arch
!= lxc_seccomp_arch_ppc64
) {
499 cur_rule_arch
= lxc_seccomp_arch_unknown
;
502 cur_rule_arch
= lxc_seccomp_arch_ppc64
;
506 else if (strcmp(line
, "[ppc]") == 0 ||
507 strcmp(line
, "[PPC]") == 0) {
508 if (native_arch
!= lxc_seccomp_arch_ppc
&&
509 native_arch
!= lxc_seccomp_arch_ppc64
) {
510 cur_rule_arch
= lxc_seccomp_arch_unknown
;
513 cur_rule_arch
= lxc_seccomp_arch_ppc
;
516 #ifdef SCMP_ARCH_MIPS
517 else if (strcmp(line
, "[mips64]") == 0 ||
518 strcmp(line
, "[MIPS64]") == 0) {
519 if (native_arch
!= lxc_seccomp_arch_mips64
) {
520 cur_rule_arch
= lxc_seccomp_arch_unknown
;
523 cur_rule_arch
= lxc_seccomp_arch_mips64
;
524 } else if (strcmp(line
, "[mips64n32]") == 0 ||
525 strcmp(line
, "[MIPS64N32]") == 0) {
526 if (native_arch
!= lxc_seccomp_arch_mips64
) {
527 cur_rule_arch
= lxc_seccomp_arch_unknown
;
530 cur_rule_arch
= lxc_seccomp_arch_mips64n32
;
531 } else if (strcmp(line
, "[mips]") == 0 ||
532 strcmp(line
, "[MIPS]") == 0) {
533 if (native_arch
!= lxc_seccomp_arch_mips
&&
534 native_arch
!= lxc_seccomp_arch_mips64
) {
535 cur_rule_arch
= lxc_seccomp_arch_unknown
;
538 cur_rule_arch
= lxc_seccomp_arch_mips
;
539 } else if (strcmp(line
, "[mipsel64]") == 0 ||
540 strcmp(line
, "[MIPSEL64]") == 0) {
541 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
542 cur_rule_arch
= lxc_seccomp_arch_unknown
;
545 cur_rule_arch
= lxc_seccomp_arch_mipsel64
;
546 } else if (strcmp(line
, "[mipsel64n32]") == 0 ||
547 strcmp(line
, "[MIPSEL64N32]") == 0) {
548 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
549 cur_rule_arch
= lxc_seccomp_arch_unknown
;
552 cur_rule_arch
= lxc_seccomp_arch_mipsel64n32
;
553 } else if (strcmp(line
, "[mipsel]") == 0 ||
554 strcmp(line
, "[MIPSEL]") == 0) {
555 if (native_arch
!= lxc_seccomp_arch_mipsel
&&
556 native_arch
!= lxc_seccomp_arch_mipsel64
) {
557 cur_rule_arch
= lxc_seccomp_arch_unknown
;
560 cur_rule_arch
= lxc_seccomp_arch_mipsel
;
563 #ifdef SCMP_ARCH_S390X
564 else if (strcmp(line
, "[s390x]") == 0 ||
565 strcmp(line
, "[S390X]") == 0) {
566 if (native_arch
!= lxc_seccomp_arch_s390x
) {
567 cur_rule_arch
= lxc_seccomp_arch_unknown
;
570 cur_rule_arch
= lxc_seccomp_arch_s390x
;
579 /* irrelevant arch - i.e. arm on i386 */
580 if (cur_rule_arch
== lxc_seccomp_arch_unknown
)
583 /* read optional action which follows the syscall */
584 action
= get_and_clear_v2_action(line
, default_rule_action
);
586 ERROR("Failed to interpret action.");
590 if (cur_rule_arch
== native_arch
||
591 cur_rule_arch
== lxc_seccomp_arch_native
||
592 compat_arch
[0] == SCMP_ARCH_NATIVE
) {
593 INFO("Adding native rule for %s action %d(%s).", line
, action
,
594 get_action_name(action
));
595 if (!do_resolve_add_rule(SCMP_ARCH_NATIVE
, line
, conf
->seccomp_ctx
, action
))
598 else if (cur_rule_arch
!= lxc_seccomp_arch_all
) {
600 cur_rule_arch
== lxc_seccomp_arch_mips64n32
||
601 cur_rule_arch
== lxc_seccomp_arch_mipsel64n32
? 1 : 0;
603 INFO("Adding compat-only rule for %s action %d(%s).", line
, action
,
604 get_action_name(action
));
605 if (!do_resolve_add_rule(compat_arch
[arch_index
], line
, compat_ctx
[arch_index
], action
))
609 INFO("Adding native rule for %s action %d(%s).", line
, action
,
610 get_action_name(action
));
611 if (!do_resolve_add_rule(SCMP_ARCH_NATIVE
, line
, conf
->seccomp_ctx
, action
))
613 INFO("Adding compat rule for %s action %d(%s).", line
, action
,
614 get_action_name(action
));
615 if (!do_resolve_add_rule(compat_arch
[0], line
, compat_ctx
[0], action
))
617 if (compat_arch
[1] != SCMP_ARCH_NATIVE
&&
618 !do_resolve_add_rule(compat_arch
[1], line
, compat_ctx
[1], action
))
624 INFO("Merging in the compat Seccomp ctx into the main one.");
625 if (seccomp_merge(conf
->seccomp_ctx
, compat_ctx
[0]) != 0 ||
626 (compat_ctx
[1] != NULL
&& seccomp_merge(conf
->seccomp_ctx
, compat_ctx
[1]) != 0)) {
627 ERROR("Error merging compat Seccomp contexts.");
635 ERROR("Unsupported arch: %s.", line
);
639 seccomp_release(compat_ctx
[0]);
641 seccomp_release(compat_ctx
[1]);
644 #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
645 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
649 #endif /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
652 * The first line of the config file has a policy language version
653 * the second line has some directives
654 * then comes policy subject to the directives
655 * right now version must be '1' or '2'
656 * the directives must include 'whitelist'(version == 1 or 2) or 'blacklist'
657 * (version == 2) and can include 'debug' (though debug is not yet supported).
659 static int parse_config(FILE *f
, struct lxc_conf
*conf
)
664 ret
= fscanf(f
, "%d\n", &version
);
665 if (ret
!= 1 || (version
!= 1 && version
!= 2)) {
666 ERROR("Invalid version.");
669 if (!fgets(line
, 1024, f
)) {
670 ERROR("Invalid config file.");
673 if (version
== 1 && !strstr(line
, "whitelist")) {
674 ERROR("Only whitelist policy is supported.");
678 if (strstr(line
, "debug")) {
679 ERROR("Debug not yet implemented.");
684 return parse_config_v1(f
, conf
);
685 return parse_config_v2(f
, line
, conf
);
689 * use_seccomp: return true if we should try and apply a seccomp policy
690 * if defined for the container.
691 * This will return false if
692 * 1. seccomp is not enabled in the kernel
693 * 2. a seccomp policy is already enabled for this task
695 static bool use_seccomp(void)
697 FILE *f
= fopen("/proc/self/status", "r");
699 bool already_enabled
= false;
706 while (fgets(line
, 1024, f
)) {
707 if (strncmp(line
, "Seccomp:", 8) == 0) {
709 ret
= sscanf(line
+ 8, "%d", &v
);
710 if (ret
== 1 && v
!= 0)
711 already_enabled
= true;
717 if (!found
) { /* no Seccomp line, no seccomp in kernel */
718 INFO("Seccomp is not enabled in the kernel.");
721 if (already_enabled
) { /* already seccomp-confined */
722 INFO("Already seccomp-confined, not loading new policy.");
728 int lxc_read_seccomp_config(struct lxc_conf
*conf
)
732 int check_seccomp_attr_set
;
739 #if HAVE_SCMP_FILTER_CTX
740 /* XXX for debug, pass in SCMP_ACT_TRAP */
741 conf
->seccomp_ctx
= seccomp_init(SCMP_ACT_KILL
);
742 ret
= !conf
->seccomp_ctx
;
744 ret
= seccomp_init(SCMP_ACT_KILL
) < 0;
747 ERROR("Failed initializing seccomp.");
751 /* turn off no-new-privs. We don't want it in lxc, and it breaks
753 #if HAVE_SCMP_FILTER_CTX
754 check_seccomp_attr_set
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0);
756 check_seccomp_attr_set
= seccomp_attr_set(SCMP_FLTATR_CTL_NNP
, 0);
758 if (check_seccomp_attr_set
) {
759 ERROR("Failed to turn off no-new-privs.");
762 #ifdef SCMP_FLTATR_ATL_TSKIP
763 if (seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1)) {
764 WARN("Failed to turn on seccomp nop-skip, continuing");
768 f
= fopen(conf
->seccomp
, "r");
770 SYSERROR("Failed to open seccomp policy file %s.", conf
->seccomp
);
773 ret
= parse_config(f
, conf
);
778 int lxc_seccomp_load(struct lxc_conf
*conf
)
786 #if HAVE_SCMP_FILTER_CTX
791 ERROR("Error loading the seccomp policy: %s.", strerror(-ret
));
795 /* After load seccomp filter into the kernel successfully, export the current seccomp
796 * filter to log file */
797 #if HAVE_SCMP_FILTER_CTX
798 if ((lxc_log_get_level() <= LXC_LOG_LEVEL_TRACE
|| conf
->loglevel
<= LXC_LOG_LEVEL_TRACE
) &&
800 ret
= seccomp_export_pfc(conf
->seccomp_ctx
, lxc_log_fd
);
801 /* Just give an warning when export error */
803 WARN("Failed to export seccomp filter to log file: %s.", strerror(-ret
));
809 void lxc_seccomp_free(struct lxc_conf
*conf
)
812 conf
->seccomp
= NULL
;
813 #if HAVE_SCMP_FILTER_CTX
814 if (conf
->seccomp_ctx
) {
815 seccomp_release(conf
->seccomp_ctx
);
816 conf
->seccomp_ctx
= NULL
;