/chromium-webcl/src/sandbox/win/src/filesystem_dispatcher.cc

https://bitbucket.org/peixuan/chromium_r197479_base · C++ · 297 lines · 225 code · 44 blank · 28 comment · 20 complexity · d807a79e96b8c07e4b6afbdad025787e MD5 · raw file

  1. // Copyright (c) 2006-2010 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/win/src/filesystem_dispatcher.h"
  5. #include "sandbox/win/src/crosscall_client.h"
  6. #include "sandbox/win/src/filesystem_interception.h"
  7. #include "sandbox/win/src/filesystem_policy.h"
  8. #include "sandbox/win/src/interception.h"
  9. #include "sandbox/win/src/interceptors.h"
  10. #include "sandbox/win/src/ipc_tags.h"
  11. #include "sandbox/win/src/policy_broker.h"
  12. #include "sandbox/win/src/policy_params.h"
  13. #include "sandbox/win/src/sandbox.h"
  14. #include "sandbox/win/src/sandbox_nt_util.h"
  15. namespace sandbox {
  16. FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base)
  17. : policy_base_(policy_base) {
  18. static const IPCCall create_params = {
  19. {IPC_NTCREATEFILE_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE, ULONG_TYPE,
  20. ULONG_TYPE, ULONG_TYPE, ULONG_TYPE},
  21. reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtCreateFile)
  22. };
  23. static const IPCCall open_file = {
  24. {IPC_NTOPENFILE_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE, ULONG_TYPE,
  25. ULONG_TYPE},
  26. reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtOpenFile)
  27. };
  28. static const IPCCall attribs = {
  29. {IPC_NTQUERYATTRIBUTESFILE_TAG, WCHAR_TYPE, ULONG_TYPE, INOUTPTR_TYPE},
  30. reinterpret_cast<CallbackGeneric>(
  31. &FilesystemDispatcher::NtQueryAttributesFile)
  32. };
  33. static const IPCCall full_attribs = {
  34. {IPC_NTQUERYFULLATTRIBUTESFILE_TAG, WCHAR_TYPE, ULONG_TYPE, INOUTPTR_TYPE},
  35. reinterpret_cast<CallbackGeneric>(
  36. &FilesystemDispatcher::NtQueryFullAttributesFile)
  37. };
  38. static const IPCCall set_info = {
  39. {IPC_NTSETINFO_RENAME_TAG, VOIDPTR_TYPE, INOUTPTR_TYPE, INOUTPTR_TYPE,
  40. ULONG_TYPE, ULONG_TYPE},
  41. reinterpret_cast<CallbackGeneric>(
  42. &FilesystemDispatcher::NtSetInformationFile)
  43. };
  44. ipc_calls_.push_back(create_params);
  45. ipc_calls_.push_back(open_file);
  46. ipc_calls_.push_back(attribs);
  47. ipc_calls_.push_back(full_attribs);
  48. ipc_calls_.push_back(set_info);
  49. }
  50. bool FilesystemDispatcher::SetupService(InterceptionManager* manager,
  51. int service) {
  52. switch (service) {
  53. case IPC_NTCREATEFILE_TAG:
  54. return INTERCEPT_NT(manager, NtCreateFile, CREATE_FILE_ID, 48);
  55. case IPC_NTOPENFILE_TAG:
  56. return INTERCEPT_NT(manager, NtOpenFile, OPEN_FILE_ID, 28);
  57. case IPC_NTQUERYATTRIBUTESFILE_TAG:
  58. return INTERCEPT_NT(manager, NtQueryAttributesFile, QUERY_ATTRIB_FILE_ID,
  59. 12);
  60. case IPC_NTQUERYFULLATTRIBUTESFILE_TAG:
  61. return INTERCEPT_NT(manager, NtQueryFullAttributesFile,
  62. QUERY_FULL_ATTRIB_FILE_ID, 12);
  63. case IPC_NTSETINFO_RENAME_TAG:
  64. return INTERCEPT_NT(manager, NtSetInformationFile, SET_INFO_FILE_ID, 24);
  65. default:
  66. return false;
  67. }
  68. }
  69. bool FilesystemDispatcher::NtCreateFile(
  70. IPCInfo* ipc, std::wstring* name, DWORD attributes, DWORD desired_access,
  71. DWORD file_attributes, DWORD share_access, DWORD create_disposition,
  72. DWORD create_options) {
  73. if (!PreProcessName(*name, name)) {
  74. // The path requested might contain a reparse point.
  75. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  76. return true;
  77. }
  78. const wchar_t* filename = name->c_str();
  79. ULONG broker = TRUE;
  80. CountedParameterSet<OpenFile> params;
  81. params[OpenFile::NAME] = ParamPickerMake(filename);
  82. params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
  83. params[OpenFile::OPTIONS] = ParamPickerMake(create_options);
  84. params[OpenFile::BROKER] = ParamPickerMake(broker);
  85. // To evaluate the policy we need to call back to the policy object. We
  86. // are just middlemen in the operation since is the FileSystemPolicy which
  87. // knows what to do.
  88. EvalResult result = policy_base_->EvalPolicy(IPC_NTCREATEFILE_TAG,
  89. params.GetBase());
  90. HANDLE handle;
  91. ULONG_PTR io_information = 0;
  92. NTSTATUS nt_status;
  93. if (!FileSystemPolicy::CreateFileAction(result, *ipc->client_info, *name,
  94. attributes, desired_access,
  95. file_attributes, share_access,
  96. create_disposition, create_options,
  97. &handle, &nt_status,
  98. &io_information)) {
  99. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  100. return true;
  101. }
  102. // Return operation status on the IPC.
  103. ipc->return_info.extended[0].ulong_ptr = io_information;
  104. ipc->return_info.nt_status = nt_status;
  105. ipc->return_info.handle = handle;
  106. return true;
  107. }
  108. bool FilesystemDispatcher::NtOpenFile(
  109. IPCInfo* ipc, std::wstring* name, DWORD attributes, DWORD desired_access,
  110. DWORD share_access, DWORD open_options) {
  111. if (!PreProcessName(*name, name)) {
  112. // The path requested might contain a reparse point.
  113. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  114. return true;
  115. }
  116. const wchar_t* filename = name->c_str();
  117. ULONG broker = TRUE;
  118. CountedParameterSet<OpenFile> params;
  119. params[OpenFile::NAME] = ParamPickerMake(filename);
  120. params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
  121. params[OpenFile::OPTIONS] = ParamPickerMake(open_options);
  122. params[OpenFile::BROKER] = ParamPickerMake(broker);
  123. // To evaluate the policy we need to call back to the policy object. We
  124. // are just middlemen in the operation since is the FileSystemPolicy which
  125. // knows what to do.
  126. EvalResult result = policy_base_->EvalPolicy(IPC_NTOPENFILE_TAG,
  127. params.GetBase());
  128. HANDLE handle;
  129. ULONG_PTR io_information = 0;
  130. NTSTATUS nt_status;
  131. if (!FileSystemPolicy::OpenFileAction(result, *ipc->client_info, *name,
  132. attributes, desired_access,
  133. share_access, open_options, &handle,
  134. &nt_status, &io_information)) {
  135. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  136. return true;
  137. }
  138. // Return operation status on the IPC.
  139. ipc->return_info.extended[0].ulong_ptr = io_information;
  140. ipc->return_info.nt_status = nt_status;
  141. ipc->return_info.handle = handle;
  142. return true;
  143. }
  144. bool FilesystemDispatcher::NtQueryAttributesFile(
  145. IPCInfo* ipc, std::wstring* name, DWORD attributes, CountedBuffer* info) {
  146. if (sizeof(FILE_BASIC_INFORMATION) != info->Size())
  147. return false;
  148. if (!PreProcessName(*name, name)) {
  149. // The path requested might contain a reparse point.
  150. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  151. return true;
  152. }
  153. ULONG broker = TRUE;
  154. const wchar_t* filename = name->c_str();
  155. CountedParameterSet<FileName> params;
  156. params[FileName::NAME] = ParamPickerMake(filename);
  157. params[FileName::BROKER] = ParamPickerMake(broker);
  158. // To evaluate the policy we need to call back to the policy object. We
  159. // are just middlemen in the operation since is the FileSystemPolicy which
  160. // knows what to do.
  161. EvalResult result = policy_base_->EvalPolicy(IPC_NTQUERYATTRIBUTESFILE_TAG,
  162. params.GetBase());
  163. FILE_BASIC_INFORMATION* information =
  164. reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer());
  165. NTSTATUS nt_status;
  166. if (!FileSystemPolicy::QueryAttributesFileAction(result, *ipc->client_info,
  167. *name, attributes,
  168. information, &nt_status)) {
  169. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  170. return true;
  171. }
  172. // Return operation status on the IPC.
  173. ipc->return_info.nt_status = nt_status;
  174. return true;
  175. }
  176. bool FilesystemDispatcher::NtQueryFullAttributesFile(
  177. IPCInfo* ipc, std::wstring* name, DWORD attributes, CountedBuffer* info) {
  178. if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size())
  179. return false;
  180. if (!PreProcessName(*name, name)) {
  181. // The path requested might contain a reparse point.
  182. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  183. return true;
  184. }
  185. ULONG broker = TRUE;
  186. const wchar_t* filename = name->c_str();
  187. CountedParameterSet<FileName> params;
  188. params[FileName::NAME] = ParamPickerMake(filename);
  189. params[FileName::BROKER] = ParamPickerMake(broker);
  190. // To evaluate the policy we need to call back to the policy object. We
  191. // are just middlemen in the operation since is the FileSystemPolicy which
  192. // knows what to do.
  193. EvalResult result = policy_base_->EvalPolicy(
  194. IPC_NTQUERYFULLATTRIBUTESFILE_TAG, params.GetBase());
  195. FILE_NETWORK_OPEN_INFORMATION* information =
  196. reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer());
  197. NTSTATUS nt_status;
  198. if (!FileSystemPolicy::QueryFullAttributesFileAction(result,
  199. *ipc->client_info,
  200. *name, attributes,
  201. information,
  202. &nt_status)) {
  203. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  204. return true;
  205. }
  206. // Return operation status on the IPC.
  207. ipc->return_info.nt_status = nt_status;
  208. return true;
  209. }
  210. bool FilesystemDispatcher::NtSetInformationFile(
  211. IPCInfo* ipc, HANDLE handle, CountedBuffer* status, CountedBuffer* info,
  212. DWORD length, DWORD info_class) {
  213. if (sizeof(IO_STATUS_BLOCK) != status->Size())
  214. return false;
  215. if (length != info->Size())
  216. return false;
  217. FILE_RENAME_INFORMATION* rename_info =
  218. reinterpret_cast<FILE_RENAME_INFORMATION*>(info->Buffer());
  219. if (!IsSupportedRenameCall(rename_info, length, info_class))
  220. return false;
  221. std::wstring name;
  222. name.assign(rename_info->FileName, rename_info->FileNameLength /
  223. sizeof(rename_info->FileName[0]));
  224. if (!PreProcessName(name, &name)) {
  225. // The path requested might contain a reparse point.
  226. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  227. return true;
  228. }
  229. ULONG broker = TRUE;
  230. const wchar_t* filename = name.c_str();
  231. CountedParameterSet<FileName> params;
  232. params[FileName::NAME] = ParamPickerMake(filename);
  233. params[FileName::BROKER] = ParamPickerMake(broker);
  234. // To evaluate the policy we need to call back to the policy object. We
  235. // are just middlemen in the operation since is the FileSystemPolicy which
  236. // knows what to do.
  237. EvalResult result = policy_base_->EvalPolicy(IPC_NTSETINFO_RENAME_TAG,
  238. params.GetBase());
  239. IO_STATUS_BLOCK* io_status =
  240. reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer());
  241. NTSTATUS nt_status;
  242. if (!FileSystemPolicy::SetInformationFileAction(result, *ipc->client_info,
  243. handle, rename_info, length,
  244. info_class, io_status,
  245. &nt_status)) {
  246. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  247. return true;
  248. }
  249. // Return operation status on the IPC.
  250. ipc->return_info.nt_status = nt_status;
  251. return true;
  252. }
  253. } // namespace sandbox