PageRenderTime 44ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/sandbox/src/filesystem_interception.cc

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