]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
seccomp: fix type mismatch when parsing syscall arguments filters 2345/head
authorFelix Abecassis <fabecassis@nvidia.com>
Thu, 24 May 2018 05:25:53 +0000 (22:25 -0700)
committerFelix Abecassis <fabecassis@nvidia.com>
Thu, 24 May 2018 05:38:25 +0000 (22:38 -0700)
Specifier %lli was insufficient for the type uint64_t, all values
between 2^63-1 and 2^64-1 were silently converted to 2^63-1.

We can't use %llu since it doesn't handle hexadecimal. Instead, we
parse the values as strings and then use strtoull(3).

Signed-off-by: Felix Abecassis <fabecassis@nvidia.com>
src/lxc/seccomp.c
src/lxc/utils.c
src/lxc/utils.h

index 98ab5cf26422a45deb5ceff3df418f354f6e67bd..c7b8c12199edc7549f6c7d5bf175ba759154413c 100644 (file)
@@ -32,6 +32,7 @@
 #include "config.h"
 #include "log.h"
 #include "lxcseccomp.h"
+#include "utils.h"
 
 lxc_log_define(lxc_seccomp, lxc);
 
@@ -180,7 +181,7 @@ static int get_seccomp_arg_value(char *key, struct v2_rule_args *rule_args)
        uint64_t mask = 0;
        enum scmp_compare op = 0;
        uint32_t index = 0;
-       char s[31] = {0};
+       char s[31] = {0}, v[24] = {0}, m[24] = {0};
        char *tmp = NULL;
 
        tmp = strchr(key, '[');
@@ -188,12 +189,24 @@ static int get_seccomp_arg_value(char *key, struct v2_rule_args *rule_args)
                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(v, &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");
index a734b3d6c48b86a31aebe52d6c7ccb9e6f046b0f..2669a4d4beff218a4e02d3e15f980f3b00fdedd9 100644 (file)
@@ -1958,6 +1958,29 @@ int lxc_safe_ulong(const char *numstr, unsigned long *converted)
        return 0;
 }
 
+int lxc_safe_uint64(const char *numstr, uint64_t *converted)
+{
+       char *err = NULL;
+       uint64_t u;
+
+       while (isspace(*numstr))
+               numstr++;
+
+       if (*numstr == '-')
+               return -EINVAL;
+
+       errno = 0;
+       u = strtoull(numstr, &err, 0);
+       if (errno == ERANGE && u == ULLONG_MAX)
+               return -ERANGE;
+
+       if (err == numstr || *err != '\0')
+               return -EINVAL;
+
+       *converted = u;
+       return 0;
+}
+
 int lxc_safe_int(const char *numstr, int *converted)
 {
        char *err = NULL;
index 62f087311ccfa3b2f747bffe9fe87be3e2c80eb7..dd451064407699f762c1a6ac0088f5e4547ebe22 100644 (file)
@@ -530,6 +530,7 @@ extern int lxc_safe_int(const char *numstr, int *converted);
 extern int lxc_safe_long(const char *numstr, long int *converted);
 extern int lxc_safe_long_long(const char *numstr, long long int *converted);
 extern int lxc_safe_ulong(const char *numstr, unsigned long *converted);
+extern int lxc_safe_uint64(const char *numstr, uint64_t *converted);
 /* Handles B, kb, MB, GB. Detects overflows and reports -ERANGE. */
 extern int parse_byte_size_string(const char *s, int64_t *converted);