#include <systemd/sd-login.h>
#endif
+#include "fileio.h"
#include "mkdir.h"
#include "hashmap.h"
#include "journal-file.h"
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;
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;
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);
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
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));
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);
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;
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;
}
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,
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);
if (ucred) {
uint32_t audit;
-#ifdef HAVE_LOGIND
- uid_t owner;
-#endif
+ uid_t loginuid;
realuid = ucred->uid;
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);
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);
+ }
#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);
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 {
selinux_context = strappend("_SELINUX_CONTEXT=", con);
if (selinux_context)
IOVEC_SET_STRING(iovec[n++], selinux_context);
-
freecon(con);
}
}
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, ...) {
int priority) {
int rl;
- char *path = NULL, *c;
+ char _cleanup_free_ *path = NULL;
+ char *c;
assert(s);
assert(iovec || n == 0);
}
}
- 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);
return r;
}
+ sd_journal_set_data_threshold(j, 0);
+
SD_JOURNAL_FOREACH(j) {
Object *o = NULL;
JournalFile *f;
if (r >= 0)
rm_rf("/run/log/journal", false, true, false);
- if (j)
- sd_journal_close(j);
+ sd_journal_close(j);
return r;
}
}
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;
}
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);
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)
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;
}
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);
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;