summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2018-05-03 18:45:39 +0200
committerLennart Poettering <lennart@poettering.net>2018-05-17 20:36:52 +0200
commit6550c24c7f21ee398a1ca0ab43603b23a3414108 (patch)
treef99265f8feb8ced015942db9978da228eb461cd1 /src
parent0e960f9b5cb42bdbb9e0aafe2b543f969f6e0aae (diff)
downloadsystemd-6550c24c7f21ee398a1ca0ab43603b23a3414108.tar.gz
systemd-6550c24c7f21ee398a1ca0ab43603b23a3414108.tar.bz2
systemd-6550c24c7f21ee398a1ca0ab43603b23a3414108.zip
rlimit-util: rework rlimit_{from|to}_string() to work without "Limit" prefix
let's make the call more generic, so that we can also easily use it for parsing "RLIMIT_xyz" style constants.
Diffstat (limited to 'src')
-rw-r--r--src/basic/rlimit-util.c48
-rw-r--r--src/basic/rlimit-util.h1
-rw-r--r--src/core/dbus-execute.c114
-rw-r--r--src/core/execute.c6
-rw-r--r--src/shared/bus-unit-util.c37
-rw-r--r--src/shared/bus-util.c18
-rw-r--r--src/test/test-rlimit-util.c36
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);