audit: turn the audit fd into a static variable

As audit is pretty much just a special kind of logging we should treat
it similar, and manage the audit fd in a static variable.

This simplifies the audit fd sharing with the SELinux access checking
code quite a bit.
This commit is contained in:
Lennart Poettering 2012-10-02 17:40:09 -04:00
parent cad45ba11e
commit c1165f822c
7 changed files with 115 additions and 39 deletions

View File

@ -1020,7 +1020,9 @@ libsystemd_core_la_SOURCES = \
src/core/killall.h \
src/core/killall.c \
src/core/syscall-list.c \
src/core/syscall-list.h
src/core/syscall-list.h \
src/core/audit-fd.c \
src/core/audit-fd.h
nodist_libsystemd_core_la_SOURCES = \
src/core/load-fragment-gperf.c \

71
src/core/audit-fd.c Normal file
View File

@ -0,0 +1,71 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
/***
This file is part of systemd.
Copyright 2012 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>
#include <errno.h>
#include "audit-fd.h"
#include "log.h"
#ifdef HAVE_AUDIT
#include <libaudit.h>
static bool initialized = false;
static int audit_fd;
int get_audit_fd(void) {
if (!initialized) {
audit_fd = audit_open();
if (audit_fd < 0) {
if (errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
log_error("Failed to connect to audit log: %m");
audit_fd = errno ? -errno : -EINVAL;
}
initialized = true;
}
return audit_fd;
}
void close_audit_fd(void) {
if (initialized && audit_fd >= 0)
close_nointr_nofail(audit_fd);
initialized = true;
audit_fd = -ECONNRESET;
}
#else
int get_audit_fd(void) {
return -EAFNOSUPPORT;
}
void close_audit_fd(void) {
}
#endif

25
src/core/audit-fd.h Normal file
View File

@ -0,0 +1,25 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
Copyright 2012 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/>.
***/
int get_audit_fd(void);
void close_audit_fd(void);

View File

@ -68,6 +68,7 @@
#include "watchdog.h"
#include "cgroup-util.h"
#include "path-util.h"
#include "audit-fd.h"
/* As soon as 16 units are in our GC queue, make sure to run a gc sweep */
#define GC_QUEUE_ENTRIES_MAX 16
@ -257,10 +258,6 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
m->pin_cgroupfs_fd = -1;
m->idle_pipe[0] = m->idle_pipe[1] = -1;
#ifdef HAVE_AUDIT
m->audit_fd = -1;
#endif
m->signal_watch.fd = m->mount_watch.fd = m->udev_watch.fd = m->epoll_fd = m->dev_autofs_fd = m->swap_watch.fd = -1;
m->current_job_id = 1; /* start as id #1, so that we can leave #0 around as "null-like" value */
@ -307,14 +304,6 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) {
if ((r = bus_init(m, running_as != SYSTEMD_SYSTEM)) < 0)
goto fail;
#ifdef HAVE_AUDIT
if ((m->audit_fd = audit_open()) < 0 &&
/* If the kernel lacks netlink or audit support,
* don't worry about it. */
errno != EAFNOSUPPORT && errno != EPROTONOSUPPORT)
log_error("Failed to connect to audit log: %m");
#endif
m->taint_usr = dir_is_empty("/usr") > 0;
*_m = m;
@ -498,11 +487,6 @@ void manager_free(Manager *m) {
if (m->notify_watch.fd >= 0)
close_nointr_nofail(m->notify_watch.fd);
#ifdef HAVE_AUDIT
if (m->audit_fd >= 0)
audit_close(m->audit_fd);
#endif
free(m->notify_socket);
lookup_paths_free(&m->lookup_paths);
@ -1553,8 +1537,10 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
#ifdef HAVE_AUDIT
char *p;
int audit_fd;
if (m->audit_fd < 0)
audit_fd = get_audit_fd();
if (audit_fd < 0)
return;
/* Don't generate audit events if the service was already
@ -1573,12 +1559,11 @@ void manager_send_unit_audit(Manager *m, Unit *u, int type, bool success) {
return;
}
if (audit_log_user_comm_message(m->audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
if (audit_log_user_comm_message(audit_fd, type, "", p, NULL, NULL, NULL, success) < 0) {
if (errno == EPERM) {
/* We aren't allowed to send audit messages?
* Then let's not retry again. */
audit_close(m->audit_fd);
m->audit_fd = -1;
close_audit_fd();
} else
log_warning("Failed to send audit message: %m");
}

View File

@ -200,11 +200,6 @@ struct Manager {
* file system */
int pin_cgroupfs_fd;
/* Audit fd */
#ifdef HAVE_AUDIT
int audit_fd;
#endif
/* Flags */
SystemdRunningAs running_as;
ManagerExitCode exit_code:5;

View File

@ -32,6 +32,7 @@
#include "dbus-common.h"
#include "audit.h"
#include "selinux-util.h"
#include "audit-fd.h"
#include <stdio.h>
#include <string.h>
@ -44,7 +45,6 @@
#include <limits.h>
static bool initialized = false;
static int audit_fd = -1;
struct auditstruct {
const char *path;
@ -169,11 +169,11 @@ static int log_callback(int type, const char *fmt, ...) {
va_start(ap, fmt);
#ifdef HAVE_AUDIT
if (audit_fd >= 0) {
if (get_audit_fd() >= 0) {
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(get_audit_fd(), AUDIT_USER_AVC, buf, NULL, NULL, NULL, 0);
va_end(ap);
return 0;
@ -210,12 +210,9 @@ static int access_init(void) {
return r;
}
static int selinux_init(Manager *m, DBusError *error) {
static int selinux_init(DBusError *error) {
int r;
#ifdef HAVE_AUDIT
audit_fd = m->audit_fd;
#endif
if (initialized)
return 0;
@ -318,7 +315,6 @@ static int get_calling_context(
still be generated if the access would be denied in enforcing mode.
*/
static int selinux_access_check(
Manager *m,
DBusConnection *connection,
DBusMessage *message,
const char *path,
@ -330,13 +326,12 @@ static int selinux_access_check(
const char *tclass = NULL;
struct auditstruct audit;
assert(m);
assert(connection);
assert(message);
assert(permission);
assert(error);
r = selinux_init(m, error);
r = selinux_init(error);
if (r < 0)
return r;
@ -416,7 +411,7 @@ int selinux_unit_access_check(
assert(permission);
assert(error);
return selinux_access_check(u->manager, connection, message, u->source_path ? u->source_path : u->fragment_path, permission, error);
return selinux_access_check(connection, message, u->source_path ? u->source_path : u->fragment_path, permission, error);
}
int selinux_manager_access_check(
@ -432,7 +427,7 @@ int selinux_manager_access_check(
assert(permission);
assert(error);
return selinux_access_check(m, connection, message, NULL, permission, error);
return selinux_access_check(connection, message, NULL, permission, error);
}
void selinux_access_finish(void) {

View File

@ -22,8 +22,11 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <sys/types.h>
#include "capability.h"
int audit_session_from_pid(pid_t pid, uint32_t *id);
int audit_loginuid_from_pid(pid_t pid, uid_t *uid);
#endif