Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Leap:42.1:Staging:C
systemd
0001-journal-call-connect-with-dropped-privileg...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0001-journal-call-connect-with-dropped-privileges.patch of Package systemd
Based on 524daa8c3e2bd63ad9dbc24711cdcfb45a65b2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl> Date: Thu, 1 Jan 2015 04:40:41 +0100 Subject: journal: call connect() with dropped privileges When systemd starts a service, it first opened /run/systemd/journal/stdout socket, and only later switched to the right user.group (if they are specified). Later on, journald looked at the credentials, and saw root.root, because credentials are stored at the time the socket is opened. As a result, all messages passed over _TRANSPORT=stdout were logged with _UID=0, _GID=0. Drop real uid and gid temporarily to fix the issue. --- src/core/execute.c | 82 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 21 deletions(-) --- src/core/execute.c +++ src/core/execute.c 2015-01-22 11:53:55.845518536 +0000 @@ -215,12 +215,52 @@ static int open_null_as(int flags, int n return r; } -static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd) { - int fd, r; +static int connect_journal_socket(int fd, uid_t uid, gid_t gid) { union sockaddr_union sa = { .un.sun_family = AF_UNIX, .un.sun_path = "/run/systemd/journal/stdout", }; + uid_t olduid = ((uid_t) -1); + gid_t oldgid = ((gid_t) -1); + int r; + + if (gid != ((gid_t) -1)) { + oldgid = getgid(); + + r = setegid(gid); + if (r < 0) + return -errno; + } + + if (uid != ((uid_t) -1)) { + olduid = getuid(); + + r = seteuid(uid); + if (r < 0) { + r = -errno; + goto restore_gid; + } + } + + r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); + if (r < 0) + r = -errno; + + /* If we fail to restore the uid or gid, things will likely + fail later on. This should only happen if an LSM interferes. */ + + if (uid != ((uid_t) -1)) + (void) seteuid(olduid); + + restore_gid: + if (gid != ((gid_t) -1)) + (void) setegid(oldgid); + + return r; +} + +static int connect_logger_as(const ExecContext *context, ExecOutput output, const char *ident, const char *unit_id, int nfd, uid_t uid, gid_t gid) { + int fd, r; assert(context); assert(output < _EXEC_OUTPUT_MAX); @@ -231,10 +271,10 @@ static int connect_logger_as(const ExecC if (fd < 0) return -errno; - r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)); + r = connect_journal_socket(fd, uid, gid); if (r < 0) { close_nointr_nofail(fd); - return -errno; + return r; } if (shutdown(fd, SHUT_RD) < 0) { @@ -354,7 +394,7 @@ static int setup_input(const ExecContext } } -static int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin) { +static int setup_output(const ExecContext *context, int fileno, int socket_fd, const char *ident, const char *unit_id, bool apply_tty_stdin, uid_t uid, gid_t gid) { ExecOutput o; ExecInput i; int r; @@ -421,9 +461,9 @@ static int setup_output(const ExecContex case EXEC_OUTPUT_KMSG_AND_CONSOLE: case EXEC_OUTPUT_JOURNAL: case EXEC_OUTPUT_JOURNAL_AND_CONSOLE: - r = connect_logger_as(context, o, ident, unit_id, fileno); + r = connect_logger_as(context, o, ident, unit_id, fileno, uid, gid); if (r < 0) { - log_struct_unit(LOG_CRIT, unit_id, + log_struct_unit(LOG_ERR, unit_id, "MESSAGE=Failed to connect std%s of %s to the journal socket: %s", fileno == STDOUT_FILENO ? "out" : "err", unit_id, strerror(-r), @@ -1291,6 +1331,15 @@ int exec_spawn(ExecCommand *command, } } + if (context->user) { + username = context->user; + err = get_user_creds(&username, &uid, &gid, &home, &shell); + if (err < 0) { + r = EXIT_USER; + goto fail_child; + } + } + /* If a socket is connected to STDIN/STDOUT/STDERR, we * must sure to drop O_NONBLOCK */ if (socket_fd >= 0) @@ -1302,13 +1351,13 @@ int exec_spawn(ExecCommand *command, goto fail_child; } - err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin); + err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin, uid, gid); if (err < 0) { r = EXIT_STDOUT; goto fail_child; } - err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin); + err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), unit_id, apply_tty_stdin, uid, gid); if (err < 0) { r = EXIT_STDERR; goto fail_child; @@ -1390,21 +1439,12 @@ int exec_spawn(ExecCommand *command, if (context->utmp_id) utmp_put_init_process(context->utmp_id, getpid(), getsid(0), context->tty_path); - if (context->user) { - username = context->user; - err = get_user_creds(&username, &uid, &gid, &home, &shell); + if (context->user && is_terminal_input(context->std_input)) { + err = chown_terminal(STDIN_FILENO, uid); if (err < 0) { - r = EXIT_USER; + r = EXIT_STDIN; goto fail_child; } - - if (is_terminal_input(context->std_input)) { - err = chown_terminal(STDIN_FILENO, uid); - if (err < 0) { - r = EXIT_STDIN; - goto fail_child; - } - } } #ifdef HAVE_PAM
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor