DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (d38398e5144e)

VCS Links

AddCondition

Perms

Policy

SandboxBroker

Macros

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
/* -*- 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_SandboxBroker_h
#define mozilla_SandboxBroker_h

#include "mozilla/SandboxBrokerCommon.h"

#include "base/platform_thread.h"
#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"
#include "nsDataHashtable.h"
#include "nsHashKeys.h"
#include "nsString.h"

namespace mozilla {

namespace ipc {
class FileDescriptor;
}

// This class implements a broker for filesystem operations requested
// by a sandboxed child process -- opening files and accessing their
// metadata.  (This is necessary in order to restrict access by path;
// seccomp-bpf can filter only on argument register values, not
// parameters passed in memory like pathnames.)
//
// The broker currently runs on a thread in the parent process (with
// effective uid changed on B2G), which is for memory efficiency
// (compared to forking a process) and simplicity (compared to having
// a separate executable and serializing/deserializing the policy).
//
// See also ../SandboxBrokerClient.h for the corresponding client.

class SandboxBroker final
  : private SandboxBrokerCommon
  , public PlatformThread::Delegate
{
 public:
  enum Perms {
    MAY_ACCESS    = 1 << 0,
    MAY_READ      = 1 << 1,
    MAY_WRITE     = 1 << 2,
    MAY_CREATE    = 1 << 3,
    // This flag is for testing policy changes -- when the client is
    // used with the seccomp-bpf integration, an access to this file
    // will invoke a crash dump with the context of the syscall.
    // (This overrides all other flags.)
    CRASH_INSTEAD = 1 << 4,
    // Applies to everything below this path, including subdirs created
    // at runtime
    RECURSIVE     = 1 << 5,
  };
  // Bitwise operations on enum values return ints, so just use int in
  // the hash table type (and below) to avoid cluttering code with casts.
  typedef nsDataHashtable<nsCStringHashKey, int> PathMap;

  class Policy {
    PathMap mMap;
  public:
    Policy();
    Policy(const Policy& aOther);
    ~Policy();

    enum AddCondition {
      AddIfExistsNow,
      AddAlways,
    };
    // Typically, files that don't exist at policy creation time don't
    // need to be whitelisted, but this allows adding entries for
    // them if they'll exist later.  See also the overload below.
    void AddPath(int aPerms, const char* aPath, AddCondition aCond);
    // This adds all regular files (not directories) in the tree
    // rooted at the given path.
    void AddTree(int aPerms, const char* aPath);
    // A directory, and all files and directories under it, even those
    // added after creation (the dir itself must exist).
    void AddDir(int aPerms, const char* aPath);
    // All files in a directory with a given prefix; useful for devices.
    void AddFilePrefix(int aPerms, const char* aDir, const char* aPrefix);
    // Everything starting with the given path, even those files/dirs
    // added after creation. The file or directory may or may not exist.
    void AddPrefix(int aPerms, const char* aPath);
    // Adds a file or dir (end with /) if it exists, and a prefix otherwhise.
    void AddDynamic(int aPerms, const char* aPath);
    // Default: add file if it exists when creating policy or if we're
    // conferring permission to create it (log files, etc.).
    void AddPath(int aPerms, const char* aPath) {
      AddPath(aPerms, aPath,
              (aPerms & MAY_CREATE) ? AddAlways : AddIfExistsNow);
    }
    int Lookup(const nsACString& aPath) const;
    int Lookup(const char* aPath) const {
      return Lookup(nsDependentCString(aPath));
    }
  private:
    // ValidatePath checks |path| and returns true if these conditions are met
    // * Greater than 0 length
    // * Is an absolute path
    // * No trailing slash
    // * No /../ path traversal
    bool ValidatePath(const char* path) const;
    void AddPrefixInternal(int aPerms, const nsACString& aPath);
  };

  // Constructing a broker involves creating a socketpair and a
  // background thread to handle requests, so it can fail.  If this
  // returns nullptr, do not use the value of aClientFdOut.
  static UniquePtr<SandboxBroker>
    Create(UniquePtr<const Policy> aPolicy, int aChildPid,
           ipc::FileDescriptor& aClientFdOut);
  virtual ~SandboxBroker();

 private:
  PlatformThreadHandle mThread;
  int mFileDesc;
  const int mChildPid;
  const UniquePtr<const Policy> mPolicy;

  SandboxBroker(UniquePtr<const Policy> aPolicy, int aChildPid,
                int& aClientFd);
  void ThreadMain(void) override;
  void AuditPermissive(int aOp, int aFlags, int aPerms, const char* aPath);
  void AuditDenial(int aOp, int aFlags, int aPerms, const char* aPath);
  // Remap relative paths to absolute paths.
  size_t ConvertToRealPath(char* aPath, size_t aBufSize, size_t aPathLen);

  // Holding a UniquePtr should disallow copying, but to make that explicit:
  SandboxBroker(const SandboxBroker&) = delete;
  void operator=(const SandboxBroker&) = delete;
};

} // namespace mozilla

#endif // mozilla_SandboxBroker_h