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"
38 #define MIPS_ARCH_O32 lxc_seccomp_arch_mipsel
39 #define MIPS_ARCH_N64 lxc_seccomp_arch_mipsel64
41 #define MIPS_ARCH_O32 lxc_seccomp_arch_mips
42 #define MIPS_ARCH_N64 lxc_seccomp_arch_mips64
45 lxc_log_define(lxc_seccomp
, lxc
);
47 static int parse_config_v1(FILE *f
, struct lxc_conf
*conf
)
50 size_t line_bufsz
= 0;
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
;
124 static uint32_t get_v2_action(char *line
, uint32_t def_action
)
129 p
= strchr(line
, ' ');
137 if (!*p
|| *p
== '#')
140 ret
= get_v2_default_action(p
);
151 struct seccomp_v2_rule_args
{
155 enum scmp_compare op
;
158 struct seccomp_v2_rule
{
161 struct seccomp_v2_rule_args args_value
[6];
164 static enum scmp_compare
parse_v2_rule_op(char *s
)
166 if (strcmp(s
, "SCMP_CMP_NE") == 0 || strcmp(s
, "!=") == 0)
168 else if (strcmp(s
, "SCMP_CMP_LT") == 0 || strcmp(s
, "<") == 0)
170 else if (strcmp(s
, "SCMP_CMP_LE") == 0 || strcmp(s
, "<=") == 0)
172 else if (strcmp(s
, "SCMP_CMP_EQ") == 0 || strcmp(s
, "==") == 0)
174 else if (strcmp(s
, "SCMP_CMP_GE") == 0 || strcmp(s
, ">=") == 0)
176 else if (strcmp(s
, "SCMP_CMP_GT") == 0 || strcmp(s
, ">") == 0)
178 else if (strcmp(s
, "SCMP_CMP_MASKED_EQ") == 0 || strcmp(s
, "&=") == 0)
179 return SCMP_CMP_MASKED_EQ
;
181 return _SCMP_CMP_MAX
;
185 * This function is used to parse the args string into the structure.
186 * args string format:[index,value,op,valueTwo] or [index,value,op]
187 * index: the index for syscall arguments (type uint)
188 * value: the value for syscall arguments (type uint64)
189 * op: the operator for syscall arguments(string),
190 a valid list of constants as of libseccomp v2.3.2 is
191 SCMP_CMP_NE,SCMP_CMP_LE,SCMP_CMP_LE, SCMP_CMP_EQ, SCMP_CMP_GE,
192 SCMP_CMP_GT, SCMP_CMP_MASKED_EQ, or !=,<=,==,>=,>,&=
193 * valueTwo: the value for syscall arguments only used for mask eq (type uint64, optional)
194 * Returns 0 on success, < 0 otherwise.
196 static int get_seccomp_arg_value(char *key
, struct seccomp_v2_rule_args
*rule_args
)
200 uint64_t mask
= 0, value
= 0;
201 enum scmp_compare op
= 0;
203 char s
[31] = {0}, v
[24] = {0}, m
[24] = {0};
205 tmp
= strchr(key
, '[');
207 ERROR("Failed to interpret args");
211 ret
= sscanf(tmp
, "[%i,%23[^,],%30[^0-9^,],%23[^,]", &index
, v
, s
, m
);
212 if ((ret
!= 3 && ret
!= 4) || index
>= 6) {
213 ERROR("Failed to interpret args value");
217 ret
= lxc_safe_uint64(v
, &value
);
219 ERROR("Invalid argument value");
223 ret
= lxc_safe_uint64(m
, &mask
);
225 ERROR("Invalid argument mask");
229 op
= parse_v2_rule_op(s
);
230 if (op
== _SCMP_CMP_MAX
) {
231 ERROR("Failed to interpret args operator value");
235 rule_args
->index
= index
;
236 rule_args
->value
= value
;
237 rule_args
->mask
= mask
;
242 /* This function is used to parse the seccomp rule entry.
243 * @line : seccomp rule entry string.
244 * @def_action : default action used in the case if the 'line' contain non valid action.
245 * @rules : output struct.
246 * Returns 0 on success, < 0 otherwise.
248 static int parse_v2_rules(char *line
, uint32_t def_action
,
249 struct seccomp_v2_rule
*rules
)
252 char *key
= NULL
, *saveptr
= NULL
, *tmp
= NULL
;
258 /* read optional action which follows the syscall */
259 rules
->action
= get_v2_action(tmp
, def_action
);
263 if (!strchr(tmp
, '['))
267 for ((key
= strtok_r(tmp
, "]", &saveptr
)), i
= 0; key
&& i
< 6;
268 (key
= strtok_r(NULL
, "]", &saveptr
)), i
++) {
269 ret
= get_seccomp_arg_value(key
, &rules
->args_value
[i
]);
285 #if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
286 enum lxc_hostarch_t
{
287 lxc_seccomp_arch_all
= 0,
288 lxc_seccomp_arch_native
,
289 lxc_seccomp_arch_i386
,
290 lxc_seccomp_arch_x32
,
291 lxc_seccomp_arch_amd64
,
292 lxc_seccomp_arch_arm
,
293 lxc_seccomp_arch_arm64
,
294 lxc_seccomp_arch_ppc64
,
295 lxc_seccomp_arch_ppc64le
,
296 lxc_seccomp_arch_ppc
,
297 lxc_seccomp_arch_mips
,
298 lxc_seccomp_arch_mips64
,
299 lxc_seccomp_arch_mips64n32
,
300 lxc_seccomp_arch_mipsel
,
301 lxc_seccomp_arch_mipsel64
,
302 lxc_seccomp_arch_mipsel64n32
,
303 lxc_seccomp_arch_s390x
,
304 lxc_seccomp_arch_unknown
= 999,
307 int get_hostarch(void)
310 if (uname(&uts
) < 0) {
311 SYSERROR("Failed to read host arch");
315 if (strcmp(uts
.machine
, "i686") == 0)
316 return lxc_seccomp_arch_i386
;
318 else if (strcmp(uts
.machine
, "x86_64") == 0)
319 return lxc_seccomp_arch_amd64
;
320 else if (strncmp(uts
.machine
, "armv7", 5) == 0)
321 return lxc_seccomp_arch_arm
;
322 else if (strncmp(uts
.machine
, "aarch64", 7) == 0)
323 return lxc_seccomp_arch_arm64
;
324 else if (strncmp(uts
.machine
, "ppc64le", 7) == 0)
325 return lxc_seccomp_arch_ppc64le
;
326 else if (strncmp(uts
.machine
, "ppc64", 5) == 0)
327 return lxc_seccomp_arch_ppc64
;
328 else if (strncmp(uts
.machine
, "ppc", 3) == 0)
329 return lxc_seccomp_arch_ppc
;
330 else if (strncmp(uts
.machine
, "mips64", 6) == 0)
331 return MIPS_ARCH_N64
;
332 else if (strncmp(uts
.machine
, "mips", 4) == 0)
333 return MIPS_ARCH_O32
;
334 else if (strncmp(uts
.machine
, "s390x", 5) == 0)
335 return lxc_seccomp_arch_s390x
;
337 return lxc_seccomp_arch_unknown
;
340 scmp_filter_ctx
get_new_ctx(enum lxc_hostarch_t n_arch
,
341 uint32_t default_policy_action
, bool *needs_merge
)
348 case lxc_seccomp_arch_i386
:
349 arch
= SCMP_ARCH_X86
;
351 case lxc_seccomp_arch_x32
:
352 arch
= SCMP_ARCH_X32
;
354 case lxc_seccomp_arch_amd64
:
355 arch
= SCMP_ARCH_X86_64
;
357 case lxc_seccomp_arch_arm
:
358 arch
= SCMP_ARCH_ARM
;
360 #ifdef SCMP_ARCH_AARCH64
361 case lxc_seccomp_arch_arm64
:
362 arch
= SCMP_ARCH_AARCH64
;
365 #ifdef SCMP_ARCH_PPC64LE
366 case lxc_seccomp_arch_ppc64le
:
367 arch
= SCMP_ARCH_PPC64LE
;
370 #ifdef SCMP_ARCH_PPC64
371 case lxc_seccomp_arch_ppc64
:
372 arch
= SCMP_ARCH_PPC64
;
376 case lxc_seccomp_arch_ppc
:
377 arch
= SCMP_ARCH_PPC
;
380 #ifdef SCMP_ARCH_MIPS
381 case lxc_seccomp_arch_mips
:
382 arch
= SCMP_ARCH_MIPS
;
384 case lxc_seccomp_arch_mips64
:
385 arch
= SCMP_ARCH_MIPS64
;
387 case lxc_seccomp_arch_mips64n32
:
388 arch
= SCMP_ARCH_MIPS64N32
;
390 case lxc_seccomp_arch_mipsel
:
391 arch
= SCMP_ARCH_MIPSEL
;
393 case lxc_seccomp_arch_mipsel64
:
394 arch
= SCMP_ARCH_MIPSEL64
;
396 case lxc_seccomp_arch_mipsel64n32
:
397 arch
= SCMP_ARCH_MIPSEL64N32
;
400 #ifdef SCMP_ARCH_S390X
401 case lxc_seccomp_arch_s390x
:
402 arch
= SCMP_ARCH_S390X
;
409 ctx
= seccomp_init(default_policy_action
);
411 ERROR("Error initializing seccomp context");
415 ret
= seccomp_attr_set(ctx
, SCMP_FLTATR_CTL_NNP
, 0);
417 ERROR("%s - Failed to turn off no-new-privs", strerror(-ret
));
418 seccomp_release(ctx
);
422 #ifdef SCMP_FLTATR_ATL_TSKIP
423 ret
= seccomp_attr_set(ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
425 WARN("%s - Failed to turn on seccomp nop-skip, continuing", strerror(-ret
));
428 ret
= seccomp_arch_exist(ctx
, arch
);
430 if (ret
!= -EEXIST
) {
431 ERROR("%s - Failed to determine whether arch %d is "
432 "already present in the main seccomp context",
433 strerror(-ret
), (int)n_arch
);
434 seccomp_release(ctx
);
438 ret
= seccomp_arch_add(ctx
, arch
);
440 ERROR("%s - Failed to add arch %d to main seccomp context",
441 strerror(-ret
), (int)n_arch
);
442 seccomp_release(ctx
);
445 TRACE("Added arch %d to main seccomp context", (int)n_arch
);
447 ret
= seccomp_arch_remove(ctx
, SCMP_ARCH_NATIVE
);
449 ERROR("Failed to remove native arch from main seccomp context");
450 seccomp_release(ctx
);
453 TRACE("Removed native arch from main seccomp context");
457 *needs_merge
= false;
458 TRACE("Arch %d already present in main seccomp context", (int)n_arch
);
464 bool do_resolve_add_rule(uint32_t arch
, char *line
, scmp_filter_ctx ctx
,
465 struct seccomp_v2_rule
*rule
)
468 struct scmp_arg_cmp arg_cmp
[6];
470 ret
= seccomp_arch_exist(ctx
, arch
);
471 if (arch
&& ret
!= 0) {
472 ERROR("%s - Seccomp: rule and context arch do not match (arch %d)", strerror(-ret
), arch
);
476 /*get the syscall name*/
477 char *p
= strchr(line
, ' ');
481 if (strncmp(line
, "reject_force_umount", 19) == 0) {
482 ret
= seccomp_rule_add_exact(ctx
, SCMP_ACT_ERRNO(EACCES
),
483 SCMP_SYS(umount2
), 1,
484 SCMP_A1(SCMP_CMP_MASKED_EQ
, MNT_FORCE
, MNT_FORCE
));
486 ERROR("%s - Failed loading rule to reject force umount", strerror(-ret
));
490 INFO("Set seccomp rule to reject force umounts");
494 nr
= seccomp_syscall_resolve_name(line
);
495 if (nr
== __NR_SCMP_ERROR
) {
496 WARN("Failed to resolve syscall \"%s\"", line
);
497 WARN("This syscall will NOT be blacklisted");
502 WARN("Got negative return value %d for syscall \"%s\"", nr
, line
);
503 WARN("This syscall will NOT be blacklisted");
507 memset(&arg_cmp
, 0, sizeof(arg_cmp
));
508 for (i
= 0; i
< rule
->args_num
; i
++) {
509 INFO("arg_cmp[%d]: SCMP_CMP(%u, %llu, %llu, %llu)", i
,
510 rule
->args_value
[i
].index
,
511 (long long unsigned int)rule
->args_value
[i
].op
,
512 (long long unsigned int)rule
->args_value
[i
].mask
,
513 (long long unsigned int)rule
->args_value
[i
].value
);
515 if (SCMP_CMP_MASKED_EQ
== rule
->args_value
[i
].op
)
516 arg_cmp
[i
] = SCMP_CMP(rule
->args_value
[i
].index
,
517 rule
->args_value
[i
].op
,
518 rule
->args_value
[i
].mask
,
519 rule
->args_value
[i
].value
);
521 arg_cmp
[i
] = SCMP_CMP(rule
->args_value
[i
].index
,
522 rule
->args_value
[i
].op
,
523 rule
->args_value
[i
].value
);
526 ret
= seccomp_rule_add_exact_array(ctx
, rule
->action
, nr
,
527 rule
->args_num
, arg_cmp
);
529 ERROR("%s - Failed loading rule for %s (nr %d action %d (%s))",
530 strerror(-ret
), line
, nr
, rule
->action
,
531 get_action_name(rule
->action
));
552 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
556 enum lxc_hostarch_t cur_rule_arch
, native_arch
;
557 size_t line_bufsz
= 0;
558 bool blacklist
= false;
559 char *rule_line
= NULL
;
560 uint32_t default_policy_action
= -1, default_rule_action
= -1;
561 struct seccomp_v2_rule rule
;
562 struct scmp_ctx_info
{
563 uint32_t architectures
[3];
564 scmp_filter_ctx contexts
[3];
568 if (strncmp(line
, "blacklist", 9) == 0)
570 else if (strncmp(line
, "whitelist", 9) != 0) {
571 ERROR("Bad seccomp policy style \"%s\"", line
);
575 p
= strchr(line
, ' ');
577 default_policy_action
= get_v2_default_action(p
+ 1);
578 if (default_policy_action
== -2)
582 /* for blacklist, allow any syscall which has no rule */
584 if (default_policy_action
== -1)
585 default_policy_action
= SCMP_ACT_ALLOW
;
587 if (default_rule_action
== -1)
588 default_rule_action
= SCMP_ACT_KILL
;
590 if (default_policy_action
== -1)
591 default_policy_action
= SCMP_ACT_KILL
;
593 if (default_rule_action
== -1)
594 default_rule_action
= SCMP_ACT_ALLOW
;
597 memset(&ctx
, 0, sizeof(ctx
));
598 ctx
.architectures
[0] = SCMP_ARCH_NATIVE
;
599 ctx
.architectures
[1] = SCMP_ARCH_NATIVE
;
600 ctx
.architectures
[2] = SCMP_ARCH_NATIVE
;
601 native_arch
= get_hostarch();
602 cur_rule_arch
= native_arch
;
603 if (native_arch
== lxc_seccomp_arch_amd64
) {
604 cur_rule_arch
= lxc_seccomp_arch_all
;
606 ctx
.architectures
[0] = SCMP_ARCH_X86
;
607 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_i386
,
608 default_policy_action
,
609 &ctx
.needs_merge
[0]);
610 if (!ctx
.contexts
[0])
613 ctx
.architectures
[1] = SCMP_ARCH_X32
;
614 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_x32
,
615 default_policy_action
,
616 &ctx
.needs_merge
[1]);
617 if (!ctx
.contexts
[1])
620 ctx
.architectures
[2] = SCMP_ARCH_X86_64
;
621 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_amd64
,
622 default_policy_action
,
623 &ctx
.needs_merge
[2]);
624 if (!ctx
.contexts
[2])
627 } else if (native_arch
== lxc_seccomp_arch_ppc64
) {
628 cur_rule_arch
= lxc_seccomp_arch_all
;
630 ctx
.architectures
[0] = SCMP_ARCH_PPC
;
631 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_ppc
,
632 default_policy_action
,
633 &ctx
.needs_merge
[0]);
634 if (!ctx
.contexts
[0])
637 ctx
.architectures
[2] = SCMP_ARCH_PPC64
;
638 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_ppc64
,
639 default_policy_action
,
640 &ctx
.needs_merge
[2]);
641 if (!ctx
.contexts
[2])
645 } else if (native_arch
== lxc_seccomp_arch_arm64
) {
646 cur_rule_arch
= lxc_seccomp_arch_all
;
648 ctx
.architectures
[0] = SCMP_ARCH_ARM
;
649 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_arm
,
650 default_policy_action
,
651 &ctx
.needs_merge
[0]);
652 if (!ctx
.contexts
[0])
655 #ifdef SCMP_ARCH_AARCH64
656 ctx
.architectures
[2] = SCMP_ARCH_AARCH64
;
657 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_arm64
,
658 default_policy_action
,
659 &ctx
.needs_merge
[2]);
660 if (!ctx
.contexts
[2])
664 #ifdef SCMP_ARCH_MIPS
665 } else if (native_arch
== lxc_seccomp_arch_mips64
) {
666 cur_rule_arch
= lxc_seccomp_arch_all
;
668 ctx
.architectures
[0] = SCMP_ARCH_MIPS
;
669 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_mips
,
670 default_policy_action
,
671 &ctx
.needs_merge
[0]);
672 if (!ctx
.contexts
[0])
675 ctx
.architectures
[1] = SCMP_ARCH_MIPS64N32
;
676 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_mips64n32
,
677 default_policy_action
,
678 &ctx
.needs_merge
[1]);
679 if (!ctx
.contexts
[1])
682 ctx
.architectures
[2] = SCMP_ARCH_MIPS64
;
683 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_mips64
,
684 default_policy_action
,
685 &ctx
.needs_merge
[2]);
686 if (!ctx
.contexts
[2])
688 } else if (native_arch
== lxc_seccomp_arch_mipsel64
) {
689 cur_rule_arch
= lxc_seccomp_arch_all
;
691 ctx
.architectures
[0] = SCMP_ARCH_MIPSEL
;
692 ctx
.contexts
[0] = get_new_ctx(lxc_seccomp_arch_mipsel
,
693 default_policy_action
,
694 &ctx
.needs_merge
[0]);
695 if (!ctx
.contexts
[0])
698 ctx
.architectures
[1] = SCMP_ARCH_MIPSEL64N32
;
699 ctx
.contexts
[1] = get_new_ctx(lxc_seccomp_arch_mipsel64n32
,
700 default_policy_action
,
701 &ctx
.needs_merge
[1]);
702 if (!ctx
.contexts
[1])
705 ctx
.architectures
[2] = SCMP_ARCH_MIPSEL64
;
706 ctx
.contexts
[2] = get_new_ctx(lxc_seccomp_arch_mipsel64
,
707 default_policy_action
,
708 &ctx
.needs_merge
[2]);
709 if (!ctx
.contexts
[2])
714 if (default_policy_action
!= SCMP_ACT_KILL
) {
715 ret
= seccomp_reset(conf
->seccomp_ctx
, default_policy_action
);
717 ERROR("Error re-initializing Seccomp");
721 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0);
723 ERROR("%s - Failed to turn off no-new-privs", strerror(-ret
));
727 #ifdef SCMP_FLTATR_ATL_TSKIP
728 ret
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
730 WARN("%s - Failed to turn on seccomp nop-skip, continuing", strerror(-ret
));
734 while (getline(&rule_line
, &line_bufsz
, f
) != -1) {
741 remove_trailing_newlines(line
);
743 INFO("Processing \"%s\"", line
);
744 if (line
[0] == '[') {
745 /* Read the architecture for next set of rules. */
746 if (strcmp(line
, "[x86]") == 0 ||
747 strcmp(line
, "[X86]") == 0) {
748 if (native_arch
!= lxc_seccomp_arch_i386
&&
749 native_arch
!= lxc_seccomp_arch_amd64
) {
750 cur_rule_arch
= lxc_seccomp_arch_unknown
;
754 cur_rule_arch
= lxc_seccomp_arch_i386
;
755 } else if (strcmp(line
, "[x32]") == 0 ||
756 strcmp(line
, "[X32]") == 0) {
757 if (native_arch
!= lxc_seccomp_arch_amd64
) {
758 cur_rule_arch
= lxc_seccomp_arch_unknown
;
762 cur_rule_arch
= lxc_seccomp_arch_x32
;
763 } else if (strcmp(line
, "[X86_64]") == 0 ||
764 strcmp(line
, "[x86_64]") == 0) {
765 if (native_arch
!= lxc_seccomp_arch_amd64
) {
766 cur_rule_arch
= lxc_seccomp_arch_unknown
;
770 cur_rule_arch
= lxc_seccomp_arch_amd64
;
771 } else if (strcmp(line
, "[all]") == 0 ||
772 strcmp(line
, "[ALL]") == 0) {
773 cur_rule_arch
= lxc_seccomp_arch_all
;
776 else if (strcmp(line
, "[arm]") == 0 ||
777 strcmp(line
, "[ARM]") == 0) {
778 if (native_arch
!= lxc_seccomp_arch_arm
&&
779 native_arch
!= lxc_seccomp_arch_arm64
) {
780 cur_rule_arch
= lxc_seccomp_arch_unknown
;
784 cur_rule_arch
= lxc_seccomp_arch_arm
;
787 #ifdef SCMP_ARCH_AARCH64
788 else if (strcmp(line
, "[arm64]") == 0 ||
789 strcmp(line
, "[ARM64]") == 0) {
790 if (native_arch
!= lxc_seccomp_arch_arm64
) {
791 cur_rule_arch
= lxc_seccomp_arch_unknown
;
795 cur_rule_arch
= lxc_seccomp_arch_arm64
;
798 #ifdef SCMP_ARCH_PPC64LE
799 else if (strcmp(line
, "[ppc64le]") == 0 ||
800 strcmp(line
, "[PPC64LE]") == 0) {
801 if (native_arch
!= lxc_seccomp_arch_ppc64le
) {
802 cur_rule_arch
= lxc_seccomp_arch_unknown
;
806 cur_rule_arch
= lxc_seccomp_arch_ppc64le
;
809 #ifdef SCMP_ARCH_PPC64
810 else if (strcmp(line
, "[ppc64]") == 0 ||
811 strcmp(line
, "[PPC64]") == 0) {
812 if (native_arch
!= lxc_seccomp_arch_ppc64
) {
813 cur_rule_arch
= lxc_seccomp_arch_unknown
;
817 cur_rule_arch
= lxc_seccomp_arch_ppc64
;
821 else if (strcmp(line
, "[ppc]") == 0 ||
822 strcmp(line
, "[PPC]") == 0) {
823 if (native_arch
!= lxc_seccomp_arch_ppc
&&
824 native_arch
!= lxc_seccomp_arch_ppc64
) {
825 cur_rule_arch
= lxc_seccomp_arch_unknown
;
829 cur_rule_arch
= lxc_seccomp_arch_ppc
;
832 #ifdef SCMP_ARCH_MIPS
833 else if (strcmp(line
, "[mips64]") == 0 ||
834 strcmp(line
, "[MIPS64]") == 0) {
835 if (native_arch
!= lxc_seccomp_arch_mips64
) {
836 cur_rule_arch
= lxc_seccomp_arch_unknown
;
840 cur_rule_arch
= lxc_seccomp_arch_mips64
;
841 } else if (strcmp(line
, "[mips64n32]") == 0 ||
842 strcmp(line
, "[MIPS64N32]") == 0) {
843 if (native_arch
!= lxc_seccomp_arch_mips64
) {
844 cur_rule_arch
= lxc_seccomp_arch_unknown
;
848 cur_rule_arch
= lxc_seccomp_arch_mips64n32
;
849 } else if (strcmp(line
, "[mips]") == 0 ||
850 strcmp(line
, "[MIPS]") == 0) {
851 if (native_arch
!= lxc_seccomp_arch_mips
&&
852 native_arch
!= lxc_seccomp_arch_mips64
) {
853 cur_rule_arch
= lxc_seccomp_arch_unknown
;
857 cur_rule_arch
= lxc_seccomp_arch_mips
;
858 } else if (strcmp(line
, "[mipsel64]") == 0 ||
859 strcmp(line
, "[MIPSEL64]") == 0) {
860 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
861 cur_rule_arch
= lxc_seccomp_arch_unknown
;
865 cur_rule_arch
= lxc_seccomp_arch_mipsel64
;
866 } else if (strcmp(line
, "[mipsel64n32]") == 0 ||
867 strcmp(line
, "[MIPSEL64N32]") == 0) {
868 if (native_arch
!= lxc_seccomp_arch_mipsel64
) {
869 cur_rule_arch
= lxc_seccomp_arch_unknown
;
873 cur_rule_arch
= lxc_seccomp_arch_mipsel64n32
;
874 } else if (strcmp(line
, "[mipsel]") == 0 ||
875 strcmp(line
, "[MIPSEL]") == 0) {
876 if (native_arch
!= lxc_seccomp_arch_mipsel
&&
877 native_arch
!= lxc_seccomp_arch_mipsel64
) {
878 cur_rule_arch
= lxc_seccomp_arch_unknown
;
882 cur_rule_arch
= lxc_seccomp_arch_mipsel
;
885 #ifdef SCMP_ARCH_S390X
886 else if (strcmp(line
, "[s390x]") == 0 ||
887 strcmp(line
, "[S390X]") == 0) {
888 if (native_arch
!= lxc_seccomp_arch_s390x
) {
889 cur_rule_arch
= lxc_seccomp_arch_unknown
;
893 cur_rule_arch
= lxc_seccomp_arch_s390x
;
902 /* irrelevant arch - i.e. arm on i386 */
903 if (cur_rule_arch
== lxc_seccomp_arch_unknown
)
906 memset(&rule
, 0, sizeof(rule
));
907 /* read optional action which follows the syscall */
908 ret
= parse_v2_rules(line
, default_rule_action
, &rule
);
910 ERROR("Failed to interpret seccomp rule");
914 if (!do_resolve_add_rule(SCMP_ARCH_NATIVE
, line
,
915 conf
->seccomp_ctx
, &rule
))
918 INFO("Added native rule for arch %d for %s action %d(%s)",
919 SCMP_ARCH_NATIVE
, line
, rule
.action
,
920 get_action_name(rule
.action
));
922 if (ctx
.architectures
[0] != SCMP_ARCH_NATIVE
) {
923 if (!do_resolve_add_rule(ctx
.architectures
[0], line
,
924 ctx
.contexts
[0], &rule
))
927 INFO("Added compat rule for arch %d for %s action %d(%s)",
928 ctx
.architectures
[0], line
, rule
.action
,
929 get_action_name(rule
.action
));
932 if (ctx
.architectures
[1] != SCMP_ARCH_NATIVE
) {
933 if (!do_resolve_add_rule(ctx
.architectures
[1], line
,
934 ctx
.contexts
[1], &rule
))
937 INFO("Added compat rule for arch %d for %s action %d(%s)",
938 ctx
.architectures
[1], line
, rule
.action
,
939 get_action_name(rule
.action
));
942 if (ctx
.architectures
[2] != SCMP_ARCH_NATIVE
) {
943 if (!do_resolve_add_rule(ctx
.architectures
[2], line
,
944 ctx
.contexts
[2], &rule
))
947 INFO("Added native rule for arch %d for %s action %d(%s)",
948 ctx
.architectures
[2], line
, rule
.action
,
949 get_action_name(rule
.action
));
953 INFO("Merging compat seccomp contexts into main context");
954 if (ctx
.contexts
[0]) {
955 if (ctx
.needs_merge
[0]) {
956 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[0]);
958 ERROR("Failed to merge first compat seccomp "
959 "context into main context");
963 TRACE("Merged first compat seccomp context into main context");
965 seccomp_release(ctx
.contexts
[0]);
966 ctx
.contexts
[0] = NULL
;
970 if (ctx
.contexts
[1]) {
971 if (ctx
.needs_merge
[1]) {
972 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[1]);
974 ERROR("Failed to merge first compat seccomp "
975 "context into main context");
979 TRACE("Merged second compat seccomp context into main context");
981 seccomp_release(ctx
.contexts
[1]);
982 ctx
.contexts
[1] = NULL
;
986 if (ctx
.contexts
[2]) {
987 if (ctx
.needs_merge
[2]) {
988 ret
= seccomp_merge(conf
->seccomp_ctx
, ctx
.contexts
[2]);
990 ERROR("Failed to merge third compat seccomp "
991 "context into main context");
995 TRACE("Merged third compat seccomp context into main context");
997 seccomp_release(ctx
.contexts
[2]);
998 ctx
.contexts
[2] = NULL
;
1006 ERROR("Unsupported architecture \"%s\"", line
);
1010 if (ctx
.contexts
[0])
1011 seccomp_release(ctx
.contexts
[0]);
1013 if (ctx
.contexts
[1])
1014 seccomp_release(ctx
.contexts
[1]);
1016 if (ctx
.contexts
[2])
1017 seccomp_release(ctx
.contexts
[2]);
1023 #else /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
1024 static int parse_config_v2(FILE *f
, char *line
, struct lxc_conf
*conf
)
1028 #endif /* HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH */
1031 * The first line of the config file has a policy language version
1032 * the second line has some directives
1033 * then comes policy subject to the directives
1034 * right now version must be '1' or '2'
1035 * the directives must include 'whitelist'(version == 1 or 2) or 'blacklist'
1036 * (version == 2) and can include 'debug' (though debug is not yet supported).
1038 static int parse_config(FILE *f
, struct lxc_conf
*conf
)
1040 char line
[MAXPATHLEN
];
1043 ret
= fscanf(f
, "%d\n", &version
);
1044 if (ret
!= 1 || (version
!= 1 && version
!= 2)) {
1045 ERROR("Invalid version");
1049 if (!fgets(line
, MAXPATHLEN
, f
)) {
1050 ERROR("Invalid config file");
1054 if (version
== 1 && !strstr(line
, "whitelist")) {
1055 ERROR("Only whitelist policy is supported");
1059 if (strstr(line
, "debug")) {
1060 ERROR("Debug not yet implemented");
1065 return parse_config_v1(f
, conf
);
1067 return parse_config_v2(f
, line
, conf
);
1071 * use_seccomp: return true if we should try and apply a seccomp policy
1072 * if defined for the container.
1073 * This will return false if
1074 * 1. seccomp is not enabled in the kernel
1075 * 2. a seccomp policy is already enabled for this task
1077 static bool use_seccomp(void)
1081 size_t line_bufsz
= 0;
1083 bool already_enabled
= false, found
= false;
1085 f
= fopen("/proc/self/status", "r");
1089 while (getline(&line
, &line_bufsz
, f
) != -1) {
1090 if (strncmp(line
, "Seccomp:", 8) == 0) {
1093 ret
= sscanf(line
+ 8, "%d", &v
);
1094 if (ret
== 1 && v
!= 0)
1095 already_enabled
= true;
1104 INFO("Seccomp is not enabled in the kernel");
1108 if (already_enabled
) {
1109 INFO("Already seccomp-confined, not loading new policy");
1116 int lxc_read_seccomp_config(struct lxc_conf
*conf
)
1118 int check_seccomp_attr_set
, ret
;
1127 #if HAVE_SCMP_FILTER_CTX
1128 /* XXX for debug, pass in SCMP_ACT_TRAP */
1129 conf
->seccomp_ctx
= seccomp_init(SCMP_ACT_KILL
);
1130 ret
= !conf
->seccomp_ctx
;
1132 ret
= seccomp_init(SCMP_ACT_KILL
) < 0;
1135 ERROR("Failed initializing seccomp");
1139 /* turn off no-new-privs. We don't want it in lxc, and it breaks
1141 #if HAVE_SCMP_FILTER_CTX
1142 check_seccomp_attr_set
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_CTL_NNP
, 0);
1144 check_seccomp_attr_set
= seccomp_attr_set(SCMP_FLTATR_CTL_NNP
, 0);
1146 if (check_seccomp_attr_set
) {
1147 ERROR("%s - Failed to turn off no-new-privs", strerror(-check_seccomp_attr_set
));
1150 #ifdef SCMP_FLTATR_ATL_TSKIP
1151 check_seccomp_attr_set
= seccomp_attr_set(conf
->seccomp_ctx
, SCMP_FLTATR_ATL_TSKIP
, 1);
1152 if (check_seccomp_attr_set
< 0)
1153 WARN("%s - Failed to turn on seccomp nop-skip, continuing",
1154 strerror(-check_seccomp_attr_set
));
1157 f
= fopen(conf
->seccomp
, "r");
1159 SYSERROR("Failed to open seccomp policy file %s", conf
->seccomp
);
1163 ret
= parse_config(f
, conf
);
1169 int lxc_seccomp_load(struct lxc_conf
*conf
)
1179 #if HAVE_SCMP_FILTER_CTX
1180 ret
= seccomp_load(conf
->seccomp_ctx
);
1182 ret
= seccomp_load();
1185 ERROR("%s- Error loading the seccomp policy", strerror(-ret
));
1189 /* After load seccomp filter into the kernel successfully, export the current seccomp
1190 * filter to log file */
1191 #if HAVE_SCMP_FILTER_CTX
1192 if ((lxc_log_get_level() <= LXC_LOG_LEVEL_TRACE
||
1193 conf
->loglevel
<= LXC_LOG_LEVEL_TRACE
) &&
1195 ret
= seccomp_export_pfc(conf
->seccomp_ctx
, lxc_log_fd
);
1196 /* Just give an warning when export error */
1198 WARN("%s - Failed to export seccomp filter to log file", strerror(-ret
));
1205 void lxc_seccomp_free(struct lxc_conf
*conf
)
1207 free(conf
->seccomp
);
1208 conf
->seccomp
= NULL
;
1210 #if HAVE_SCMP_FILTER_CTX
1211 if (conf
->seccomp_ctx
) {
1212 seccomp_release(conf
->seccomp_ctx
);
1213 conf
->seccomp_ctx
= NULL
;