From: Felix Abecassis Date: Thu, 24 May 2018 05:25:53 +0000 (-0700) Subject: seccomp: fix type mismatch when parsing syscall arguments filters X-Git-Tag: lxc-3.1.0~293^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eacebcc3cb8cf5d29556c85fe826096723475242;p=thirdparty%2Flxc.git seccomp: fix type mismatch when parsing syscall arguments filters 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 --- diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index 98ab5cf26..c7b8c1219 100644 --- a/src/lxc/seccomp.c +++ b/src/lxc/seccomp.c @@ -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"); diff --git a/src/lxc/utils.c b/src/lxc/utils.c index a734b3d6c..2669a4d4b 100644 --- a/src/lxc/utils.c +++ b/src/lxc/utils.c @@ -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; diff --git a/src/lxc/utils.h b/src/lxc/utils.h index 62f087311..dd4510644 100644 --- a/src/lxc/utils.h +++ b/src/lxc/utils.h @@ -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);