summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2017-02-09 11:58:39 +0100
committerLennart Poettering <lennart@poettering.net>2017-02-09 13:17:58 +0100
commit6732edab4eff2f656690681bc37595a59470e4a1 (patch)
treee062b027c34ceda274c0e8a46408709a43ff4ffb
parent23deef88b9bb020c87c8b4ad30113a4f97445a1a (diff)
execute: set working directory to /root if User= is not set, but WorkingDirectory=~ is
Or actually, try to to do the right thing depending on what is available: - If we know $HOME from User=, then use that. - If the UID for the service is 0, hardcode that WorkingDirectory=~ means WorkingDirectory=/root - In any other case (which will be the unprivileged --user case), use get_home_dir() to find the $HOME of the user we are running as. - Otherwise fail. Fixes: #5246 #5124
-rw-r--r--src/core/execute.c50
1 files changed, 45 insertions, 5 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index 1e32697723..492df2fedb 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -2017,14 +2017,18 @@ static int apply_working_directory(
const char *home,
const bool needs_mount_ns) {
- const char *d;
- const char *wd;
+ const char *d, *wd;
assert(context);
- if (context->working_directory_home)
+ if (context->working_directory_home) {
+
+ if (!home)
+ return -ENXIO;
+
wd = home;
- else if (context->working_directory)
+
+ } else if (context->working_directory)
wd = context->working_directory;
else
wd = "/";
@@ -2181,6 +2185,35 @@ static int send_user_lookup(
return 0;
}
+static int acquire_home(const ExecContext *c, uid_t uid, const char** home, char **buf) {
+ int r;
+
+ assert(c);
+ assert(home);
+ assert(buf);
+
+ /* If WorkingDirectory=~ is set, try to acquire a usable home directory. */
+
+ if (*home)
+ return 0;
+
+ if (!c->working_directory_home)
+ return 0;
+
+ if (uid == 0) {
+ /* Hardcode /root as home directory for UID 0 */
+ *home = "/root";
+ return 1;
+ }
+
+ r = get_home_dir(buf);
+ if (r < 0)
+ return r;
+
+ *home = *buf;
+ return 1;
+}
+
static int exec_child(
Unit *unit,
ExecCommand *command,
@@ -2198,7 +2231,7 @@ static int exec_child(
char **error_message) {
_cleanup_strv_free_ char **our_env = NULL, **pass_env = NULL, **accum_env = NULL, **final_argv = NULL;
- _cleanup_free_ char *mac_selinux_context_net = NULL;
+ _cleanup_free_ char *mac_selinux_context_net = NULL, *home_buffer = NULL;
_cleanup_free_ gid_t *supplementary_gids = NULL;
const char *username = NULL, *groupname = NULL;
const char *home = NULL, *shell = NULL;
@@ -2351,6 +2384,13 @@ static int exec_child(
user_lookup_fd = safe_close(user_lookup_fd);
+ r = acquire_home(context, uid, &home, &home_buffer);
+ if (r < 0) {
+ *exit_status = EXIT_CHDIR;
+ *error_message = strdup("Failed to determine $HOME for user");
+ return r;
+ }
+
/* If a socket is connected to STDIN/STDOUT/STDERR, we
* must sure to drop O_NONBLOCK */
if (socket_fd >= 0)