diff options
Diffstat (limited to 'security/sandbox/linux/SandboxOpenedFiles.h')
-rw-r--r-- | security/sandbox/linux/SandboxOpenedFiles.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/security/sandbox/linux/SandboxOpenedFiles.h b/security/sandbox/linux/SandboxOpenedFiles.h new file mode 100644 index 0000000000..24881b93f0 --- /dev/null +++ b/security/sandbox/linux/SandboxOpenedFiles.h @@ -0,0 +1,97 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_SandboxOpenedFiles_h +#define mozilla_SandboxOpenedFiles_h + +#include "mozilla/Atomics.h" +#include "mozilla/Range.h" +#include "mozilla/UniquePtr.h" + +#include <vector> +#include <string> + +// The use of C++ standard library containers here should be safe; the +// standard (section container.requirements.dataraces) requires that +// using const methods/pointers not introduce data races (e.g., from +// interior mutability or global state). +// +// Reentrancy isn't guaranteed, and the library could use async signal +// unsafe mutexes for "read-only" operations, but I'm assuming that that's +// not the case at least for simple containers like string and vector. + +namespace mozilla { + +// This class represents a file that's been pre-opened for a media +// plugin. It can be move-constructed but not copied. +class SandboxOpenedFile final { + public: + enum class Dup { NO, YES }; + struct Error {}; + + // This constructor opens the named file and saves the descriptor. + // If the open fails, IsOpen() will return false and GetDesc() will + // quietly return -1. If aDup is Dup::YES, GetDesc() will return a + // dup() of the descriptor every time it's called; otherwise, the + // first call will return the descriptor and any further calls will + // log an error message and return -1. + explicit SandboxOpenedFile(const char* aPath, Dup aDup = Dup::NO); + + // This constructor is for files which the process will try to open + // but we don't want to grant access: using it will always fail + // (GetDesc will return -1) without logging. + SandboxOpenedFile(const char* aPath, Error); + + // Simulates opening the pre-opened file; see the constructor's + // comment for details. Does not set errno on error, but may modify + // it as a side-effect. Thread-safe and intended to be async signal safe. + int GetDesc() const; + + const char* Path() const { return mPath.c_str(); } + + bool IsOpen() const { return mMaybeFd >= 0; } + + ~SandboxOpenedFile(); + + MOZ_IMPLICIT SandboxOpenedFile(SandboxOpenedFile&& aMoved); + + private: + std::string mPath; + mutable Atomic<int> mMaybeFd; + bool mDup; + bool mExpectError; + + int TakeDesc() const { return mMaybeFd.exchange(-1); } +}; + +// This class represents a collection of files to be used to handle +// open() calls from the media plugin (and the dynamic loader). +// Because the seccomp-bpf policy exists until the process exits, this +// object must not be destroyed after the syscall filter is installed. +class SandboxOpenedFiles { + public: + SandboxOpenedFiles() = default; + + template <typename... Args> + void Add(Args&&... aArgs) { + mFiles.emplace_back(std::forward<Args>(aArgs)...); + } + + int GetDesc(const char* aPath) const; + + private: + std::vector<SandboxOpenedFile> mFiles; + + // We could allow destroying instances of this class that aren't + // used with seccomp-bpf (e.g., for unit testing) by having the + // destructor check a flag set by the syscall policy and crash, + // but let's not write that code until we actually need it. + ~SandboxOpenedFiles() = delete; +}; + +} // namespace mozilla + +#endif // mozilla_SandboxOpenedFiles_h |