summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2015-11-10 16:10:24 +0100
committerLennart Poettering <lennart@poettering.net>2015-11-10 17:31:31 +0100
commitd580265eb4bbbafabdb3b7f0b501c0b05b76b2b7 (patch)
treee6274430c7edb85a4da57301898c6f1600ec2095
parent65dce26488030eff078c498673d5d93e3c87b6a1 (diff)
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.
-rw-r--r--src/core/load-fragment.c75
1 files 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;
}