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