Use /bootstrap-apex for bootstrap APEXes

This new directory is bind-mounted to /apex in the bootstrap mount
namespace so that apexd-bootstrap mounts bootstrap APEXes there via
/apex.

The directory is shared between two mount namespaces, hence visible
in the default mount namespace.

Bug: 290148078
Test: VendorApexHostTestCases
Change-Id: I841480e41be8def5a4c6a4aa874c4e21465a71d3
This commit is contained in:
Jooyung Han 2023-08-09 07:05:31 +00:00
parent 790c6315c3
commit 566c65239f
5 changed files with 37 additions and 11 deletions

View file

@ -832,6 +832,12 @@ static void MountExtraFilesystems() {
CHECKCALL(mount("tmpfs", "/apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
if (NeedsTwoMountNamespaces()) {
// /bootstrap-apex is used to mount "bootstrap" APEXes.
CHECKCALL(mount("tmpfs", "/bootstrap-apex", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
}
// /linkerconfig is used to keep generated linker configuration
CHECKCALL(mount("tmpfs", "/linkerconfig", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));

View file

@ -66,15 +66,6 @@ static std::string GetMountNamespaceId() {
return ret;
}
// In case we have two sets of APEXes (non-updatable, updatable), we need two separate mount
// namespaces.
static bool NeedsTwoMountNamespaces() {
if (IsRecoveryMode()) return false;
// In microdroid, there's only one set of APEXes in built-in directories include block devices.
if (IsMicrodroid()) return false;
return true;
}
static android::base::unique_fd bootstrap_ns_fd;
static android::base::unique_fd default_ns_fd;
@ -83,6 +74,15 @@ static std::string default_ns_id;
} // namespace
// In case we have two sets of APEXes (non-updatable, updatable), we need two separate mount
// namespaces.
bool NeedsTwoMountNamespaces() {
if (IsRecoveryMode()) return false;
// In microdroid, there's only one set of APEXes in built-in directories include block devices.
if (IsMicrodroid()) return false;
return true;
}
bool SetupMountNamespaces() {
// Set the propagation type of / as shared so that any mounting event (e.g.
// /data) is by default visible to all processes. When private mounting is
@ -163,6 +163,23 @@ bool SetupMountNamespaces() {
PLOG(ERROR) << "Cannot switch back to bootstrap mount namespace";
return false;
}
// Some components (e.g. servicemanager) need to access bootstrap
// APEXes from the default mount namespace. To achieve that, we bind-mount
// /apex to /bootstrap-apex in the bootstrap mount namespace. Since /bootstrap-apex
// is "shared", the mounts are visible in the default mount namespace as well.
//
// The end result will look like:
// in the bootstrap mount namespace:
// /apex (== /bootstrap-apex)
// {bootstrap APEXes from the read-only partition}
//
// in the default mount namespace:
// /bootstrap-apex
// {bootstrap APEXes from the read-only partition}
// /apex
// {APEXes, can be from /data partition}
if (!(BindMount("/bootstrap-apex", "/apex"))) return false;
} else {
// Otherwise, default == bootstrap
default_ns_fd.reset(OpenMountNamespace());

View file

@ -24,9 +24,12 @@ namespace init {
enum MountNamespace { NS_BOOTSTRAP, NS_DEFAULT };
bool SetupMountNamespaces();
base::Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace);
base::Result<MountNamespace> GetCurrentMountNamespace();
bool NeedsTwoMountNamespaces();
} // namespace init
} // namespace android

View file

@ -757,7 +757,7 @@ void SelinuxRestoreContext() {
selinux_android_restorecon("/dev/device-mapper", 0);
selinux_android_restorecon("/apex", 0);
selinux_android_restorecon("/bootstrap-apex", 0);
selinux_android_restorecon("/linkerconfig", 0);
// adb remount, snapshot-based updates, and DSUs all create files during

View file

@ -91,7 +91,7 @@ endif
#
# create some directories (some are mount points) and symlinks
LOCAL_POST_INSTALL_CMD := mkdir -p $(addprefix $(TARGET_ROOT_OUT)/, \
dev proc sys system data data_mirror odm oem acct config storage mnt apex debug_ramdisk \
dev proc sys system data data_mirror odm oem acct config storage mnt apex bootstrap-apex debug_ramdisk \
linkerconfig second_stage_resources postinstall $(BOARD_ROOT_EXTRA_FOLDERS)); \
ln -sf /system/bin $(TARGET_ROOT_OUT)/bin; \
ln -sf /system/etc $(TARGET_ROOT_OUT)/etc; \