From: Lennart Poettering Date: Tue, 2 Oct 2012 21:40:09 +0000 (-0400) Subject: audit: turn the audit fd into a static variable X-Git-Tag: v194~11 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=c1165f822cd9f8c3467b5f825ce933ab8374b361 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. --- diff --git a/Makefile.am b/Makefile.am index 031e1ac27..683685192 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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 \ diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c new file mode 100644 index 000000000..0a8626fbc --- /dev/null +++ b/src/core/audit-fd.c @@ -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 . +***/ + +#include +#include + +#include "audit-fd.h" +#include "log.h" + +#ifdef HAVE_AUDIT + +#include + +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 diff --git a/src/core/audit-fd.h b/src/core/audit-fd.h new file mode 100644 index 000000000..8b58289dc --- /dev/null +++ b/src/core/audit-fd.h @@ -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 . +***/ + +int get_audit_fd(void); +void close_audit_fd(void); diff --git a/src/core/manager.c b/src/core/manager.c index 3cd99154e..6fecbc3f7 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -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"); } diff --git a/src/core/manager.h b/src/core/manager.h index 913752f9e..22145024f 100644 --- a/src/core/manager.h +++ b/src/core/manager.h @@ -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; diff --git a/src/core/selinux-access.c b/src/core/selinux-access.c index 3a244ad9f..9ddc042ec 100644 --- a/src/core/selinux-access.c +++ b/src/core/selinux-access.c @@ -32,6 +32,7 @@ #include "dbus-common.h" #include "audit.h" #include "selinux-util.h" +#include "audit-fd.h" #include #include @@ -44,7 +45,6 @@ #include 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) { diff --git a/src/shared/audit.h b/src/shared/audit.h index f2740bc42..490a0b032 100644 --- a/src/shared/audit.h +++ b/src/shared/audit.h @@ -22,8 +22,11 @@ along with systemd; If not, see . ***/ +#include + #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