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