perm.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. /*++
  2. Copyright (c) 2014 Minoca Corp. All Rights Reserved
  3. Module Name:
  4. perm.c
  5. Abstract:
  6. This module handles permission and access rights management in the I/O
  7. subsystem.
  8. Author:
  9. Evan Green 10-Dec-2014
  10. Environment:
  11. Kernel
  12. --*/
  13. //
  14. // ------------------------------------------------------------------- Includes
  15. //
  16. #include <minoca/kernel/kernel.h>
  17. #include "iop.h"
  18. //
  19. // ---------------------------------------------------------------- Definitions
  20. //
  21. //
  22. // ------------------------------------------------------ Data Type Definitions
  23. //
  24. //
  25. // ----------------------------------------------- Internal Function Prototypes
  26. //
  27. //
  28. // -------------------------------------------------------------------- Globals
  29. //
  30. //
  31. // Set this to TRUE to break whenever access denied is returned.
  32. //
  33. BOOL IoBreakOnAccessDenied = FALSE;
  34. //
  35. // ------------------------------------------------------------------ Functions
  36. //
  37. KSTATUS
  38. IopCheckPermissions (
  39. BOOL FromKernelMode,
  40. PPATH_POINT PathPoint,
  41. ULONG Access
  42. )
  43. /*++
  44. Routine Description:
  45. This routine performs a permission check for the current user at the given
  46. path point.
  47. Arguments:
  48. FromKernelMode - Supplies a boolean indicating whether the request actually
  49. originates from kernel mode or not.
  50. PathPoint - Supplies a pointer to the path point to check.
  51. Access - Supplies the desired access the user needs.
  52. Return Value:
  53. STATUS_SUCCESS if the user has permission to access the given object in
  54. the requested way.
  55. STATUS_ACCESS_DENIED if the permission was not granted.
  56. --*/
  57. {
  58. PFILE_OBJECT FileObject;
  59. ULONG Rights;
  60. KSTATUS Status;
  61. PKTHREAD Thread;
  62. Thread = KeGetCurrentThread();
  63. FileObject = PathPoint->PathEntry->FileObject;
  64. Rights = 0;
  65. //
  66. // If the caller wants execute permissions and none of the execute bits are
  67. // set, then even fancy override permissions can't make it succeed. This
  68. // doesn't apply to directories.
  69. //
  70. if ((FileObject->Properties.Type != IoObjectRegularDirectory) &&
  71. (FileObject->Properties.Type != IoObjectObjectDirectory)) {
  72. if (((Access & IO_ACCESS_EXECUTE) != 0) &&
  73. ((FileObject->Properties.Permissions &
  74. FILE_PERMISSION_ALL_EXECUTE) == 0)) {
  75. if (IoBreakOnAccessDenied != FALSE) {
  76. RtlDebugBreak();
  77. }
  78. Status = STATUS_ACCESS_DENIED;
  79. goto CheckPermissionsEnd;
  80. }
  81. }
  82. //
  83. // If this is kernel mode, then none of the other checks apply.
  84. //
  85. if (FromKernelMode != FALSE) {
  86. Status = STATUS_SUCCESS;
  87. goto CheckPermissionsEnd;
  88. }
  89. //
  90. // Determine whether to use the access bits of the user, group, or other.
  91. //
  92. Rights = FileObject->Properties.Permissions >> FILE_PERMISSION_OTHER_SHIFT;
  93. if (FileObject->Properties.UserId == Thread->Identity.EffectiveUserId) {
  94. Rights = FileObject->Properties.Permissions >>
  95. FILE_PERMISSION_USER_SHIFT;
  96. } else if (PsIsUserInGroup(FileObject->Properties.GroupId) != FALSE) {
  97. Rights = FileObject->Properties.Permissions >>
  98. FILE_PERMISSION_GROUP_SHIFT;
  99. }
  100. //
  101. // Check the rights. Exit out if they succeed on their own.
  102. //
  103. if ((Rights & Access & FILE_PERMISSION_ACCESS_MASK) == Access) {
  104. Status = STATUS_SUCCESS;
  105. goto CheckPermissionsEnd;
  106. }
  107. //
  108. // Succeed and exit if the user has file system override permissions.
  109. //
  110. if (KSUCCESS(PsCheckPermission(PERMISSION_FILE_ACCESS))) {
  111. Status = STATUS_SUCCESS;
  112. goto CheckPermissionsEnd;
  113. }
  114. //
  115. // If the user has the read/search permission, then succeed for:
  116. // 1) Read permissions on anything.
  117. // 2) Read/execute permissions on directories.
  118. //
  119. if (KSUCCESS(PsCheckPermission(PERMISSION_READ_SEARCH))) {
  120. if (Access == IO_ACCESS_READ) {
  121. Status = STATUS_SUCCESS;
  122. goto CheckPermissionsEnd;
  123. }
  124. if (((Access & IO_ACCESS_WRITE) == 0) &&
  125. ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
  126. (FileObject->Properties.Type == IoObjectObjectDirectory))) {
  127. Status = STATUS_SUCCESS;
  128. goto CheckPermissionsEnd;
  129. }
  130. }
  131. //
  132. // Sorry, no access this time.
  133. //
  134. if (IoBreakOnAccessDenied != FALSE) {
  135. RtlDebugBreak();
  136. }
  137. Status = STATUS_ACCESS_DENIED;
  138. CheckPermissionsEnd:
  139. return Status;
  140. }
  141. KSTATUS
  142. IopCheckDeletePermission (
  143. BOOL FromKernelMode,
  144. PPATH_POINT DirectoryPathPoint,
  145. PPATH_POINT FilePathPoint
  146. )
  147. /*++
  148. Routine Description:
  149. This routine performs a permission check for the current user at the given
  150. path point, in preparation for removing a directory entry during a rename
  151. or unlink operation.
  152. Arguments:
  153. FromKernelMode - Supplies a boolean indicating whether or not this
  154. request actually originated from kernel mode.
  155. DirectoryPathPoint - Supplies a pointer to the directory path point the
  156. file resides in.
  157. FilePathPoint - Supplies a pointer to the file path point being deleted or
  158. renamed.
  159. Return Value:
  160. STATUS_SUCCESS if the user has permission to access the given object in
  161. the requested way.
  162. STATUS_ACCESS_DENIED if the permission was not granted.
  163. --*/
  164. {
  165. PFILE_OBJECT DirectoryFileObject;
  166. PFILE_OBJECT FileObject;
  167. KSTATUS Status;
  168. PKTHREAD Thread;
  169. Thread = KeGetCurrentThread();
  170. DirectoryFileObject = DirectoryPathPoint->PathEntry->FileObject;
  171. //
  172. // First ensure the caller has write access to the directory.
  173. //
  174. Status = IopCheckPermissions(FromKernelMode,
  175. DirectoryPathPoint,
  176. IO_ACCESS_WRITE);
  177. if (!KSUCCESS(Status)) {
  178. goto CheckDeletePermissionEnd;
  179. }
  180. //
  181. // If the restricted bit is set, then only the file owner can rename or
  182. // delete the file, even though the caller has write permission in the
  183. // directory. This is often used on temporary directories to prevent users
  184. // from deleting each others files.
  185. //
  186. if ((DirectoryFileObject->Properties.Permissions &
  187. FILE_PERMISSION_RESTRICTED) != 0) {
  188. FileObject = FilePathPoint->PathEntry->FileObject;
  189. if (Thread->Identity.EffectiveUserId != FileObject->Properties.UserId) {
  190. if (!KSUCCESS(PsCheckPermission(PERMISSION_FILE_ACCESS))) {
  191. Status = STATUS_ACCESS_DENIED;
  192. goto CheckDeletePermissionEnd;
  193. }
  194. }
  195. }
  196. Status = STATUS_SUCCESS;
  197. CheckDeletePermissionEnd:
  198. return Status;
  199. }
  200. //
  201. // --------------------------------------------------------- Internal Functions
  202. //