diff --git a/src/lxc/seccomp.c b/src/lxc/seccomp.c index eeb9c8bf3..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); @@ -164,7 +165,6 @@ static enum scmp_compare parse_v2_rule_op(char *s) /* 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), @@ -181,21 +181,32 @@ 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[30] = {0}; + char s[31] = {0}, v[24] = {0}, m[24] = {0}; char *tmp = NULL; - 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(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);