]> git.proxmox.com Git - mirror_lxc.git/blobdiff - src/lxc/seccomp.c
seccomp: fix get_seccomp_arg_value()
[mirror_lxc.git] / src / lxc / seccomp.c
index ad13665893fb89c116443092f5a7a4f135ac1276..176964c3a743f917b7a2878264a6fbdbeed06332 100644 (file)
 
 #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)
@@ -75,61 +88,57 @@ 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;
@@ -139,7 +148,7 @@ struct v2_rule_args {
 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)
@@ -162,9 +171,9 @@ 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),
@@ -174,28 +183,39 @@ static enum scmp_compare parse_v2_rule_op(char *s)
  * 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");
@@ -580,19 +600,21 @@ static int parse_config_v2(FILE *f, char *line, struct lxc_conf *conf)
                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;