security/sandbox/win/src/registry_interception.cc

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
michael@0 2 // Use of this source code is governed by a BSD-style license that can be
michael@0 3 // found in the LICENSE file.
michael@0 4
michael@0 5 #include "sandbox/win/src/registry_interception.h"
michael@0 6
michael@0 7 #include "sandbox/win/src/crosscall_client.h"
michael@0 8 #include "sandbox/win/src/ipc_tags.h"
michael@0 9 #include "sandbox/win/src/sandbox_factory.h"
michael@0 10 #include "sandbox/win/src/sandbox_nt_util.h"
michael@0 11 #include "sandbox/win/src/sharedmem_ipc_client.h"
michael@0 12 #include "sandbox/win/src/target_services.h"
michael@0 13
michael@0 14 namespace sandbox {
michael@0 15
michael@0 16 NTSTATUS WINAPI TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey,
michael@0 17 PHANDLE key, ACCESS_MASK desired_access,
michael@0 18 POBJECT_ATTRIBUTES object_attributes,
michael@0 19 ULONG title_index, PUNICODE_STRING class_name,
michael@0 20 ULONG create_options, PULONG disposition) {
michael@0 21 // Check if the process can create it first.
michael@0 22 NTSTATUS status = orig_CreateKey(key, desired_access, object_attributes,
michael@0 23 title_index, class_name, create_options,
michael@0 24 disposition);
michael@0 25 if (NT_SUCCESS(status))
michael@0 26 return status;
michael@0 27
michael@0 28 // We don't trust that the IPC can work this early.
michael@0 29 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
michael@0 30 return status;
michael@0 31
michael@0 32 do {
michael@0 33 if (!ValidParameter(key, sizeof(HANDLE), WRITE))
michael@0 34 break;
michael@0 35
michael@0 36 if (disposition && !ValidParameter(disposition, sizeof(ULONG), WRITE))
michael@0 37 break;
michael@0 38
michael@0 39 // At this point we don't support class_name.
michael@0 40 if (class_name && class_name->Buffer && class_name->Length)
michael@0 41 break;
michael@0 42
michael@0 43 // We don't support creating link keys, volatile keys and backup/restore.
michael@0 44 if (create_options)
michael@0 45 break;
michael@0 46
michael@0 47 void* memory = GetGlobalIPCMemory();
michael@0 48 if (NULL == memory)
michael@0 49 break;
michael@0 50
michael@0 51 wchar_t* name;
michael@0 52 uint32 attributes = 0;
michael@0 53 HANDLE root_directory = 0;
michael@0 54 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
michael@0 55 &root_directory);
michael@0 56 if (!NT_SUCCESS(ret) || NULL == name)
michael@0 57 break;
michael@0 58
michael@0 59 SharedMemIPCClient ipc(memory);
michael@0 60 CrossCallReturn answer = {0};
michael@0 61
michael@0 62 ResultCode code = CrossCall(ipc, IPC_NTCREATEKEY_TAG, name, attributes,
michael@0 63 root_directory, desired_access, title_index,
michael@0 64 create_options, &answer);
michael@0 65
michael@0 66 operator delete(name, NT_ALLOC);
michael@0 67
michael@0 68 if (SBOX_ALL_OK != code)
michael@0 69 break;
michael@0 70
michael@0 71 if (!NT_SUCCESS(answer.nt_status))
michael@0 72 // TODO(nsylvain): We should return answer.nt_status here instead
michael@0 73 // of status. We can do this only after we checked the policy.
michael@0 74 // otherwise we will returns ACCESS_DENIED for all paths
michael@0 75 // that are not specified by a policy, even though your token allows
michael@0 76 // access to that path, and the original call had a more meaningful
michael@0 77 // error. Bug 4369
michael@0 78 break;
michael@0 79
michael@0 80 __try {
michael@0 81 *key = answer.handle;
michael@0 82
michael@0 83 if (disposition)
michael@0 84 *disposition = answer.extended[0].unsigned_int;
michael@0 85
michael@0 86 status = answer.nt_status;
michael@0 87 } __except(EXCEPTION_EXECUTE_HANDLER) {
michael@0 88 break;
michael@0 89 }
michael@0 90 } while (false);
michael@0 91
michael@0 92 return status;
michael@0 93 }
michael@0 94
michael@0 95 NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, PHANDLE key,
michael@0 96 ACCESS_MASK desired_access,
michael@0 97 POBJECT_ATTRIBUTES object_attributes) {
michael@0 98 // We don't trust that the IPC can work this early.
michael@0 99 if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
michael@0 100 return status;
michael@0 101
michael@0 102 do {
michael@0 103 if (!ValidParameter(key, sizeof(HANDLE), WRITE))
michael@0 104 break;
michael@0 105
michael@0 106 void* memory = GetGlobalIPCMemory();
michael@0 107 if (NULL == memory)
michael@0 108 break;
michael@0 109
michael@0 110 wchar_t* name;
michael@0 111 uint32 attributes;
michael@0 112 HANDLE root_directory;
michael@0 113 NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
michael@0 114 &root_directory);
michael@0 115 if (!NT_SUCCESS(ret) || NULL == name)
michael@0 116 break;
michael@0 117
michael@0 118 SharedMemIPCClient ipc(memory);
michael@0 119 CrossCallReturn answer = {0};
michael@0 120 ResultCode code = CrossCall(ipc, IPC_NTOPENKEY_TAG, name, attributes,
michael@0 121 root_directory, desired_access, &answer);
michael@0 122
michael@0 123 operator delete(name, NT_ALLOC);
michael@0 124
michael@0 125 if (SBOX_ALL_OK != code)
michael@0 126 break;
michael@0 127
michael@0 128 if (!NT_SUCCESS(answer.nt_status))
michael@0 129 // TODO(nsylvain): We should return answer.nt_status here instead
michael@0 130 // of status. We can do this only after we checked the policy.
michael@0 131 // otherwise we will returns ACCESS_DENIED for all paths
michael@0 132 // that are not specified by a policy, even though your token allows
michael@0 133 // access to that path, and the original call had a more meaningful
michael@0 134 // error. Bug 4369
michael@0 135 break;
michael@0 136
michael@0 137 __try {
michael@0 138 *key = answer.handle;
michael@0 139 status = answer.nt_status;
michael@0 140 } __except(EXCEPTION_EXECUTE_HANDLER) {
michael@0 141 break;
michael@0 142 }
michael@0 143 } while (false);
michael@0 144
michael@0 145 return status;
michael@0 146 }
michael@0 147
michael@0 148 NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, PHANDLE key,
michael@0 149 ACCESS_MASK desired_access,
michael@0 150 POBJECT_ATTRIBUTES object_attributes) {
michael@0 151 // Check if the process can open it first.
michael@0 152 NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes);
michael@0 153 if (NT_SUCCESS(status))
michael@0 154 return status;
michael@0 155
michael@0 156 return CommonNtOpenKey(status, key, desired_access, object_attributes);
michael@0 157 }
michael@0 158
michael@0 159 NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx,
michael@0 160 PHANDLE key, ACCESS_MASK desired_access,
michael@0 161 POBJECT_ATTRIBUTES object_attributes,
michael@0 162 ULONG open_options) {
michael@0 163 // Check if the process can open it first.
michael@0 164 NTSTATUS status = orig_OpenKeyEx(key, desired_access, object_attributes,
michael@0 165 open_options);
michael@0 166
michael@0 167 // We do not support open_options at this time. The 2 current known values
michael@0 168 // are REG_OPTION_CREATE_LINK, to open a symbolic link, and
michael@0 169 // REG_OPTION_BACKUP_RESTORE to open the key with special privileges.
michael@0 170 if (NT_SUCCESS(status) || open_options != 0)
michael@0 171 return status;
michael@0 172
michael@0 173 return CommonNtOpenKey(status, key, desired_access, object_attributes);
michael@0 174 }
michael@0 175
michael@0 176 } // namespace sandbox

mercurial