summaryrefslogtreecommitdiffstats
path: root/security/sandbox/chromium/sandbox/win/src/signed_interception.cc
blob: 4f4310d6052b73725c08af1f73dca8210a40c26d (plain)
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
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/signed_interception.h"

#include <stdint.h>

#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/policy_target.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sharedmem_ipc_client.h"
#include "sandbox/win/src/target_services.h"
#include "mozilla/sandboxing/sandboxLogging.h"

namespace sandbox {

NTSTATUS WINAPI
TargetNtCreateSection(NtCreateSectionFunction orig_CreateSection,
                      PHANDLE section_handle,
                      ACCESS_MASK desired_access,
                      POBJECT_ATTRIBUTES object_attributes,
                      PLARGE_INTEGER maximum_size,
                      ULONG section_page_protection,
                      ULONG allocation_attributes,
                      HANDLE file_handle) {
  do {
    // The section only needs to have SECTION_MAP_EXECUTE, but the permissions
    // vary depending on the OS. Windows 1903 and higher requests (SECTION_QUERY
    // | SECTION_MAP_READ | SECTION_MAP_EXECUTE) while previous OS versions also
    // request SECTION_MAP_WRITE. Just check for EXECUTE.
    if (!(desired_access & SECTION_MAP_EXECUTE))
      break;
    if (object_attributes)
      break;
    if (maximum_size)
      break;
    if (section_page_protection != PAGE_EXECUTE)
      break;
    if (allocation_attributes != SEC_IMAGE)
      break;

    mozilla::sandboxing::LogBlocked("NtCreateSection");

    // IPC must be fully started.
    void* memory = GetGlobalIPCMemory();
    if (!memory)
      break;

    std::unique_ptr<wchar_t, NtAllocDeleter> path;

    if (!NtGetPathFromHandle(file_handle, &path))
      break;

    const wchar_t* const_name = path.get();

    CountedParameterSet<NameBased> params;
    params[NameBased::NAME] = ParamPickerMake(const_name);

    // Check if this will be sent to the broker.
    if (!QueryBroker(IpcTag::NTCREATESECTION, params.GetBase()))
      break;

    if (!ValidParameter(section_handle, sizeof(HANDLE), WRITE))
      break;

    CrossCallReturn answer = {0};
    answer.nt_status = STATUS_INVALID_IMAGE_HASH;
    SharedMemIPCClient ipc(memory);
    ResultCode code =
        CrossCall(ipc, IpcTag::NTCREATESECTION, file_handle, &answer);

    if (code != SBOX_ALL_OK)
      break;

    if (!NT_SUCCESS(answer.nt_status))
      break;

    __try {
      *section_handle = answer.handle;
      mozilla::sandboxing::LogAllowed("NtCreateSection");
      return answer.nt_status;
    } __except (EXCEPTION_EXECUTE_HANDLER) {
      break;
    }
  } while (false);

  // Fall back to the original API in all failure cases.
  return orig_CreateSection(section_handle, desired_access, object_attributes,
                            maximum_size, section_page_protection,
                            allocation_attributes, file_handle);
}

}  // namespace sandbox