chiark / gitweb /
journald: Do not always record _AUDIT_SESSION and _AUDIT_LOGINUID
[elogind.git] / src / journal / journald-server.c
index 654f7ace2177e2f309a4ff92d7cc27ab3e02c223..28ce69dccd6b764e989d3bcf5579b86238e42ab3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/sockios.h>
 #include <sys/statvfs.h>
 #include <sys/mman.h>
+#include <sys/timerfd.h>
 
 #include <libudev.h>
 #include <systemd/sd-journal.h>
@@ -67,6 +68,7 @@
 
 #define USER_JOURNALS_MAX 1024
 
+#define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE)
 #define DEFAULT_RATE_LIMIT_INTERVAL (10*USEC_PER_SEC)
 #define DEFAULT_RATE_LIMIT_BURST 200
 
@@ -174,7 +176,7 @@ static uint64_t available_space(Server *s) {
 }
 
 static void server_read_file_gid(Server *s) {
-        const char *adm = "adm";
+        const char *g = "systemd-journal";
         int r;
 
         assert(s);
@@ -182,9 +184,9 @@ static void server_read_file_gid(Server *s) {
         if (s->file_gid_valid)
                 return;
 
-        r = get_group_creds(&adm, &s->file_gid);
+        r = get_group_creds(&g, &s->file_gid);
         if (r < 0)
-                log_warning("Failed to resolve 'adm' group: %s", strerror(-r));
+                log_warning("Failed to resolve '%s' group: %s", g, strerror(-r));
 
         /* if we couldn't read the gid, then it will be 0, but that's
          * fine and we shouldn't try to resolve the group again, so
@@ -344,6 +346,33 @@ void server_rotate(Server *s) {
         }
 }
 
+void server_sync(Server *s) {
+        JournalFile *f;
+        void *k;
+        Iterator i;
+        int r;
+
+        static const struct itimerspec sync_timer_disable = {};
+
+        if (s->system_journal) {
+                r = journal_file_set_offline(s->system_journal);
+                if (r < 0)
+                        log_error("Failed to sync system journal: %s", strerror(-r));
+        }
+
+        HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) {
+                r = journal_file_set_offline(f);
+                if (r < 0)
+                        log_error("Failed to sync user journal: %s", strerror(-r));
+        }
+
+        r = timerfd_settime(s->sync_timer_fd, 0, &sync_timer_disable, NULL);
+        if (r < 0)
+                log_error("Failed to disable max timer: %m");
+
+        s->sync_scheduled = false;
+}
+
 void server_vacuum(Server *s) {
         char *p;
         char ids[33];
@@ -475,8 +504,10 @@ static void write_to_journal(Server *s, uid_t uid, struct iovec *iovec, unsigned
         }
 
         r = journal_file_append_entry(f, NULL, iovec, n, &s->seqnum, NULL, NULL);
-        if (r >= 0)
+        if (r >= 0) {
+                server_schedule_sync(s);
                 return;
+        }
 
         if (vacuumed || !shall_try_append_again(f, r)) {
                 log_error("Failed to write entry, ignoring: %s", strerror(-r));
@@ -524,8 +555,10 @@ static void dispatch_message_real(
         assert(n + N_IOVEC_META_FIELDS <= m);
 
         if (ucred) {
+#ifdef HAVE_AUDIT
                 uint32_t audit;
                 uid_t loginuid;
+#endif
 
                 realuid = ucred->uid;
 
@@ -565,6 +598,7 @@ static void dispatch_message_real(
                                 IOVEC_SET_STRING(iovec[n++], cmdline);
                 }
 
+#ifdef HAVE_AUDIT
                 r = audit_session_from_pid(ucred->pid, &audit);
                 if (r >= 0)
                         if (asprintf(&audit_session, "_AUDIT_SESSION=%lu", (unsigned long) audit) >= 0)
@@ -574,6 +608,7 @@ static void dispatch_message_real(
                 if (r >= 0)
                         if (asprintf(&audit_loginuid, "_AUDIT_LOGINUID=%lu", (unsigned long) loginuid) >= 0)
                                 IOVEC_SET_STRING(iovec[n++], audit_loginuid);
+#endif
 
                 t = shortened_cgroup_path(ucred->pid);
                 if (t) {
@@ -593,7 +628,7 @@ static void dispatch_message_real(
                                 IOVEC_SET_STRING(iovec[n++], session);
                 }
 
-                if (sd_pid_get_owner_uid(ucred->uid, &owner) >= 0) {
+                if (sd_pid_get_owner_uid(ucred->pid, &owner) >= 0) {
                         owner_valid = true;
                         if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0)
                                 IOVEC_SET_STRING(iovec[n++], owner_uid);
@@ -688,7 +723,7 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
         struct iovec iovec[N_IOVEC_META_FIELDS + 4];
         int n = 0;
         va_list ap;
-        struct ucred ucred;
+        struct ucred ucred = {};
 
         assert(s);
         assert(format);
@@ -709,7 +744,6 @@ void server_driver_message(Server *s, sd_id128_t message_id, const char *format,
                 IOVEC_SET_STRING(iovec[n++], mid);
         }
 
-        zero(ucred);
         ucred.pid = getpid();
         ucred.uid = getuid();
         ucred.gid = getgid();
@@ -960,8 +994,7 @@ finish:
         if (r >= 0)
                 rm_rf("/run/log/journal", false, true, false);
 
-        if (j)
-                sd_journal_close(j);
+        sd_journal_close(j);
 
         return r;
 }
@@ -991,11 +1024,10 @@ int process_event(Server *s, struct epoll_event *ev) {
                         return -errno;
                 }
 
-                log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
-
                 if (sfsi.ssi_signo == SIGUSR1) {
                         touch("/run/systemd/journal/flushed");
                         server_flush_to_var(s);
+                        server_sync(s);
                         return 1;
                 }
 
@@ -1005,8 +1037,23 @@ int process_event(Server *s, struct epoll_event *ev) {
                         return 1;
                 }
 
+                log_info("Received SIG%s", signal_to_string(sfsi.ssi_signo));
+
                 return 0;
 
+        } else if (ev->data.fd == s->sync_timer_fd) {
+                int r;
+                uint64_t t;
+
+                log_debug("Got sync request from epoll.");
+
+                r = read(ev->data.fd, (void *)&t, sizeof(t));
+                if (r < 0)
+                        return 0;
+
+                server_sync(s);
+                return 1;
+
         } else if (ev->data.fd == s->dev_kmsg_fd) {
                 int r;
 
@@ -1286,16 +1333,67 @@ static int server_parse_config_file(Server *s) {
         return r;
 }
 
+static int server_open_sync_timer(Server *s) {
+        int r;
+        struct epoll_event ev;
+
+        assert(s);
+
+        s->sync_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
+        if (s->sync_timer_fd < 0)
+                return -errno;
+
+        zero(ev);
+        ev.events = EPOLLIN;
+        ev.data.fd = s->sync_timer_fd;
+
+        r = epoll_ctl(s->epoll_fd, EPOLL_CTL_ADD, s->sync_timer_fd, &ev);
+        if (r < 0) {
+                log_error("Failed to add idle timer fd to epoll object: %m");
+                return -errno;
+        }
+
+        return 0;
+}
+
+int server_schedule_sync(Server *s) {
+        int r;
+
+        assert(s);
+
+        if (s->sync_scheduled)
+                return 0;
+
+        if (s->sync_interval_usec) {
+                struct itimerspec sync_timer_enable = {
+                        .it_value.tv_sec = s->sync_interval_usec / USEC_PER_SEC,
+                        .it_value.tv_nsec = s->sync_interval_usec % MSEC_PER_SEC,
+                };
+
+                r = timerfd_settime(s->sync_timer_fd, 0, &sync_timer_enable, NULL);
+                if (r < 0)
+                        return -errno;
+        }
+
+        s->sync_scheduled = true;
+
+        return 0;
+}
+
 int server_init(Server *s) {
         int n, r, fd;
 
         assert(s);
 
         zero(*s);
-        s->syslog_fd = s->native_fd = s->stdout_fd = s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
+        s->sync_timer_fd = s->syslog_fd = s->native_fd = s->stdout_fd =
+            s->signal_fd = s->epoll_fd = s->dev_kmsg_fd = -1;
         s->compress = true;
         s->seal = true;
 
+        s->sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC;
+        s->sync_scheduled = false;
+
         s->rate_limit_interval = DEFAULT_RATE_LIMIT_INTERVAL;
         s->rate_limit_burst = DEFAULT_RATE_LIMIT_BURST;
 
@@ -1395,6 +1493,10 @@ int server_init(Server *s) {
         if (r < 0)
                 return r;
 
+        r = server_open_sync_timer(s);
+        if (r < 0)
+                return r;
+
         r = open_signalfd(s);
         if (r < 0)
                 return r;
@@ -1467,6 +1569,9 @@ void server_done(Server *s) {
         if (s->dev_kmsg_fd >= 0)
                 close_nointr_nofail(s->dev_kmsg_fd);
 
+        if (s->sync_timer_fd >= 0)
+                close_nointr_nofail(s->sync_timer_fd);
+
         if (s->rate_limit)
                 journal_rate_limit_free(s->rate_limit);