X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fjournal%2Fjournald-server.c;h=ac565c7ece96ce1b1bbf57962c9fe04467ddea1e;hp=0ff2866c11b36210e598ad9d6558780db48dc71c;hb=a24c64f03f9c5c0304451d8542fee853187a5168;hpb=d025f1e4dca8fc1436aff76f9e6185fe3e728daa diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 0ff2866c1..ac565c7ec 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -34,6 +34,7 @@ #include #endif +#include "fileio.h" #include "mkdir.h" #include "hashmap.h" #include "journal-file.h" @@ -91,13 +92,14 @@ DEFINE_STRING_TABLE_LOOKUP(split_mode, SplitMode); DEFINE_CONFIG_PARSE_ENUM(config_parse_split_mode, split_mode, SplitMode, "Failed to parse split mode setting"); static uint64_t available_space(Server *s) { - char ids[33], *p; + char ids[33]; + char _cleanup_free_ *p = NULL; const char *f; sd_id128_t machine; struct statvfs ss; uint64_t sum = 0, avail = 0, ss_avail = 0; int r; - DIR *d; + DIR _cleanup_closedir_ *d = NULL; usec_t ts; JournalMetrics *m; @@ -125,13 +127,11 @@ static uint64_t available_space(Server *s) { return 0; d = opendir(p); - free(p); - if (!d) return 0; if (fstatvfs(dirfd(d), &ss) < 0) - goto finish; + return 0; for (;;) { struct stat st; @@ -170,14 +170,11 @@ static uint64_t available_space(Server *s) { s->cached_available_space = avail; s->cached_available_space_timestamp = ts; -finish: - closedir(d); - return avail; } static void server_read_file_gid(Server *s) { - const char *adm = "adm"; + const char *g = "systemd-journal"; int r; assert(s); @@ -185,9 +182,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 @@ -336,7 +333,7 @@ void server_rotate(Server *s) { HASHMAP_FOREACH_KEY(f, k, s->user_journals, i) { r = journal_file_rotate(&f, s->compress, s->seal); if (r < 0) - if (f->path) + if (f) log_error("Failed to rotate %s: %s", f->path, strerror(-r)); else log_error("Failed to create user journal: %s", strerror(-r)); @@ -396,7 +393,8 @@ void server_vacuum(Server *s) { static char *shortened_cgroup_path(pid_t pid) { int r; - char *process_path, *init_path, *path; + char _cleanup_free_ *process_path = NULL, *init_path = NULL; + char *path; assert(pid > 0); @@ -405,10 +403,8 @@ static char *shortened_cgroup_path(pid_t pid) { return NULL; r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, 1, &init_path); - if (r < 0) { - free(process_path); + if (r < 0) return NULL; - } if (endswith(init_path, "/system")) init_path[strlen(init_path) - 7] = 0; @@ -416,23 +412,12 @@ static char *shortened_cgroup_path(pid_t pid) { init_path[0] = 0; if (startswith(process_path, init_path)) { - char *p; - - p = strdup(process_path + strlen(init_path)); - if (!p) { - free(process_path); - free(init_path); - return NULL; - } - path = p; + path = strdup(process_path + strlen(init_path)); } else { path = process_path; process_path = NULL; } - free(process_path); - free(init_path); - return path; } @@ -519,7 +504,7 @@ static void dispatch_message_real( const char *label, size_t label_len, const char *unit_id) { - char *pid = NULL, *uid = NULL, *gid = NULL, + char _cleanup_free_ *pid = NULL, *uid = NULL, *gid = NULL, *source_time = NULL, *boot_id = NULL, *machine_id = NULL, *comm = NULL, *cmdline = NULL, *hostname = NULL, *audit_session = NULL, *audit_loginuid = NULL, @@ -530,7 +515,8 @@ static void dispatch_message_real( sd_id128_t id; int r; char *t; - uid_t loginuid = 0, realuid = 0; + uid_t realuid = 0, owner = 0, journal_uid; + bool owner_valid = false; assert(s); assert(iovec); @@ -539,9 +525,7 @@ static void dispatch_message_real( if (ucred) { uint32_t audit; -#ifdef HAVE_LOGIND - uid_t owner; -#endif + uid_t loginuid; realuid = ucred->uid; @@ -572,7 +556,7 @@ static void dispatch_message_real( IOVEC_SET_STRING(iovec[n++], exe); } - r = get_process_cmdline(ucred->pid, LINE_MAX, false, &t); + r = get_process_cmdline(ucred->pid, 0, false, &t); if (r >= 0) { cmdline = strappend("_CMDLINE=", t); free(t); @@ -609,16 +593,25 @@ 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->uid, &owner) >= 0) { + owner_valid = true; if (asprintf(&owner_uid, "_SYSTEMD_OWNER_UID=%lu", (unsigned long) owner) >= 0) IOVEC_SET_STRING(iovec[n++], owner_uid); + } #endif if (cg_pid_get_unit(ucred->pid, &t) >= 0) { unit = strappend("_SYSTEMD_UNIT=", t); free(t); - } else if (unit_id) - unit = strappend("_SYSTEMD_UNIT=", unit_id); + } else if (cg_pid_get_user_unit(ucred->pid, &t) >= 0) { + unit = strappend("_SYSTEMD_USER_UNIT=", t); + free(t); + } else if (unit_id) { + if (session) + unit = strappend("_SYSTEMD_USER_UNIT=", unit_id); + else + unit = strappend("_SYSTEMD_UNIT=", unit_id); + } if (unit) IOVEC_SET_STRING(iovec[n++], unit); @@ -627,9 +620,7 @@ static void dispatch_message_real( if (label) { selinux_context = malloc(sizeof("_SELINUX_CONTEXT=") + label_len); if (selinux_context) { - memcpy(selinux_context, "_SELINUX_CONTEXT=", sizeof("_SELINUX_CONTEXT=")-1); - memcpy(selinux_context+sizeof("_SELINUX_CONTEXT=")-1, label, label_len); - selinux_context[sizeof("_SELINUX_CONTEXT=")-1+label_len] = 0; + *((char*) mempcpy(stpcpy(selinux_context, "_SELINUX_CONTEXT="), label, label_len)) = 0; IOVEC_SET_STRING(iovec[n++], selinux_context); } } else { @@ -639,7 +630,6 @@ static void dispatch_message_real( selinux_context = strappend("_SELINUX_CONTEXT=", con); if (selinux_context) IOVEC_SET_STRING(iovec[n++], selinux_context); - freecon(con); } } @@ -675,28 +665,21 @@ static void dispatch_message_real( assert(n <= m); - write_to_journal(s, - s->split_mode == SPLIT_NONE ? 0 : - (s->split_mode == SPLIT_UID ? realuid : - (realuid == 0 ? 0 : loginuid)), iovec, n); - - free(pid); - free(uid); - free(gid); - free(comm); - free(exe); - free(cmdline); - free(source_time); - free(boot_id); - free(machine_id); - free(hostname); - free(audit_session); - free(audit_loginuid); - free(cgroup); - free(session); - free(owner_uid); - free(unit); - free(selinux_context); + if (s->split_mode == SPLIT_UID && realuid > 0) + /* Split up strictly by any UID */ + journal_uid = realuid; + else if (s->split_mode == SPLIT_LOGIN && realuid > 0 && owner_valid && owner > 0) + /* Split up by login UIDs, this avoids creation of + * individual journals for system UIDs. We do this + * only if the realuid is not root, in order not to + * accidentally leak privileged information to the + * user that is logged by a privileged process that is + * part of an unprivileged session.*/ + journal_uid = owner; + else + journal_uid = 0; + + write_to_journal(s, journal_uid, iovec, n); } void server_driver_message(Server *s, sd_id128_t message_id, const char *format, ...) { @@ -744,7 +727,8 @@ void server_dispatch_message( int priority) { int rl; - char *path = NULL, *c; + char _cleanup_free_ *path = NULL; + char *c; assert(s); assert(iovec || n == 0); @@ -778,18 +762,16 @@ void server_dispatch_message( } } - rl = journal_rate_limit_test(s->rate_limit, path, priority & LOG_PRIMASK, available_space(s)); + rl = journal_rate_limit_test(s->rate_limit, path, + priority & LOG_PRIMASK, available_space(s)); - if (rl == 0) { - free(path); + if (rl == 0) return; - } /* Write a suppression message if we suppressed something */ if (rl > 1) - server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, "Suppressed %u messages from %s", rl - 1, path); - - free(path); + server_driver_message(s, SD_MESSAGE_JOURNAL_DROPPED, + "Suppressed %u messages from %s", rl - 1, path); finish: dispatch_message_real(s, iovec, n, m, ucred, tv, label, label_len, unit_id); @@ -934,6 +916,8 @@ int server_flush_to_var(Server *s) { return r; } + sd_journal_set_data_threshold(j, 0); + SD_JOURNAL_FOREACH(j) { Object *o = NULL; JournalFile *f; @@ -1232,7 +1216,8 @@ static int open_signalfd(Server *s) { } static int server_parse_proc_cmdline(Server *s) { - char *line, *w, *state; + char _cleanup_free_ *line = NULL; + char *w, *state; int r; size_t l; @@ -1246,13 +1231,11 @@ static int server_parse_proc_cmdline(Server *s) { } FOREACH_WORD_QUOTED(w, l, line, state) { - char *word; + char _cleanup_free_ *word; word = strndup(w, l); - if (!word) { - r = -ENOMEM; - goto finish; - } + if (!word) + return -ENOMEM; if (startswith(word, "systemd.journald.forward_to_syslog=")) { r = parse_boolean(word + 35); @@ -1274,25 +1257,18 @@ static int server_parse_proc_cmdline(Server *s) { s->forward_to_console = r; } else if (startswith(word, "systemd.journald")) log_warning("Invalid systemd.journald parameter. Ignoring."); - - free(word); } - r = 0; - -finish: - free(line); - return r; + return 0; } static int server_parse_config_file(Server *s) { - FILE *f; - const char *fn; + static const char *fn = "/etc/systemd/journald.conf"; + FILE _cleanup_fclose_ *f = NULL; int r; assert(s); - fn = "/etc/systemd/journald.conf"; f = fopen(fn, "re"); if (!f) { if (errno == ENOENT) @@ -1302,12 +1278,11 @@ static int server_parse_config_file(Server *s) { return -errno; } - r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, (void*) journald_gperf_lookup, false, s); + r = config_parse(fn, f, "Journal\0", config_item_perf_lookup, + (void*) journald_gperf_lookup, false, s); if (r < 0) log_warning("Failed to parse configuration file: %s", strerror(-r)); - fclose(f); - return r; } @@ -1336,6 +1311,12 @@ int server_init(Server *s) { server_parse_config_file(s); server_parse_proc_cmdline(s); + if (!!s->rate_limit_interval ^ !!s->rate_limit_burst) { + log_debug("Setting both rate limit interval and burst from %llu,%u to 0,0", + (long long unsigned) s->rate_limit_interval, + s->rate_limit_burst); + s->rate_limit_interval = s->rate_limit_burst = 0; + } mkdir_p("/run/systemd/journal", 0755); @@ -1422,7 +1403,8 @@ int server_init(Server *s) { if (!s->udev) return -ENOMEM; - s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, s->rate_limit_burst); + s->rate_limit = journal_rate_limit_new(s->rate_limit_interval, + s->rate_limit_burst); if (!s->rate_limit) return -ENOMEM;