#define _GNU_SOURCE
#include <errno.h>
+#include <seccomp.h>
#include <stdio.h>
#include <stdlib.h>
-#include <seccomp.h>
#include <sys/mount.h>
#include <sys/utsname.h>
#include "config.h"
#include "log.h"
#include "lxcseccomp.h"
+#include "utils.h"
lxc_log_define(lxc_seccomp, lxc);
static int parse_config_v1(FILE *f, struct lxc_conf *conf)
{
- char line[1024];
- int ret;
+ int ret = 0;
+ size_t line_bufsz = 0;
+ char *line = NULL;
- while (fgets(line, 1024, f)) {
+ while (getline(&line, &line_bufsz, f) != -1) {
int nr;
+
ret = sscanf(line, "%d", &nr);
if (ret != 1)
return -1;
- ret = seccomp_rule_add(
+
#if HAVE_SCMP_FILTER_CTX
- conf->seccomp_ctx,
+ ret = seccomp_rule_add(conf->seccomp_ctx, SCMP_ACT_ALLOW, nr, 0);
+#else
+ ret = seccomp_rule_add(SCMP_ACT_ALLOW, nr, 0);
#endif
- SCMP_ACT_ALLOW, nr, 0);
if (ret < 0) {
ERROR("Failed loading allow rule for %d", nr);
- return ret;
+ break;
}
}
- return 0;
+ free(line);
+
+ return ret;
}
#if HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH
-static void remove_trailing_newlines(char *l)
+static const char *get_action_name(uint32_t action)
{
- char *p = l;
+ /* The upper 16 bits indicate the type of the seccomp action. */
+ switch (action & 0xffff0000) {
+ case SCMP_ACT_KILL:
+ return "kill";
+ case SCMP_ACT_ALLOW:
+ return "allow";
+ case SCMP_ACT_TRAP:
+ return "trap";
+ case SCMP_ACT_ERRNO(0):
+ return "errno";
+ }
- while (*p)
- p++;
- while (--p >= l && *p == '\n')
- *p = '\0';
+ return "invalid action";
}
static uint32_t get_v2_default_action(char *line)
while (*line == ' ')
line++;
+
/* After 'whitelist' or 'blacklist' comes default behavior. */
- if (strncmp(line, "kill", 4) == 0)
+ if (strncmp(line, "kill", 4) == 0) {
ret_action = SCMP_ACT_KILL;
- else if (strncmp(line, "errno", 5) == 0) {
- int e;
- if (sscanf(line + 5, "%d", &e) != 1) {
- ERROR("Bad errno value in %s", line);
+ } else if (strncmp(line, "errno", 5) == 0) {
+ int e, ret;
+
+ ret = sscanf(line + 5, "%d", &e);
+ if (ret != 1) {
+ ERROR("Failed to parse errno value from %s", line);
return -2;
}
+
ret_action = SCMP_ACT_ERRNO(e);
- } else if (strncmp(line, "allow", 5) == 0)
+ } else if (strncmp(line, "allow", 5) == 0) {
ret_action = SCMP_ACT_ALLOW;
- else if (strncmp(line, "trap", 4) == 0)
+ } else if (strncmp(line, "trap", 4) == 0) {
ret_action = SCMP_ACT_TRAP;
- return ret_action;
-}
-
-static const char *get_action_name(uint32_t action)
-{
- /* The upper 16 bits indicate the type of the seccomp action. */
- switch(action & 0xffff0000){
- case SCMP_ACT_KILL:
- return "kill";
- case SCMP_ACT_ALLOW:
- return "allow";
- case SCMP_ACT_TRAP:
- return "trap";
- case SCMP_ACT_ERRNO(0):
- return "errno";
- default:
- return "invalid action";
}
+
+ return ret_action;
}
static uint32_t get_v2_action(char *line, uint32_t def_action)
{
- char *p = strchr(line, ' ');
+ char *p;
uint32_t ret;
+ p = strchr(line, ' ');
if (!p)
return def_action;
p++;
+
while (*p == ' ')
p++;
+
if (!*p || *p == '#')
return def_action;
+
ret = get_v2_default_action(p);
- switch(ret) {
- case -2: return -1;
- case -1: return def_action;
- default: return ret;
+ switch (ret) {
+ case -2:
+ return -1;
+ case -1:
+ return def_action;
}
+
+ return ret;
}
-struct v2_rule_args {
+struct seccomp_v2_rule_args {
uint32_t index;
uint64_t value;
uint64_t mask;
struct seccomp_v2_rule {
uint32_t action;
uint32_t args_num;
- struct v2_rule_args args_value[6];
+ struct seccomp_v2_rule_args args_value[6];
};
static enum scmp_compare parse_v2_rule_op(char *s)
return _SCMP_CMP_MAX;
}
-/* This function is used to parse the args string into the structure.
+/*
+ * This function is used to parse the args string into the structure.
* args string format:[index,value,op,valueTwo] or [index,value,op]
- * For one arguments, [index,value,valueTwo,op]
* index: the index for syscall arguments (type uint)
* value: the value for syscall arguments (type uint64)
* op: the operator for syscall arguments(string),
* valueTwo: the value for syscall arguments only used for mask eq (type uint64, optional)
* Returns 0 on success, < 0 otherwise.
*/
-static int get_seccomp_arg_value(char *key, struct v2_rule_args *rule_args)
+static int get_seccomp_arg_value(char *key, struct seccomp_v2_rule_args *rule_args)
{
int ret = 0;
- uint64_t value = 0;
- uint64_t mask = 0;
- enum scmp_compare op = 0;
uint32_t index = 0;
- char s[30] = {0};
+ uint64_t mask = 0, value = 0;
+ enum scmp_compare op = 0;
char *tmp = NULL;
+ char s[31] = {0}, v[24] = {0}, m[24] = {0};
- memset(s, 0, sizeof(s));
tmp = strchr(key, '[');
if (!tmp) {
ERROR("Failed to interpret args");
return -1;
}
- ret = sscanf(tmp, "[%i,%lli,%30[^0-9^,],%lli", &index, (long long unsigned int *)&value, s, (long long unsigned int *)&mask);
+
+ ret = sscanf(tmp, "[%i,%23[^,],%30[^0-9^,],%23[^,]", &index, v, s, m);
if ((ret != 3 && ret != 4) || index >= 6) {
ERROR("Failed to interpret args value");
return -1;
}
+ ret = lxc_safe_uint64(v, &value);
+ if (ret < 0) {
+ ERROR("Invalid argument value");
+ return -1;
+ }
+
+ ret = lxc_safe_uint64(m, &mask);
+ if (ret < 0) {
+ ERROR("Invalid argument mask");
+ return -1;
+ }
+
op = parse_v2_rule_op(s);
if (op == _SCMP_CMP_MAX) {
ERROR("Failed to interpret args operator value");
cur_rule_arch = lxc_seccomp_arch_all;
ctx.architectures[0] = SCMP_ARCH_ARM;
- ctx.contexts[0] = get_new_ctx(lxc_seccomp_arch_arm,
- default_policy_action,
- &ctx.needs_merge[0]);
+ ctx.contexts[0] =
+ get_new_ctx(lxc_seccomp_arch_arm, default_policy_action,
+ &ctx.needs_merge[0]);
if (!ctx.contexts[0])
goto bad;
+#ifdef SCMP_ARCH_AARCH64
ctx.architectures[2] = SCMP_ARCH_AARCH64;
- ctx.contexts[2] = get_new_ctx(lxc_seccomp_arch_arm64,
- default_policy_action,
- &ctx.needs_merge[2]);
+ ctx.contexts[2] =
+ get_new_ctx(lxc_seccomp_arch_arm64, default_policy_action,
+ &ctx.needs_merge[2]);
if (!ctx.contexts[2])
goto bad;
#endif
+#endif
#ifdef SCMP_ARCH_MIPS
} else if (native_arch == lxc_seccomp_arch_mips64) {
cur_rule_arch = lxc_seccomp_arch_all;