175 lines
6.8 KiB
Diff
175 lines
6.8 KiB
Diff
From 97033df7a71b1bc506094ad872a28ed9b3bde0cb 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: [PATCH] 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.
|
|
|
|
(cherry picked from commit 524daa8c3e2bd63ad9dbc24711cdcfb45a65b2db)
|
|
|
|
Conflicts:
|
|
src/core/execute.c
|
|
---
|
|
src/core/execute.c | 86 +++++++++++++++++++++++++++++++++++++++---------------
|
|
1 file changed, 62 insertions(+), 24 deletions(-)
|
|
|
|
diff --git a/src/core/execute.c b/src/core/execute.c
|
|
index f45f1c1410..ed75035bf4 100644
|
|
--- a/src/core/execute.c
|
|
+++ b/src/core/execute.c
|
|
@@ -217,12 +217,52 @@ static int open_null_as(int flags, int nfd) {
|
|
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_INVALID;
|
|
+ gid_t oldgid = GID_INVALID;
|
|
+ int r;
|
|
+
|
|
+ if (gid != GID_INVALID) {
|
|
+ oldgid = getgid();
|
|
+
|
|
+ r = setegid(gid);
|
|
+ if (r < 0)
|
|
+ return -errno;
|
|
+ }
|
|
+
|
|
+ if (uid != UID_INVALID) {
|
|
+ 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_INVALID)
|
|
+ (void) seteuid(olduid);
|
|
+
|
|
+ restore_gid:
|
|
+ if (gid != GID_INVALID)
|
|
+ (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);
|
|
@@ -233,11 +273,9 @@ static int connect_logger_as(const ExecContext *context, ExecOutput output, cons
|
|
if (fd < 0)
|
|
return -errno;
|
|
|
|
- r = connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path));
|
|
- if (r < 0) {
|
|
- safe_close(fd);
|
|
- return -errno;
|
|
- }
|
|
+ r = connect_journal_socket(fd, uid, gid);
|
|
+ if (r < 0)
|
|
+ return r;
|
|
|
|
if (shutdown(fd, SHUT_RD) < 0) {
|
|
safe_close(fd);
|
|
@@ -356,7 +394,7 @@ static int setup_input(const ExecContext *context, int socket_fd, bool apply_tty
|
|
}
|
|
}
|
|
|
|
-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;
|
|
@@ -423,9 +461,9 @@ static int setup_output(const ExecContext *context, int fileno, int socket_fd, c
|
|
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),
|
|
@@ -1324,6 +1362,15 @@ static int exec_child(ExecCommand *command,
|
|
}
|
|
}
|
|
|
|
+ if (context->user) {
|
|
+ username = context->user;
|
|
+ err = get_user_creds(&username, &uid, &gid, &home, &shell);
|
|
+ if (err < 0) {
|
|
+ *error = EXIT_USER;
|
|
+ return err;
|
|
+ }
|
|
+ }
|
|
+
|
|
/* If a socket is connected to STDIN/STDOUT/STDERR, we
|
|
* must sure to drop O_NONBLOCK */
|
|
if (socket_fd >= 0)
|
|
@@ -1335,13 +1382,13 @@ static int exec_child(ExecCommand *command,
|
|
return err;
|
|
}
|
|
|
|
- err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin);
|
|
+ err = setup_output(context, STDOUT_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
|
|
if (err < 0) {
|
|
*error = EXIT_STDOUT;
|
|
return err;
|
|
}
|
|
|
|
- err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin);
|
|
+ err = setup_output(context, STDERR_FILENO, socket_fd, basename(command->path), params->unit_id, params->apply_tty_stdin, uid, gid);
|
|
if (err < 0) {
|
|
*error = EXIT_STDERR;
|
|
return err;
|
|
@@ -1416,21 +1463,12 @@ static int exec_child(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) {
|
|
- *error = EXIT_USER;
|
|
+ *error = EXIT_STDIN;
|
|
return err;
|
|
}
|
|
-
|
|
- if (is_terminal_input(context->std_input)) {
|
|
- err = chown_terminal(STDIN_FILENO, uid);
|
|
- if (err < 0) {
|
|
- *error = EXIT_STDIN;
|
|
- return err;
|
|
- }
|
|
- }
|
|
}
|
|
|
|
#ifdef ENABLE_KDBUS
|