]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: when parsing resource limits, be more careful with types and corner cases
authorLennart Poettering <lennart@poettering.net>
Tue, 10 Nov 2015 15:10:24 +0000 (16:10 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 10 Nov 2015 16:31:31 +0000 (17:31 +0100)
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

index cb26761b298f59f90219cf54e4ccbb86720f0c78..cdc2ad950d41c66282dc4be1ff4e99011b26005b 100644 (file)
@@ -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;
 }