mirror of
https://github.com/systemd/systemd.git
synced 2025-02-10 17:57:40 +03:00
selinux: rework selinux access check logic
a) Instead of parsing the bus messages inside of selinux-access.c simply pass everything pre-parsed in the functions b) implement the access checking with a macro that resolves to nothing on non-selinux builds c) split out the selinux checks into their own sources selinux-util.[ch] d) this unifies the job creation code behind the D-Bus calls Manager.StartUnit() and Unit.Start().
This commit is contained in:
parent
71ef24d095
commit
cad45ba11e
@ -829,6 +829,8 @@ libsystemd_label_la_SOURCES = \
|
||||
src/shared/socket-label.c \
|
||||
src/shared/label.c \
|
||||
src/shared/label.h \
|
||||
src/shared/selinux-util.c \
|
||||
src/shared/selinux-util.h \
|
||||
src/shared/mkdir.c \
|
||||
src/shared/mkdir.h \
|
||||
src/shared/ask-password-api.c \
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus-automount.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_AUTOMOUNT_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Automount\">\n" \
|
||||
@ -68,5 +69,7 @@ DBusHandlerResult bus_automount_message_handler(Unit *u, DBusConnection *c, DBus
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus-device.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_DEVICE_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Device\">\n" \
|
||||
@ -61,5 +62,7 @@ DBusHandlerResult bus_device_message_handler(Unit *u, DBusConnection *c, DBusMes
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "log.h"
|
||||
#include "dbus-job.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_JOB_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Job\">\n" \
|
||||
@ -68,7 +69,8 @@ static int bus_job_append_unit(DBusMessageIter *i, const char *property, void *d
|
||||
if (!dbus_message_iter_open_container(i, DBUS_TYPE_STRUCT, NULL, &sub))
|
||||
return -ENOMEM;
|
||||
|
||||
if (!(p = unit_dbus_path(j->unit)))
|
||||
p = unit_dbus_path(j->unit);
|
||||
if (!p)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &j->unit->id) ||
|
||||
@ -94,43 +96,39 @@ static const BusProperty bus_job_properties[] = {
|
||||
};
|
||||
|
||||
static DBusHandlerResult bus_job_message_dispatch(Job *j, DBusConnection *connection, DBusMessage *message) {
|
||||
DBusMessage *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Job", "Cancel")) {
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
goto oom;
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "stop");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
job_finish_and_invalidate(j, JOB_CANCELED, true);
|
||||
|
||||
} else {
|
||||
const BusBoundProperties bps[] = {
|
||||
{ "org.freedesktop.systemd1.Job", bus_job_properties, j },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
|
||||
|
||||
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
|
||||
Manager *m = data;
|
||||
Job *j;
|
||||
int r;
|
||||
DBusMessage *reply;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
|
||||
assert(connection);
|
||||
assert(message);
|
||||
@ -145,7 +143,10 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
|
||||
Iterator i;
|
||||
size_t size;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
/* We roll our own introspection code here, instead of
|
||||
@ -153,7 +154,8 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
|
||||
* need to generate our introspection string
|
||||
* dynamically. */
|
||||
|
||||
if (!(f = open_memstream(&introspection, &size)))
|
||||
f = open_memstream(&introspection, &size);
|
||||
if (!f)
|
||||
goto oom;
|
||||
|
||||
fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
|
||||
@ -188,36 +190,28 @@ static DBusHandlerResult bus_job_message_handler(DBusConnection *connection, DBu
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
if ((r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j)) < 0) {
|
||||
r = manager_get_job_from_dbus_path(m, dbus_message_get_path(message), &j);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r == -ENOENT) {
|
||||
DBusError e;
|
||||
|
||||
if (r == -ENOMEM)
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
||||
if (r == -ENOENT) {
|
||||
DBusError e;
|
||||
|
||||
dbus_error_init(&e);
|
||||
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
|
||||
return bus_send_error_reply(connection, message, &e, r);
|
||||
}
|
||||
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
dbus_error_init(&e);
|
||||
dbus_set_error_const(&e, DBUS_ERROR_UNKNOWN_OBJECT, "Unknown job");
|
||||
return bus_send_error_reply(connection, message, &e, r);
|
||||
}
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
|
||||
return bus_job_message_dispatch(j, connection, message);
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "watchdog.h"
|
||||
#include "hwclock.h"
|
||||
#include "path-util.h"
|
||||
#include "dbus-unit.h"
|
||||
|
||||
#define BUS_MANAGER_INTERFACE_BEGIN \
|
||||
" <interface name=\"org.freedesktop.systemd1.Manager\">\n"
|
||||
@ -424,20 +425,6 @@ static int bus_manager_append_progress(DBusMessageIter *i, const char *property,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *message_get_sender_with_fallback(DBusMessage *m) {
|
||||
const char *s;
|
||||
|
||||
assert(m);
|
||||
|
||||
if ((s = dbus_message_get_sender(m)))
|
||||
return s;
|
||||
|
||||
/* When the message came in from a direct connection the
|
||||
* message will have no sender. We fix that here. */
|
||||
|
||||
return ":no-sender";
|
||||
}
|
||||
|
||||
static DBusMessage *message_from_file_changes(
|
||||
DBusMessage *m,
|
||||
UnitFileChange *changes,
|
||||
@ -562,12 +549,11 @@ static const BusProperty bus_manager_properties[] = {
|
||||
};
|
||||
|
||||
static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) {
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
_cleanup_free_ char * path = NULL;
|
||||
Manager *m = data;
|
||||
|
||||
int r;
|
||||
DBusError error;
|
||||
DBusMessage *reply = NULL;
|
||||
char * path = NULL;
|
||||
JobType job_type = _JOB_TYPE_INVALID;
|
||||
bool reload_if_possible = false;
|
||||
const char *member;
|
||||
@ -579,9 +565,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
dbus_error_init(&error);
|
||||
|
||||
member = dbus_message_get_member(message);
|
||||
r = selinux_manager_access_check(connection, message, m, &error);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {
|
||||
const char *name;
|
||||
@ -594,15 +577,20 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (!(u = manager_get_unit(m, name))) {
|
||||
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);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(path = unit_dbus_path(u)))
|
||||
path = unit_dbus_path(u);
|
||||
if (!path)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -621,15 +609,20 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (!(u = cgroup_unit_by_pid(m, (pid_t) pid))) {
|
||||
u = cgroup_unit_by_pid(m, (pid_t) pid);
|
||||
if (!u) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "No unit for PID %lu is loaded.", (unsigned long) pid);
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(path = unit_dbus_path(u)))
|
||||
path = unit_dbus_path(u);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -648,13 +641,18 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
|
||||
r = manager_load_unit(m, name, NULL, &error, &u);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(path = unit_dbus_path(u)))
|
||||
path = unit_dbus_path(u);
|
||||
if (!path)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -713,6 +711,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
|
||||
|
||||
r = unit_kill(u, who, signo, &error);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
@ -731,15 +731,20 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (!(j = manager_get_job(m, id))) {
|
||||
j = manager_get_job(m, id);
|
||||
if (!j) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "Job %u does not exist.", (unsigned) id);
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_UNIT_ACCESS_CHECK(j->unit, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(path = job_dbus_path(j)))
|
||||
path = job_dbus_path(j);
|
||||
if (!path)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -750,16 +755,22 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
manager_clear_jobs(m);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailed")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reload");
|
||||
|
||||
manager_reset_failed(m);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ResetFailedUnit")) {
|
||||
@ -773,14 +784,18 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (!(u = manager_get_unit(m, name))) {
|
||||
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, "reload");
|
||||
|
||||
unit_reset_failed(u);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) {
|
||||
@ -789,7 +804,10 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
Unit *u;
|
||||
const char *k;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
@ -818,7 +836,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
f = unit_following(u);
|
||||
following = f ? f->id : "";
|
||||
|
||||
if (!(u_path = unit_dbus_path(u)))
|
||||
u_path = unit_dbus_path(u);
|
||||
if (!u_path)
|
||||
goto oom;
|
||||
|
||||
if (u->job) {
|
||||
@ -868,7 +887,10 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
Iterator i;
|
||||
Job *j;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
@ -889,10 +911,12 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
state = job_state_to_string(j->state);
|
||||
type = job_type_to_string(j->type);
|
||||
|
||||
if (!(j_path = job_dbus_path(j)))
|
||||
j_path = job_dbus_path(j);
|
||||
if (!j_path)
|
||||
goto oom;
|
||||
|
||||
if (!(u_path = unit_dbus_path(j->unit))) {
|
||||
u_path = unit_dbus_path(j->unit);
|
||||
if (!u_path) {
|
||||
free(j_path);
|
||||
goto oom;
|
||||
}
|
||||
@ -922,38 +946,49 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
char *client;
|
||||
Set *s;
|
||||
|
||||
if (!(s = BUS_CONNECTION_SUBSCRIBED(m, connection))) {
|
||||
if (!(s = set_new(string_hash_func, string_compare_func)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
s = BUS_CONNECTION_SUBSCRIBED(m, connection);
|
||||
if (!s) {
|
||||
s = set_new(string_hash_func, string_compare_func);
|
||||
if (!s)
|
||||
goto oom;
|
||||
|
||||
if (!(dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL))) {
|
||||
if (!dbus_connection_set_data(connection, m->subscribed_data_slot, s, NULL)) {
|
||||
set_free(s);
|
||||
goto oom;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(client = strdup(message_get_sender_with_fallback(message))))
|
||||
client = strdup(bus_message_get_sender_with_fallback(message));
|
||||
if (!client)
|
||||
goto oom;
|
||||
|
||||
if ((r = set_put(s, client)) < 0) {
|
||||
r = set_put(s, client);
|
||||
if (r < 0) {
|
||||
free(client);
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) {
|
||||
char *client;
|
||||
|
||||
if (!(client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) message_get_sender_with_fallback(message)))) {
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
client = set_remove(BUS_CONNECTION_SUBSCRIBED(m, connection), (char*) bus_message_get_sender_with_fallback(message));
|
||||
if (!client) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUBSCRIBED, "Client is not subscribed.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
|
||||
free(client);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) {
|
||||
@ -961,10 +996,14 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
char *dump = NULL;
|
||||
size_t size;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(f = open_memstream(&dump, &size)))
|
||||
f = open_memstream(&dump, &size);
|
||||
if (!f)
|
||||
goto oom;
|
||||
|
||||
manager_dump_units(m, f, NULL);
|
||||
@ -989,6 +1028,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
dbus_bool_t cleanup;
|
||||
Snapshot *s;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "start");
|
||||
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
&error,
|
||||
@ -997,16 +1038,19 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (name && name[0] == 0)
|
||||
if (isempty(name))
|
||||
name = NULL;
|
||||
|
||||
if ((r = snapshot_create(m, name, cleanup, &error, &s)) < 0)
|
||||
r = snapshot_create(m, name, cleanup, &error, &s);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!(path = unit_dbus_path(UNIT(s))))
|
||||
path = unit_dbus_path(UNIT(s));
|
||||
if (!path)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -1024,7 +1068,10 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
const char *k;
|
||||
size_t size;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
/* We roll our own introspection code here, instead of
|
||||
@ -1032,7 +1079,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
* need to generate our introspection string
|
||||
* dynamically. */
|
||||
|
||||
if (!(f = open_memstream(&introspection, &size)))
|
||||
f = open_memstream(&introspection, &size);
|
||||
if (!f)
|
||||
goto oom;
|
||||
|
||||
fputs(INTROSPECTION_BEGIN, f);
|
||||
@ -1043,7 +1091,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
if (k != u->id)
|
||||
continue;
|
||||
|
||||
if (!(p = bus_path_escape(k))) {
|
||||
p = bus_path_escape(k);
|
||||
if (!p) {
|
||||
fclose(f);
|
||||
free(introspection);
|
||||
goto oom;
|
||||
@ -1078,6 +1127,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reload");
|
||||
|
||||
assert(!m->queued_message);
|
||||
|
||||
/* Instead of sending the reply back right away, we
|
||||
@ -1085,7 +1136,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
* after the reload is finished. That way the caller
|
||||
* knows when the reload finished. */
|
||||
|
||||
if (!(m->queued_message = dbus_message_new_method_return(message)))
|
||||
m->queued_message = dbus_message_new_method_return(message);
|
||||
if (!m->queued_message)
|
||||
goto oom;
|
||||
|
||||
m->queued_message_connection = connection;
|
||||
@ -1093,6 +1145,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reload");
|
||||
|
||||
/* We don't send a reply back here, the client should
|
||||
* just wait for us disconnecting. */
|
||||
|
||||
@ -1100,60 +1154,75 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "halt");
|
||||
|
||||
if (m->running_as == SYSTEMD_SYSTEM) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Exit is only supported for user service managers.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOTSUP);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
m->exit_code = MANAGER_EXIT;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reboot")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
if (m->running_as != SYSTEMD_SYSTEM) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Reboot is only supported for system managers.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOTSUP);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
m->exit_code = MANAGER_REBOOT;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "PowerOff")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "halt");
|
||||
|
||||
if (m->running_as != SYSTEMD_SYSTEM) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Powering off is only supported for system managers.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOTSUP);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
m->exit_code = MANAGER_POWEROFF;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Halt")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "halt");
|
||||
|
||||
if (m->running_as != SYSTEMD_SYSTEM) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "Halting is only supported for system managers.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOTSUP);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
m->exit_code = MANAGER_HALT;
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "KExec")) {
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
if (m->running_as != SYSTEMD_SYSTEM) {
|
||||
dbus_set_error(&error, BUS_ERROR_NOT_SUPPORTED, "kexec is only supported for system managers.");
|
||||
return bus_send_error_reply(connection, message, &error, -ENOTSUP);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
m->exit_code = MANAGER_KEXEC;
|
||||
@ -1163,6 +1232,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
char *u, *v;
|
||||
int k;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
&error,
|
||||
@ -1225,20 +1296,21 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) {
|
||||
char **l = NULL, **e = NULL;
|
||||
|
||||
if ((r = bus_parse_strv(message, &l)) < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
r = bus_parse_strv(message, &l);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
e = strv_env_merge(2, m->environment, l);
|
||||
strv_free(l);
|
||||
|
||||
if (!e)
|
||||
goto oom;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message))) {
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply) {
|
||||
strv_free(e);
|
||||
goto oom;
|
||||
}
|
||||
@ -1249,12 +1321,13 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) {
|
||||
char **l = NULL, **e = NULL;
|
||||
|
||||
if ((r = bus_parse_strv(message, &l)) < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
r = bus_parse_strv(message, &l);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
e = strv_env_delete(m->environment, 1, l);
|
||||
strv_free(l);
|
||||
@ -1274,16 +1347,16 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
char **l_set = NULL, **l_unset = NULL, **e = NULL, **f = NULL;
|
||||
DBusMessageIter iter;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "reboot");
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
goto oom;
|
||||
|
||||
r = bus_parse_strv_iter(&iter, &l_unset);
|
||||
if (r < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, NULL, r);
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_next(&iter)) {
|
||||
strv_free(l_unset);
|
||||
@ -1327,6 +1400,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
Iterator i;
|
||||
UnitFileList *item;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
@ -1374,6 +1449,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
UnitFileState state;
|
||||
const char *s;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
&error,
|
||||
@ -1411,6 +1488,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
dbus_bool_t runtime, force;
|
||||
int carries_install_info = -1;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, streq(member, "MaskUnitFiles") ? "disable" : "enable");
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
goto oom;
|
||||
|
||||
@ -1469,6 +1548,8 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
unsigned n_changes = 0;
|
||||
dbus_bool_t runtime;
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, streq(member, "UnmaskUnitFiles") ? "enable" : "disable");
|
||||
|
||||
if (!dbus_message_iter_init(message, &iter))
|
||||
goto oom;
|
||||
|
||||
@ -1513,16 +1594,17 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
{ "org.freedesktop.systemd1.Manager", bus_manager_properties, m },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
||||
if (job_type != _JOB_TYPE_INVALID) {
|
||||
const char *name, *smode, *old_name = NULL;
|
||||
JobMode mode;
|
||||
Job *j;
|
||||
JobBusClient *cl;
|
||||
Unit *u;
|
||||
bool b;
|
||||
dbus_bool_t b;
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "StartUnitReplace"))
|
||||
b = dbus_message_get_args(
|
||||
@ -1539,86 +1621,37 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &smode,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
if (!b)
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (old_name)
|
||||
if (!(u = manager_get_unit(m, old_name)) ||
|
||||
!u->job ||
|
||||
u->job->type != JOB_START) {
|
||||
if (old_name) {
|
||||
u = manager_get_unit(m, old_name);
|
||||
if (!u || !u->job || u->job->type != JOB_START) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_JOB, "No job queued for unit %s", old_name);
|
||||
return bus_send_error_reply(connection, message, &error, -ENOENT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
|
||||
mode = job_mode_from_string(smode);
|
||||
if (mode < 0) {
|
||||
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
}
|
||||
|
||||
if ((r = manager_load_unit(m, name, NULL, &error, &u)) < 0)
|
||||
r = manager_load_unit(m, name, NULL, &error, &u);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (reload_if_possible && unit_can_reload(u)) {
|
||||
if (job_type == JOB_RESTART)
|
||||
job_type = JOB_RELOAD_OR_START;
|
||||
else if (job_type == JOB_TRY_RESTART)
|
||||
job_type = JOB_RELOAD;
|
||||
}
|
||||
|
||||
if (job_type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", name);
|
||||
return bus_send_error_reply(connection, message, &error, -EPERM);
|
||||
}
|
||||
|
||||
if ((job_type == JOB_START && u->refuse_manual_start) ||
|
||||
(job_type == JOB_STOP && u->refuse_manual_stop) ||
|
||||
((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
|
||||
(u->refuse_manual_start || u->refuse_manual_stop))) {
|
||||
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
|
||||
return bus_send_error_reply(connection, message, &error, -EPERM);
|
||||
}
|
||||
|
||||
if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
cl = job_bus_client_new(connection, message_get_sender_with_fallback(message));
|
||||
if (!cl)
|
||||
goto oom;
|
||||
|
||||
LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
goto oom;
|
||||
|
||||
if (!(path = job_dbus_path(j)))
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
reply,
|
||||
DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_INVALID))
|
||||
goto oom;
|
||||
return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
if (reply)
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
free(path);
|
||||
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_MOUNT_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Mount\">\n" \
|
||||
@ -161,5 +162,7 @@ DBusHandlerResult bus_mount_message_handler(Unit *u, DBusConnection *c, DBusMess
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps );
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "dbus-path.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_PATH_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Path\">\n" \
|
||||
@ -115,5 +116,7 @@ DBusHandlerResult bus_path_message_handler(Unit *u, DBusConnection *c, DBusMessa
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-service.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_SERVICE_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Service\">\n" \
|
||||
@ -154,5 +155,7 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status");
|
||||
|
||||
return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus-snapshot.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_SNAPSHOT_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Snapshot\">\n" \
|
||||
@ -52,17 +53,19 @@ static const BusProperty bus_snapshot_properties[] = {
|
||||
|
||||
DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
|
||||
Snapshot *s = SNAPSHOT(u);
|
||||
|
||||
DBusMessage *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
DBusError error;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Snapshot", "Remove")) {
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "stop");
|
||||
|
||||
snapshot_remove(SNAPSHOT(u));
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else {
|
||||
@ -71,22 +74,20 @@ DBusHandlerResult bus_snapshot_message_handler(Unit *u, DBusConnection *c, DBusM
|
||||
{ "org.freedesktop.systemd1.Snapshot", bus_snapshot_properties, s },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
if (!dbus_connection_send(c, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_SOCKET_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Socket\">\n" \
|
||||
@ -138,5 +139,7 @@ DBusHandlerResult bus_socket_message_handler(Unit *u, DBusConnection *c, DBusMes
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-kill.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_SWAP_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Swap\">\n" \
|
||||
@ -108,5 +109,7 @@ DBusHandlerResult bus_swap_message_handler(Unit *u, DBusConnection *c, DBusMessa
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "dbus-unit.h"
|
||||
#include "dbus-target.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_TARGET_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Target\">\n" \
|
||||
@ -51,5 +52,7 @@ DBusHandlerResult bus_target_message_handler(Unit *u, DBusConnection *c, DBusMes
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "dbus-timer.h"
|
||||
#include "dbus-execute.h"
|
||||
#include "dbus-common.h"
|
||||
#include "selinux-access.h"
|
||||
|
||||
#define BUS_TIMER_INTERFACE \
|
||||
" <interface name=\"org.freedesktop.systemd1.Timer\">\n" \
|
||||
@ -133,5 +134,7 @@ DBusHandlerResult bus_timer_message_handler(Unit *u, DBusConnection *c, DBusMess
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
|
||||
|
||||
return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
|
||||
}
|
||||
|
@ -406,25 +406,14 @@ static int bus_unit_append_load_error(DBusMessageIter *i, const char *property,
|
||||
}
|
||||
|
||||
static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *connection, DBusMessage *message) {
|
||||
DBusMessage *reply = NULL;
|
||||
Manager *m = u->manager;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
DBusError error;
|
||||
JobType job_type = _JOB_TYPE_INVALID;
|
||||
char *path = NULL;
|
||||
bool reload_if_possible = false;
|
||||
int r;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
r = selinux_unit_access_check(
|
||||
connection,
|
||||
message,
|
||||
m,
|
||||
u->source_path ? u->source_path : u->fragment_path,
|
||||
&error);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Start"))
|
||||
job_type = JOB_START;
|
||||
else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "Stop"))
|
||||
@ -465,6 +454,8 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
|
||||
if (signo <= 0 || signo >= _NSIG)
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "stop");
|
||||
|
||||
r = unit_kill(u, who, signo, &error);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
@ -475,9 +466,12 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
|
||||
|
||||
} else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Unit", "ResetFailed")) {
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "reload");
|
||||
|
||||
unit_reset_failed(u);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
} else if (UNIT_VTABLE(u)->bus_message_handler)
|
||||
@ -488,15 +482,6 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
|
||||
if (job_type != _JOB_TYPE_INVALID) {
|
||||
const char *smode;
|
||||
JobMode mode;
|
||||
Job *j;
|
||||
|
||||
if ((job_type == JOB_START && u->refuse_manual_start) ||
|
||||
(job_type == JOB_STOP && u->refuse_manual_stop) ||
|
||||
((job_type == JOB_RESTART || job_type == JOB_TRY_RESTART) &&
|
||||
(u->refuse_manual_start || u->refuse_manual_stop))) {
|
||||
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, may be requested by dependency only.");
|
||||
return bus_send_error_reply(connection, message, &error, -EPERM);
|
||||
}
|
||||
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
@ -505,53 +490,23 @@ static DBusHandlerResult bus_unit_message_dispatch(Unit *u, DBusConnection *conn
|
||||
DBUS_TYPE_INVALID))
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
|
||||
if (reload_if_possible && unit_can_reload(u)) {
|
||||
if (job_type == JOB_RESTART)
|
||||
job_type = JOB_RELOAD_OR_START;
|
||||
else if (job_type == JOB_TRY_RESTART)
|
||||
job_type = JOB_RELOAD;
|
||||
}
|
||||
|
||||
if ((mode = job_mode_from_string(smode)) == _JOB_MODE_INVALID) {
|
||||
mode = job_mode_from_string(smode);
|
||||
if (mode < 0) {
|
||||
dbus_set_error(&error, BUS_ERROR_INVALID_JOB_MODE, "Job mode %s is invalid.", smode);
|
||||
return bus_send_error_reply(connection, message, &error, -EINVAL);
|
||||
}
|
||||
|
||||
if ((r = manager_add_job(m, job_type, u, mode, true, &error, &j)) < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
goto oom;
|
||||
|
||||
if (!(path = job_dbus_path(j)))
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
reply,
|
||||
DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_INVALID))
|
||||
goto oom;
|
||||
return bus_unit_queue_job(connection, message, u, job_type, mode, reload_if_possible);
|
||||
}
|
||||
|
||||
if (reply) {
|
||||
if (reply)
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
free(path);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
free(path);
|
||||
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
@ -559,7 +514,7 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
Manager *m = data;
|
||||
Unit *u;
|
||||
int r;
|
||||
DBusMessage *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
DBusError error;
|
||||
|
||||
assert(connection);
|
||||
@ -571,6 +526,8 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
if (streq(dbus_message_get_path(message), "/org/freedesktop/systemd1/unit")) {
|
||||
/* Be nice to gdbus and return introspection data for our mid-level paths */
|
||||
|
||||
SELINUX_MANAGER_ACCESS_CHECK(m, connection, message, "status");
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
|
||||
char *introspection = NULL;
|
||||
FILE *f;
|
||||
@ -578,7 +535,8 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
const char *k;
|
||||
size_t size;
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
/* We roll our own introspection code here, instead of
|
||||
@ -586,7 +544,8 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
* need to generate our introspection string
|
||||
* dynamically. */
|
||||
|
||||
if (!(f = open_memstream(&introspection, &size)))
|
||||
f = open_memstream(&introspection, &size);
|
||||
if (!f)
|
||||
goto oom;
|
||||
|
||||
fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
|
||||
@ -601,7 +560,8 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
if (k != u->id)
|
||||
continue;
|
||||
|
||||
if (!(p = bus_path_escape(k))) {
|
||||
p = bus_path_escape(k);
|
||||
if (!p) {
|
||||
fclose(f);
|
||||
free(introspection);
|
||||
goto oom;
|
||||
@ -634,8 +594,6 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
@ -643,19 +601,14 @@ static DBusHandlerResult bus_unit_message_handler(DBusConnection *connection, DB
|
||||
}
|
||||
|
||||
r = manager_load_unit_from_dbus_path(m, dbus_message_get_path(message), &error, &u);
|
||||
if (r < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
}
|
||||
|
||||
return bus_unit_message_dispatch(u, connection, message);
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
@ -785,6 +738,87 @@ oom:
|
||||
log_error("Failed to allocate unit remove signal.");
|
||||
}
|
||||
|
||||
DBusHandlerResult bus_unit_queue_job(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
Unit *u,
|
||||
JobType type,
|
||||
JobMode mode,
|
||||
bool reload_if_possible) {
|
||||
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
Job *j;
|
||||
JobBusClient *cl;
|
||||
DBusError error;
|
||||
int r;
|
||||
|
||||
assert(connection);
|
||||
assert(message);
|
||||
assert(u);
|
||||
assert(type >= 0 && type < _JOB_TYPE_MAX);
|
||||
assert(mode >= 0 && mode < _JOB_MODE_MAX);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
if (reload_if_possible && unit_can_reload(u)) {
|
||||
if (type == JOB_RESTART)
|
||||
type = JOB_RELOAD_OR_START;
|
||||
else if (type == JOB_TRY_RESTART)
|
||||
type = JOB_RELOAD;
|
||||
}
|
||||
|
||||
SELINUX_UNIT_ACCESS_CHECK(u, connection, message,
|
||||
(type == JOB_START || type == JOB_RESTART || type == JOB_TRY_RESTART) ? "start" :
|
||||
type == JOB_STOP ? "stop" : "reload");
|
||||
|
||||
if (type == JOB_STOP && u->load_state == UNIT_ERROR && unit_active_state(u) == UNIT_INACTIVE) {
|
||||
dbus_set_error(&error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s not loaded.", u->id);
|
||||
return bus_send_error_reply(connection, message, &error, -EPERM);
|
||||
}
|
||||
|
||||
if ((type == JOB_START && u->refuse_manual_start) ||
|
||||
(type == JOB_STOP && u->refuse_manual_stop) ||
|
||||
((type == JOB_RESTART || type == JOB_TRY_RESTART) && (u->refuse_manual_start || u->refuse_manual_stop))) {
|
||||
dbus_set_error(&error, BUS_ERROR_ONLY_BY_DEPENDENCY, "Operation refused, unit %s may be requested by dependency only.", u->id);
|
||||
return bus_send_error_reply(connection, message, &error, -EPERM);
|
||||
}
|
||||
|
||||
r = manager_add_job(u->manager, type, u, mode, true, &error, &j);
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(connection, message, &error, r);
|
||||
|
||||
cl = job_bus_client_new(connection, bus_message_get_sender_with_fallback(message));
|
||||
if (!cl)
|
||||
goto oom;
|
||||
|
||||
LIST_PREPEND(JobBusClient, client, j->bus_client_list, cl);
|
||||
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
path = job_dbus_path(j);
|
||||
if (!path)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
reply,
|
||||
DBUS_TYPE_OBJECT_PATH, &path,
|
||||
DBUS_TYPE_INVALID))
|
||||
goto oom;
|
||||
|
||||
if (!dbus_connection_send(connection, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
|
||||
oom:
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
}
|
||||
|
||||
const BusProperty bus_unit_properties[] = {
|
||||
{ "Id", bus_property_append_string, "s", offsetof(Unit, id), true },
|
||||
{ "Names", bus_unit_append_names, "as", 0 },
|
||||
|
@ -133,6 +133,15 @@ extern const BusProperty bus_unit_properties[];
|
||||
void bus_unit_send_change_signal(Unit *u);
|
||||
void bus_unit_send_removed_signal(Unit *u);
|
||||
|
||||
|
||||
DBusHandlerResult bus_unit_queue_job(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
Unit *u,
|
||||
JobType type,
|
||||
JobMode mode,
|
||||
bool reload_if_possible);
|
||||
|
||||
extern const DBusObjectPathVTable bus_unit_vtable;
|
||||
|
||||
extern const char bus_unit_interface[];
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "bus-errors.h"
|
||||
#include "dbus-common.h"
|
||||
#include "audit.h"
|
||||
#include "selinux-util.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
@ -42,11 +43,8 @@
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
/* FD to send audit messages to */
|
||||
static bool initialized = false;
|
||||
static int audit_fd = -1;
|
||||
static int selinux_enabled = -1;
|
||||
static int first_time = 1;
|
||||
static int selinux_enforcing = 0;
|
||||
|
||||
struct auditstruct {
|
||||
const char *path;
|
||||
@ -56,106 +54,13 @@ struct auditstruct {
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
/*
|
||||
Define a mapping between the systemd method calls and the SELinux access to check.
|
||||
We define two tables, one for access checks on unit files, and one for
|
||||
access checks for the system in general.
|
||||
|
||||
If we do not find a match in either table, then the "undefined" system
|
||||
check will be called.
|
||||
*/
|
||||
|
||||
static const char unit_methods[] =
|
||||
"DisableUnitFiles\0" "disable\0"
|
||||
"EnableUnitFiles\0" "enable\0"
|
||||
"GetUnit\0" "status\0"
|
||||
"GetUnitFileState\0" "status\0"
|
||||
"Kill\0" "stop\0"
|
||||
"KillUnit\0" "stop\0"
|
||||
"LinkUnitFiles\0" "enable\0"
|
||||
"MaskUnitFiles\0" "disable\0"
|
||||
"PresetUnitFiles\0" "enable\0"
|
||||
"ReenableUnitFiles\0" "enable\0"
|
||||
"ReloadOrRestart\0" "start\0"
|
||||
"ReloadOrRestartUnit\0" "start\0"
|
||||
"ReloadOrTryRestart\0" "start\0"
|
||||
"ReloadOrTryRestartUnit\0" "start\0"
|
||||
"Reload\0" "reload\0"
|
||||
"ReloadUnit\0" "reload\0"
|
||||
"ResetFailedUnit\0" "stop\0"
|
||||
"Restart\0" "start\0"
|
||||
"RestartUnit\0" "start\0"
|
||||
"Start\0" "start\0"
|
||||
"StartUnit\0" "start\0"
|
||||
"StartUnitReplace\0" "start\0"
|
||||
"Stop\0" "stop\0"
|
||||
"StopUnit\0" "stop\0"
|
||||
"TryRestart\0" "start\0"
|
||||
"TryRestartUnit\0" "start\0"
|
||||
"UnmaskUnitFiles\0" "enable\0";
|
||||
|
||||
static const char system_methods[] =
|
||||
"ClearJobs\0" "reboot\0"
|
||||
"CreateSnapshot\0" "status\0"
|
||||
"Dump\0" "status\0"
|
||||
"Exit\0" "halt\0"
|
||||
"FlushDevices\0" "halt\0"
|
||||
"Get\0" "status\0"
|
||||
"GetAll\0" "status\0"
|
||||
"GetJob\0" "status\0"
|
||||
"GetSeat\0" "status\0"
|
||||
"GetSession\0" "status\0"
|
||||
"GetSessionByPID\0" "status\0"
|
||||
"GetUnitByPID\0" "status\0"
|
||||
"GetUser\0" "status\0"
|
||||
"Halt\0" "halt\0"
|
||||
"Introspect\0" "status\0"
|
||||
"KExec\0" "reboot\0"
|
||||
"KillSession\0" "halt\0"
|
||||
"KillUser\0" "halt\0"
|
||||
"LoadUnit\0" "reload\0"
|
||||
"ListJobs\0" "status\0"
|
||||
"ListSeats\0" "status\0"
|
||||
"ListSessions\0" "status\0"
|
||||
"ListUnits\0" "status\0"
|
||||
"ListUnitFiles\0" "status\0"
|
||||
"ListUsers\0" "status\0"
|
||||
"LockSession\0" "halt\0"
|
||||
"PowerOff\0" "halt\0"
|
||||
"Reboot\0" "reboot\0"
|
||||
"Reload\0" "reload\0"
|
||||
"Reexecute\0" "reload\0"
|
||||
"ResetFailed\0" "reload\0"
|
||||
"Subscribe\0" "status\0"
|
||||
"SwithcRoot\0" "reboot\0"
|
||||
"SetEnvironment\0" "status\0"
|
||||
"SetUserLinger\0" "halt\0"
|
||||
"TerminateSeat\0" "halt\0"
|
||||
"TerminateSession\0" "halt\0"
|
||||
"TerminateUser\0" "halt\0"
|
||||
"Unsubscribe\0" "status\0"
|
||||
"UnsetEnvironment\0" "status\0"
|
||||
"UnsetAndSetEnvironment\0" "status\0";
|
||||
|
||||
/*
|
||||
If the admin toggles the selinux enforcment mode this callback
|
||||
will get called before the next access check
|
||||
*/
|
||||
static int setenforce_callback(int enforcing)
|
||||
{
|
||||
selinux_enforcing = enforcing;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This mimics dbus_bus_get_unix_user() */
|
||||
static int bus_get_selinux_security_context(
|
||||
DBusConnection *connection,
|
||||
const char *name,
|
||||
char **scon,
|
||||
DBusError *error) {
|
||||
|
||||
DBusMessage *m = NULL, *reply = NULL;
|
||||
int r;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
|
||||
|
||||
m = dbus_message_new_method_call(
|
||||
DBUS_SERVICE_DBUS,
|
||||
@ -163,54 +68,34 @@ static int bus_get_selinux_security_context(
|
||||
DBUS_INTERFACE_DBUS,
|
||||
"GetConnectionSELinuxSecurityContext");
|
||||
if (!m) {
|
||||
r = -errno;
|
||||
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto finish;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!r) {
|
||||
r = -errno;
|
||||
if (!dbus_message_append_args(
|
||||
m,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto finish;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
|
||||
if (!reply) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
if (!reply)
|
||||
return -EIO;
|
||||
|
||||
r = dbus_set_error_from_message(error, reply);
|
||||
if (!r) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
if (dbus_set_error_from_message(error, reply))
|
||||
return -EIO;
|
||||
|
||||
r = dbus_message_get_args(
|
||||
reply, error,
|
||||
DBUS_TYPE_STRING, scon,
|
||||
DBUS_TYPE_INVALID);
|
||||
if (!r) {
|
||||
r = -errno;
|
||||
goto finish;
|
||||
}
|
||||
if (!dbus_message_get_args(
|
||||
reply, error,
|
||||
DBUS_TYPE_STRING, scon,
|
||||
DBUS_TYPE_INVALID))
|
||||
return -EIO;
|
||||
|
||||
r = 0;
|
||||
finish:
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This mimics dbus_bus_get_unix_user() */
|
||||
static int bus_get_audit_data(
|
||||
DBusConnection *connection,
|
||||
const char *name,
|
||||
@ -222,7 +107,7 @@ static int bus_get_audit_data(
|
||||
|
||||
pid = bus_get_unix_process_id(connection, name, error);
|
||||
if (pid <= 0)
|
||||
return -EINVAL;
|
||||
return -EIO;
|
||||
|
||||
r = audit_loginuid_from_pid(pid, &audit->loginuid);
|
||||
if (r < 0)
|
||||
@ -247,26 +132,27 @@ static int bus_get_audit_data(
|
||||
Any time an access gets denied this callback will be called
|
||||
with the aduit data. We then need to just copy the audit data into the msgbuf.
|
||||
*/
|
||||
static int audit_callback(void *auditdata, security_class_t cls,
|
||||
char *msgbuf, size_t msgbufsize)
|
||||
{
|
||||
static int audit_callback(
|
||||
void *auditdata,
|
||||
security_class_t cls,
|
||||
char *msgbuf,
|
||||
size_t msgbufsize) {
|
||||
|
||||
struct auditstruct *audit = (struct auditstruct *) auditdata;
|
||||
|
||||
snprintf(msgbuf, msgbufsize,
|
||||
"auid=%d uid=%d gid=%d",
|
||||
"auid=%d uid=%d gid=%d%s%s%s%s%s%s",
|
||||
audit->loginuid,
|
||||
audit->uid, audit->gid);
|
||||
audit->uid,
|
||||
audit->gid,
|
||||
(audit->path ? " path=\"" : ""),
|
||||
strempty(audit->path),
|
||||
(audit->path ? "\"" : ""),
|
||||
(audit->cmdline ? " cmdline=\"" : ""),
|
||||
strempty(audit->cmdline),
|
||||
(audit->cmdline ? "\"" : ""));
|
||||
|
||||
if (audit->path) {
|
||||
strncat(msgbuf," path=\"", msgbufsize);
|
||||
strncat(msgbuf, audit->path, msgbufsize);
|
||||
strncat(msgbuf,"\"", msgbufsize);
|
||||
}
|
||||
|
||||
if (audit->cmdline) {
|
||||
strncat(msgbuf," cmdline=\"", msgbufsize);
|
||||
strncat(msgbuf, audit->cmdline, msgbufsize);
|
||||
strncat(msgbuf,"\"", msgbufsize);
|
||||
}
|
||||
msgbuf[msgbufsize-1] = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -277,24 +163,25 @@ static int audit_callback(void *auditdata, security_class_t cls,
|
||||
user_avc's into the /var/log/audit/audit.log, otherwise they will be
|
||||
sent to syslog.
|
||||
*/
|
||||
static int log_callback(int type, const char *fmt, ...)
|
||||
{
|
||||
static int log_callback(int type, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
|
||||
#ifdef HAVE_AUDIT
|
||||
if (audit_fd >= 0) {
|
||||
char buf[LINE_MAX*2];
|
||||
char buf[LINE_MAX];
|
||||
|
||||
vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC,
|
||||
buf, NULL, NULL, NULL, 0);
|
||||
audit_log_user_avc_message(audit_fd, AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
log_metav(LOG_USER | LOG_INFO, __FILE__, __LINE__, __FUNCTION__, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -304,42 +191,35 @@ static int log_callback(int type, const char *fmt, ...)
|
||||
If you want to cleanup memory you should need to call selinux_access_finish.
|
||||
*/
|
||||
static int access_init(void) {
|
||||
|
||||
int r = -1;
|
||||
int r;
|
||||
|
||||
if (avc_open(NULL, 0)) {
|
||||
log_error("avc_open failed: %m");
|
||||
log_error("avc_open() failed: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) &audit_callback);
|
||||
selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) &log_callback);
|
||||
selinux_set_callback(SELINUX_CB_SETENFORCE, (union selinux_callback) &setenforce_callback);
|
||||
selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback) audit_callback);
|
||||
selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback) log_callback);
|
||||
|
||||
if ((r = security_getenforce()) >= 0) {
|
||||
setenforce_callback(r);
|
||||
if (security_getenforce() >= 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
r = -errno;
|
||||
avc_destroy();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int selinux_init(Manager *m, DBusError *error) {
|
||||
|
||||
int r;
|
||||
|
||||
#ifdef HAVE_AUDIT
|
||||
audit_fd = m->audit_fd;
|
||||
#endif
|
||||
if (!first_time)
|
||||
if (initialized)
|
||||
return 0;
|
||||
|
||||
if (selinux_enabled < 0)
|
||||
selinux_enabled = is_selinux_enabled() == 1;
|
||||
|
||||
if (selinux_enabled) {
|
||||
/* if not first time is not set, then initialize access */
|
||||
if (use_selinux()) {
|
||||
r = access_init();
|
||||
if (r < 0) {
|
||||
dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to initialize SELinux.");
|
||||
@ -347,49 +227,46 @@ static int selinux_init(Manager *m, DBusError *error) {
|
||||
}
|
||||
}
|
||||
|
||||
first_time = 0;
|
||||
initialized = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_audit_data(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
struct auditstruct *audit,
|
||||
DBusError *error) {
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
struct auditstruct *audit,
|
||||
DBusError *error) {
|
||||
|
||||
const char *sender;
|
||||
int r;
|
||||
int r, fd;
|
||||
struct ucred ucred;
|
||||
socklen_t len;
|
||||
|
||||
sender = dbus_message_get_sender(message);
|
||||
if (sender)
|
||||
return bus_get_audit_data(connection, sender, audit, error);
|
||||
else {
|
||||
int fd;
|
||||
struct ucred ucred;
|
||||
socklen_t len;
|
||||
|
||||
if (!dbus_connection_get_unix_fd(connection, &fd))
|
||||
return -EINVAL;
|
||||
if (!dbus_connection_get_unix_fd(connection, &fd))
|
||||
return -EINVAL;
|
||||
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
|
||||
if (r < 0) {
|
||||
log_error("Failed to determine peer credentials: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
audit->uid = ucred.uid;
|
||||
audit->gid = ucred.gid;
|
||||
|
||||
r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
|
||||
if (r < 0) {
|
||||
log_error("Failed to determine peer credentials: %m");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
audit->uid = ucred.uid;
|
||||
audit->gid = ucred.gid;
|
||||
|
||||
r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -397,10 +274,10 @@ static int get_audit_data(
|
||||
connections. Whether it is on the bus or a local connection.
|
||||
*/
|
||||
static int get_calling_context(
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
security_context_t *scon,
|
||||
DBusError *error) {
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
security_context_t *scon,
|
||||
DBusError *error) {
|
||||
|
||||
const char *sender;
|
||||
int r;
|
||||
@ -414,14 +291,13 @@ static int get_calling_context(
|
||||
sender = dbus_message_get_sender(message);
|
||||
if (sender) {
|
||||
r = bus_get_selinux_security_context(connection, sender, scon, error);
|
||||
if (r == 0)
|
||||
return 0;
|
||||
if (r >= 0)
|
||||
return r;
|
||||
|
||||
log_debug("bus_get_selinux_security_context failed %m");
|
||||
}
|
||||
|
||||
r = dbus_connection_get_unix_fd(connection, &fd);
|
||||
if (! r) {
|
||||
if (!dbus_connection_get_unix_fd(connection, &fd)) {
|
||||
log_error("bus_connection_get_unix_fd failed %m");
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -435,54 +311,51 @@ static int get_calling_context(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
This function returns the SELinux permission to check and whether or not the
|
||||
check requires a unit file.
|
||||
*/
|
||||
static void selinux_perm_lookup(const char *method, const char **perm, bool *require_unit) {
|
||||
const char *m, *p;
|
||||
|
||||
NULSTR_FOREACH_PAIR(m, p, unit_methods)
|
||||
if (streq(method, m)) {
|
||||
*perm = p;
|
||||
*require_unit = true;
|
||||
return;
|
||||
}
|
||||
|
||||
NULSTR_FOREACH_PAIR(m, p, system_methods)
|
||||
if (streq(method, m)) {
|
||||
*perm = p;
|
||||
*require_unit = false;
|
||||
return;
|
||||
}
|
||||
|
||||
*require_unit = false;
|
||||
*perm = "undefined";
|
||||
}
|
||||
|
||||
/*
|
||||
This function communicates with the kernel to check whether or not it should
|
||||
allow the access.
|
||||
If the machine is in permissive mode it will return ok. Audit messages will
|
||||
still be generated if the access would be denied in enforcing mode.
|
||||
*/
|
||||
static int selinux_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error, const char *perm, const char *path) {
|
||||
security_context_t scon = NULL;
|
||||
security_context_t fcon = NULL;
|
||||
static int selinux_access_check(
|
||||
Manager *m,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
const char *path,
|
||||
const char *permission,
|
||||
DBusError *error) {
|
||||
|
||||
security_context_t scon = NULL, fcon = NULL;
|
||||
int r = 0;
|
||||
const char *tclass = NULL;
|
||||
struct auditstruct audit;
|
||||
|
||||
assert(m);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
assert(permission);
|
||||
assert(error);
|
||||
|
||||
r = selinux_init(m, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (!use_selinux())
|
||||
return 0;
|
||||
|
||||
log_debug("SELinux access check for path=%s permission=%s", strna(path), permission);
|
||||
|
||||
audit.uid = audit.loginuid = (uid_t) -1;
|
||||
audit.gid = (gid_t) -1;
|
||||
audit.cmdline = NULL;
|
||||
audit.path = path;
|
||||
|
||||
r = get_calling_context(connection, message, &scon, error);
|
||||
if (r != 0) {
|
||||
if (r < 0) {
|
||||
log_error("Failed to get caller's security context on: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (path) {
|
||||
tclass = "service";
|
||||
/* get the file context of the unit file */
|
||||
@ -490,7 +363,7 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message
|
||||
if (r < 0) {
|
||||
dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "Failed to get file context on %s.", path);
|
||||
r = -errno;
|
||||
log_error("Failed to get security context on: %s %m",path);
|
||||
log_error("Failed to get security context on %s: %m",path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@ -507,156 +380,92 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message
|
||||
|
||||
(void) get_audit_data(connection, message, &audit, error);
|
||||
|
||||
errno= 0;
|
||||
r = selinux_check_access(scon, fcon, tclass, perm, &audit);
|
||||
errno = 0;
|
||||
r = selinux_check_access(scon, fcon, tclass, permission, &audit);
|
||||
if (r < 0) {
|
||||
dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
|
||||
r = -errno;
|
||||
log_error("SELinux policy denies access.");
|
||||
dbus_set_error(error, DBUS_ERROR_ACCESS_DENIED, "SELinux policy denies access.");
|
||||
}
|
||||
|
||||
log_debug("SELinux checkaccess scon %s tcon %s tclass %s perm %s path %s cmdline %s: %d", scon, fcon, tclass, perm, path, audit.cmdline, r);
|
||||
log_debug("SELinux access check scon=%s tcon=%s tclass=%s perm=%s path=%s cmdline=%s: %i", scon, fcon, tclass, permission, path, audit.cmdline, r);
|
||||
|
||||
finish:
|
||||
free(audit.cmdline);
|
||||
freecon(scon);
|
||||
freecon(fcon);
|
||||
|
||||
if (r && security_getenforce() != 1) {
|
||||
dbus_error_init(error);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
Clean up memory allocated in selinux_avc_init
|
||||
*/
|
||||
int selinux_unit_access_check(
|
||||
Unit *u,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
const char *permission,
|
||||
DBusError *error) {
|
||||
|
||||
assert(u);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
assert(permission);
|
||||
assert(error);
|
||||
|
||||
return selinux_access_check(u->manager, connection, message, u->source_path ? u->source_path : u->fragment_path, permission, error);
|
||||
}
|
||||
|
||||
int selinux_manager_access_check(
|
||||
Manager *m,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
const char *permission,
|
||||
DBusError *error) {
|
||||
|
||||
assert(m);
|
||||
assert(connection);
|
||||
assert(message);
|
||||
assert(permission);
|
||||
assert(error);
|
||||
|
||||
return selinux_access_check(m, connection, message, NULL, permission, error);
|
||||
}
|
||||
|
||||
void selinux_access_finish(void) {
|
||||
if (!first_time)
|
||||
avc_destroy();
|
||||
first_time = 1;
|
||||
}
|
||||
if (!initialized)
|
||||
return;
|
||||
|
||||
int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) {
|
||||
const char *perm;
|
||||
bool require_unit;
|
||||
const char *member;
|
||||
int r;
|
||||
|
||||
log_debug("SELinux unit access check %s\n", path);
|
||||
r = selinux_init(m, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (! selinux_enabled)
|
||||
return 0;
|
||||
|
||||
member = dbus_message_get_member(message);
|
||||
|
||||
selinux_perm_lookup(member, &perm, &require_unit);
|
||||
log_debug("SELinux dbus-unit Look %s up perm %s require_unit %d", member, perm, require_unit);
|
||||
|
||||
r = selinux_access_check(connection, message, m, error, perm, path);
|
||||
|
||||
/* if SELinux is in permissive mode return 0 */
|
||||
if (r && (security_getenforce() != 1 )) {
|
||||
dbus_error_init(error);
|
||||
r = 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int selinux_manager_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error) {
|
||||
int r = -1;
|
||||
const char *member;
|
||||
bool require_unit;
|
||||
const char *perm;
|
||||
char *path = NULL;
|
||||
|
||||
log_debug("SELinux manager access check\n");
|
||||
r = selinux_init(m, error);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (! selinux_enabled)
|
||||
return 0;
|
||||
|
||||
member = dbus_message_get_member(message);
|
||||
|
||||
selinux_perm_lookup(member, &perm, &require_unit);
|
||||
log_debug("SELinux dbus-manager Lookup %s perm %s require_unit %d", member, perm, require_unit);
|
||||
|
||||
if (require_unit) {
|
||||
const char *name, *smode, *old_name = NULL;
|
||||
Unit *u;
|
||||
|
||||
if (! dbus_message_get_args(
|
||||
message,
|
||||
error,
|
||||
DBUS_TYPE_STRING, &old_name,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &smode,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_error_init(error);
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
error,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &smode,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_error_init(error);
|
||||
if (!dbus_message_get_args(
|
||||
message,
|
||||
error,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
r = -EINVAL;
|
||||
/* This is broken for now, if I can not get a name
|
||||
return success.
|
||||
*/
|
||||
log_error("SELinux dbus-manager failed to find unit %m");
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log_debug("SELinux dbus-manager load unit %s", name);
|
||||
r = manager_load_unit(m, name, NULL, error, &u);
|
||||
if (r < 0) {
|
||||
log_error("Unit %s is not loaded.", name);
|
||||
/* This is broken for now, if I can not load a unit
|
||||
return success.
|
||||
*/
|
||||
dbus_error_init(error);
|
||||
r = 0;
|
||||
goto finish;
|
||||
}
|
||||
|
||||
path = u->source_path ? u->source_path : u->fragment_path;
|
||||
if (!path) {
|
||||
// r = -1;
|
||||
log_error("Unit %s does not have path.", name);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
r = selinux_access_check(connection, message, m, error, perm, path);
|
||||
|
||||
finish:
|
||||
/* if SELinux is in permissive mode return 0 */
|
||||
if (r && (security_getenforce() != 1 )) {
|
||||
dbus_error_init(error);
|
||||
r = 0;
|
||||
}
|
||||
return r;
|
||||
avc_destroy();
|
||||
initialized = false;
|
||||
}
|
||||
|
||||
#else
|
||||
int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) {
|
||||
|
||||
int selinux_unit_access_check(
|
||||
Unit *u,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
const char *permission,
|
||||
DBusError *error) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int selinux_manager_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error) {
|
||||
int selinux_manager_access_check(
|
||||
Manager *m,
|
||||
DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
const char *permission,
|
||||
DBusError *error) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void selinux_access_finish(void) {
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,7 +1,6 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#ifndef selinuxaccesshfoo
|
||||
#define selinuxaccesshfoo
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
@ -23,6 +22,38 @@
|
||||
***/
|
||||
|
||||
void selinux_access_finish(void);
|
||||
int selinux_manager_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, DBusError *error);
|
||||
int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error);
|
||||
int selinux_manager_access_check(Manager *manager, DBusConnection *connection, DBusMessage *message, const char *permission, DBusError *error);
|
||||
int selinux_unit_access_check(Unit *unit, DBusConnection *connection, DBusMessage *message, const char *permission, DBusError *error);
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
|
||||
#define SELINUX_MANAGER_ACCESS_CHECK(manager, connection, message, permission) \
|
||||
do { \
|
||||
DBusError _error; \
|
||||
int _r; \
|
||||
DBusConnection *_c = (connection); \
|
||||
DBusMessage *_m = (message); \
|
||||
dbus_error_init(&_error); \
|
||||
_r = selinux_manager_access_check((manager), _c, _m, (permission), &_error); \
|
||||
if (_r < 0) \
|
||||
return bus_send_error_reply(_c, _m, &_error, _r); \
|
||||
} while (false)
|
||||
|
||||
#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) \
|
||||
do { \
|
||||
DBusError _error; \
|
||||
int _r; \
|
||||
DBusConnection *_c = (connection); \
|
||||
DBusMessage *_m = (message); \
|
||||
dbus_error_init(&_error); \
|
||||
_r = selinux_unit_access_check((unit), _c, _m, (permission), &_error); \
|
||||
if (_r < 0) \
|
||||
return bus_send_error_reply(_c, _m, &_error, _r); \
|
||||
} while (false)
|
||||
|
||||
#else
|
||||
|
||||
#define SELINUX_MANAGER_ACCESS_CHECK(manager, connection, message, permission) do { } while (false)
|
||||
#define SELINUX_UNIT_ACCESS_CHECK(unit, connection, message, permission) do { } while (false)
|
||||
|
||||
#endif
|
||||
|
@ -30,11 +30,12 @@
|
||||
#endif
|
||||
|
||||
#include "selinux-setup.h"
|
||||
#include "selinux-util.h"
|
||||
#include "label.h"
|
||||
#include "mount-setup.h"
|
||||
#include "macro.h"
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
#include "label.h"
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
static int null_log(int type, const char *fmt, ...) {
|
||||
@ -83,7 +84,7 @@ int selinux_setup(bool *loaded_policy) {
|
||||
char timespan[FORMAT_TIMESPAN_MAX];
|
||||
char *label;
|
||||
|
||||
label_retest_selinux();
|
||||
retest_selinux();
|
||||
|
||||
/* Transition to the new context */
|
||||
r = label_get_create_label_from_exe(SYSTEMD_BINARY_PATH, &label);
|
||||
|
@ -229,7 +229,8 @@ int bus_connect_system_polkit(DBusConnection **_bus, DBusError *error) {
|
||||
|
||||
dbus_connection_set_exit_on_disconnect(bus, FALSE);
|
||||
|
||||
if ((r = sync_auth(bus, error)) < 0) {
|
||||
r = sync_auth(bus, error);
|
||||
if (r < 0) {
|
||||
dbus_connection_close(bus);
|
||||
dbus_connection_unref(bus);
|
||||
return r;
|
||||
@ -273,7 +274,7 @@ DBusHandlerResult bus_default_message_handler(
|
||||
const BusBoundProperties *bound_properties) {
|
||||
|
||||
DBusError error;
|
||||
DBusMessage *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
int r;
|
||||
|
||||
assert(c);
|
||||
@ -283,7 +284,8 @@ DBusHandlerResult bus_default_message_handler(
|
||||
|
||||
if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect") && introspection) {
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID))
|
||||
@ -334,14 +336,12 @@ get_prop:
|
||||
data = (char*)bp->base + p->offset;
|
||||
if (p->indirect)
|
||||
data = *(void**)data;
|
||||
r = p->append(&sub, property, data);
|
||||
if (r < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
r = p->append(&sub, property, data);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(c, message, NULL, r);
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_close_container(&iter, &sub))
|
||||
goto oom;
|
||||
@ -364,7 +364,8 @@ get_prop:
|
||||
return bus_send_error_reply(c, message, &error, -EINVAL);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_method_return(message)))
|
||||
reply = dbus_message_new_method_return(message);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
dbus_message_iter_init_append(reply, &iter);
|
||||
@ -388,13 +389,10 @@ get_prop:
|
||||
if (p->indirect)
|
||||
data = *(void**)data;
|
||||
r = p->append(&sub3, p->property, data);
|
||||
if (r < 0) {
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
if (r == -ENOMEM)
|
||||
goto oom;
|
||||
if (r < 0)
|
||||
return bus_send_error_reply(c, message, NULL, r);
|
||||
}
|
||||
|
||||
if (!dbus_message_iter_close_container(&sub2, &sub3) ||
|
||||
!dbus_message_iter_close_container(&sub, &sub2))
|
||||
@ -506,16 +504,12 @@ set_prop:
|
||||
if (!dbus_connection_send(c, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
oom:
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
|
||||
dbus_error_free(&error);
|
||||
|
||||
return DBUS_HANDLER_RESULT_NEED_MEMORY;
|
||||
@ -720,7 +714,7 @@ const char *bus_errno_to_dbus(int error) {
|
||||
}
|
||||
|
||||
DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message, DBusError *berror, int error) {
|
||||
DBusMessage *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
const char *name, *text;
|
||||
|
||||
if (berror && dbus_error_is_set(berror)) {
|
||||
@ -731,14 +725,13 @@ DBusHandlerResult bus_send_error_reply(DBusConnection *c, DBusMessage *message,
|
||||
text = strerror(-error);
|
||||
}
|
||||
|
||||
if (!(reply = dbus_message_new_error(message, name, text)))
|
||||
reply = dbus_message_new_error(message, name, text);
|
||||
if (!reply)
|
||||
goto oom;
|
||||
|
||||
if (!dbus_connection_send(c, reply, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
|
||||
if (berror)
|
||||
dbus_error_free(berror);
|
||||
|
||||
@ -896,7 +889,8 @@ int bus_parse_strv_iter(DBusMessageIter *iter, char ***_l) {
|
||||
dbus_message_iter_next(&sub);
|
||||
}
|
||||
|
||||
if (!(l = new(char*, n+1)))
|
||||
l = new(char*, n+1);
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
dbus_message_iter_recurse(iter, &sub);
|
||||
@ -1126,7 +1120,7 @@ static void release_name_pending_cb(DBusPendingCall *pending, void *userdata) {
|
||||
}
|
||||
|
||||
void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
|
||||
DBusMessage *m = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
|
||||
DBusPendingCall *pending = NULL;
|
||||
|
||||
assert(bus);
|
||||
@ -1156,7 +1150,6 @@ void bus_async_unregister_and_exit(DBusConnection *bus, const char *name) {
|
||||
if (!dbus_pending_call_set_notify(pending, release_name_pending_cb, bus, NULL))
|
||||
goto oom;
|
||||
|
||||
dbus_message_unref(m);
|
||||
dbus_pending_call_unref(pending);
|
||||
|
||||
return;
|
||||
@ -1168,9 +1161,6 @@ oom:
|
||||
dbus_pending_call_cancel(pending);
|
||||
dbus_pending_call_unref(pending);
|
||||
}
|
||||
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
}
|
||||
|
||||
DBusHandlerResult bus_exit_idle_filter(DBusConnection *bus, DBusMessage *m, void *userdata) {
|
||||
@ -1195,7 +1185,7 @@ pid_t bus_get_unix_process_id(
|
||||
const char *name,
|
||||
DBusError *error) {
|
||||
|
||||
DBusMessage *m = NULL, *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *m = NULL, *reply = NULL;
|
||||
uint32_t pid = 0;
|
||||
|
||||
m = dbus_message_new_method_call(
|
||||
@ -1205,7 +1195,7 @@ pid_t bus_get_unix_process_id(
|
||||
"GetConnectionUnixProcessID");
|
||||
if (!m) {
|
||||
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto finish;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!dbus_message_append_args(
|
||||
@ -1213,28 +1203,21 @@ pid_t bus_get_unix_process_id(
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
|
||||
goto finish;
|
||||
return 0;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error);
|
||||
if (!reply)
|
||||
goto finish;
|
||||
return 0;
|
||||
|
||||
if (dbus_set_error_from_message(error, reply))
|
||||
goto finish;
|
||||
return 0;
|
||||
|
||||
if (!dbus_message_get_args(
|
||||
reply, error,
|
||||
DBUS_TYPE_UINT32, &pid,
|
||||
DBUS_TYPE_INVALID))
|
||||
goto finish;
|
||||
|
||||
finish:
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (reply)
|
||||
dbus_message_unref(reply);
|
||||
return 0;
|
||||
|
||||
return (pid_t) pid;
|
||||
}
|
||||
@ -1265,7 +1248,8 @@ int bus_method_call_with_reply(
|
||||
int first_arg_type, ...) {
|
||||
|
||||
DBusError error;
|
||||
DBusMessage *m, *reply;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *m = NULL;
|
||||
DBusMessage *reply;
|
||||
va_list ap;
|
||||
int r = 0;
|
||||
|
||||
@ -1308,9 +1292,6 @@ int bus_method_call_with_reply(
|
||||
dbus_message_unref(reply);
|
||||
|
||||
finish:
|
||||
if (m)
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (return_error)
|
||||
*return_error = error;
|
||||
else
|
||||
@ -1319,8 +1300,27 @@ finish:
|
||||
return r;
|
||||
}
|
||||
|
||||
void bus_message_unrefp(DBusMessage **reply) {
|
||||
if (!reply)
|
||||
return;
|
||||
|
||||
void dbus_message_unref_p(DBusMessage **reply) {
|
||||
if (*reply)
|
||||
dbus_message_unref(*reply);
|
||||
if (!*reply)
|
||||
return;
|
||||
|
||||
dbus_message_unref(*reply);
|
||||
}
|
||||
|
||||
const char *bus_message_get_sender_with_fallback(DBusMessage *m) {
|
||||
const char *s;
|
||||
|
||||
assert(m);
|
||||
|
||||
s = dbus_message_get_sender(m);
|
||||
if (s)
|
||||
return s;
|
||||
|
||||
/* When the message came in from a direct connection the
|
||||
* message will have no sender. We fix that here. */
|
||||
|
||||
return ":no-sender";
|
||||
}
|
||||
|
@ -214,5 +214,8 @@ int bus_method_call_with_reply(DBusConnection *bus,
|
||||
DBusError *return_error,
|
||||
int first_arg_type, ...);
|
||||
|
||||
void dbus_message_unref_p(DBusMessage **reply);
|
||||
#define _cleanup_dbus_msg_unref_ __attribute__((cleanup(dbus_message_unref_p)))
|
||||
const char *bus_message_get_sender_with_fallback(DBusMessage *m);
|
||||
|
||||
void bus_message_unrefp(DBusMessage **reply);
|
||||
|
||||
#define _cleanup_dbus_message_unref_ __attribute__((cleanup(bus_message_unrefp)))
|
||||
|
@ -31,25 +31,12 @@
|
||||
#include "path-util.h"
|
||||
|
||||
#ifdef HAVE_SELINUX
|
||||
#include "selinux-util.h"
|
||||
#include <selinux/selinux.h>
|
||||
#include <selinux/label.h>
|
||||
|
||||
static struct selabel_handle *label_hnd = NULL;
|
||||
|
||||
static int use_selinux_cached = -1;
|
||||
|
||||
static inline bool use_selinux(void) {
|
||||
|
||||
if (use_selinux_cached < 0)
|
||||
use_selinux_cached = is_selinux_enabled() > 0;
|
||||
|
||||
return use_selinux_cached;
|
||||
}
|
||||
|
||||
void label_retest_selinux(void) {
|
||||
use_selinux_cached = -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int label_init(const char *prefix) {
|
||||
|
38
src/shared/selinux-util.c
Normal file
38
src/shared/selinux-util.c
Normal file
@ -0,0 +1,38 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <selinux/selinux.h>
|
||||
|
||||
#include "selinux-util.h"
|
||||
|
||||
static int use_selinux_cached = -1;
|
||||
|
||||
bool use_selinux(void) {
|
||||
|
||||
if (use_selinux_cached < 0)
|
||||
use_selinux_cached = is_selinux_enabled() > 0;
|
||||
|
||||
return use_selinux_cached;
|
||||
}
|
||||
|
||||
void retest_selinux(void) {
|
||||
use_selinux_cached = -1;
|
||||
}
|
27
src/shared/selinux-util.h
Normal file
27
src/shared/selinux-util.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2010 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation; either version 2.1 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
systemd is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool use_selinux(void);
|
||||
void retest_selinux(void);
|
@ -1445,7 +1445,7 @@ static void check_triggering_units(
|
||||
DBusConnection *bus,
|
||||
const char *unit_name) {
|
||||
|
||||
DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
DBusMessageIter iter, sub;
|
||||
char *service_trigger = NULL;
|
||||
const char *interface = "org.freedesktop.systemd1.Unit",
|
||||
@ -1523,7 +1523,7 @@ static int start_unit_one(
|
||||
DBusError *error,
|
||||
Set *s) {
|
||||
|
||||
DBusMessage _cleanup_dbus_msg_unref_ *reply = NULL;
|
||||
_cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
|
||||
const char *path;
|
||||
int r;
|
||||
_cleanup_free_ char *n, *p = NULL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user