From d580265eb4bbbafabdb3b7f0b501c0b05b76b2b7 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 10 Nov 2015 16:10:24 +0100 Subject: core: when parsing resource limits, be more careful with types and corner cases Let's not convert RLIM_INFINITY to "unsigned long long" and then back to rlim_t, but let's leave it in the right type right-away. Parse resource limits as 64 bit in all cases, as according to the man page that's what libc does anyway. Make sure setting a resource limit to (uint64_t) -1 results in a parsing error, and isn't implicitly converted to RLIM_INFINITY. --- src/core/load-fragment.c | 75 +++++++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 30 deletions(-) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index cb26761b29..cdc2ad950d 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -1035,19 +1035,21 @@ int config_parse_bounding_set( return 0; } -int config_parse_limit(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { struct rlimit **rl = data; - unsigned long long u; + rlim_t v; + int r; assert(filename); assert(lvalue); @@ -1057,15 +1059,22 @@ int config_parse_limit(const char *unit, rl += ltype; if (streq(rvalue, "infinity")) - u = (unsigned long long) RLIM_INFINITY; + v = RLIM_INFINITY; else { - int r; + uint64_t u; - r = safe_atollu(rvalue, &u); + /* setrlimit(2) suggests rlim_t is always 64bit on Linux. */ + assert_cc(sizeof(rlim_t) == sizeof(uint64_t)); + + r = safe_atou64(rvalue, &u); + if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) + r = -ERANGE; if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); return 0; } + + v = (rlim_t) u; } if (!*rl) { @@ -1074,23 +1083,25 @@ int config_parse_limit(const char *unit, return log_oom(); } - (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u; + (*rl)->rlim_cur = (*rl)->rlim_max = v; return 0; } -int config_parse_bytes_limit(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_bytes_limit( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { struct rlimit **rl = data; - uint64_t bytes; + rlim_t bytes; + int r; assert(filename); assert(lvalue); @@ -1100,15 +1111,19 @@ int config_parse_bytes_limit(const char *unit, rl += ltype; if (streq(rvalue, "infinity")) - bytes = (uint64_t) RLIM_INFINITY; + bytes = RLIM_INFINITY; else { - int r; + uint64_t u; - r = parse_size(rvalue, 1024, &bytes); + r = parse_size(rvalue, 1024, &u); + if (r >= 0 && u >= (uint64_t) RLIM_INFINITY) + r = -ERANGE; if (r < 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse resource value, ignoring: %s", rvalue); return 0; } + + bytes = (rlim_t) u; } if (!*rl) { @@ -1117,7 +1132,7 @@ int config_parse_bytes_limit(const char *unit, return log_oom(); } - (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) bytes; + (*rl)->rlim_cur = (*rl)->rlim_max = bytes; return 0; } -- cgit v1.2.3-54-g00ecf