From: Lucas Servén Marín Date: Thu, 29 Apr 2021 12:09:31 +0000 (+0200) Subject: fix: create relative home path correctly X-Git-Tag: v4.9~17^2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fpull%2F327%2Fhead;p=thirdparty%2Fshadow.git fix: create relative home path correctly Currently, supplying a relative path via the --prefix flag to the useradd command triggers a bug in the creation of home directories. The code seems to unintentionally prepend a leading "/" to all paths, quietly transforming a relative prefixed home path into an absolute path. This can be seen in the following strace logs from running "useradd --create-home --prefix tmp/root squat": ``` access("tmp/root//home/squat", F_OK) = -1 ENOENT (No such file or directory) access("/mp", F_OK) = 0 access("/mp/root", F_OK) = 0 access("/mp/root/home", F_OK) = 0 access("/mp/root/home/squat", F_OK) = -1 ENOENT (No such file or directory) mkdir("/mp/root/home/squat", 000) = 0 chown("/mp/root/home/squat", 0, 0) = 0 chmod("/mp/root/home/squat", 0755) = 0 chown("tmp/root//home/squat", 1000, 1000) = -1 ENOENT (No such file or directory) chmod("tmp/root//home/squat", 0700) = -1 ENOENT (No such file or directory) ``` Note that the relative path is correctly probed in the beginning and it is only during the recursive creation that the path is turned into an absolute path. This invocation results in the creation of a "/mp" hierarchy in the root of the filesystem. Similar problems occur when using `--prefix ./tmp/root`. This commit fixes the handling of relative paths by not assuming that the given path is anchored with a "/". Signed-off-by: Lucas Servén Marín --- diff --git a/src/useradd.c b/src/useradd.c index a0369cd87..b8beadd8f 100644 --- a/src/useradd.c +++ b/src/useradd.c @@ -2171,7 +2171,6 @@ static void create_home (void) Prog, user_home); fail_exit (E_HOMEDIR); } - ++bhome; #ifdef WITH_SELINUX if (set_selinux_file_context (prefix_user_home) != 0) { @@ -2188,7 +2187,11 @@ static void create_home (void) */ cp = strtok (bhome, "/"); while (cp) { - strcat (path, "/"); + /* Avoid turning a relative path into an absolute path. + */ + if (bhome[0] == '/' || strlen (path) != 0) { + strcat (path, "/"); + } strcat (path, cp); if (access (path, F_OK) != 0) { /* Check if parent directory is BTRFS, fail if requesting