SandboxOpenedFiles.h (3373B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_SandboxOpenedFiles_h 8 #define mozilla_SandboxOpenedFiles_h 9 10 #include "mozilla/Atomics.h" 11 12 #include <vector> 13 #include <string> 14 15 // The use of C++ standard library containers here should be safe; the 16 // standard (section container.requirements.dataraces) requires that 17 // using const methods/pointers not introduce data races (e.g., from 18 // interior mutability or global state). 19 // 20 // Reentrancy isn't guaranteed, and the library could use async signal 21 // unsafe mutexes for "read-only" operations, but I'm assuming that that's 22 // not the case at least for simple containers like string and vector. 23 24 namespace mozilla { 25 26 // This class represents a file that's been pre-opened for a media 27 // plugin. It can be move-constructed but not copied. 28 class SandboxOpenedFile final { 29 public: 30 enum class Dup { NO, YES }; 31 struct Error {}; 32 33 // This constructor opens the named file and saves the descriptor. 34 // If the open fails, IsOpen() will return false and GetDesc() will 35 // quietly return -1. If aDup is Dup::YES, GetDesc() will return a 36 // dup() of the descriptor every time it's called; otherwise, the 37 // first call will return the descriptor and any further calls will 38 // log an error message and return -1. 39 explicit SandboxOpenedFile(const char* aPath, Dup aDup = Dup::NO); 40 41 // This constructor is for files which the process will try to open 42 // but we don't want to grant access: using it will always fail 43 // (GetDesc will return -1) without logging. 44 SandboxOpenedFile(const char* aPath, Error); 45 46 // Simulates opening the pre-opened file; see the constructor's 47 // comment for details. Does not set errno on error, but may modify 48 // it as a side-effect. Thread-safe and intended to be async signal safe. 49 int GetDesc() const; 50 51 const char* Path() const { return mPath.c_str(); } 52 53 bool IsOpen() const { return mMaybeFd >= 0; } 54 55 ~SandboxOpenedFile(); 56 57 MOZ_IMPLICIT SandboxOpenedFile(SandboxOpenedFile&& aMoved); 58 59 private: 60 std::string mPath; 61 mutable Atomic<int> mMaybeFd; 62 bool mDup; 63 bool mExpectError; 64 65 int TakeDesc() const { return mMaybeFd.exchange(-1); } 66 }; 67 68 // This class represents a collection of files to be used to handle 69 // open() calls from the media plugin (and the dynamic loader). 70 // Because the seccomp-bpf policy exists until the process exits, this 71 // object must not be destroyed after the syscall filter is installed. 72 class SandboxOpenedFiles { 73 public: 74 SandboxOpenedFiles() = default; 75 76 template <typename... Args> 77 void Add(Args&&... aArgs) { 78 mFiles.emplace_back(std::forward<Args>(aArgs)...); 79 } 80 81 int GetDesc(const char* aPath) const; 82 83 private: 84 std::vector<SandboxOpenedFile> mFiles; 85 86 // We could allow destroying instances of this class that aren't 87 // used with seccomp-bpf (e.g., for unit testing) by having the 88 // destructor check a flag set by the syscall policy and crash, 89 // but let's not write that code until we actually need it. 90 ~SandboxOpenedFiles() = delete; 91 }; 92 93 } // namespace mozilla 94 95 #endif // mozilla_SandboxOpenedFiles_h