filesystem_dispatcher.cc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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 <stdint.h>
  6. #include "sandbox/win/src/crosscall_client.h"
  7. #include "sandbox/win/src/filesystem_interception.h"
  8. #include "sandbox/win/src/filesystem_policy.h"
  9. #include "sandbox/win/src/interception.h"
  10. #include "sandbox/win/src/interceptors.h"
  11. #include "sandbox/win/src/ipc_tags.h"
  12. #include "sandbox/win/src/policy_broker.h"
  13. #include "sandbox/win/src/policy_params.h"
  14. #include "sandbox/win/src/sandbox.h"
  15. #include "sandbox/win/src/sandbox_nt_util.h"
  16. namespace sandbox {
  17. FilesystemDispatcher::FilesystemDispatcher(PolicyBase* policy_base)
  18. : policy_base_(policy_base) {
  19. static const IPCCall create_params = {
  20. {IpcTag::NTCREATEFILE,
  21. {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE,
  22. UINT32_TYPE, UINT32_TYPE}},
  23. reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtCreateFile)};
  24. static const IPCCall open_file = {
  25. {IpcTag::NTOPENFILE,
  26. {WCHAR_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE, UINT32_TYPE}},
  27. reinterpret_cast<CallbackGeneric>(&FilesystemDispatcher::NtOpenFile)};
  28. static const IPCCall attribs = {
  29. {IpcTag::NTQUERYATTRIBUTESFILE, {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}},
  30. reinterpret_cast<CallbackGeneric>(
  31. &FilesystemDispatcher::NtQueryAttributesFile)};
  32. static const IPCCall full_attribs = {
  33. {IpcTag::NTQUERYFULLATTRIBUTESFILE,
  34. {WCHAR_TYPE, UINT32_TYPE, INOUTPTR_TYPE}},
  35. reinterpret_cast<CallbackGeneric>(
  36. &FilesystemDispatcher::NtQueryFullAttributesFile)};
  37. static const IPCCall set_info = {
  38. {IpcTag::NTSETINFO_RENAME,
  39. {VOIDPTR_TYPE, INOUTPTR_TYPE, INOUTPTR_TYPE, UINT32_TYPE, UINT32_TYPE}},
  40. reinterpret_cast<CallbackGeneric>(
  41. &FilesystemDispatcher::NtSetInformationFile)};
  42. ipc_calls_.push_back(create_params);
  43. ipc_calls_.push_back(open_file);
  44. ipc_calls_.push_back(attribs);
  45. ipc_calls_.push_back(full_attribs);
  46. ipc_calls_.push_back(set_info);
  47. }
  48. bool FilesystemDispatcher::SetupService(InterceptionManager* manager,
  49. IpcTag service) {
  50. switch (service) {
  51. case IpcTag::NTCREATEFILE:
  52. return INTERCEPT_NT(manager, NtCreateFile, CREATE_FILE_ID, 48);
  53. case IpcTag::NTOPENFILE:
  54. return INTERCEPT_NT(manager, NtOpenFile, OPEN_FILE_ID, 28);
  55. case IpcTag::NTQUERYATTRIBUTESFILE:
  56. return INTERCEPT_NT(manager, NtQueryAttributesFile, QUERY_ATTRIB_FILE_ID,
  57. 12);
  58. case IpcTag::NTQUERYFULLATTRIBUTESFILE:
  59. return INTERCEPT_NT(manager, NtQueryFullAttributesFile,
  60. QUERY_FULL_ATTRIB_FILE_ID, 12);
  61. case IpcTag::NTSETINFO_RENAME:
  62. return INTERCEPT_NT(manager, NtSetInformationFile, SET_INFO_FILE_ID, 24);
  63. default:
  64. return false;
  65. }
  66. }
  67. bool FilesystemDispatcher::NtCreateFile(IPCInfo* ipc,
  68. std::wstring* name,
  69. uint32_t attributes,
  70. uint32_t desired_access,
  71. uint32_t file_attributes,
  72. uint32_t share_access,
  73. uint32_t create_disposition,
  74. uint32_t create_options) {
  75. if (!PreProcessName(name)) {
  76. // The path requested might contain a reparse point.
  77. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  78. return true;
  79. }
  80. EvalResult result = EvalPolicy(IpcTag::NTCREATEFILE, *name, desired_access,
  81. create_disposition == FILE_OPEN);
  82. HANDLE handle;
  83. ULONG_PTR io_information = 0;
  84. NTSTATUS nt_status;
  85. if (!FileSystemPolicy::CreateFileAction(
  86. result, *ipc->client_info, *name, attributes, desired_access,
  87. file_attributes, share_access, create_disposition, create_options,
  88. &handle, &nt_status, &io_information)) {
  89. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  90. return true;
  91. }
  92. // Return operation status on the IPC.
  93. ipc->return_info.extended[0].ulong_ptr = io_information;
  94. ipc->return_info.nt_status = nt_status;
  95. ipc->return_info.handle = handle;
  96. return true;
  97. }
  98. bool FilesystemDispatcher::NtOpenFile(IPCInfo* ipc,
  99. std::wstring* name,
  100. uint32_t attributes,
  101. uint32_t desired_access,
  102. uint32_t share_access,
  103. uint32_t open_options) {
  104. if (!PreProcessName(name)) {
  105. // The path requested might contain a reparse point.
  106. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  107. return true;
  108. }
  109. EvalResult result =
  110. EvalPolicy(IpcTag::NTOPENFILE, *name, desired_access, true);
  111. HANDLE handle;
  112. ULONG_PTR io_information = 0;
  113. NTSTATUS nt_status;
  114. if (!FileSystemPolicy::OpenFileAction(
  115. result, *ipc->client_info, *name, attributes, desired_access,
  116. share_access, open_options, &handle, &nt_status, &io_information)) {
  117. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  118. return true;
  119. }
  120. // Return operation status on the IPC.
  121. ipc->return_info.extended[0].ulong_ptr = io_information;
  122. ipc->return_info.nt_status = nt_status;
  123. ipc->return_info.handle = handle;
  124. return true;
  125. }
  126. bool FilesystemDispatcher::NtQueryAttributesFile(IPCInfo* ipc,
  127. std::wstring* name,
  128. uint32_t attributes,
  129. CountedBuffer* info) {
  130. if (sizeof(FILE_BASIC_INFORMATION) != info->Size())
  131. return false;
  132. if (!PreProcessName(name)) {
  133. // The path requested might contain a reparse point.
  134. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  135. return true;
  136. }
  137. EvalResult result = EvalPolicy(IpcTag::NTQUERYATTRIBUTESFILE, *name);
  138. FILE_BASIC_INFORMATION* information =
  139. reinterpret_cast<FILE_BASIC_INFORMATION*>(info->Buffer());
  140. NTSTATUS nt_status;
  141. if (!FileSystemPolicy::QueryAttributesFileAction(result, *ipc->client_info,
  142. *name, attributes,
  143. information, &nt_status)) {
  144. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  145. return true;
  146. }
  147. // Return operation status on the IPC.
  148. ipc->return_info.nt_status = nt_status;
  149. return true;
  150. }
  151. bool FilesystemDispatcher::NtQueryFullAttributesFile(IPCInfo* ipc,
  152. std::wstring* name,
  153. uint32_t attributes,
  154. CountedBuffer* info) {
  155. if (sizeof(FILE_NETWORK_OPEN_INFORMATION) != info->Size())
  156. return false;
  157. if (!PreProcessName(name)) {
  158. // The path requested might contain a reparse point.
  159. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  160. return true;
  161. }
  162. EvalResult result = EvalPolicy(IpcTag::NTQUERYFULLATTRIBUTESFILE, *name);
  163. FILE_NETWORK_OPEN_INFORMATION* information =
  164. reinterpret_cast<FILE_NETWORK_OPEN_INFORMATION*>(info->Buffer());
  165. NTSTATUS nt_status;
  166. if (!FileSystemPolicy::QueryFullAttributesFileAction(
  167. result, *ipc->client_info, *name, attributes, information,
  168. &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::NtSetInformationFile(IPCInfo* ipc,
  177. HANDLE handle,
  178. CountedBuffer* status,
  179. CountedBuffer* info,
  180. uint32_t length,
  181. uint32_t info_class) {
  182. if (sizeof(IO_STATUS_BLOCK) != status->Size())
  183. return false;
  184. if (length != info->Size())
  185. return false;
  186. FILE_RENAME_INFORMATION* rename_info =
  187. reinterpret_cast<FILE_RENAME_INFORMATION*>(info->Buffer());
  188. if (!IsSupportedRenameCall(rename_info, length, info_class))
  189. return false;
  190. std::wstring name;
  191. name.assign(rename_info->FileName,
  192. rename_info->FileNameLength / sizeof(rename_info->FileName[0]));
  193. if (!PreProcessName(&name)) {
  194. // The path requested might contain a reparse point.
  195. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  196. return true;
  197. }
  198. EvalResult result = EvalPolicy(IpcTag::NTSETINFO_RENAME, name);
  199. IO_STATUS_BLOCK* io_status =
  200. reinterpret_cast<IO_STATUS_BLOCK*>(status->Buffer());
  201. NTSTATUS nt_status;
  202. if (!FileSystemPolicy::SetInformationFileAction(
  203. result, *ipc->client_info, handle, rename_info, length, info_class,
  204. io_status, &nt_status)) {
  205. ipc->return_info.nt_status = STATUS_ACCESS_DENIED;
  206. return true;
  207. }
  208. // Return operation status on the IPC.
  209. ipc->return_info.nt_status = nt_status;
  210. return true;
  211. }
  212. EvalResult FilesystemDispatcher::EvalPolicy(IpcTag ipc_tag,
  213. const std::wstring& name,
  214. uint32_t desired_access,
  215. bool open_only) {
  216. CountedParameterSet<OpenFile> params;
  217. const wchar_t* name_ptr = name.c_str();
  218. params[OpenFile::NAME] = ParamPickerMake(name_ptr);
  219. params[OpenFile::ACCESS] = ParamPickerMake(desired_access);
  220. uint32_t open_only_int = open_only;
  221. params[OpenFile::OPENONLY] = ParamPickerMake(open_only_int);
  222. return policy_base_->EvalPolicy(ipc_tag, params.GetBase());
  223. }
  224. } // namespace sandbox