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
31 #include <sys/mount.h>
32 #include <sys/utsname.h>
36 #include "lxcseccomp.h"
40 #define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel
41 #define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64
43 #define MIPS_ARCH_O32 lxc_seccomp_arch_mips
44 #define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
47 lxc_log_define(seccomp
, lxc
);
49 static int parse_config_v1(FILE *f
, char *line
, size_t *line_bufsz
, struct lxc_conf
*conf
)
53 while (getline(&line
, line_bufsz
, f
) != -1) {
56 ret
= sscanf(line
, "%d", &nr
);
62 #if HAVE_SCMP_FILTER_CTX
63 ret
= seccomp_rule_add(conf
->seccomp_ctx
, SCMP_ACT_ALLOW
, nr
, 0);
65 ret
= seccomp_rule_add(SCMP_ACT_ALLOW
, nr
, 0);
68 ERROR("Failed loading allow rule for %d", nr
);
77 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
78 static const char *get_action_name(uint32_t action
)
80 /* The upper 16 bits indicate the type of the seccomp action. */
81 switch (action
& 0xffff0000) {
88 case SCMP_ACT_ERRNO(0):
92 return "invalid action";
95 static uint32_t get_v2_default_action(char *line
)
97 uint32_t ret_action
= -1;
102 /* After 'whitelist' or 'blacklist' comes default behavior. */
103 if (strncmp(line
, "kill", 4) == 0) {
104 ret_action
= SCMP_ACT_KILL
;
105 } else if (strncmp(line
, "errno", 5) == 0) {
108 ret
= sscanf(line
+ 5, "%d", &e
);
110 ERROR("Failed to parse errno value from %s", line
);
114 ret_action
= SCMP_ACT_ERRNO(e
);
115 } else if (strncmp(line
, "allow", 5) == 0) {
116 ret_action
= SCMP_ACT_ALLOW
;
117 } else if (strncmp(line
, "trap", 4) == 0) {
118 ret_action
= SCMP_ACT_TRAP
;
119 } else if (line
[0]) {
120 ERROR("Unrecognized seccomp action \"%s\"", line
);
127 static uint32_t get_v2_action(char *line
, uint32_t def_action
)
132 p
= strchr(line
, ' ');
140 if (!*p
|| *p
== '#')
143 ret
= get_v2_default_action(p
);
154 struct seccomp_v2_rule_args
{
158 enum scmp_compare op
;
161 struct seccomp_v2_rule
{
164 struct seccomp_v2_rule_args args_value
[6];
167 static enum scmp_compare
parse_v2_rule_op(char *s
)
169 if (strcmp(s
, "SCMP_CMP_NE") == 0 || strcmp(s
, "!=") == 0)
171 else if (strcmp(s
, "SCMP_CMP_LT") == 0 || strcmp(s
, "<") == 0)
173 else if (strcmp(s
, "SCMP_CMP_LE") == 0 || strcmp(s
, "<=") == 0)
175 else if (strcmp(s
, "SCMP_CMP_EQ") == 0 || strcmp(s
, "==") == 0)
177 else if (strcmp(s
, "SCMP_CMP_GE") == 0 || strcmp(s
, ">=") == 0)
179 else if (strcmp(s
, "SCMP_CMP_GT") == 0 || strcmp(s
, ">") == 0)
181 else if (strcmp(s
, "SCMP_CMP_MASKED_EQ") == 0 || strcmp(s
, "&=") == 0)
182 return SCMP_CMP_MASKED_EQ
;
184 return _SCMP_CMP_MAX
;
188 * This function is used to parse the args string into the structure.
189 * args string format:[index,value,op,mask] or [index,value,op]
190 * index: the index for syscall arguments (type uint)
191 * value: the value for syscall arguments (type uint64)
192 * op: the operator for syscall arguments(string),
193 a valid list of constants as of libseccomp v2.3.2 is
194 SCMP_CMP_NE,SCMP_CMP_LE,SCMP_CMP_LE, SCMP_CMP_EQ, SCMP_CMP_GE,
195 SCMP_CMP_GT, SCMP_CMP_MASKED_EQ, or !=,<=,==,>=,>,&=
196 * mask: the mask to apply on "value" for SCMP_CMP_MASKED_EQ (type uint64, optional)
197 * Returns 0 on success, < 0 otherwise.
199 static int get_seccomp_arg_value(char *key
, struct seccomp_v2_rule_args
*rule_args
)
203 uint64_t mask
= 0, value
= 0;
204 enum scmp_compare op
= 0;
206 char s
[31] = {0}, v
[24] = {0}, m
[24] = {'0'};
208 tmp
= strchr(key
, '[');
210 ERROR("Failed to interpret args");
214 ret
= sscanf(tmp
, "[%i,%23[^,],%30[^0-9^,],%23[^,]", &index
, v
, s
, m
);
215 if ((ret
!= 3 && ret
!= 4) || index
>= 6) {
216 ERROR("Failed to interpret args value");
220 ret
= lxc_safe_uint64(v
, &value
, 0);
222 ERROR("Invalid argument value");
226 ret
= lxc_safe_uint64(m
, &mask
, 0);
228 ERROR("Invalid argument mask");
232 op
= parse_v2_rule_op(s
);
233 if (op
== _SCMP_CMP_MAX
) {
234 ERROR("Failed to interpret args operator value");
238 rule_args
->index
= index
;
239 rule_args
->value
= value
;
240 rule_args
->mask
= mask
;
245 /* This function is used to parse the seccomp rule entry.
246 * @line : seccomp rule entry string.
247 * @def_action : default action used in the case if the 'line' contain non valid action.
248 * @rules : output struct.
249 * Returns 0 on success, < 0 otherwise.
251 static int parse_v2_rules(char *line
, uint32_t def_action
,
252 struct seccomp_v2_rule
*rules
)
255 char *key
= NULL
, *saveptr
= NULL
, *tmp
= NULL
;
261 /* read optional action which follows the syscall */
262 rules
->action
= get_v2_action(tmp
, def_action
);
263 if (rules
->action
== -1) {
264 ERROR("Failed to interpret action");
271 if (!strchr(tmp
, '['))
275 for ((key
= strtok_r(tmp
, "]", &saveptr
)), i
= 0; key
&& i
< 6;
276 (key
= strtok_r(NULL
, "]", &saveptr
)), i
++) {
277 ret
= get_seccomp_arg_value(key
, &rules
->args_value
[i
]);
293 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
294 enum lxc_hostarch_t
{
295 lxc_seccomp_arch_all
= 0,
296 lxc_seccomp_arch_native
,
297 lxc_seccomp_arch_i386
,
298 lxc_seccomp_arch_x32
,
299 lxc_seccomp_arch_amd64
,
300 lxc_seccomp_arch_arm
,
301 lxc_seccomp_arch_arm64
,
302 lxc_seccomp_arch_ppc64
,
303 lxc_seccomp_arch_ppc64le
,
304 lxc_seccomp_arch_ppc
,
305 lxc_seccomp_arch_mips
,
306 lxc_seccomp_arch_mips64
,
307 lxc_seccomp_arch_mips64n32
,
308 lxc_seccomp_arch_mipsel
,
309 lxc_seccomp_arch_mipsel64
,
310 lxc_seccomp_arch_mipsel64n32
,
311 lxc_seccomp_arch_s390x
,
312 lxc_seccomp_arch_unknown
= 999,
315 int get_hostarch(void)
318 if (uname(&uts
) < 0) {
319 SYSERROR("Failed to read host arch");
323 if (strcmp(uts
.machine
, "i686") == 0)
324 return lxc_seccomp_arch_i386
;
326 else if (strcmp(uts
.machine
, "x86_64") == 0)
327 return lxc_seccomp_arch_amd64
;
328 else if (strncmp(uts
.machine
, "armv7", 5) == 0)
329 return lxc_seccomp_arch_arm
;
330 else if (strncmp(uts
.machine
, "aarch64", 7) == 0)
331 return lxc_seccomp_arch_arm64
;
332 else if (strncmp(uts
.machine
, "ppc64le", 7) == 0)
333 return lxc_seccomp_arch_ppc64le
;
334 else if (strncmp(uts
.machine
, "ppc64", 5) == 0)
335 return lxc_seccomp_arch_ppc64
;
336 else if (strncmp(uts
.machine
, "ppc", 3) == 0)
337 return lxc_seccomp_arch_ppc
;
338 else if (strncmp(uts
.machine
, "mips64", 6) == 0)
339 return MIPS_ARCH_N64
;
340 else if (strncmp(uts
.machine
, "mips", 4) == 0)
341 return MIPS_ARCH_O32
;
342 else if (strncmp(uts
.machine
, "s390x", 5) == 0)
343 return lxc_seccomp_arch_s390x
;
345 return lxc_seccomp_arch_unknown
;
348 scmp_filter_ctx
get_new_ctx(enum lxc_hostarch_t n_arch
,
349 uint32_t default_policy_action
, bool *needs_merge
)
356 case lxc_seccomp_arch_i386
:
357 arch
= SCMP_ARCH_X86
;
359 case lxc_seccomp_arch_x32
:
360 arch
= SCMP_ARCH_X32
;
362 case lxc_seccomp_arch_amd64
:
363 arch
= SCMP_ARCH_X86_64
;
365 case lxc_seccomp_arch_arm
:
366 arch
= SCMP_ARCH_ARM
;
368 #ifdef SCMP_ARCH_AARCH64
369 case lxc_seccomp_arch_arm64
:
370 arch
= SCMP_ARCH_AARCH64
;
373 #ifdef SCMP_ARCH_PPC64LE
374 case lxc_seccomp_arch_ppc64le
:
375 arch
= SCMP_ARCH_PPC64LE
;
378 #ifdef SCMP_ARCH_PPC64
379 case lxc_seccomp_arch_ppc64
:
380 arch
= SCMP_ARCH_PPC64
;
384 case lxc_seccomp_arch_ppc
:
385 arch
= SCMP_ARCH_PPC
;
388 #ifdef SCMP_ARCH_MIPS
389 case lxc_seccomp_arch_mips
:
390 arch
= SCMP_ARCH_MIPS
;
392 case lxc_seccomp_arch_mips64
:
393 arch
= SCMP_ARCH_MIPS64
;
395 case lxc_seccomp_arch_mips64n32
:
396 arch
= SCMP_ARCH_MIPS64N32
;
398 case lxc_seccomp_arch_mipsel
:
399 arch
= SCMP_ARCH_MIPSEL
;
401 case lxc_seccomp_arch_mipsel64
:
402 arch
= SCMP_ARCH_MIPSEL64
;
404 case lxc_seccomp_arch_mipsel64n32
:
405 arch
= SCMP_ARCH_MIPSEL64N32
;
408 #ifdef SCMP_ARCH_S390X
409 case lxc_seccomp_arch_s390x
:
410 arch
= SCMP_ARCH_S390X
;
417 ctx
= seccomp_init(default_policy_action
);
419 ERROR("Error initializing seccomp context");
423 ret
= seccomp_attr_set(ctx
, SCMP_FLTATR_CTL_NNP
, 0);
426 SYSERROR("Failed to turn off no-new-privs");
427 seccomp_release(ctx
);
431 #ifdef SCMP_FLTATR_ATL_TSKIP
432 ret
= seccomp_attr_set(ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
435 SYSWARN("Failed to turn on seccomp nop-skip, continuing");
439 ret
= seccomp_arch_exist(ctx
, arch
);
441 if (ret
!= -EEXIST
) {
443 SYSERROR("Failed to determine whether arch %d is "
444 "already present in the main seccomp context",
446 seccomp_release(ctx
);
450 ret
= seccomp_arch_add(ctx
, arch
);
453 SYSERROR("Failed to add arch %d to main seccomp context",
455 seccomp_release(ctx
);
458 TRACE("Added arch %d to main seccomp context", (int)n_arch
);
460 ret
= seccomp_arch_remove(ctx
, SCMP_ARCH_NATIVE
);
462 ERROR("Failed to remove native arch from main seccomp context");
463 seccomp_release(ctx
);
466 TRACE("Removed native arch from main seccomp context");
470 *needs_merge
= false;
471 TRACE("Arch %d already present in main seccomp context", (int)n_arch
);
477 bool do_resolve_add_rule(uint32_t arch
, char *line
, scmp_filter_ctx ctx
,
478 struct seccomp_v2_rule
*rule
)
481 struct scmp_arg_cmp arg_cmp
[6];
483 ret
= seccomp_arch_exist(ctx
, arch
);
484 if (arch
&& ret
!= 0) {
486 SYSERROR("Seccomp: rule and context arch do not match (arch %d)", arch
);
490 /*get the syscall name*/
491 char *p
= strchr(line
, ' ');
495 if (strncmp(line
, "reject_force_umount", 19) == 0) {
496 ret
= seccomp_rule_add_exact(ctx
, SCMP_ACT_ERRNO(EACCES
),
497 SCMP_SYS(umount2
), 1,
498 SCMP_A1(SCMP_CMP_MASKED_EQ
, MNT_FORCE
, MNT_FORCE
));
501 SYSERROR("Failed loading rule to reject force umount");
505 INFO("Set seccomp rule to reject force umounts");
509 nr
= seccomp_syscall_resolve_name(line
);
510 if (nr
== __NR_SCMP_ERROR
) {
511 WARN("Failed to resolve syscall \"%s\"", line
);
512 WARN("This syscall will NOT be handled by seccomp");
517 WARN("Got negative return value %d for syscall \"%s\"", nr
, line
);
518 WARN("This syscall will NOT be handled by seccomp");
522 memset(&arg_cmp
, 0, sizeof(arg_cmp
));
523 for (i
= 0; i
< rule
->args_num
; i
++) {
524 INFO("arg_cmp[%d]: SCMP_CMP(%u, %llu, %llu, %llu)", i
,
525 rule
->args_value
[i
].index
,
526 (long long unsigned int)rule
->args_value
[i
].op
,
527 (long long unsigned int)rule
->args_value
[i
].mask
,
528 (long long unsigned int)rule
->args_value
[i
].value
);
530 if (SCMP_CMP_MASKED_EQ
== rule
->args_value
[i
].op
)
531 arg_cmp
[i
] = SCMP_CMP(rule
->args_value
[i
].index
,
532 rule
->args_value
[i
].op
,
533 rule
->args_value
[i
].mask
,
534 rule
->args_value
[i
].value
);
536 arg_cmp
[i
] = SCMP_CMP(rule
->args_value
[i
].index
,
537 rule
->args_value
[i
].op
,
538 rule
->args_value
[i
].value
);
541 ret
= seccomp_rule_add_exact_array(ctx
, rule
->action
, nr
,
542 rule
->args_num
, arg_cmp
);
545 SYSERROR("Failed loading rule for %s (nr %d action %d (%s))",
546 line
, nr
, rule
->action
, get_action_name(rule
->action
));
567 static int parse_config_v2(FILE *f
, char *line
, size_t *line_bufsz
, struct lxc_conf
*conf
)
571 enum lxc_hostarch_t cur_rule_arch
, native_arch
;
572 bool blacklist
= false;
573 uint32_t default_policy_action
= -1, default_rule_action
= -1;
574 struct seccomp_v2_rule rule
;
575 struct scmp_ctx_info
{
576 uint32_t architectures
[3];
577 scmp_filter_ctx contexts
[3];
581 if (strncmp(line
, "blacklist", 9) == 0)
583 else if (strncmp(line
, "whitelist", 9) != 0) {
584 ERROR("Bad seccomp policy style \"%s\"", line
);
588 p
= strchr(line
, ' ');
590 default_policy_action
= get_v2_default_action(p
+ 1);
591 if (default_policy_action
== -2)
595 /* for blacklist, allow any syscall which has no rule */
597 if (default_policy_action
== -1)
598 default_policy_action
= SCMP_ACT_ALLOW
;
600 if (default_rule_action
== -1)
601 default_rule_action
= SCMP_ACT_KILL
;
603 if (default_policy_action
== -1)
604 default_policy_action
= SCMP_ACT_KILL
;
606 if (default_rule_action
== -1)
607 default_rule_action
= SCMP_ACT_ALLOW
;
610 memset(&ctx
, 0, sizeof(ctx
));
611 ctx
.architectures
[0] = SCMP_ARCH_NATIVE
;
612 ctx
.architectures
[1] = SCMP_ARCH_NATIVE
;
613 ctx
.architectures
[2] = SCMP_ARCH_NATIVE
;
614 native_arch
= get_hostarch();
615 cur_rule_arch
= native_arch
;
616 if (native_arch
== lxc_seccomp_arch_amd64
) {
617 cur_rule_arch
= lxc_seccomp_arch_all
;
619 ctx
.architectures
[0] = SCMP_ARCH_X86
;
620 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_i386
,
621 default_policy_action
,
622 &ctx
.needs_merge
[0]);
623 if (!ctx
.contexts
[0])
626 ctx
.architectures
[1] = SCMP_ARCH_X32
;
627 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_x32
,
628 default_policy_action
,
629 &ctx
.needs_merge
[1]);
630 if (!ctx
.contexts
[1])
633 ctx
.architectures
[2] = SCMP_ARCH_X86_64
;
634 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_amd64
,
635 default_policy_action
,
636 &ctx
.needs_merge
[2]);
637 if (!ctx
.contexts
[2])
640 } else if (native_arch
== lxc_seccomp_arch_ppc64
) {
641 cur_rule_arch
= lxc_seccomp_arch_all
;
643 ctx
.architectures
[0] = SCMP_ARCH_PPC
;
644 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_ppc
,
645 default_policy_action
,
646 &ctx
.needs_merge
[0]);
647 if (!ctx
.contexts
[0])
650 ctx
.architectures
[2] = SCMP_ARCH_PPC64
;
651 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_ppc64
,
652 default_policy_action
,
653 &ctx
.needs_merge
[2]);
654 if (!ctx
.contexts
[2])
658 } else if (native_arch
== lxc_seccomp_arch_arm64
) {
659 cur_rule_arch
= lxc_seccomp_arch_all
;
661 ctx
.architectures
[0] = SCMP_ARCH_ARM
;
662 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_arm
,
663 default_policy_action
,
664 &ctx
.needs_merge
[0]);
665 if (!ctx
.contexts
[0])
668 #ifdef SCMP_ARCH_AARCH64
669 ctx
.architectures
[2] = SCMP_ARCH_AARCH64
;
670 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_arm64
,
671 default_policy_action
,
672 &ctx
.needs_merge
[2]);
673 if (!ctx
.contexts
[2])
677 #ifdef SCMP_ARCH_MIPS
678 } else if (native_arch
== lxc_seccomp_arch_mips64
) {
679 cur_rule_arch
= lxc_seccomp_arch_all
;
681 ctx
.architectures
[0] = SCMP_ARCH_MIPS
;
682 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_mips
,
683 default_policy_action
,
684 &ctx
.needs_merge
[0]);
685 if (!ctx
.contexts
[0])
688 ctx
.architectures
[1] = SCMP_ARCH_MIPS64N32
;
689 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_mips64n32
,
690 default_policy_action
,
691 &ctx
.needs_merge
[1]);
692 if (!ctx
.contexts
[1])
695 ctx
.architectures
[2] = SCMP_ARCH_MIPS64
;
696 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_mips64
,
697 default_policy_action
,
698 &ctx
.needs_merge
[2]);
699 if (!ctx
.contexts
[2])
701 } else if (native_arch
== lxc_seccomp_arch_mipsel64
) {
702 cur_rule_arch
= lxc_seccomp_arch_all
;
704 ctx
.architectures
[0] = SCMP_ARCH_MIPSEL
;
705 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_mipsel
,
706 default_policy_action
,
707 &ctx
.needs_merge
[0]);
708 if (!ctx
.contexts
[0])
711 ctx
.architectures
[1] = SCMP_ARCH_MIPSEL64N32
;
712 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32
,
713 default_policy_action
,
714 &ctx
.needs_merge
[1]);
715 if (!ctx
.contexts
[1])
718 ctx
.architectures
[2] = SCMP_ARCH_MIPSEL64
;
719 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_mipsel64
,
720 default_policy_action
,
721 &ctx
.needs_merge
[2]);
722 if (!ctx
.contexts
[2])
727 if (default_policy_action
!= SCMP_ACT_KILL
) {
728 ret
= seccomp_reset(conf
->seccomp_ctx
, default_policy_action
);
730 ERROR("Error re-initializing Seccomp");
734 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0);
737 SYSERROR("Failed to turn off no-new-privs");
741 #ifdef SCMP_FLTATR_ATL_TSKIP
742 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
745 SYSWARN("Failed to turn on seccomp nop-skip, continuing");
750 while (getline(&line
, line_bufsz
, f
) != -1) {
757 remove_trailing_newlines(line
);
759 INFO("Processing \"%s\"", line
);
760 if (line
[0] == '[') {
761 /* Read the architecture for next set of rules. */
762 if (strcmp(line
, "[x86]") == 0 ||
763 strcmp(line
, "[X86]") == 0) {
764 if (native_arch
!= lxc_seccomp_arch_i386
&&
765 native_arch
!= lxc_seccomp_arch_amd64
) {
766 cur_rule_arch
= lxc_seccomp_arch_unknown
;
770 cur_rule_arch
= lxc_seccomp_arch_i386
;
771 } else if (strcmp(line
, "[x32]") == 0 ||
772 strcmp(line
, "[X32]") == 0) {
773 if (native_arch
!= lxc_seccomp_arch_amd64
) {
774 cur_rule_arch
= lxc_seccomp_arch_unknown
;
778 cur_rule_arch
= lxc_seccomp_arch_x32
;
779 } else if (strcmp(line
, "[X86_64]") == 0 ||
780 strcmp(line
, "[x86_64]") == 0) {
781 if (native_arch
!= lxc_seccomp_arch_amd64
) {
782 cur_rule_arch
= lxc_seccomp_arch_unknown
;
786 cur_rule_arch
= lxc_seccomp_arch_amd64
;
787 } else if (strcmp(line
, "[all]") == 0 ||
788 strcmp(line
, "[ALL]") == 0) {
789 cur_rule_arch
= lxc_seccomp_arch_all
;
792 else if (strcmp(line
, "[arm]") == 0 ||
793 strcmp(line
, "[ARM]") == 0) {
794 if (native_arch
!= lxc_seccomp_arch_arm
&&
795 native_arch
!= lxc_seccomp_arch_arm64
) {
796 cur_rule_arch
= lxc_seccomp_arch_unknown
;
800 cur_rule_arch
= lxc_seccomp_arch_arm
;
803 #ifdef SCMP_ARCH_AARCH64
804 else if (strcmp(line
, "[arm64]") == 0 ||
805 strcmp(line
, "[ARM64]") == 0) {
806 if (native_arch
!= lxc_seccomp_arch_arm64
) {
807 cur_rule_arch
= lxc_seccomp_arch_unknown
;
811 cur_rule_arch
= lxc_seccomp_arch_arm64
;
814 #ifdef SCMP_ARCH_PPC64LE
815 else if (strcmp(line
, "[ppc64le]") == 0 ||
816 strcmp(line
, "[PPC64LE]") == 0) {
817 if (native_arch
!= lxc_seccomp_arch_ppc64le
) {
818 cur_rule_arch
= lxc_seccomp_arch_unknown
;
822 cur_rule_arch
= lxc_seccomp_arch_ppc64le
;
825 #ifdef SCMP_ARCH_PPC64
826 else if (strcmp(line
, "[ppc64]") == 0 ||
827 strcmp(line
, "[PPC64]") == 0) {
828 if (native_arch
!= lxc_seccomp_arch_ppc64
) {
829 cur_rule_arch
= lxc_seccomp_arch_unknown
;
833 cur_rule_arch
= lxc_seccomp_arch_ppc64
;
837 else if (strcmp(line
, "[ppc]") == 0 ||
838 strcmp(line
, "[PPC]") == 0) {
839 if (native_arch
!= lxc_seccomp_arch_ppc
&&
840 native_arch
!= lxc_seccomp_arch_ppc64
) {
841 cur_rule_arch
= lxc_seccomp_arch_unknown
;
845 cur_rule_arch
= lxc_seccomp_arch_ppc
;
848 #ifdef SCMP_ARCH_MIPS
849 else if (strcmp(line
, "[mips64]") == 0 ||
850 strcmp(line
, "[MIPS64]") == 0) {
851 if (native_arch
!= lxc_seccomp_arch_mips64
) {
852 cur_rule_arch
= lxc_seccomp_arch_unknown
;
856 cur_rule_arch
= lxc_seccomp_arch_mips64
;
857 } else if (strcmp(line
, "[mips64n32]") == 0 ||
858 strcmp(line
, "[MIPS64N32]") == 0) {
859 if (native_arch
!= lxc_seccomp_arch_mips64
) {
860 cur_rule_arch
= lxc_seccomp_arch_unknown
;
864 cur_rule_arch
= lxc_seccomp_arch_mips64n32
;
865 } else if (strcmp(line
, "[mips]") == 0 ||
866 strcmp(line
, "[MIPS]") == 0) {
867 if (native_arch
!= lxc_seccomp_arch_mips
&&
868 native_arch
!= lxc_seccomp_arch_mips64
) {
869 cur_rule_arch
= lxc_seccomp_arch_unknown
;
873 cur_rule_arch
= lxc_seccomp_arch_mips
;
874 } else if (strcmp(line
, "[mipsel64]") == 0 ||
875 strcmp(line
, "[MIPSEL64]") == 0) {
876 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
877 cur_rule_arch
= lxc_seccomp_arch_unknown
;
881 cur_rule_arch
= lxc_seccomp_arch_mipsel64
;
882 } else if (strcmp(line
, "[mipsel64n32]") == 0 ||
883 strcmp(line
, "[MIPSEL64N32]") == 0) {
884 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
885 cur_rule_arch
= lxc_seccomp_arch_unknown
;
889 cur_rule_arch
= lxc_seccomp_arch_mipsel64n32
;
890 } else if (strcmp(line
, "[mipsel]") == 0 ||
891 strcmp(line
, "[MIPSEL]") == 0) {
892 if (native_arch
!= lxc_seccomp_arch_mipsel
&&
893 native_arch
!= lxc_seccomp_arch_mipsel64
) {
894 cur_rule_arch
= lxc_seccomp_arch_unknown
;
898 cur_rule_arch
= lxc_seccomp_arch_mipsel
;
901 #ifdef SCMP_ARCH_S390X
902 else if (strcmp(line
, "[s390x]") == 0 ||
903 strcmp(line
, "[S390X]") == 0) {
904 if (native_arch
!= lxc_seccomp_arch_s390x
) {
905 cur_rule_arch
= lxc_seccomp_arch_unknown
;
909 cur_rule_arch
= lxc_seccomp_arch_s390x
;
919 /* irrelevant arch - i.e. arm on i386 */
920 if (cur_rule_arch
== lxc_seccomp_arch_unknown
)
923 memset(&rule
, 0, sizeof(rule
));
924 /* read optional action which follows the syscall */
925 ret
= parse_v2_rules(line
, default_rule_action
, &rule
);
927 ERROR("Failed to interpret seccomp rule");
931 if (!do_resolve_add_rule(SCMP_ARCH_NATIVE
, line
,
932 conf
->seccomp_ctx
, &rule
))
935 INFO("Added native rule for arch %d for %s action %d(%s)",
936 SCMP_ARCH_NATIVE
, line
, rule
.action
,
937 get_action_name(rule
.action
));
939 if (ctx
.architectures
[0] != SCMP_ARCH_NATIVE
) {
940 if (!do_resolve_add_rule(ctx
.architectures
[0], line
,
941 ctx
.contexts
[0], &rule
))
944 INFO("Added compat rule for arch %d for %s action %d(%s)",
945 ctx
.architectures
[0], line
, rule
.action
,
946 get_action_name(rule
.action
));
949 if (ctx
.architectures
[1] != SCMP_ARCH_NATIVE
) {
950 if (!do_resolve_add_rule(ctx
.architectures
[1], line
,
951 ctx
.contexts
[1], &rule
))
954 INFO("Added compat rule for arch %d for %s action %d(%s)",
955 ctx
.architectures
[1], line
, rule
.action
,
956 get_action_name(rule
.action
));
959 if (ctx
.architectures
[2] != SCMP_ARCH_NATIVE
) {
960 if (!do_resolve_add_rule(ctx
.architectures
[2], line
,
961 ctx
.contexts
[2], &rule
))
964 INFO("Added native rule for arch %d for %s action %d(%s)",
965 ctx
.architectures
[2], line
, rule
.action
,
966 get_action_name(rule
.action
));
970 INFO("Merging compat seccomp contexts into main context");
971 if (ctx
.contexts
[0]) {
972 if (ctx
.needs_merge
[0]) {
973 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[0]);
975 ERROR("Failed to merge first compat seccomp "
976 "context into main context");
980 TRACE("Merged first compat seccomp context into main context");
982 seccomp_release(ctx
.contexts
[0]);
983 ctx
.contexts
[0] = NULL
;
987 if (ctx
.contexts
[1]) {
988 if (ctx
.needs_merge
[1]) {
989 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[1]);
991 ERROR("Failed to merge first compat seccomp "
992 "context into main context");
996 TRACE("Merged second compat seccomp context into main context");
998 seccomp_release(ctx
.contexts
[1]);
999 ctx
.contexts
[1] = NULL
;
1003 if (ctx
.contexts
[2]) {
1004 if (ctx
.needs_merge
[2]) {
1005 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[2]);
1007 ERROR("Failed to merge third compat seccomp "
1008 "context into main context");
1012 TRACE("Merged third compat seccomp context into main context");
1014 seccomp_release(ctx
.contexts
[2]);
1015 ctx
.contexts
[2] = NULL
;
1023 ERROR("Unsupported architecture \"%s\"", line
);
1027 if (ctx
.contexts
[0])
1028 seccomp_release(ctx
.contexts
[0]);
1030 if (ctx
.contexts
[1])
1031 seccomp_release(ctx
.contexts
[1]);
1033 if (ctx
.contexts
[2])
1034 seccomp_release(ctx
.contexts
[2]);
1040 #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
1041 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
1045 #endif /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
1048 * The first line of the config file has a policy language version
1049 * the second line has some directives
1050 * then comes policy subject to the directives
1051 * right now version must be '1' or '2'
1052 * the directives must include 'whitelist'(version == 1 or 2) or 'blacklist'
1053 * (version == 2) and can include 'debug' (though debug is not yet supported).
1055 static int parse_config(FILE *f
, struct lxc_conf
*conf
)
1058 size_t line_bufsz
= 0;
1061 ret
= fscanf(f
, "%d\n", &version
);
1062 if (ret
!= 1 || (version
!= 1 && version
!= 2)) {
1063 ERROR("Invalid version");
1067 if (getline(&line
, &line_bufsz
, f
) == -1) {
1068 ERROR("Invalid config file");
1072 if (version
== 1 && !strstr(line
, "whitelist")) {
1073 ERROR("Only whitelist policy is supported");
1077 if (strstr(line
, "debug")) {
1078 ERROR("Debug not yet implemented");
1083 return parse_config_v1(f
, line
, &line_bufsz
, conf
);
1085 return parse_config_v2(f
, line
, &line_bufsz
, conf
);
1093 * use_seccomp: return true if we should try and apply a seccomp policy
1094 * if defined for the container.
1095 * This will return false if
1096 * 1. seccomp is not enabled in the kernel
1097 * 2. a seccomp policy is already enabled for this task
1099 static bool use_seccomp(void)
1103 size_t line_bufsz
= 0;
1105 bool already_enabled
= false, found
= false;
1107 f
= fopen("/proc/self/status", "r");
1111 while (getline(&line
, &line_bufsz
, f
) != -1) {
1112 if (strncmp(line
, "Seccomp:", 8) == 0) {
1115 ret
= sscanf(line
+ 8, "%d", &v
);
1116 if (ret
== 1 && v
!= 0)
1117 already_enabled
= true;
1126 INFO("Seccomp is not enabled in the kernel");
1130 if (already_enabled
) {
1131 INFO("Already seccomp-confined, not loading new policy");
1138 int lxc_read_seccomp_config(struct lxc_conf
*conf
)
1149 #if HAVE_SCMP_FILTER_CTX
1150 /* XXX for debug, pass in SCMP_ACT_TRAP */
1151 conf
->seccomp_ctx
= seccomp_init(SCMP_ACT_KILL
);
1152 ret
= !conf
->seccomp_ctx
;
1154 ret
= seccomp_init(SCMP_ACT_KILL
) < 0;
1157 ERROR("Failed initializing seccomp");
1161 /* turn off no-new-privs. We don't want it in lxc, and it breaks
1163 #if HAVE_SCMP_FILTER_CTX
1164 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0);
1166 ret
= seccomp_attr_set(SCMP_FLTATR_CTL_NNP
, 0);
1170 SYSERROR("Failed to turn off no-new-privs");
1174 #ifdef SCMP_FLTATR_ATL_TSKIP
1175 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
1178 SYSWARN("Failed to turn on seccomp nop-skip, continuing");
1182 f
= fopen(conf
->seccomp
, "r");
1184 SYSERROR("Failed to open seccomp policy file %s", conf
->seccomp
);
1188 ret
= parse_config(f
, conf
);
1194 int lxc_seccomp_load(struct lxc_conf
*conf
)
1204 #if HAVE_SCMP_FILTER_CTX
1205 ret
= seccomp_load(conf
->seccomp_ctx
);
1207 ret
= seccomp_load();
1211 SYSERROR("Error loading the seccomp policy");
1215 /* After load seccomp filter into the kernel successfully, export the current seccomp
1216 * filter to log file */
1217 #if HAVE_SCMP_FILTER_CTX
1218 if ((lxc_log_get_level() <= LXC_LOG_LEVEL_TRACE
||
1219 conf
->loglevel
<= LXC_LOG_LEVEL_TRACE
) &&
1221 ret
= seccomp_export_pfc(conf
->seccomp_ctx
, lxc_log_fd
);
1222 /* Just give an warning when export error */
1225 SYSWARN("Failed to export seccomp filter to log file");
1233 void lxc_seccomp_free(struct lxc_conf
*conf
)
1235 free(conf
->seccomp
);
1236 conf
->seccomp
= NULL
;
1238 #if HAVE_SCMP_FILTER_CTX
1239 if (conf
->seccomp_ctx
) {
1240 seccomp_release(conf
->seccomp_ctx
);
1241 conf
->seccomp_ctx
= NULL
;