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/filesystem_interception.h"
      6 
      7 #include "sandbox/win/src/crosscall_client.h"
      8 #include "sandbox/win/src/ipc_tags.h"
      9 #include "sandbox/win/src/policy_params.h"
     10 #include "sandbox/win/src/policy_target.h"
     11 #include "sandbox/win/src/sandbox_factory.h"
     12 #include "sandbox/win/src/sandbox_nt_util.h"
     13 #include "sandbox/win/src/sharedmem_ipc_client.h"
     14 #include "sandbox/win/src/target_services.h"
     15 
     16 namespace sandbox {
     17 
     18 NTSTATUS WINAPI TargetNtCreateFile(NtCreateFileFunction orig_CreateFile,
     19                                    PHANDLE file, ACCESS_MASK desired_access,
     20                                    POBJECT_ATTRIBUTES object_attributes,
     21                                    PIO_STATUS_BLOCK io_status,
     22                                    PLARGE_INTEGER allocation_size,
     23                                    ULONG file_attributes, ULONG sharing,
     24                                    ULONG disposition, ULONG options,
     25                                    PVOID ea_buffer, ULONG ea_length) {
     26   // Check if the process can open it first.
     27   NTSTATUS status = orig_CreateFile(file, desired_access, object_attributes,
     28                                     io_status, allocation_size,
     29                                     file_attributes, sharing, disposition,
     30                                     options, ea_buffer, ea_length);
     31   if (STATUS_ACCESS_DENIED != status)
     32     return status;
     33 
     34   // We don't trust that the IPC can work this early.
     35   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
     36     return status;
     37 
     38   wchar_t* name = NULL;
     39   do {
     40     if (!ValidParameter(file, sizeof(HANDLE), WRITE))
     41       break;
     42     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
     43       break;
     44 
     45     void* memory = GetGlobalIPCMemory();
     46     if (NULL == memory)
     47       break;
     48 
     49     uint32 attributes = 0;
     50     NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
     51                                     NULL);
     52     if (!NT_SUCCESS(ret) || NULL == name)
     53       break;
     54 
     55     ULONG broker = FALSE;
     56     CountedParameterSet<OpenFile> params;
     57     params[OpenFile::NAME] = ParamPickerMake(name);
     58     params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
     59     params[OpenFile::OPTIONS] = ParamPickerMake(options);
     60     params[OpenFile::BROKER] = ParamPickerMake(broker);
     61 
     62     if (!QueryBroker(IPC_NTCREATEFILE_TAG, params.GetBase()))
     63       break;
     64 
     65     SharedMemIPCClient ipc(memory);
     66     CrossCallReturn answer = {0};
     67     // The following call must match in the parameters with
     68     // FilesystemDispatcher::ProcessNtCreateFile.
     69     ResultCode code = CrossCall(ipc, IPC_NTCREATEFILE_TAG, name, attributes,
     70                                 desired_access, file_attributes, sharing,
     71                                 disposition, options, &answer);
     72     if (SBOX_ALL_OK != code)
     73       break;
     74 
     75     if (!NT_SUCCESS(answer.nt_status))
     76         return answer.nt_status;
     77 
     78     __try {
     79       *file = answer.handle;
     80       io_status->Status = answer.nt_status;
     81       io_status->Information = answer.extended[0].ulong_ptr;
     82       status = io_status->Status;
     83     } __except(EXCEPTION_EXECUTE_HANDLER) {
     84       break;
     85     }
     86   } while (false);
     87 
     88   if (name)
     89     operator delete(name, NT_ALLOC);
     90 
     91   return status;
     92 }
     93 
     94 NTSTATUS WINAPI TargetNtOpenFile(NtOpenFileFunction orig_OpenFile, PHANDLE file,
     95                                  ACCESS_MASK desired_access,
     96                                  POBJECT_ATTRIBUTES object_attributes,
     97                                  PIO_STATUS_BLOCK io_status, ULONG sharing,
     98                                  ULONG options) {
     99   // Check if the process can open it first.
    100   NTSTATUS status = orig_OpenFile(file, desired_access, object_attributes,
    101                                   io_status, sharing, options);
    102   if (STATUS_ACCESS_DENIED != status)
    103     return status;
    104 
    105   // We don't trust that the IPC can work this early.
    106   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    107     return status;
    108 
    109   wchar_t* name = NULL;
    110   do {
    111     if (!ValidParameter(file, sizeof(HANDLE), WRITE))
    112       break;
    113     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
    114       break;
    115 
    116     void* memory = GetGlobalIPCMemory();
    117     if (NULL == memory)
    118       break;
    119 
    120     uint32 attributes;
    121     NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
    122                                     NULL);
    123     if (!NT_SUCCESS(ret) || NULL == name)
    124       break;
    125 
    126     ULONG broker = FALSE;
    127     CountedParameterSet<OpenFile> params;
    128     params[OpenFile::NAME] = ParamPickerMake(name);
    129     params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
    130     params[OpenFile::OPTIONS] = ParamPickerMake(options);
    131     params[OpenFile::BROKER] = ParamPickerMake(broker);
    132 
    133     if (!QueryBroker(IPC_NTOPENFILE_TAG, params.GetBase()))
    134       break;
    135 
    136     SharedMemIPCClient ipc(memory);
    137     CrossCallReturn answer = {0};
    138     ResultCode code = CrossCall(ipc, IPC_NTOPENFILE_TAG, name, attributes,
    139                                 desired_access, sharing, options, &answer);
    140     if (SBOX_ALL_OK != code)
    141       break;
    142 
    143     if (!NT_SUCCESS(answer.nt_status))
    144       return answer.nt_status;
    145 
    146     __try {
    147       *file = answer.handle;
    148       io_status->Status = answer.nt_status;
    149       io_status->Information = answer.extended[0].ulong_ptr;
    150       status = io_status->Status;
    151     } __except(EXCEPTION_EXECUTE_HANDLER) {
    152       break;
    153     }
    154   } while (false);
    155 
    156   if (name)
    157     operator delete(name, NT_ALLOC);
    158 
    159   return status;
    160 }
    161 
    162 NTSTATUS WINAPI TargetNtQueryAttributesFile(
    163     NtQueryAttributesFileFunction orig_QueryAttributes,
    164     POBJECT_ATTRIBUTES object_attributes,
    165     PFILE_BASIC_INFORMATION file_attributes) {
    166   // Check if the process can query it first.
    167   NTSTATUS status = orig_QueryAttributes(object_attributes, file_attributes);
    168   if (STATUS_ACCESS_DENIED != status)
    169     return status;
    170 
    171   // We don't trust that the IPC can work this early.
    172   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    173     return status;
    174 
    175   wchar_t* name = NULL;
    176   do {
    177     if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE))
    178       break;
    179 
    180     void* memory = GetGlobalIPCMemory();
    181     if (NULL == memory)
    182       break;
    183 
    184     uint32 attributes = 0;
    185     NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
    186                                     NULL);
    187     if (!NT_SUCCESS(ret) || NULL == name)
    188       break;
    189 
    190     InOutCountedBuffer file_info(file_attributes,
    191                                  sizeof(FILE_BASIC_INFORMATION));
    192 
    193     ULONG broker = FALSE;
    194     CountedParameterSet<FileName> params;
    195     params[FileName::NAME] = ParamPickerMake(name);
    196     params[FileName::BROKER] = ParamPickerMake(broker);
    197 
    198     if (!QueryBroker(IPC_NTQUERYATTRIBUTESFILE_TAG, params.GetBase()))
    199       break;
    200 
    201     SharedMemIPCClient ipc(memory);
    202     CrossCallReturn answer = {0};
    203     ResultCode code = CrossCall(ipc, IPC_NTQUERYATTRIBUTESFILE_TAG, name,
    204                                 attributes, file_info, &answer);
    205 
    206     operator delete(name, NT_ALLOC);
    207 
    208     if (SBOX_ALL_OK != code)
    209       break;
    210 
    211     return answer.nt_status;
    212 
    213   } while (false);
    214 
    215   if (name)
    216     operator delete(name, NT_ALLOC);
    217 
    218   return status;
    219 }
    220 
    221 NTSTATUS WINAPI TargetNtQueryFullAttributesFile(
    222     NtQueryFullAttributesFileFunction orig_QueryFullAttributes,
    223     POBJECT_ATTRIBUTES object_attributes,
    224     PFILE_NETWORK_OPEN_INFORMATION file_attributes) {
    225   // Check if the process can query it first.
    226   NTSTATUS status = orig_QueryFullAttributes(object_attributes,
    227                                              file_attributes);
    228   if (STATUS_ACCESS_DENIED != status)
    229     return status;
    230 
    231   // We don't trust that the IPC can work this early.
    232   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    233     return status;
    234 
    235   wchar_t* name = NULL;
    236   do {
    237     if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION),
    238                         WRITE))
    239       break;
    240 
    241     void* memory = GetGlobalIPCMemory();
    242     if (NULL == memory)
    243       break;
    244 
    245     uint32 attributes = 0;
    246     NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
    247                                     NULL);
    248     if (!NT_SUCCESS(ret) || NULL == name)
    249       break;
    250 
    251     InOutCountedBuffer file_info(file_attributes,
    252                                  sizeof(FILE_NETWORK_OPEN_INFORMATION));
    253 
    254     ULONG broker = FALSE;
    255     CountedParameterSet<FileName> params;
    256     params[FileName::NAME] = ParamPickerMake(name);
    257     params[FileName::BROKER] = ParamPickerMake(broker);
    258 
    259     if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()))
    260       break;
    261 
    262     SharedMemIPCClient ipc(memory);
    263     CrossCallReturn answer = {0};
    264     ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name,
    265                                 attributes, file_info, &answer);
    266 
    267     operator delete(name, NT_ALLOC);
    268 
    269     if (SBOX_ALL_OK != code)
    270       break;
    271 
    272     return answer.nt_status;
    273   } while (false);
    274 
    275   if (name)
    276     operator delete(name, NT_ALLOC);
    277 
    278   return status;
    279 }
    280 
    281 NTSTATUS WINAPI TargetNtSetInformationFile(
    282     NtSetInformationFileFunction orig_SetInformationFile, HANDLE file,
    283     PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length,
    284     FILE_INFORMATION_CLASS file_info_class) {
    285   // Check if the process can open it first.
    286   NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length,
    287                                             file_info_class);
    288   if (STATUS_ACCESS_DENIED != status)
    289     return status;
    290 
    291   // We don't trust that the IPC can work this early.
    292   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    293     return status;
    294 
    295   wchar_t* name = NULL;
    296   do {
    297     void* memory = GetGlobalIPCMemory();
    298     if (NULL == memory)
    299       break;
    300 
    301     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
    302       break;
    303 
    304     if (!ValidParameter(file_info, length, READ))
    305       break;
    306 
    307     FILE_RENAME_INFORMATION* file_rename_info =
    308         reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info);
    309     OBJECT_ATTRIBUTES object_attributes;
    310     UNICODE_STRING object_name;
    311     InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL);
    312 
    313     __try {
    314       if (!IsSupportedRenameCall(file_rename_info, length, file_info_class))
    315         break;
    316 
    317       object_attributes.RootDirectory = file_rename_info->RootDirectory;
    318       object_name.Buffer = file_rename_info->FileName;
    319       object_name.Length = object_name.MaximumLength =
    320           static_cast<USHORT>(file_rename_info->FileNameLength);
    321     } __except(EXCEPTION_EXECUTE_HANDLER) {
    322       break;
    323     }
    324 
    325     NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL);
    326     if (!NT_SUCCESS(ret) || !name)
    327       break;
    328 
    329     ULONG broker = FALSE;
    330     CountedParameterSet<FileName> params;
    331     params[FileName::NAME] = ParamPickerMake(name);
    332     params[FileName::BROKER] = ParamPickerMake(broker);
    333 
    334     if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase()))
    335       break;
    336 
    337     InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK));
    338     // This is actually not an InOut buffer, only In, but using InOut facility
    339     // really helps to simplify the code.
    340     InOutCountedBuffer file_info_buffer(file_info, length);
    341 
    342     SharedMemIPCClient ipc(memory);
    343     CrossCallReturn answer = {0};
    344     ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file,
    345                                 io_status_buffer, file_info_buffer, length,
    346                                 file_info_class, &answer);
    347 
    348     if (SBOX_ALL_OK != code)
    349       break;
    350 
    351     status = answer.nt_status;
    352   } while (false);
    353 
    354   if (name)
    355     operator delete(name, NT_ALLOC);
    356 
    357   return status;
    358 }
    359 
    360 }  // namespace sandbox
    361