File: network_sandbox_hook_linux.cc

package info (click to toggle)
chromium 145.0.7632.159-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,976,224 kB
  • sloc: cpp: 36,198,469; ansic: 7,634,080; javascript: 3,564,060; python: 1,649,622; xml: 838,470; asm: 717,087; pascal: 185,708; sh: 88,786; perl: 88,718; objc: 79,984; sql: 59,811; cs: 42,452; fortran: 24,101; makefile: 21,144; tcl: 15,277; php: 14,022; yacc: 9,066; ruby: 7,553; awk: 3,720; lisp: 3,233; lex: 1,328; ada: 727; jsp: 228; sed: 36
file content (125 lines) | stat: -rw-r--r-- 4,490 bytes parent folder | download | duplicates (9)
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
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/network/network_sandbox_hook_linux.h"

#include <dlfcn.h>

#include <optional>

#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
#include "sandbox/linux/syscall_broker/broker_file_permission.h"
#include "sandbox/policy/features.h"

using sandbox::syscall_broker::BrokerFilePermission;
using sandbox::syscall_broker::MakeBrokerCommandSet;

namespace network {

sandbox::syscall_broker::BrokerCommandSet GetNetworkBrokerCommandSet() {
  return MakeBrokerCommandSet({
      sandbox::syscall_broker::COMMAND_ACCESS,
      sandbox::syscall_broker::COMMAND_MKDIR,
      sandbox::syscall_broker::COMMAND_OPEN,
      sandbox::syscall_broker::COMMAND_READLINK,
      sandbox::syscall_broker::COMMAND_RENAME,
      sandbox::syscall_broker::COMMAND_RMDIR,
      sandbox::syscall_broker::COMMAND_STAT,
      sandbox::syscall_broker::COMMAND_UNLINK,
      sandbox::syscall_broker::COMMAND_INOTIFY_ADD_WATCH,
  });
}

std::vector<BrokerFilePermission> GetNetworkFilePermissions(
    std::vector<std::string> network_context_parent_dirs) {
  if (!base::FeatureList::IsEnabled(
          sandbox::policy::features::kNetworkServiceFileAllowlist)) {
    return {BrokerFilePermission::AllPermissions("/"),
            BrokerFilePermission::AllPermissionsRecursive("/")};
  }

  const std::array<base::FilePath, 5> system_config_files = {
      base::FilePath("/etc/hosts"), base::FilePath("/etc/resolv.conf"),
      base::FilePath("/etc/nsswitch.conf"), base::FilePath("/etc/host.conf"),
      base::FilePath("/etc/gai.conf")};

  // Each system config file needs read permissions and watch permissions, and
  // read and watch permissions for its symlink target, if any. This is up to
  // 4 permissions.
  constexpr size_t kMaxPermissionsPerSystemConfigFile = 4;

  std::vector<BrokerFilePermission> perms;
  perms.reserve(system_config_files.size() *
                    kMaxPermissionsPerSystemConfigFile +
                network_context_parent_dirs.size());

  for (const base::FilePath& system_config_file : system_config_files) {
    perms.push_back(BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
        system_config_file.value()));
    perms.push_back(BrokerFilePermission::ReadOnly(system_config_file.value()));

    std::optional<base::FilePath> target_path =
        base::ReadSymbolicLinkAbsolute(system_config_file);
    if (!target_path.has_value()) {
      continue;
    }

    VLOG(1) << "Adding permissions for symlink: " << target_path->value();
    perms.push_back(BrokerFilePermission::InotifyAddWatchWithIntermediateDirs(
        target_path->value()));
    perms.push_back(BrokerFilePermission::ReadOnly(target_path->value()));
  }

  for (std::string dir_str : network_context_parent_dirs) {
    if (*dir_str.rbegin() != '/') {
      dir_str += "/";
    }
    VLOG(1) << "Granting ReadWriteCreateRecursive permissions to " << dir_str;
    perms.push_back(
        BrokerFilePermission::ReadWriteCreateRecursive(std::move(dir_str)));
  }

  return perms;
}

#if BUILDFLAG(IS_CHROMEOS)
void LoadNetworkLibraries() {
  const std::string libraries[]{
      // On ChromeOS DNS resolution will occur in process, so load the libraries
      // now. Note that depending on the glibc version, these libraries may have
      // been built directly into libc.so, so it's not an error if they fail to
      // load.
      "libnss_files.so.2", "libnss_dns.so.2"};
  for (const auto& library_name : libraries) {
    if (!dlopen(library_name.c_str(),
                RTLD_LAZY | RTLD_GLOBAL | RTLD_NODELETE)) {
      VLOG(1) << "LoadNetworkLibraries() dlopen() of " << library_name
              << " failed with error: " << dlerror();
    }
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS)

bool NetworkPreSandboxHook(std::vector<std::string> network_context_parent_dirs,
                           sandbox::policy::SandboxLinux::Options options) {
#if BUILDFLAG(IS_CHROMEOS)
  LoadNetworkLibraries();
#endif

  auto* instance = sandbox::policy::SandboxLinux::GetInstance();

  VLOG(1) << "Using network service sandbox.";

  instance->StartBrokerProcess(
      GetNetworkBrokerCommandSet(),
      GetNetworkFilePermissions(std::move(network_context_parent_dirs)),
      options);

  return true;
}

}  // namespace network