]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
chase: carefully handle result of extracting parent directory
authorYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 20 Jul 2023 06:17:27 +0000 (15:17 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Sat, 29 Jul 2023 12:58:30 +0000 (21:58 +0900)
Should not change any behavior.

src/basic/chase.c

index 4d883e18d8eb62754337e7c2b0184249b822a017..b612a2fef619eb877c873f6cf1b8f08cc6322edc 100644 (file)
@@ -292,9 +292,25 @@ int chaseat(int dir_fd, const char *path, ChaseFlags flags, char **ret_path, int
                         }
 
                         r = path_extract_directory(done, &parent);
-                        if (r >= 0 || r == -EDESTADDRREQ)
+                        if (r >= 0) {
+                                assert(!need_absolute || path_is_absolute(parent));
                                 free_and_replace(done, parent);
-                        else if (IN_SET(r, -EINVAL, -EADDRNOTAVAIL)) {
+                        } else if (r == -EDESTADDRREQ) {
+                                /* 'done' contains filename only (i.e. no slash). */
+                                assert(!need_absolute);
+                                done = mfree(done);
+                        } else if (r == -EADDRNOTAVAIL) {
+                                /* 'done' is "/". This branch should be already handled in the above. */
+                                assert(!FLAGS_SET(flags, CHASE_AT_RESOLVE_IN_ROOT));
+                                assert_not_reached();
+                        } else if (r == -EINVAL) {
+                                /* 'done' is an empty string, ends with '..', or an invalid path. */
+                                assert(!need_absolute);
+                                assert(!FLAGS_SET(flags, CHASE_AT_RESOLVE_IN_ROOT));
+
+                                if (!path_is_valid(done))
+                                        return -EINVAL;
+
                                 /* If we're at the top of "dir_fd", start appending ".." to "done". */
                                 if (!path_extend(&done, ".."))
                                         return -ENOMEM;