From 5eb441caca209e40ff990b25a7409279660211e6 Mon Sep 17 00:00:00 2001 From: Jooyung Han Date: Sat, 23 Jul 2022 01:41:18 +0900 Subject: [PATCH] Respect `namespace mnt` This fixes the regression of aosp/2153354. SwitchToMountNamespaceIfNeeded() is supposed to switch between "default" mount namespace and "bootstrap" mount namespace. But it shouldn't affect services with its own mount namespace. Bug: 239882455 Test: make a hal service start in a separate mount namespace using 'namespace mnt' in its definition. see the mount namespace of the service process $ cat /proc/$(pgrep -f myservice)/ns/mnt Change-Id: I8c80eaec723241c405f48980b9e88640123c43ad --- init/mount_namespace.cpp | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp index bce1cc3de..fead371d1 100644 --- a/init/mount_namespace.cpp +++ b/init/mount_namespace.cpp @@ -190,15 +190,33 @@ bool SetupMountNamespaces() { return success; } +// Switch the mount namespace of the current process from bootstrap to default OR from default to +// bootstrap. If the current mount namespace is neither bootstrap nor default, keep it that way. Result SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace) { if (IsRecoveryMode() || !IsApexUpdatable()) { // we don't have multiple namespaces in recovery mode or if apex is not updatable return {}; } - const auto& ns_id = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_id : default_ns_id; + + const std::string current_namespace_id = GetMountNamespaceId(); + MountNamespace current_mount_namespace; + if (current_namespace_id == bootstrap_ns_id) { + current_mount_namespace = NS_BOOTSTRAP; + } else if (current_namespace_id == default_ns_id) { + current_mount_namespace = NS_DEFAULT; + } else { + // services with `namespace mnt` start in its own mount namespace. So we need to keep it. + return {}; + } + + // We're already in the target mount namespace. + if (current_mount_namespace == target_mount_namespace) { + return {}; + } + const auto& ns_fd = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_fd : default_ns_fd; const auto& ns_name = target_mount_namespace == NS_BOOTSTRAP ? "bootstrap" : "default"; - if (ns_id != GetMountNamespaceId() && ns_fd.get() != -1) { + if (ns_fd.get() != -1) { if (setns(ns_fd.get(), CLONE_NEWNS) == -1) { return ErrnoError() << "Failed to switch to " << ns_name << " mount namespace."; }