chiark / gitweb /
audit: turn the audit fd into a static variable
authorLennart Poettering <lennart@poettering.net>
Tue, 2 Oct 2012 21:40:09 +0000 (17:40 -0400)
committerLennart Poettering <lennart@poettering.net>
Tue, 2 Oct 2012 21:40:09 +0000 (17:40 -0400)
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.

Makefile.am
src/core/audit-fd.c [new file with mode: 0644]
src/core/audit-fd.h [new file with mode: 0644]
src/core/manager.c
src/core/manager.h
src/core/selinux-access.c
src/shared/audit.h

index 031e1ac..6836851 100644 (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 \
diff --git a/src/core/audit-fd.c b/src/core/audit-fd.c
new file mode 100644 (file)
index 0000000..0a8626f
--- /dev/null
@@ -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
diff --git a/src/core/audit-fd.h b/src/core/audit-fd.h
new file mode 100644 (file)
index 0000000..8b58289
--- /dev/null
@@ -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);
index 3cd9915..6fecbc3 100644 (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");
         }
index 913752f..2214502 100644 (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;
index 3a244ad..9ddc042 100644 (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) {
index f2740bc..490a0b0 100644 (file)
   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