summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2014-02-22 02:47:29 +0100
committerLennart Poettering <lennart@poettering.net>2014-02-22 03:05:34 +0100
commit90060676c442604780634c0a993e3f9c3733f8e6 (patch)
treeb9a4ea6ffee5bcffdf63f3034f7c460f5559c30f /src/core
parent1620510ada018f1e1f0be114714826f6698501f2 (diff)
cgroup: Extend DeviceAllow= syntax to whitelist groups of devices, not just particular devices nodes
Diffstat (limited to 'src/core')
-rw-r--r--src/core/cgroup.c86
-rw-r--r--src/core/dbus-cgroup.c7
-rw-r--r--src/core/load-fragment.c10
3 files changed, 95 insertions, 8 deletions
diff --git a/src/core/cgroup.c b/src/core/cgroup.c
index 707ce470a1..50de02d0ce 100644
--- a/src/core/cgroup.c
+++ b/src/core/cgroup.c
@@ -191,6 +191,82 @@ static int whitelist_device(const char *path, const char *node, const char *acc)
return r;
}
+static int whitelist_major(const char *path, const char *name, char type, const char *acc) {
+ _cleanup_fclose_ FILE *f = NULL;
+ char line[LINE_MAX];
+ bool good = false;
+ int r;
+
+ assert(path);
+ assert(acc);
+ assert(type == 'b' || type == 'c');
+
+ f = fopen("/proc/devices", "re");
+ if (!f) {
+ log_warning("Cannot open /proc/devices to resolve %s (%c): %m", name, type);
+ return -errno;
+ }
+
+ FOREACH_LINE(line, f, goto fail) {
+ char buf[2+DECIMAL_STR_MAX(unsigned)+3+4], *p, *w;
+ unsigned maj;
+
+ truncate_nl(line);
+
+ if (type == 'c' && streq(line, "Character devices:")) {
+ good = true;
+ continue;
+ }
+
+ if (type == 'b' && streq(line, "Block devices:")) {
+ good = true;
+ continue;
+ }
+
+ if (isempty(line)) {
+ good = false;
+ continue;
+ }
+
+ if (!good)
+ continue;
+
+ p = strstrip(line);
+
+ w = strpbrk(p, WHITESPACE);
+ if (!w)
+ continue;
+ *w = 0;
+
+ r = safe_atou(p, &maj);
+ if (r < 0)
+ continue;
+ if (maj <= 0)
+ continue;
+
+ w++;
+ w += strspn(w, WHITESPACE);
+ if (!streq(w, name))
+ continue;
+
+ sprintf(buf,
+ "%c %u:* %s",
+ type,
+ maj,
+ acc);
+
+ r = cg_set_attribute("devices", path, "devices.allow", buf);
+ if (r < 0)
+ log_warning("Failed to set devices.allow on %s: %s", path, strerror(-r));
+ }
+
+ return 0;
+
+fail:
+ log_warning("Failed to read /proc/devices: %m");
+ return -errno;
+}
+
void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const char *path) {
int r;
@@ -306,7 +382,15 @@ void cgroup_context_apply(CGroupContext *c, CGroupControllerMask mask, const cha
continue;
acc[k++] = 0;
- whitelist_device(path, a->path, acc);
+
+ if (startswith(a->path, "/dev/"))
+ whitelist_device(path, a->path, acc);
+ else if (startswith(a->path, "block-"))
+ whitelist_major(path, a->path + 6, 'b', acc);
+ else if (startswith(a->path, "char-"))
+ whitelist_major(path, a->path + 5, 'c', acc);
+ else
+ log_debug("Ignoring device %s while writing cgroup attribute.", a->path);
}
}
}
diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c
index 792f37eef5..b8a77254d9 100644
--- a/src/core/dbus-cgroup.c
+++ b/src/core/dbus-cgroup.c
@@ -442,8 +442,11 @@ int bus_cgroup_set_property(
while ((r = sd_bus_message_read(message, "(ss)", &path, &rwm)) > 0) {
- if (!path_startswith(path, "/dev"))
- return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
+ if ((!startswith(path, "/dev/") &&
+ !startswith(path, "block-") &&
+ !startswith(path, "char-")) ||
+ strpbrk(path, WHITESPACE))
+ return sd_bus_error_set_errnof(error, EINVAL, "DeviceAllow= requires device node");
if (isempty(rwm))
rwm = "rwm";
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index e74a790e25..5b1e990921 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2368,9 +2368,10 @@ int config_parse_device_allow(
if (!path)
return log_oom();
- if (!path_startswith(path, "/dev")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid device node path '%s'. Ignoring.", path);
+ if (!startswith(path, "/dev/") &&
+ !startswith(path, "block-") &&
+ !startswith(path, "char-")) {
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
return 0;
}
@@ -2379,8 +2380,7 @@ int config_parse_device_allow(
m = "rwm";
if (!in_charset(m, "rwm")) {
- log_syntax(unit, LOG_ERR, filename, line, EINVAL,
- "Invalid device rights '%s'. Ignoring.", m);
+ log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device rights '%s'. Ignoring.", m);
return 0;
}