mirror of
https://github.com/systemd/systemd.git
synced 2024-11-30 13:53:39 +08:00
journal: split user logs into their own journal files
This commit is contained in:
parent
260a2be455
commit
f4b4781191
15
Makefile.am
15
Makefile.am
@ -978,14 +978,17 @@ systemd_journald_SOURCES = \
|
||||
src/journal/journald.c \
|
||||
src/journal/sd-journal.c \
|
||||
src/journal/lookup3.c \
|
||||
src/sd-id128.c
|
||||
src/sd-id128.c \
|
||||
src/acl-util.c
|
||||
|
||||
systemd_journald_CFLAGS = \
|
||||
$(AM_CFLAGS)
|
||||
$(AM_CFLAGS) \
|
||||
$(ACL_CFLAGS)
|
||||
|
||||
systemd_journald_LDADD = \
|
||||
libsystemd-basic.la \
|
||||
libsystemd-daemon.la
|
||||
libsystemd-daemon.la \
|
||||
$(ACL_LIBS)
|
||||
|
||||
systemd_journalctl_SOURCES = \
|
||||
src/journal/journalctl.c \
|
||||
@ -1143,10 +1146,12 @@ systemd_uaccess_SOURCES = \
|
||||
|
||||
if HAVE_ACL
|
||||
systemd_logind_SOURCES += \
|
||||
src/logind-acl.c
|
||||
src/logind-acl.c \
|
||||
src/acl-util.c
|
||||
|
||||
systemd_uaccess_SOURCES += \
|
||||
src/logind-acl.c
|
||||
src/logind-acl.c \
|
||||
src/acl-util.c
|
||||
endif
|
||||
|
||||
systemd_uaccess_CFLAGS = \
|
||||
|
68
src/acl-util.c
Normal file
68
src/acl-util.c
Normal file
@ -0,0 +1,68 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
#include <assert.h>
|
||||
#include <sys/acl.h>
|
||||
#include <acl/libacl.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "acl-util.h"
|
||||
|
||||
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry) {
|
||||
acl_entry_t i;
|
||||
int found;
|
||||
|
||||
assert(acl);
|
||||
assert(entry);
|
||||
|
||||
for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
found > 0;
|
||||
found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
|
||||
acl_tag_t tag;
|
||||
uid_t *u;
|
||||
bool b;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_USER)
|
||||
continue;
|
||||
|
||||
u = acl_get_qualifier(i);
|
||||
if (!u)
|
||||
return -errno;
|
||||
|
||||
b = *u == uid;
|
||||
acl_free(u);
|
||||
|
||||
if (b) {
|
||||
*entry = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
27
src/acl-util.h
Normal file
27
src/acl-util.h
Normal file
@ -0,0 +1,27 @@
|
||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||
|
||||
#ifndef fooaclutilhfoo
|
||||
#define fooaclutilhfoo
|
||||
|
||||
/***
|
||||
This file is part of systemd.
|
||||
|
||||
Copyright 2011 Lennart Poettering
|
||||
|
||||
systemd is free software; you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 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
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||
***/
|
||||
|
||||
int acl_find_uid(acl_t acl, uid_t uid, acl_entry_t *entry);
|
||||
|
||||
#endif
|
@ -29,6 +29,31 @@
|
||||
#include "util.h"
|
||||
#include "sd-id128.h"
|
||||
|
||||
typedef struct JournalFile {
|
||||
int fd;
|
||||
char *path;
|
||||
struct stat last_stat;
|
||||
int prot;
|
||||
bool writable;
|
||||
|
||||
Header *header;
|
||||
|
||||
HashItem *hash_table;
|
||||
void *hash_table_window;
|
||||
uint64_t hash_table_window_size;
|
||||
|
||||
uint64_t *bisect_table;
|
||||
void *bisect_table_window;
|
||||
uint64_t bisect_table_window_size;
|
||||
|
||||
void *window;
|
||||
uint64_t window_offset;
|
||||
uint64_t window_size;
|
||||
|
||||
Object *current;
|
||||
uint64_t current_offset;
|
||||
} JournalFile;
|
||||
|
||||
typedef struct JournalCoursor {
|
||||
sd_id128_t file_id;
|
||||
sd_id128_t boot_id;
|
||||
@ -38,8 +63,6 @@ typedef struct JournalCoursor {
|
||||
uint64_t xor_hash;
|
||||
} JournalCoursor;
|
||||
|
||||
typedef struct JournalFile JournalFile;
|
||||
|
||||
int journal_file_open(const char *fname, int flags, mode_t mode, JournalFile **ret);
|
||||
|
||||
void journal_file_close(JournalFile *j);
|
||||
|
@ -25,21 +25,109 @@
|
||||
#include <sys/signalfd.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/acl.h>
|
||||
#include <acl/libacl.h>
|
||||
|
||||
#include "hashmap.h"
|
||||
#include "journal-private.h"
|
||||
#include "sd-daemon.h"
|
||||
#include "socket-util.h"
|
||||
#include "acl-util.h"
|
||||
|
||||
typedef struct Server {
|
||||
int syslog_fd;
|
||||
int epoll_fd;
|
||||
int signal_fd;
|
||||
|
||||
JournalFile *runtime_journal;
|
||||
JournalFile *system_journal;
|
||||
Hashmap *user_journals;
|
||||
} Server;
|
||||
|
||||
static void fix_perms(JournalFile *f, uid_t uid) {
|
||||
acl_t acl;
|
||||
acl_entry_t entry;
|
||||
acl_permset_t permset;
|
||||
int r;
|
||||
|
||||
assert(f);
|
||||
|
||||
r = fchmod_and_fchown(f->fd, 0640, 0, 0);
|
||||
if (r < 0)
|
||||
log_warning("Failed to fix access mode/rights on %s, ignoring: %s", f->path, strerror(-r));
|
||||
|
||||
if (uid <= 0)
|
||||
return;
|
||||
|
||||
acl = acl_get_fd(f->fd);
|
||||
if (!acl) {
|
||||
log_warning("Failed to read ACL on %s, ignoring: %m", f->path);
|
||||
return;
|
||||
}
|
||||
|
||||
r = acl_find_uid(acl, uid, &entry);
|
||||
if (r <= 0) {
|
||||
|
||||
if (acl_create_entry(&acl, &entry) < 0 ||
|
||||
acl_set_tag_type(entry, ACL_USER) < 0 ||
|
||||
acl_set_qualifier(entry, &uid) < 0) {
|
||||
log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
|
||||
goto finish;
|
||||
}
|
||||
}
|
||||
|
||||
if (acl_get_permset(entry, &permset) < 0 ||
|
||||
acl_add_perm(permset, ACL_READ) < 0 ||
|
||||
acl_calc_mask(&acl) < 0) {
|
||||
log_warning("Failed to patch ACL on %s, ignoring: %m", f->path);
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (acl_set_fd(f->fd, acl) < 0)
|
||||
log_warning("Failed to set ACL on %s, ignoring: %m", f->path);
|
||||
|
||||
finish:
|
||||
acl_free(acl);
|
||||
}
|
||||
|
||||
static JournalFile* find_journal(Server *s, uid_t uid) {
|
||||
char *p;
|
||||
int r;
|
||||
JournalFile *f;
|
||||
|
||||
assert(s);
|
||||
|
||||
/* We split up user logs only on /var, not on /run */
|
||||
if (!s->system_journal)
|
||||
return s->runtime_journal;
|
||||
|
||||
if (uid <= 0)
|
||||
return s->system_journal;
|
||||
|
||||
f = hashmap_get(s->user_journals, UINT32_TO_PTR(uid));
|
||||
if (f)
|
||||
return f;
|
||||
|
||||
if (asprintf(&p, "/var/log/journal/%lu.journal", (unsigned long) uid) < 0)
|
||||
return s->system_journal;
|
||||
|
||||
r = journal_file_open(p, O_RDWR|O_CREAT, 0640, &f);
|
||||
free(p);
|
||||
|
||||
if (r < 0)
|
||||
return s->system_journal;
|
||||
|
||||
fix_perms(f, uid);
|
||||
|
||||
r = hashmap_put(s->user_journals, UINT32_TO_PTR(uid), f);
|
||||
if (r < 0) {
|
||||
journal_file_close(f);
|
||||
return s->system_journal;
|
||||
}
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
static void process_message(Server *s, const char *buf, struct ucred *ucred, struct timeval *tv) {
|
||||
char *message = NULL, *pid = NULL, *uid = NULL, *gid = NULL,
|
||||
*source_time = NULL, *boot_id = NULL, *machine_id = NULL,
|
||||
@ -47,7 +135,6 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str
|
||||
*audit_session = NULL, *audit_loginuid = NULL,
|
||||
*syslog_priority = NULL, *syslog_facility = NULL,
|
||||
*exe = NULL;
|
||||
dual_timestamp ts;
|
||||
struct iovec iovec[15];
|
||||
unsigned n = 0;
|
||||
char idbuf[33];
|
||||
@ -55,8 +142,8 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str
|
||||
int r;
|
||||
char *t;
|
||||
int priority = LOG_USER | LOG_INFO;
|
||||
|
||||
dual_timestamp_get(&ts);
|
||||
uid_t loginuid = 0;
|
||||
JournalFile *f;
|
||||
|
||||
parse_syslog_priority((char**) &buf, &priority);
|
||||
skip_syslog_date((char**) &buf);
|
||||
@ -73,7 +160,6 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str
|
||||
|
||||
if (ucred) {
|
||||
uint32_t session;
|
||||
uid_t loginuid;
|
||||
|
||||
if (asprintf(&pid, "PID=%lu", (unsigned long) ucred->pid) >= 0)
|
||||
IOVEC_SET_STRING(iovec[n++], pid);
|
||||
@ -143,10 +229,15 @@ static void process_message(Server *s, const char *buf, struct ucred *ucred, str
|
||||
free(t);
|
||||
}
|
||||
|
||||
r = journal_file_append_entry(s->system_journal, &ts, iovec, n, NULL, NULL);
|
||||
if (r < 0)
|
||||
log_error("Failed to write entry: %s", strerror(-r));
|
||||
f = find_journal(s, loginuid);
|
||||
if (!f)
|
||||
log_warning("Dropping message, as we can't find a place to store the data.");
|
||||
else {
|
||||
r = journal_file_append_entry(f, NULL, iovec, n, NULL, NULL);
|
||||
|
||||
if (r < 0)
|
||||
log_error("Failed to write entry, ignoring: %s", strerror(-r));
|
||||
}
|
||||
|
||||
free(message);
|
||||
free(pid);
|
||||
@ -253,20 +344,6 @@ static int process_event(Server *s, struct epoll_event *ev) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int open_system_journal(JournalFile **f) {
|
||||
int r;
|
||||
|
||||
r = journal_file_open("/var/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f);
|
||||
if (r == -ENOENT) {
|
||||
mkdir_p("/run/log/journal", 0755);
|
||||
|
||||
r = journal_file_open("/run/log/journal/system.journal", O_RDWR|O_CREAT, 0644, f);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int server_init(Server *s) {
|
||||
int n, one, r;
|
||||
struct epoll_event ev;
|
||||
@ -348,8 +425,18 @@ static int server_init(Server *s) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = open_system_journal(&s->system_journal);
|
||||
if (r < 0) {
|
||||
r = journal_file_open("/var/log/journal/system.journal", O_RDWR|O_CREAT, 0640, &s->system_journal);
|
||||
if (r >= 0)
|
||||
fix_perms(s->system_journal, 0);
|
||||
else if (r == -ENOENT) {
|
||||
mkdir_p("/run/log/journal", 0755);
|
||||
|
||||
r = journal_file_open("/run/log/journal/system.journal", O_RDWR|O_CREAT, 0640, &s->runtime_journal);
|
||||
if (r >= 0)
|
||||
fix_perms(s->runtime_journal, 0);
|
||||
}
|
||||
|
||||
if (r < 0 && r != -ENOENT) {
|
||||
log_error("Failed to open journal: %s", strerror(-r));
|
||||
return r;
|
||||
}
|
||||
@ -383,6 +470,9 @@ static void server_done(Server *s) {
|
||||
if (s->system_journal)
|
||||
journal_file_close(s->system_journal);
|
||||
|
||||
if (s->runtime_journal)
|
||||
journal_file_close(s->runtime_journal);
|
||||
|
||||
while ((f = hashmap_steal_first(s->user_journals)))
|
||||
journal_file_close(f);
|
||||
|
||||
@ -412,7 +502,7 @@ int main(int argc, char *argv[]) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
log_set_target(LOG_TARGET_AUTO);
|
||||
log_set_target(LOG_TARGET_CONSOLE);
|
||||
log_parse_environment();
|
||||
log_open();
|
||||
|
||||
|
@ -43,33 +43,6 @@
|
||||
|
||||
#define DEFAULT_WINDOW_SIZE (128ULL*1024ULL*1024ULL)
|
||||
|
||||
struct JournalFile {
|
||||
int fd;
|
||||
char *path;
|
||||
struct stat last_stat;
|
||||
int prot;
|
||||
bool writable;
|
||||
|
||||
Header *header;
|
||||
|
||||
HashItem *hash_table;
|
||||
void *hash_table_window;
|
||||
uint64_t hash_table_window_size;
|
||||
|
||||
uint64_t *bisect_table;
|
||||
void *bisect_table_window;
|
||||
uint64_t bisect_table_window_size;
|
||||
|
||||
void *window;
|
||||
uint64_t window_offset;
|
||||
uint64_t window_size;
|
||||
|
||||
Object *current;
|
||||
uint64_t current_offset;
|
||||
|
||||
LIST_FIELDS(JournalFile, files);
|
||||
};
|
||||
|
||||
struct sd_journal {
|
||||
Hashmap *files;
|
||||
};
|
||||
|
@ -27,46 +27,7 @@
|
||||
|
||||
#include "logind-acl.h"
|
||||
#include "util.h"
|
||||
|
||||
static int find_acl(acl_t acl, uid_t uid, acl_entry_t *entry) {
|
||||
acl_entry_t i;
|
||||
int found;
|
||||
|
||||
assert(acl);
|
||||
assert(entry);
|
||||
|
||||
for (found = acl_get_entry(acl, ACL_FIRST_ENTRY, &i);
|
||||
found > 0;
|
||||
found = acl_get_entry(acl, ACL_NEXT_ENTRY, &i)) {
|
||||
|
||||
acl_tag_t tag;
|
||||
uid_t *u;
|
||||
bool b;
|
||||
|
||||
if (acl_get_tag_type(i, &tag) < 0)
|
||||
return -errno;
|
||||
|
||||
if (tag != ACL_USER)
|
||||
continue;
|
||||
|
||||
u = acl_get_qualifier(i);
|
||||
if (!u)
|
||||
return -errno;
|
||||
|
||||
b = *u == uid;
|
||||
acl_free(u);
|
||||
|
||||
if (b) {
|
||||
*entry = i;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (found < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#include "acl-util.h"
|
||||
|
||||
static int flush_acl(acl_t acl) {
|
||||
acl_entry_t i;
|
||||
@ -125,7 +86,7 @@ int devnode_acl(const char *path,
|
||||
} else if (del && old_uid > 0) {
|
||||
acl_entry_t entry;
|
||||
|
||||
r = find_acl(acl, old_uid, &entry);
|
||||
r = acl_find_uid(acl, old_uid, &entry);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
@ -144,7 +105,7 @@ int devnode_acl(const char *path,
|
||||
acl_permset_t permset;
|
||||
int rd, wt;
|
||||
|
||||
r = find_acl(acl, new_uid, &entry);
|
||||
r = acl_find_uid(acl, new_uid, &entry);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
|
16
src/util.c
16
src/util.c
@ -3529,6 +3529,22 @@ int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid) {
|
||||
assert(fd >= 0);
|
||||
|
||||
/* Under the assumption that we are running privileged we
|
||||
* first change the access mode and only then hand out
|
||||
* ownership to avoid a window where access is too open. */
|
||||
|
||||
if (fchmod(fd, mode) < 0)
|
||||
return -errno;
|
||||
|
||||
if (fchown(fd, uid, gid) < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
cpu_set_t* cpu_set_malloc(unsigned *ncpus) {
|
||||
cpu_set_t *r;
|
||||
unsigned n = 1024;
|
||||
|
@ -366,6 +366,7 @@ int get_ctty_devnr(pid_t pid, dev_t *d);
|
||||
int get_ctty(pid_t, dev_t *_devnr, char **r);
|
||||
|
||||
int chmod_and_chown(const char *path, mode_t mode, uid_t uid, gid_t gid);
|
||||
int fchmod_and_fchown(int fd, mode_t mode, uid_t uid, gid_t gid);
|
||||
|
||||
int rm_rf(const char *path, bool only_dirs, bool delete_root, bool honour_sticky);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user