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   do {
     39     if (!ValidParameter(file, sizeof(HANDLE), WRITE))
     40       break;
     41     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
     42       break;
     43 
     44     void* memory = GetGlobalIPCMemory();
     45     if (NULL == memory)
     46       break;
     47 
     48     wchar_t* name;
     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 
     73     operator delete(name, NT_ALLOC);
     74 
     75     if (SBOX_ALL_OK != code)
     76       break;
     77 
     78     if (!NT_SUCCESS(answer.nt_status))
     79         return answer.nt_status;
     80 
     81     __try {
     82       *file = answer.handle;
     83       io_status->Status = answer.nt_status;
     84       io_status->Information = answer.extended[0].ulong_ptr;
     85       status = io_status->Status;
     86     } __except(EXCEPTION_EXECUTE_HANDLER) {
     87       break;
     88     }
     89   } while (false);
     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   do {
    110     if (!ValidParameter(file, sizeof(HANDLE), WRITE))
    111       break;
    112     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
    113       break;
    114 
    115     void* memory = GetGlobalIPCMemory();
    116     if (NULL == memory)
    117       break;
    118 
    119     wchar_t* name;
    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 
    141     operator delete(name, NT_ALLOC);
    142 
    143     if (SBOX_ALL_OK != code)
    144       break;
    145 
    146     if (!NT_SUCCESS(answer.nt_status))
    147       return answer.nt_status;
    148 
    149     __try {
    150       *file = answer.handle;
    151       io_status->Status = answer.nt_status;
    152       io_status->Information = answer.extended[0].ulong_ptr;
    153       status = io_status->Status;
    154     } __except(EXCEPTION_EXECUTE_HANDLER) {
    155       break;
    156     }
    157   } while (false);
    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   do {
    176     if (!ValidParameter(file_attributes, sizeof(FILE_BASIC_INFORMATION), WRITE))
    177       break;
    178 
    179     void* memory = GetGlobalIPCMemory();
    180     if (NULL == memory)
    181       break;
    182 
    183     wchar_t* name = NULL;
    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   return status;
    216 }
    217 
    218 NTSTATUS WINAPI TargetNtQueryFullAttributesFile(
    219     NtQueryFullAttributesFileFunction orig_QueryFullAttributes,
    220     POBJECT_ATTRIBUTES object_attributes,
    221     PFILE_NETWORK_OPEN_INFORMATION file_attributes) {
    222   // Check if the process can query it first.
    223   NTSTATUS status = orig_QueryFullAttributes(object_attributes,
    224                                              file_attributes);
    225   if (STATUS_ACCESS_DENIED != status)
    226     return status;
    227 
    228   // We don't trust that the IPC can work this early.
    229   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    230     return status;
    231 
    232   do {
    233     if (!ValidParameter(file_attributes, sizeof(FILE_NETWORK_OPEN_INFORMATION),
    234                         WRITE))
    235       break;
    236 
    237     void* memory = GetGlobalIPCMemory();
    238     if (NULL == memory)
    239       break;
    240 
    241     wchar_t* name = NULL;
    242     uint32 attributes = 0;
    243     NTSTATUS ret = AllocAndCopyName(object_attributes, &name, &attributes,
    244                                     NULL);
    245     if (!NT_SUCCESS(ret) || NULL == name)
    246       break;
    247 
    248     InOutCountedBuffer file_info(file_attributes,
    249                                  sizeof(FILE_NETWORK_OPEN_INFORMATION));
    250 
    251     ULONG broker = FALSE;
    252     CountedParameterSet<FileName> params;
    253     params[FileName::NAME] = ParamPickerMake(name);
    254     params[FileName::BROKER] = ParamPickerMake(broker);
    255 
    256     if (!QueryBroker(IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase()))
    257       break;
    258 
    259     SharedMemIPCClient ipc(memory);
    260     CrossCallReturn answer = {0};
    261     ResultCode code = CrossCall(ipc, IPC_NTQUERYFULLATTRIBUTESFILE_TAG, name,
    262                                 attributes, file_info, &answer);
    263 
    264     operator delete(name, NT_ALLOC);
    265 
    266     if (SBOX_ALL_OK != code)
    267       break;
    268 
    269     return answer.nt_status;
    270   } while (false);
    271 
    272   return status;
    273 }
    274 
    275 NTSTATUS WINAPI TargetNtSetInformationFile(
    276     NtSetInformationFileFunction orig_SetInformationFile, HANDLE file,
    277     PIO_STATUS_BLOCK io_status, PVOID file_info, ULONG length,
    278     FILE_INFORMATION_CLASS file_info_class) {
    279   // Check if the process can open it first.
    280   NTSTATUS status = orig_SetInformationFile(file, io_status, file_info, length,
    281                                             file_info_class);
    282   if (STATUS_ACCESS_DENIED != status)
    283     return status;
    284 
    285   // We don't trust that the IPC can work this early.
    286   if (!SandboxFactory::GetTargetServices()->GetState()->InitCalled())
    287     return status;
    288 
    289   do {
    290     void* memory = GetGlobalIPCMemory();
    291     if (NULL == memory)
    292       break;
    293 
    294     if (!ValidParameter(io_status, sizeof(IO_STATUS_BLOCK), WRITE))
    295       break;
    296 
    297     if (!ValidParameter(file_info, length, READ))
    298       break;
    299 
    300     FILE_RENAME_INFORMATION* file_rename_info =
    301         reinterpret_cast<FILE_RENAME_INFORMATION*>(file_info);
    302     OBJECT_ATTRIBUTES object_attributes;
    303     UNICODE_STRING object_name;
    304     InitializeObjectAttributes(&object_attributes, &object_name, 0, NULL, NULL);
    305 
    306     __try {
    307       if (!IsSupportedRenameCall(file_rename_info, length, file_info_class))
    308         break;
    309 
    310       object_attributes.RootDirectory = file_rename_info->RootDirectory;
    311       object_name.Buffer = file_rename_info->FileName;
    312       object_name.Length = object_name.MaximumLength =
    313           static_cast<USHORT>(file_rename_info->FileNameLength);
    314     } __except(EXCEPTION_EXECUTE_HANDLER) {
    315       break;
    316     }
    317 
    318     wchar_t* name;
    319     NTSTATUS ret = AllocAndCopyName(&object_attributes, &name, NULL, NULL);
    320     if (!NT_SUCCESS(ret) || !name)
    321       break;
    322 
    323     ULONG broker = FALSE;
    324     CountedParameterSet<FileName> params;
    325     params[FileName::NAME] = ParamPickerMake(name);
    326     params[FileName::BROKER] = ParamPickerMake(broker);
    327 
    328     if (!QueryBroker(IPC_NTSETINFO_RENAME_TAG, params.GetBase()))
    329       break;
    330 
    331     InOutCountedBuffer io_status_buffer(io_status, sizeof(IO_STATUS_BLOCK));
    332     // This is actually not an InOut buffer, only In, but using InOut facility
    333     // really helps to simplify the code.
    334     InOutCountedBuffer file_info_buffer(file_info, length);
    335 
    336     SharedMemIPCClient ipc(memory);
    337     CrossCallReturn answer = {0};
    338     ResultCode code = CrossCall(ipc, IPC_NTSETINFO_RENAME_TAG, file,
    339                                 io_status_buffer, file_info_buffer, length,
    340                                 file_info_class, &answer);
    341 
    342     if (SBOX_ALL_OK != code)
    343       break;
    344 
    345     status = answer.nt_status;
    346   } while (false);
    347 
    348   return status;
    349 }
    350 
    351 }  // namespace sandbox
    352