diff options
-rw-r--r-- | src/basic/rlimit-util.c | 48 | ||||
-rw-r--r-- | src/basic/rlimit-util.h | 1 | ||||
-rw-r--r-- | src/core/dbus-execute.c | 114 | ||||
-rw-r--r-- | src/core/execute.c | 6 | ||||
-rw-r--r-- | src/shared/bus-unit-util.c | 37 | ||||
-rw-r--r-- | src/shared/bus-util.c | 18 | ||||
-rw-r--r-- | src/test/test-rlimit-util.c | 36 |
7 files changed, 161 insertions, 99 deletions
diff --git a/src/basic/rlimit-util.c b/src/basic/rlimit-util.c index d371f0a550..154b34b8c1 100644 --- a/src/basic/rlimit-util.c +++ b/src/basic/rlimit-util.c @@ -289,22 +289,38 @@ int rlimit_format(const struct rlimit *rl, char **ret) { } static const char* const rlimit_table[_RLIMIT_MAX] = { - [RLIMIT_CPU] = "LimitCPU", - [RLIMIT_FSIZE] = "LimitFSIZE", - [RLIMIT_DATA] = "LimitDATA", - [RLIMIT_STACK] = "LimitSTACK", - [RLIMIT_CORE] = "LimitCORE", - [RLIMIT_RSS] = "LimitRSS", - [RLIMIT_NOFILE] = "LimitNOFILE", - [RLIMIT_AS] = "LimitAS", - [RLIMIT_NPROC] = "LimitNPROC", - [RLIMIT_MEMLOCK] = "LimitMEMLOCK", - [RLIMIT_LOCKS] = "LimitLOCKS", - [RLIMIT_SIGPENDING] = "LimitSIGPENDING", - [RLIMIT_MSGQUEUE] = "LimitMSGQUEUE", - [RLIMIT_NICE] = "LimitNICE", - [RLIMIT_RTPRIO] = "LimitRTPRIO", - [RLIMIT_RTTIME] = "LimitRTTIME" + [RLIMIT_AS] = "AS", + [RLIMIT_CORE] = "CORE", + [RLIMIT_CPU] = "CPU", + [RLIMIT_DATA] = "DATA", + [RLIMIT_FSIZE] = "FSIZE", + [RLIMIT_LOCKS] = "LOCKS", + [RLIMIT_MEMLOCK] = "MEMLOCK", + [RLIMIT_MSGQUEUE] = "MSGQUEUE", + [RLIMIT_NICE] = "NICE", + [RLIMIT_NOFILE] = "NOFILE", + [RLIMIT_NPROC] = "NPROC", + [RLIMIT_RSS] = "RSS", + [RLIMIT_RTPRIO] = "RTPRIO", + [RLIMIT_RTTIME] = "RTTIME", + [RLIMIT_SIGPENDING] = "SIGPENDING", + [RLIMIT_STACK] = "STACK", }; DEFINE_STRING_TABLE_LOOKUP(rlimit, int); + +int rlimit_from_string_harder(const char *s) { + const char *suffix; + + /* The official prefix */ + suffix = startswith(s, "RLIMIT_"); + if (suffix) + return rlimit_from_string(suffix); + + /* Our own unit file setting prefix */ + suffix = startswith(s, "Limit"); + if (suffix) + return rlimit_from_string(suffix); + + return rlimit_from_string(s); +} diff --git a/src/basic/rlimit-util.h b/src/basic/rlimit-util.h index 3766f78d58..42f2e0e547 100644 --- a/src/basic/rlimit-util.h +++ b/src/basic/rlimit-util.h @@ -13,6 +13,7 @@ const char *rlimit_to_string(int i) _const_; int rlimit_from_string(const char *s) _pure_; +int rlimit_from_string_harder(const char *s) _pure_; int setrlimit_closest(int resource, const struct rlimit *rlim); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 3b1c77e967..143fca71b0 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -1091,8 +1091,8 @@ int bus_exec_context_set_transient_property( UnitWriteFlags flags, sd_bus_error *error) { - const char *soft = NULL; - int r, ri; + const char *suffix; + int r; assert(u); assert(c); @@ -2313,73 +2313,77 @@ int bus_exec_context_set_transient_property( } return 1; - } - ri = rlimit_from_string(name); - if (ri < 0) { - soft = endswith(name, "Soft"); - if (soft) { - const char *n; + } else if ((suffix = startswith(name, "Limit"))) { + const char *soft = NULL; + int ri; - n = strndupa(name, soft - name); - ri = rlimit_from_string(n); - if (ri >= 0) - name = n; + ri = rlimit_from_string(suffix); + if (ri < 0) { + soft = endswith(suffix, "Soft"); + if (soft) { + const char *n; + n = strndupa(suffix, soft - suffix); + ri = rlimit_from_string(n); + if (ri >= 0) + name = strjoina("Limit", n); + } } - } - - if (ri >= 0) { - uint64_t rl; - rlim_t x; - - r = sd_bus_message_read(message, "t", &rl); - if (r < 0) - return r; - - if (rl == (uint64_t) -1) - x = RLIM_INFINITY; - else { - x = (rlim_t) rl; - if ((uint64_t) x != rl) - return -ERANGE; - } + if (ri >= 0) { + uint64_t rl; + rlim_t x; - if (!UNIT_WRITE_FLAGS_NOOP(flags)) { - _cleanup_free_ char *f = NULL; - struct rlimit nl; - - if (c->rlimit[ri]) { - nl = *c->rlimit[ri]; - - if (soft) - nl.rlim_cur = x; - else - nl.rlim_max = x; - } else - /* When the resource limit is not initialized yet, then assign the value to both fields */ - nl = (struct rlimit) { - .rlim_cur = x, - .rlim_max = x, - }; - - r = rlimit_format(&nl, &f); + r = sd_bus_message_read(message, "t", &rl); if (r < 0) return r; - if (c->rlimit[ri]) - *c->rlimit[ri] = nl; + if (rl == (uint64_t) -1) + x = RLIM_INFINITY; else { - c->rlimit[ri] = newdup(struct rlimit, &nl, 1); - if (!c->rlimit[ri]) - return -ENOMEM; + x = (rlim_t) rl; + + if ((uint64_t) x != rl) + return -ERANGE; } - unit_write_settingf(u, flags, name, "%s=%s", name, f); + if (!UNIT_WRITE_FLAGS_NOOP(flags)) { + _cleanup_free_ char *f = NULL; + struct rlimit nl; + + if (c->rlimit[ri]) { + nl = *c->rlimit[ri]; + + if (soft) + nl.rlim_cur = x; + else + nl.rlim_max = x; + } else + /* When the resource limit is not initialized yet, then assign the value to both fields */ + nl = (struct rlimit) { + .rlim_cur = x, + .rlim_max = x, + }; + + r = rlimit_format(&nl, &f); + if (r < 0) + return r; + + if (c->rlimit[ri]) + *c->rlimit[ri] = nl; + else { + c->rlimit[ri] = newdup(struct rlimit, &nl, 1); + if (!c->rlimit[ri]) + return -ENOMEM; + } + + unit_write_settingf(u, flags, name, "%s=%s", name, f); + } + + return 1; } - return 1; } return 0; diff --git a/src/core/execute.c b/src/core/execute.c index fca20c5567..d60e8f6a1a 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -3176,7 +3176,7 @@ static int exec_child( r = setrlimit_closest(i, context->rlimit[i]); if (r < 0) { *exit_status = EXIT_LIMITS; - return log_unit_error_errno(unit, r, "Failed to adjust resource limit %s: %m", rlimit_to_string(i)); + return log_unit_error_errno(unit, r, "Failed to adjust resource limit RLIMIT_%s: %m", rlimit_to_string(i)); } } @@ -3975,9 +3975,9 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) { for (i = 0; i < RLIM_NLIMITS; i++) if (c->rlimit[i]) { - fprintf(f, "%s%s: " RLIM_FMT "\n", + fprintf(f, "Limit%s%s: " RLIM_FMT "\n", prefix, rlimit_to_string(i), c->rlimit[i]->rlim_max); - fprintf(f, "%s%sSoft: " RLIM_FMT "\n", + fprintf(f, "Limit%s%sSoft: " RLIM_FMT "\n", prefix, rlimit_to_string(i), c->rlimit[i]->rlim_cur); } diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 78d5141053..fc035e796e 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -684,7 +684,8 @@ static int bus_append_automount_property(sd_bus_message *m, const char *field, c } static int bus_append_execute_property(sd_bus_message *m, const char *field, const char *eq) { - int r, rl; + const char *suffix; + int r; if (STR_IN_SET(field, "User", "Group", @@ -863,25 +864,29 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con return bus_append_byte_array(m, field, decoded, sz); } - rl = rlimit_from_string(field); - if (rl >= 0) { - const char *sn; - struct rlimit l; + if ((suffix = startswith(field, "Limit"))) { + int rl; - r = rlimit_parse(rl, eq, &l); - if (r < 0) - return log_error_errno(r, "Failed to parse resource limit: %s", eq); + rl = rlimit_from_string(suffix); + if (rl >= 0) { + const char *sn; + struct rlimit l; - r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max); - if (r < 0) - return bus_log_create_error(r); + r = rlimit_parse(rl, eq, &l); + if (r < 0) + return log_error_errno(r, "Failed to parse resource limit: %s", eq); - sn = strjoina(field, "Soft"); - r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur); - if (r < 0) - return bus_log_create_error(r); + r = sd_bus_message_append(m, "(sv)", field, "t", l.rlim_max); + if (r < 0) + return bus_log_create_error(r); - return 1; + sn = strjoina(field, "Soft"); + r = sd_bus_message_append(m, "(sv)", sn, "t", l.rlim_cur); + if (r < 0) + return bus_log_create_error(r); + + return 1; + } } if (STR_IN_SET(field, "AppArmorProfile", "SmackProcessLabel")) { diff --git a/src/shared/bus-util.c b/src/shared/bus-util.c index 66724d0e78..c80fc4fcbb 100644 --- a/src/shared/bus-util.c +++ b/src/shared/bus-util.c @@ -1613,36 +1613,40 @@ int bus_property_get_rlimit( void *userdata, sd_bus_error *error) { + const char *is_soft; struct rlimit *rl; uint64_t u; rlim_t x; - const char *is_soft; assert(bus); assert(reply); assert(userdata); is_soft = endswith(property, "Soft"); + rl = *(struct rlimit**) userdata; if (rl) x = is_soft ? rl->rlim_cur : rl->rlim_max; else { struct rlimit buf = {}; + const char *s, *p; int z; - const char *s; + /* Chop off "Soft" suffix */ s = is_soft ? strndupa(property, is_soft - property) : property; - z = rlimit_from_string(strstr(s, "Limit")); + /* Skip over any prefix, such as "Default" */ + assert_se(p = strstr(s, "Limit")); + + z = rlimit_from_string(p + 5); assert(z >= 0); - getrlimit(z, &buf); + (void) getrlimit(z, &buf); x = is_soft ? buf.rlim_cur : buf.rlim_max; } - /* rlim_t might have different sizes, let's map - * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on - * all archs */ + /* rlim_t might have different sizes, let's map RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on all + * archs */ u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x; return sd_bus_message_append(reply, "t", u); diff --git a/src/test/test-rlimit-util.c b/src/test/test-rlimit-util.c index 09c35b4f8b..38de758cb6 100644 --- a/src/test/test-rlimit-util.c +++ b/src/test/test-rlimit-util.c @@ -42,6 +42,7 @@ int main(int argc, char *argv[]) { .rlim_cur = 10, .rlim_max = 5, }; + int i; log_parse_environment(); log_open(); @@ -53,10 +54,41 @@ int main(int argc, char *argv[]) { new.rlim_max = old.rlim_max; assert_se(setrlimit(RLIMIT_NOFILE, &new) >= 0); - assert_se(rlimit_from_string("LimitNOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string("NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string("LimitNOFILE") == -1); + assert_se(rlimit_from_string("RLIMIT_NOFILE") == -1); + assert_se(rlimit_from_string("xxxNOFILE") == -1); assert_se(rlimit_from_string("DefaultLimitNOFILE") == -1); - assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "LimitNOFILE")); + assert_se(rlimit_from_string_harder("NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("LimitNOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("RLIMIT_NOFILE") == RLIMIT_NOFILE); + assert_se(rlimit_from_string_harder("xxxNOFILE") == -1); + assert_se(rlimit_from_string_harder("DefaultLimitNOFILE") == -1); + + for (i = 0; i < _RLIMIT_MAX; i++) { + _cleanup_free_ char *prefixed = NULL; + const char *p; + + assert_se(p = rlimit_to_string(i)); + log_info("%i = %s", i, p); + + assert_se(rlimit_from_string(p) == i); + assert_se(rlimit_from_string_harder(p) == i); + + assert_se(prefixed = strjoin("Limit", p)); + + assert_se(rlimit_from_string(prefixed) < 0); + assert_se(rlimit_from_string_harder(prefixed) == i); + + prefixed = mfree(prefixed); + assert_se(prefixed = strjoin("RLIMIT_", p)); + + assert_se(rlimit_from_string(prefixed) < 0); + assert_se(rlimit_from_string_harder(prefixed) == i); + } + + assert_se(streq_ptr(rlimit_to_string(RLIMIT_NOFILE), "NOFILE")); assert_se(rlimit_to_string(-1) == NULL); assert_se(getrlimit(RLIMIT_NOFILE, &old) == 0); |