]> git.ipfire.org Git - thirdparty/shadow.git/commitdiff
fix: create relative home path correctly 327/head
authorLucas Servén Marín <lserven@gmail.com>
Thu, 29 Apr 2021 12:09:31 +0000 (14:09 +0200)
committerLucas Servén Marín <lserven@gmail.com>
Thu, 29 Apr 2021 13:06:53 +0000 (15:06 +0200)
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 <lserven@gmail.com>
src/useradd.c

index a0369cd8792e1365fa920916a4f1e1d80472002f..b8beadd8fcec586bfb53bd72b7beabd26169c4b7 100644 (file)
@@ -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