1*1a96fba6SXin Li // Copyright 2019 The Chromium OS Authors. All rights reserved. 2*1a96fba6SXin Li // Use of this source code is governed by a BSD-style license that can be 3*1a96fba6SXin Li // found in the LICENSE file. 4*1a96fba6SXin Li 5*1a96fba6SXin Li #include "brillo/scoped_mount_namespace.h" 6*1a96fba6SXin Li 7*1a96fba6SXin Li #include <fcntl.h> 8*1a96fba6SXin Li #include <sched.h> 9*1a96fba6SXin Li #include <sys/stat.h> 10*1a96fba6SXin Li #include <sys/types.h> 11*1a96fba6SXin Li 12*1a96fba6SXin Li #include <string> 13*1a96fba6SXin Li #include <utility> 14*1a96fba6SXin Li 15*1a96fba6SXin Li #include <base/posix/eintr_wrapper.h> 16*1a96fba6SXin Li #include <base/strings/stringprintf.h> 17*1a96fba6SXin Li 18*1a96fba6SXin Li namespace { 19*1a96fba6SXin Li constexpr char kCurrentMountNamespacePath[] = "/proc/self/ns/mnt"; 20*1a96fba6SXin Li } // anonymous namespace 21*1a96fba6SXin Li 22*1a96fba6SXin Li namespace brillo { 23*1a96fba6SXin Li ScopedMountNamespace(base::ScopedFD mount_namespace_fd)24*1a96fba6SXin LiScopedMountNamespace::ScopedMountNamespace(base::ScopedFD mount_namespace_fd) 25*1a96fba6SXin Li : mount_namespace_fd_(std::move(mount_namespace_fd)) {} 26*1a96fba6SXin Li ~ScopedMountNamespace()27*1a96fba6SXin LiScopedMountNamespace::~ScopedMountNamespace() { 28*1a96fba6SXin Li PLOG_IF(ERROR, setns(mount_namespace_fd_.get(), CLONE_NEWNS) != 0) 29*1a96fba6SXin Li << "Ignoring failure to restore original mount namespace"; 30*1a96fba6SXin Li } 31*1a96fba6SXin Li 32*1a96fba6SXin Li // static CreateForPid(pid_t pid)33*1a96fba6SXin Listd::unique_ptr<ScopedMountNamespace> ScopedMountNamespace::CreateForPid( 34*1a96fba6SXin Li pid_t pid) { 35*1a96fba6SXin Li std::string ns_path = base::StringPrintf("/proc/%d/ns/mnt", pid); 36*1a96fba6SXin Li return CreateFromPath(base::FilePath(ns_path)); 37*1a96fba6SXin Li } 38*1a96fba6SXin Li 39*1a96fba6SXin Li // static CreateFromPath(const base::FilePath & ns_path)40*1a96fba6SXin Listd::unique_ptr<ScopedMountNamespace> ScopedMountNamespace::CreateFromPath( 41*1a96fba6SXin Li const base::FilePath& ns_path) { 42*1a96fba6SXin Li base::ScopedFD original_mount_namespace_fd( 43*1a96fba6SXin Li HANDLE_EINTR(open(kCurrentMountNamespacePath, O_RDONLY))); 44*1a96fba6SXin Li if (!original_mount_namespace_fd.is_valid()) { 45*1a96fba6SXin Li PLOG(ERROR) << "Failed to open original mount namespace FD at " 46*1a96fba6SXin Li << kCurrentMountNamespacePath; 47*1a96fba6SXin Li return nullptr; 48*1a96fba6SXin Li } 49*1a96fba6SXin Li 50*1a96fba6SXin Li base::ScopedFD mount_namespace_fd( 51*1a96fba6SXin Li HANDLE_EINTR(open(ns_path.value().c_str(), O_RDONLY))); 52*1a96fba6SXin Li if (!mount_namespace_fd.is_valid()) { 53*1a96fba6SXin Li PLOG(ERROR) << "Failed to open mount namespace FD at " << ns_path.value(); 54*1a96fba6SXin Li return nullptr; 55*1a96fba6SXin Li } 56*1a96fba6SXin Li 57*1a96fba6SXin Li if (setns(mount_namespace_fd.get(), CLONE_NEWNS) != 0) { 58*1a96fba6SXin Li PLOG(ERROR) << "Failed to enter mount namespace at " << ns_path.value(); 59*1a96fba6SXin Li return nullptr; 60*1a96fba6SXin Li } 61*1a96fba6SXin Li 62*1a96fba6SXin Li return std::make_unique<ScopedMountNamespace>( 63*1a96fba6SXin Li std::move(original_mount_namespace_fd)); 64*1a96fba6SXin Li } 65*1a96fba6SXin Li 66*1a96fba6SXin Li } // namespace brillo 67