15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/registry_interception.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/crosscall_client.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/ipc_tags.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_factory.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_nt_util.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sharedmem_ipc_client.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/target_services.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sandbox {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtCreateKey(NtCreateKeyFunction orig_CreateKey,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  PHANDLE key, ACCESS_MASK desired_access,
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  POBJECT_ATTRIBUTES object_attributes,
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ULONG title_index, PUNICODE_STRING class_name,
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ULONG create_options, PULONG disposition) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the process can create it first.
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_CreateKey(key, desired_access, object_attributes,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   title_index, class_name, create_options,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   disposition);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't trust that the IPC can work this early.
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(key, sizeof(HANDLE), WRITE))
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (disposition && !ValidParameter(disposition, sizeof(ULONG), WRITE))
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At this point we don't support class_name.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (class_name && class_name->Buffer && class_name->Length)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't support creating link keys, volatile keys and backup/restore.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (create_options)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t* name;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 attributes = 0;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE root_directory = 0;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &root_directory);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(ret) || NULL == name)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTCREATEKEY_TAG, name, attributes,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                root_directory, desired_access, title_index,
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                create_options, &answer);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(name, NT_ALLOC);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(nsylvain): We should return answer.nt_status here instead
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // of status. We can do this only after we checked the policy.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // otherwise we will returns ACCESS_DENIED for all paths
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // that are not specified by a policy, even though your token allows
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // access to that path, and the original call had a more meaningful
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // error. Bug 4369
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *key = answer.handle;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (disposition)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *disposition = answer.extended[0].unsigned_int;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status = answer.nt_status;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI CommonNtOpenKey(NTSTATUS status, PHANDLE key,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ACCESS_MASK desired_access,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                POBJECT_ATTRIBUTES object_attributes) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't trust that the IPC can work this early.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ValidParameter(key, sizeof(HANDLE), WRITE))
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void* memory = GetGlobalIPCMemory();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (NULL == memory)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    wchar_t* name;
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    uint32 attributes;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HANDLE root_directory;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    &root_directory);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(ret) || NULL == name)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SharedMemIPCClient ipc(memory);
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CrossCallReturn answer = {0};
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResultCode code = CrossCall(ipc, IPC_NTOPENKEY_TAG, name, attributes,
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                root_directory, desired_access, &answer);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operator delete(name, NT_ALLOC);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SBOX_ALL_OK != code)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!NT_SUCCESS(answer.nt_status))
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TODO(nsylvain): We should return answer.nt_status here instead
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // of status. We can do this only after we checked the policy.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // otherwise we will returns ACCESS_DENIED for all paths
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // that are not specified by a policy, even though your token allows
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // access to that path, and the original call had a more meaningful
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // error. Bug 4369
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    __try {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *key = answer.handle;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      status = answer.nt_status;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } __except(EXCEPTION_EXECUTE_HANDLER) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (false);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return status;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenKey(NtOpenKeyFunction orig_OpenKey, PHANDLE key,
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                ACCESS_MASK desired_access,
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                POBJECT_ATTRIBUTES object_attributes) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the process can open it first.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenKey(key, desired_access, object_attributes);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status))
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CommonNtOpenKey(status, key, desired_access, object_attributes);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NTSTATUS WINAPI TargetNtOpenKeyEx(NtOpenKeyExFunction orig_OpenKeyEx,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  PHANDLE key, ACCESS_MASK desired_access,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  POBJECT_ATTRIBUTES object_attributes,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  ULONG open_options) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check if the process can open it first.
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NTSTATUS status = orig_OpenKeyEx(key, desired_access, object_attributes,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   open_options);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do not support open_options at this time. The 2 current known values
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are REG_OPTION_CREATE_LINK, to open a symbolic link, and
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // REG_OPTION_BACKUP_RESTORE to open the key with special privileges.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (NT_SUCCESS(status) || open_options != 0)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return status;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return CommonNtOpenKey(status, key, desired_access, object_attributes);
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace sandbox
177