selinux: use existing library calls for audit data

This commit is contained in:
Lennart Poettering 2012-09-18 01:55:49 +02:00
parent aba15a0391
commit c309067483
5 changed files with 64 additions and 155 deletions

View file

@ -1038,6 +1038,7 @@ libsystemd_core_la_LIBADD = \
libsystemd-label.la \ libsystemd-label.la \
libsystemd-shared.la \ libsystemd-shared.la \
libsystemd-dbus.la \ libsystemd-dbus.la \
libsystemd-audit.la \
libsystemd-id128-internal.la \ libsystemd-id128-internal.la \
libudev.la \ libudev.la \
$(LIBWRAP_LIBS) \ $(LIBWRAP_LIBS) \

2
TODO
View file

@ -26,6 +26,8 @@ F18:
* https://bugzilla.gnome.org/show_bug.cgi?id=680689 * https://bugzilla.gnome.org/show_bug.cgi?id=680689
* Retest multi-seat
* selinux: merge systemd selinux access controls (dwalsh) * selinux: merge systemd selinux access controls (dwalsh)
Features: Features:

View file

@ -580,7 +580,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection,
member = dbus_message_get_member(message); member = dbus_message_get_member(message);
r = selinux_manager_access_check(connection, message, m, &error); r = selinux_manager_access_check(connection, message, m, &error);
if (r) if (r < 0)
return bus_send_error_reply(connection, message, &error, r); return bus_send_error_reply(connection, message, &error, r);
if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) { if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) {

View file

@ -734,7 +734,8 @@ int manager_add_job_by_name(Manager *m, JobType type, const char *name, JobMode
assert(name); assert(name);
assert(mode < _JOB_MODE_MAX); assert(mode < _JOB_MODE_MAX);
if ((r = manager_load_unit(m, name, NULL, NULL, &unit)) < 0) r = manager_load_unit(m, name, NULL, NULL, &unit);
if (r < 0)
return r; return r;
return manager_add_job(m, type, unit, mode, override, e, _ret); return manager_add_job(m, type, unit, mode, override, e, _ret);
@ -846,7 +847,8 @@ int manager_load_unit(Manager *m, const char *name, const char *path, DBusError
/* This will load the service information files, but not actually /* This will load the service information files, but not actually
* start any services or anything. */ * start any services or anything. */
if ((r = manager_load_unit_prepare(m, name, path, e, _ret)) != 0) r = manager_load_unit_prepare(m, name, path, e, _ret);
if (r != 0)
return r; return r;
manager_dispatch_load_queue(m); manager_dispatch_load_queue(m);

View file

@ -1,4 +1,3 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/*** /***
@ -31,6 +30,7 @@
#include "dbus-unit.h" #include "dbus-unit.h"
#include "bus-errors.h" #include "bus-errors.h"
#include "dbus-common.h" #include "dbus-common.h"
#include "audit.h"
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
@ -212,49 +212,6 @@ finish:
return r; return r;
} }
static int get_cmdline(pid_t pid, char **cmdline) {
char buf[PATH_MAX];
FILE *f;
int count;
int n;
snprintf(buf, sizeof(buf), "/proc/%lu/cmdline", (unsigned long) pid);
f = fopen(buf, "re");
if (!f) {
return -errno;
}
count = fread(buf, 1, sizeof(buf), f);
fclose(f);
if (! count) {
return -errno;
}
for (n = 0; n < count - 1; n++)
{
if (buf[n] == '\0')
buf[n] = ' ';
}
(*cmdline) = strdup(buf);
if (! (*cmdline)) {
return -errno;
}
return 0;
}
static int get_pid_id(pid_t pid, const char *file, uid_t *id) {
char buf[PATH_MAX];
int r = 0;
FILE *f;
snprintf(buf, sizeof(buf), "/proc/%lu/%s", (unsigned long) pid, file);
f = fopen(buf, "re");
if (!f)
return -errno;
fscanf(f, "%d", id);
if (ferror(f))
r = -errno;
fclose(f);
return r;
}
/* This mimics dbus_bus_get_unix_user() */ /* This mimics dbus_bus_get_unix_user() */
static int bus_get_audit_data( static int bus_get_audit_data(
DBusConnection *connection, DBusConnection *connection,
@ -263,74 +220,29 @@ static int bus_get_audit_data(
DBusError *error) { DBusError *error) {
pid_t pid; pid_t pid;
DBusMessage *m = NULL, *reply = NULL; int r;
int r = -1;
m = dbus_message_new_method_call( pid = bus_get_unix_process_id(connection, name, error);
DBUS_SERVICE_DBUS, if (pid <= 0)
DBUS_PATH_DBUS, return -EINVAL;
DBUS_INTERFACE_DBUS,
"GetConnectionUnixProcessID");
if (!m) {
r = -errno;
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
goto finish;
}
r = dbus_message_append_args( r = audit_loginuid_from_pid(pid, &audit->loginuid);
m, if (r < 0)
DBUS_TYPE_STRING, &name, return r;
DBUS_TYPE_INVALID);
if (!r) {
r = -errno;
dbus_set_error_const(error, DBUS_ERROR_NO_MEMORY, NULL);
goto finish;
}
reply = dbus_connection_send_with_reply_and_block(connection, m, -1, error); r = get_process_uid(pid, &audit->uid);
if (!reply) { if (r < 0)
r = -errno; return r;
goto finish;
}
r = dbus_set_error_from_message(error, reply); r = get_process_gid(pid, &audit->gid);
if (!r) { if (r < 0)
r = -errno; return r;
goto finish;
}
r = dbus_message_get_args( r = get_process_cmdline(pid, LINE_MAX, true, &audit->cmdline);
reply, error, if (r < 0)
DBUS_TYPE_UINT32, &pid, return r;
DBUS_TYPE_INVALID);
if (!r) {
r = -errno;
goto finish;
}
r = get_pid_id(pid, "loginuid", &(audit->loginuid)); return 0;
if (r)
goto finish;
r = get_pid_id(pid, "uid", &(audit->uid));
if (r)
goto finish;
r = get_pid_id(pid, "gid", &(audit->gid));
if (r)
goto finish;
r = get_cmdline(pid, &(audit->cmdline));
if (r)
goto finish;
r = 0;
finish:
if (m)
dbus_message_unref(m);
if (reply)
dbus_message_unref(reply);
return r;
} }
/* /*
@ -435,49 +347,38 @@ static int get_audit_data(
DBusError *error) { DBusError *error) {
const char *sender; const char *sender;
int r = -1; int r;
sender = dbus_message_get_sender(message); sender = dbus_message_get_sender(message);
if (sender) { if (sender)
r = bus_get_audit_data( return bus_get_audit_data(connection, sender, audit, error);
connection, else {
sender,
audit,
error);
if (r)
goto finish;
} else {
int fd; int fd;
struct ucred ucred; struct ucred ucred;
socklen_t len; socklen_t len;
r = dbus_connection_get_unix_fd(connection, &fd);
if (!r) { if (!dbus_connection_get_unix_fd(connection, &fd))
r = -EINVAL; return -EINVAL;
goto finish;
}
r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len); r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len);
if (r < 0) { if (r < 0) {
r = -errno;
log_error("Failed to determine peer credentials: %m"); log_error("Failed to determine peer credentials: %m");
goto finish; return -errno;
} }
audit->uid = ucred.uid; audit->uid = ucred.uid;
audit->gid = ucred.gid; audit->gid = ucred.gid;
r = get_pid_id(ucred.pid, "loginuid", &(audit->loginuid)); r = audit_loginuid_from_pid(ucred.pid, &audit->loginuid);
if (r) if (r < 0)
goto finish; return r;
r = get_cmdline(ucred.pid, &(audit->cmdline)); r = get_process_cmdline(ucred.pid, LINE_MAX, true, &audit->cmdline);
if (r) if (r < 0)
goto finish; return r;
return 0;
} }
r = 0;
finish:
return r;
} }
/* /*
@ -561,7 +462,9 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message
int r = 0; int r = 0;
const char *tclass = NULL; const char *tclass = NULL;
struct auditstruct audit; struct auditstruct audit;
audit.uid = audit.loginuid = audit.gid = -1;
audit.uid = audit.loginuid = (uid_t) -1;
audit.gid = (gid_t) -1;
audit.cmdline = NULL; audit.cmdline = NULL;
audit.path = path; audit.path = path;
@ -589,9 +492,9 @@ static int selinux_access_check(DBusConnection *connection, DBusMessage *message
(void) get_audit_data(connection, message, &audit, error); (void) get_audit_data(connection, message, &audit, error);
errno=0; errno= 0;
r = selinux_check_access(scon, fcon, tclass, perm, &audit); r = selinux_check_access(scon, fcon, tclass, perm, &audit);
if ( r < 0) { if (r < 0) {
r = -errno; r = -errno;
log_error("SELinux Denied \"%s\"", audit.cmdline); log_error("SELinux Denied \"%s\"", audit.cmdline);
@ -622,21 +525,23 @@ void selinux_access_finish(void) {
int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) { int selinux_unit_access_check(DBusConnection *connection, DBusMessage *message, Manager *m, const char *path, DBusError *error) {
const char *perm; const char *perm;
int require_unit; int require_unit;
const char *member = dbus_message_get_member(message); const char *member;
int r; int r;
r = selinux_init(m, error); r = selinux_init(m, error);
if (r) if (r < 0)
return r; return r;
if (! selinux_enabled) if (! selinux_enabled)
return 0; return 0;
member = dbus_message_get_member(message);
selinux_perm_lookup(member, &perm, &require_unit); selinux_perm_lookup(member, &perm, &require_unit);
log_debug("SELinux dbus-unit Look %s up perm %s require_unit %d", 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); r = selinux_access_check(connection, message, m, error, perm, path);
if ((r < 0) && (!selinux_enforcing)) { if (r < 0 && !selinux_enforcing) {
dbus_error_init(error); dbus_error_init(error);
r = 0; r = 0;
} }
@ -652,7 +557,7 @@ int selinux_manager_access_check(DBusConnection *connection, DBusMessage *messag
char *path = NULL; char *path = NULL;
r = selinux_init(m, error); r = selinux_init(m, error);
if (r) if (r < 0)
return r; return r;
if (! selinux_enabled) if (! selinux_enabled)
@ -667,21 +572,19 @@ int selinux_manager_access_check(DBusConnection *connection, DBusMessage *messag
const char *name; const char *name;
Unit *u; Unit *u;
r = dbus_message_get_args( if (!dbus_message_get_args(
message, message,
error, error,
DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID); DBUS_TYPE_INVALID)) {
if (!r) r = -EINVAL;
goto finish; goto finish;
}
u = manager_get_unit(m, name); r = manager_load_unit(m, name, NULL, error, &u);
if ( !u ) { if (r < 0) {
if ((r = manager_load_unit(m, name, NULL, error, &u)) < 0) { dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
r = -errno; goto finish;
dbus_set_error(error, BUS_ERROR_NO_SUCH_UNIT, "Unit %s is not loaded.", name);
goto finish;
}
} }
path = u->source_path ? u->source_path : u->fragment_path; path = u->source_path ? u->source_path : u->fragment_path;
@ -706,5 +609,6 @@ int selinux_manager_access_check(DBusConnection *connection, DBusMessage *messag
return 0; return 0;
} }
void selinux_access_finish(void) {} void selinux_access_finish(void) {
}
#endif #endif