#include "path-util.h"
#include "dbus-unit.h"
#include "virt.h"
+#include "env-util.h"
#define BUS_MANAGER_INTERFACE_BEGIN \
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
" <method name=\"ResetFailedUnit\">\n" \
" <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
" </method>\n" \
+ " <method name=\"SetUnitControlGroup\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
+ " <method name=\"UnsetUnitControlGroup\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"group\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
+ " </method>\n" \
+ " <method name=\"GetUnitControlGroupAttribute\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"values\" type=\"as\" direction=\"out\"/>\n" \
+ " </method>\n" \
+ " <method name=\"SetUnitControlGroupAttribute\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"values\" type=\"as\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"\n/>" \
+ " </method>\n" \
+ " <method name=\"UnsetUnitControlGroupAttributes\">\n" \
+ " <arg name=\"name\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"attribute\" type=\"s\" direction=\"in\"/>\n" \
+ " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
+ " </method>\n" \
" <method name=\"GetJob\">\n" \
" <arg name=\"id\" type=\"u\" direction=\"in\"/>\n" \
" <arg name=\"job\" type=\"o\" direction=\"out\"/>\n" \
" <property name=\"DefaultControllers\" type=\"as\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardOutput\" type=\"s\" access=\"read\"/>\n" \
" <property name=\"DefaultStandardError\" type=\"s\" access=\"read\"/>\n" \
- " <property name=\"RuntimeWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
- " <property name=\"ShutdownWatchdogUSec\" type=\"s\" access=\"readwrite\"/>\n" \
+ " <property name=\"RuntimeWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
+ " <property name=\"ShutdownWatchdogUSec\" type=\"t\" access=\"readwrite\"/>\n" \
" <property name=\"Virtualization\" type=\"s\" access=\"read\"/>\n"
#define BUS_MANAGER_INTERFACE_END \
if (!reply)
goto oom;
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroup")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+ r = bus_unit_cgroup_set(u, &iter);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroup")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+
+ r = bus_unit_cgroup_unset(u, &iter);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetUnitControlGroupAttribute")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "start");
+
+ r = bus_unit_cgroup_attribute_set(u, &iter);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetUnitControlGroupAttribute")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
+
+ r = bus_unit_cgroup_attribute_unset(u, &iter);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnitControlGroupAttribute")) {
+ const char *name;
+ Unit *u;
+ DBusMessageIter iter;
+ _cleanup_strv_free_ char **list = NULL;
+
+ if (!dbus_message_iter_init(message, &iter))
+ goto oom;
+
+ r = bus_iter_get_basic_and_next(&iter, DBUS_TYPE_STRING, &name, true);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ u = manager_get_unit(m, name);
+ if (!u) {
+ dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
+ return bus_send_error_reply(connection, message, &error, -ENOENT);
+ }
+
+ SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
+
+ r = bus_unit_cgroup_attribute_get(u, &iter, &list);
+ if (r < 0)
+ return bus_send_error_reply(connection, message, NULL, r);
+
+ reply = dbus_message_new_method_return(message);
+ if (!reply)
+ goto oom;
+
+ dbus_message_iter_init_append(reply, &iter);
+ if (bus_append_strv_iter(&iter, list) < 0)
+ goto oom;
+
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
DBusMessageIter iter, sub;
Iterator i;
if (!client)
goto oom;
- r = set_put(s, client);
- if (r < 0) {
- free(client);
+ r = set_consume(s, client);
+ if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
- }
reply = dbus_message_new_method_return(message);
if (!reply)
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SwitchRoot")) {
const char *switch_root, *switch_root_init;
char *u, *v;
- int k;
+ bool good;
SELINUX_ACCESS_CHECK(connection, message, "reboot");
/* Safety check */
if (isempty(switch_root_init))
- k = access(switch_root, F_OK);
+ good = path_is_os_tree(switch_root);
else {
- char *p;
+ _cleanup_free_ char *p = NULL;
p = strjoin(switch_root, "/", switch_root_init, NULL);
if (!p)
goto oom;
- k = access(p, X_OK);
- free(p);
+ good = access(p, X_OK) >= 0;
}
- if (k < 0)
- return bus_send_error_reply(connection, message, NULL, -errno);
+ if (!good)
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
u = strdup(switch_root);
if (!u)
m->exit_code = MANAGER_SWITCH_ROOT;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
- char **l = NULL, **e = NULL;
+ _cleanup_strv_free_ char **l = NULL;
+ char **e = NULL;
SELINUX_ACCESS_CHECK(connection, message, "reboot");
goto oom;
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
+ if (!strv_env_is_valid(l))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
e = strv_env_merge(2, m->environment, l);
- strv_free(l);
if (!e)
goto oom;
m->environment = e;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
- char **l = NULL, **e = NULL;
+ _cleanup_strv_free_ char **l = NULL;
+ char **e = NULL;
SELINUX_ACCESS_CHECK(connection, message, "reboot");
goto oom;
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
+ if (!strv_env_name_or_assignment_is_valid(l))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
e = strv_env_delete(m->environment, 1, l);
- strv_free(l);
-
if (!e)
goto oom;
m->environment = e;
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetAndSetEnvironment")) {
- char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
+ _cleanup_strv_free_ char **l_set = NULL, **l_unset = NULL, **e = NULL;
+ char **f = NULL;
DBusMessageIter iter;
SELINUX_ACCESS_CHECK(connection, message, "reboot");
goto oom;
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
+ if (!strv_env_name_or_assignment_is_valid(l_unset))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
- if (!dbus_message_iter_next(&iter)) {
- strv_free(l_unset);
+ if (!dbus_message_iter_next(&iter))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
- }
r = bus_parse_strv_iter(&iter, &l_set);
- if (r < 0) {
- strv_free(l_unset);
- if (r == -ENOMEM)
- goto oom;
-
+ if (r == -ENOMEM)
+ goto oom;
+ if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
- }
+ if (!strv_env_is_valid(l_set))
+ return bus_send_error_reply(connection, message, NULL, -EINVAL);
e = strv_env_delete(m->environment, 1, l_unset);
- strv_free(l_unset);
-
- if (!e) {
- strv_free(l_set);
+ if (!e)
goto oom;
- }
f = strv_env_merge(2, e, l_set);
- strv_free(l_set);
- strv_free(e);
-
if (!f)
goto oom;
}
if (reply)
- if (!dbus_connection_send(connection, reply, NULL))
+ if (!bus_maybe_send_reply(connection, message, reply))
goto oom;
return DBUS_HANDLER_RESULT_HANDLED;