Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/sandbox/linux/broker/SandboxBroker.h
Line
Count
Source (jump to first uncovered line)
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_SandboxBroker_h
8
#define mozilla_SandboxBroker_h
9
10
#include "mozilla/SandboxBrokerCommon.h"
11
12
#include "base/platform_thread.h"
13
#include "mozilla/Attributes.h"
14
#include "mozilla/UniquePtr.h"
15
#include "nsDataHashtable.h"
16
#include "nsHashKeys.h"
17
#include "nsString.h"
18
19
namespace mozilla {
20
21
namespace ipc {
22
class FileDescriptor;
23
}
24
25
// This class implements a broker for filesystem operations requested
26
// by a sandboxed child process -- opening files and accessing their
27
// metadata.  (This is necessary in order to restrict access by path;
28
// seccomp-bpf can filter only on argument register values, not
29
// parameters passed in memory like pathnames.)
30
//
31
// The broker currently runs on a thread in the parent process (with
32
// effective uid changed on B2G), which is for memory efficiency
33
// (compared to forking a process) and simplicity (compared to having
34
// a separate executable and serializing/deserializing the policy).
35
//
36
// See also ../SandboxBrokerClient.h for the corresponding client.
37
38
class SandboxBroker final
39
  : private SandboxBrokerCommon
40
  , public PlatformThread::Delegate
41
{
42
 public:
43
  enum Perms {
44
    MAY_ACCESS    = 1 << 0,
45
    MAY_READ      = 1 << 1,
46
    MAY_WRITE     = 1 << 2,
47
    MAY_CREATE    = 1 << 3,
48
    // This flag is for testing policy changes -- when the client is
49
    // used with the seccomp-bpf integration, an access to this file
50
    // will invoke a crash dump with the context of the syscall.
51
    // (This overrides all other flags.)
52
    CRASH_INSTEAD = 1 << 4,
53
    // Applies to everything below this path, including subdirs created
54
    // at runtime
55
    RECURSIVE     = 1 << 5,
56
    // Allow Unix-domain socket connections to a path
57
    MAY_CONNECT   = 1 << 6,
58
  };
59
  // Bitwise operations on enum values return ints, so just use int in
60
  // the hash table type (and below) to avoid cluttering code with casts.
61
  typedef nsDataHashtable<nsCStringHashKey, int> PathPermissionMap;
62
63
  class Policy {
64
    PathPermissionMap mMap;
65
  public:
66
    Policy();
67
    Policy(const Policy& aOther);
68
    ~Policy();
69
70
    // Add permissions from AddDir/AddDynamic rules to any rules that
71
    // exist for their descendents, and remove any descendent rules
72
    // made redundant by this process.
73
    //
74
    // Call this after adding rules and before using the policy to
75
    // prevent the descendent rules from shadowing the ancestor rules
76
    // and removing permissions that we expect the file to have.
77
    void FixRecursivePermissions();
78
79
    enum AddCondition {
80
      AddIfExistsNow,
81
      AddAlways,
82
    };
83
    // Typically, files that don't exist at policy creation time don't
84
    // need to be whitelisted, but this allows adding entries for
85
    // them if they'll exist later.  See also the overload below.
86
    void AddPath(int aPerms, const char* aPath, AddCondition aCond);
87
    // This adds all regular files (not directories) in the tree
88
    // rooted at the given path.
89
    void AddTree(int aPerms, const char* aPath);
90
    // A directory, and all files and directories under it, even those
91
    // added after creation (the dir itself must exist).
92
    void AddDir(int aPerms, const char* aPath);
93
    // All files in a directory with a given prefix; useful for devices.
94
    void AddFilePrefix(int aPerms, const char* aDir, const char* aPrefix);
95
    // Everything starting with the given path, even those files/dirs
96
    // added after creation. The file or directory may or may not exist.
97
    void AddPrefix(int aPerms, const char* aPath);
98
    // Adds a file or dir (end with /) if it exists, and a prefix otherwhise.
99
    void AddDynamic(int aPerms, const char* aPath);
100
    // Adds permissions on all ancestors of a path.  (This doesn't
101
    // include the root directory, but if the path is given with a
102
    // trailing slash it includes the path without the slash.)
103
    void AddAncestors(const char* aPath, int aPerms = MAY_ACCESS);
104
    // Default: add file if it exists when creating policy or if we're
105
    // conferring permission to create it (log files, etc.).
106
30
    void AddPath(int aPerms, const char* aPath) {
107
30
      AddPath(aPerms, aPath,
108
30
              (aPerms & MAY_CREATE) ? AddAlways : AddIfExistsNow);
109
30
    }
110
    int Lookup(const nsACString& aPath) const;
111
0
    int Lookup(const char* aPath) const {
112
0
      return Lookup(nsDependentCString(aPath));
113
0
    }
114
  private:
115
    // ValidatePath checks |path| and returns true if these conditions are met
116
    // * Greater than 0 length
117
    // * Is an absolute path
118
    // * No trailing slash
119
    // * No /../ path traversal
120
    bool ValidatePath(const char* path) const;
121
    void AddPrefixInternal(int aPerms, const nsACString& aPath);
122
  };
123
124
  // Constructing a broker involves creating a socketpair and a
125
  // background thread to handle requests, so it can fail.  If this
126
  // returns nullptr, do not use the value of aClientFdOut.
127
  static UniquePtr<SandboxBroker>
128
    Create(UniquePtr<const Policy> aPolicy, int aChildPid,
129
           ipc::FileDescriptor& aClientFdOut);
130
  virtual ~SandboxBroker();
131
132
 private:
133
  PlatformThreadHandle mThread;
134
  int mFileDesc;
135
  const int mChildPid;
136
  const UniquePtr<const Policy> mPolicy;
137
  nsCString mTempPath;
138
139
  typedef nsDataHashtable<nsCStringHashKey, nsCString> PathMap;
140
  PathMap mSymlinkMap;
141
142
  SandboxBroker(UniquePtr<const Policy> aPolicy, int aChildPid,
143
                int& aClientFd);
144
  void ThreadMain(void) override;
145
  void AuditPermissive(int aOp, int aFlags, int aPerms, const char* aPath);
146
  void AuditDenial(int aOp, int aFlags, int aPerms, const char* aPath);
147
  // Remap relative paths to absolute paths.
148
  size_t ConvertRelativePath(char* aPath, size_t aBufSize, size_t aPathLen);
149
  size_t RealPath(char* aPath, size_t aBufSize, size_t aPathLen);
150
  // Remap references to /tmp and friends to the content process tempdir
151
  size_t RemapTempDirs(char* aPath, size_t aBufSize, size_t aPathLen);
152
  nsCString ReverseSymlinks(const nsACString& aPath);
153
  // Retrieves permissions for the path the original symlink sits in.
154
  int SymlinkPermissions(const char* aPath, const size_t aPathLen);
155
  // In SandboxBrokerRealPath.cpp
156
  char* SymlinkPath(const Policy* aPolicy, const char* __restrict aPath,
157
                    char* __restrict aResolved, int* aPermission);
158
159
  // Holding a UniquePtr should disallow copying, but to make that explicit:
160
  SandboxBroker(const SandboxBroker&) = delete;
161
  void operator=(const SandboxBroker&) = delete;
162
};
163
164
} // namespace mozilla
165
166
#endif // mozilla_SandboxBroker_h