From 8cbc92d5975b603002c3141364a7709a9c66e23a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Jul 2018 18:50:25 +0200 Subject: parse-util: in parse_permille() check negative earlier If 'v' is negative, it's wrong to add the decimal to it, as we'd actually need to subtract it in this case. But given that we don't want to allow negative vaues anyway, simply check earlier whether what we have parsed so far was negative, and react to that before adding the decimal to it. --- src/basic/parse-util.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index 6becf85878..db38f91c83 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -637,6 +637,8 @@ int parse_permille_unbounded(const char *p) { r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; } else { pc = endswith(p, "%"); if (!pc) @@ -657,15 +659,14 @@ int parse_permille_unbounded(const char *p) { r = safe_atoi(n, &v); if (r < 0) return r; + if (v < 0) + return -ERANGE; if (v > (INT_MAX - q) / 10) return -ERANGE; v = v * 10 + q; } - if (v < 0) - return -ERANGE; - return v; } -- cgit v1.2.1 From f806dfd34595dac8632ba777250323a4735568dc Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 2 Jul 2018 18:52:42 +0200 Subject: tree-wide: increase granularity of percent specifications all over the place to permille We so far had various placed we'd parse percentages with parse_percent(). Let's make them use parse_permille() instead, which is downward compatible (as it also parses percent values), and increases the granularity a bit. Given that on the wire we usually normalize relative specifications to something like UINT32_MAX anyway changing from base-100 to base-1000 calculations can be done easily without breaking compat. This commit doesn't document this change in the man pages. While allowing more precise specifcations permille is not as commonly understood as perent I guess, hence let's keep this out of the docs for now. --- src/core/load-fragment.c | 12 ++++++------ src/login/logind-user.c | 6 +++--- src/login/pam_systemd.c | 4 ++-- src/shared/bus-unit-util.c | 22 ++++++++++++---------- 4 files changed, 23 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 89b7bd8d09..908d16c9f2 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -3013,13 +3013,13 @@ int config_parse_cpu_quota( return 0; } - r = parse_percent_unbounded(rvalue); + r = parse_permille_unbounded(rvalue); if (r <= 0) { log_syntax(unit, LOG_ERR, filename, line, r, "Invalid CPU quota '%s', ignoring.", rvalue); return 0; } - c->cpu_quota_per_sec_usec = ((usec_t) r * USEC_PER_SEC) / 100U; + c->cpu_quota_per_sec_usec = ((usec_t) r * USEC_PER_SEC) / 1000U; return 0; } @@ -3041,7 +3041,7 @@ int config_parse_memory_limit( if (!isempty(rvalue) && !streq(rvalue, "infinity")) { - r = parse_percent(rvalue); + r = parse_permille(rvalue); if (r < 0) { r = parse_size(rvalue, 1024, &bytes); if (r < 0) { @@ -3049,7 +3049,7 @@ int config_parse_memory_limit( return 0; } } else - bytes = physical_memory_scale(r, 100U); + bytes = physical_memory_scale(r, 1000U); if (bytes >= UINT64_MAX || (bytes <= 0 && !streq(lvalue, "MemorySwapMax"))) { @@ -3102,7 +3102,7 @@ int config_parse_tasks_max( return 0; } - r = parse_percent(rvalue); + r = parse_permille(rvalue); if (r < 0) { r = safe_atou64(rvalue, &v); if (r < 0) { @@ -3110,7 +3110,7 @@ int config_parse_tasks_max( return 0; } } else - v = system_tasks_max_scale(r, 100U); + v = system_tasks_max_scale(r, 1000U); if (v <= 0 || v >= UINT64_MAX) { log_syntax(unit, LOG_ERR, filename, line, 0, "Maximum tasks value '%s' out of range, ignoring.", rvalue); diff --git a/src/login/logind-user.c b/src/login/logind-user.c index e18a6f0efe..346f792fb8 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -711,9 +711,9 @@ int config_parse_tmpfs_size( assert(data); /* First, try to parse as percentage */ - r = parse_percent(rvalue); - if (r > 0 && r < 100) - *sz = physical_memory_scale(r, 100U); + r = parse_permille(rvalue); + if (r > 0 && r < 1000) + *sz = physical_memory_scale(r, 1000U); else { uint64_t k; diff --git a/src/login/pam_systemd.c b/src/login/pam_systemd.c index 7037c13cd8..cb1b47e41d 100644 --- a/src/login/pam_systemd.c +++ b/src/login/pam_systemd.c @@ -208,9 +208,9 @@ static int append_session_memory_max(pam_handle_t *handle, sd_bus_message *m, co return r; } } else { - r = parse_percent(limit); + r = parse_permille(limit); if (r >= 0) { - r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U)); + r = sd_bus_message_append(m, "(sv)", "MemoryMaxScale", "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U)); if (r < 0) { pam_syslog(handle, LOG_ERR, "Failed to append to bus message: %s", strerror(-r)); return r; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 8f90f2c31a..c607b5319b 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -422,16 +422,16 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons return 1; } - r = parse_percent(eq); + r = parse_permille(eq); if (r >= 0) { char *n; - /* When this is a percentage we'll convert this into a relative value in the range - * 0…UINT32_MAX and pass it in the MemoryLowScale property (and related - * ones). This way the physical memory size can be determined server-side */ + /* When this is a percentage we'll convert this into a relative value in the range 0…UINT32_MAX + * and pass it in the MemoryLowScale property (and related ones). This way the physical memory + * size can be determined server-side. */ n = strjoina(field, "Scale"); - r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) (((uint64_t) UINT32_MAX * r) / 100U)); + r = sd_bus_message_append(m, "(sv)", n, "u", (uint32_t) (((uint64_t) r * UINT32_MAX) / 1000U)); if (r < 0) return bus_log_create_error(r); @@ -449,13 +449,15 @@ static int bus_append_cgroup_property(sd_bus_message *m, const char *field, cons if (isempty(eq)) r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", USEC_INFINITY); else { - r = parse_percent_unbounded(eq); - if (r <= 0) { - log_error_errno(r, "CPU quota '%s' invalid.", eq); - return -EINVAL; + r = parse_permille_unbounded(eq); + if (r == 0) { + log_error("CPU quota too small."); + return -ERANGE; } + if (r < 0) + return log_error_errno(r, "CPU quota '%s' invalid.", eq); - r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (usec_t) r * USEC_PER_SEC / 100U); + r = sd_bus_message_append(m, "(sv)", "CPUQuotaPerSecUSec", "t", (((uint64_t) r * USEC_PER_SEC) / 1000U)); } if (r < 0) -- cgit v1.2.1