From 4fe5ac83287678a5f870def74ed28f45ab22815f Mon Sep 17 00:00:00 2001
From: Ariadne Conill <ariadne@dereferenced.org>
Date: Thu, 18 Mar 2021 23:15:01 -0600
Subject: [PATCH] database: do not chroot(".") unless actually necessary

If we use default root (/), then we do not have to chroot to run scripts.
Use APK_NO_CHROOT flag for this scenario to avoid the chroot.  This helps
with using apk with bwrap and OSTree.

Closes #10736.
---
 src/apk_context.h |  1 +
 src/context.c     |  1 +
 src/database.c    | 14 ++++++++++++--
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/src/apk_context.h b/src/apk_context.h
index 8f7ca5eb..2b4b8898 100644
--- a/src/apk_context.h
+++ b/src/apk_context.h
@@ -25,6 +25,7 @@
 #define APK_NO_SCRIPTS			BIT(8)
 #define APK_NO_CACHE			BIT(9)
 #define APK_NO_COMMIT_HOOKS		BIT(10)
+#define APK_NO_CHROOT			BIT(11)
 
 #define APK_FORCE_OVERWRITE		BIT(0)
 #define APK_FORCE_OLD_APK		BIT(1)
diff --git a/src/context.c b/src/context.c
index 784f082f..a6d7e5dd 100644
--- a/src/context.c
+++ b/src/context.c
@@ -42,6 +42,7 @@ int apk_ctx_prepare(struct apk_ctx *ac)
 	if (!ac->keys_dir) ac->keys_dir = "etc/apk/keys";
 	if (!ac->root) ac->root = "/";
 	if (!ac->cache_max_age) ac->cache_max_age = 4*60*60; /* 4 hours default */
+	if (!strcmp(ac->root, "/")) ac->flags |= APK_NO_CHROOT; /* skip chroot if root is default */
 
 	ac->root_fd = openat(AT_FDCWD, ac->root, O_RDONLY | O_CLOEXEC);
 	if (ac->root_fd < 0 && (ac->open_flags & APK_OPENF_CREATE)) {
diff --git a/src/database.c b/src/database.c
index 4c32fdc3..40efd93a 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1906,8 +1906,18 @@ int apk_db_run_script(struct apk_database *db, char *fn, char **argv)
 	}
 	if (pid == 0) {
 		umask(0022);
-		if (fchdir(db->root_fd) == 0 && chroot(".") == 0)
-			execve(fn, argv, environment);
+
+		if (fchdir(db->root_fd) != 0) {
+			apk_err(out, "%s: fchdir: %s", basename(fn), strerror(errno));
+			exit(127);
+		}
+
+		if (!(db->ctx->flags & APK_NO_CHROOT) && chroot(".") != 0) {
+			apk_err(out, "%s: chroot: %s", basename(fn), strerror(errno));
+			exit(127);
+		}
+
+		execve(fn, argv, environment);
 		exit(127); /* should not get here */
 	}
 	waitpid(pid, &status, 0);
-- 
GitLab