From 256ac5c4d9f6d5f2dda1a7baf4fc461dfa8c8a37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Th=C3=A9o=20Maillart?= <tmaillart@freebox.fr>
Date: Tue, 8 Nov 2022 15:06:00 +0100
Subject: [PATCH] make_directory: fix mkdir -p when parent is a read only
 ancestor

Let's say we have just mounted our root as read only, and we have
a symlink to a rw fs, if we perform a mkdir -p to this fs but there
is an intermediate directory read only, then the syscall mkdir
returns EROFS because it could not find the dentry in its cache and
as we asked for a creation, the code path does not perform final
lookup.
We end up erroring because mkdir failed on an intermediate
directory that might exist.
Here is a patch to check if this intermediate directory already
exists
---
 libbb/make_directory.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/libbb/make_directory.c b/libbb/make_directory.c
index 7826b90..f6d9990 100644
--- a/libbb/make_directory.c
+++ b/libbb/make_directory.c
@@ -84,12 +84,16 @@ int FAST_FUNC bb_make_directory(char *path, long mode, int flags)
 		}
 
 		if (mkdir(path, 0777) < 0) {
+			int org_errno = errno;
+
 			/* If we failed for any other reason than the directory
 			 * already exists, output a diagnostic and return -1 */
-			if ((errno != EEXIST && errno != EISDIR)
+			if ((errno != EEXIST && errno != EISDIR && errno != EROFS)
 			 || !(flags & FILEUTILS_RECUR)
 			 || ((stat(path, &st) < 0) || !S_ISDIR(st.st_mode))
 			) {
+				if (org_errno == EROFS)
+					errno = org_errno;
 				fail_msg = "create";
 				break;
 			}
-- 
2.37.3

