123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /*++
- Copyright (c) 2014 Minoca Corp. All Rights Reserved
- Module Name:
- perm.c
- Abstract:
- This module handles permission and access rights management in the I/O
- subsystem.
- Author:
- Evan Green 10-Dec-2014
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/kernel.h>
- #include "iop.h"
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Set this to TRUE to break whenever access denied is returned.
- //
- BOOL IoBreakOnAccessDenied = FALSE;
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- IopCheckPermissions (
- BOOL FromKernelMode,
- PPATH_POINT PathPoint,
- ULONG Access
- )
- /*++
- Routine Description:
- This routine performs a permission check for the current user at the given
- path point.
- Arguments:
- FromKernelMode - Supplies a boolean indicating whether the request actually
- originates from kernel mode or not.
- PathPoint - Supplies a pointer to the path point to check.
- Access - Supplies the desired access the user needs.
- Return Value:
- STATUS_SUCCESS if the user has permission to access the given object in
- the requested way.
- STATUS_ACCESS_DENIED if the permission was not granted.
- --*/
- {
- PFILE_OBJECT FileObject;
- ULONG Rights;
- KSTATUS Status;
- PKTHREAD Thread;
- Thread = KeGetCurrentThread();
- FileObject = PathPoint->PathEntry->FileObject;
- Rights = 0;
- //
- // If the caller wants execute permissions and none of the execute bits are
- // set, then even fancy override permissions can't make it succeed. This
- // doesn't apply to directories.
- //
- if ((FileObject->Properties.Type != IoObjectRegularDirectory) &&
- (FileObject->Properties.Type != IoObjectObjectDirectory)) {
- if (((Access & IO_ACCESS_EXECUTE) != 0) &&
- ((FileObject->Properties.Permissions &
- FILE_PERMISSION_ALL_EXECUTE) == 0)) {
- if (IoBreakOnAccessDenied != FALSE) {
- RtlDebugBreak();
- }
- Status = STATUS_ACCESS_DENIED;
- goto CheckPermissionsEnd;
- }
- }
- //
- // If this is kernel mode, then none of the other checks apply.
- //
- if (FromKernelMode != FALSE) {
- Status = STATUS_SUCCESS;
- goto CheckPermissionsEnd;
- }
- //
- // Determine whether to use the access bits of the user, group, or other.
- //
- Rights = FileObject->Properties.Permissions >> FILE_PERMISSION_OTHER_SHIFT;
- if (FileObject->Properties.UserId == Thread->Identity.EffectiveUserId) {
- Rights = FileObject->Properties.Permissions >>
- FILE_PERMISSION_USER_SHIFT;
- } else if (PsIsUserInGroup(FileObject->Properties.GroupId) != FALSE) {
- Rights = FileObject->Properties.Permissions >>
- FILE_PERMISSION_GROUP_SHIFT;
- }
- //
- // Check the rights. Exit out if they succeed on their own.
- //
- if ((Rights & Access & FILE_PERMISSION_ACCESS_MASK) == Access) {
- Status = STATUS_SUCCESS;
- goto CheckPermissionsEnd;
- }
- //
- // Succeed and exit if the user has file system override permissions.
- //
- if (KSUCCESS(PsCheckPermission(PERMISSION_FILE_ACCESS))) {
- Status = STATUS_SUCCESS;
- goto CheckPermissionsEnd;
- }
- //
- // If the user has the read/search permission, then succeed for:
- // 1) Read permissions on anything.
- // 2) Read/execute permissions on directories.
- //
- if (KSUCCESS(PsCheckPermission(PERMISSION_READ_SEARCH))) {
- if (Access == IO_ACCESS_READ) {
- Status = STATUS_SUCCESS;
- goto CheckPermissionsEnd;
- }
- if (((Access & IO_ACCESS_WRITE) == 0) &&
- ((FileObject->Properties.Type == IoObjectRegularDirectory) ||
- (FileObject->Properties.Type == IoObjectObjectDirectory))) {
- Status = STATUS_SUCCESS;
- goto CheckPermissionsEnd;
- }
- }
- //
- // Sorry, no access this time.
- //
- if (IoBreakOnAccessDenied != FALSE) {
- RtlDebugBreak();
- }
- Status = STATUS_ACCESS_DENIED;
- CheckPermissionsEnd:
- return Status;
- }
- KSTATUS
- IopCheckDeletePermission (
- BOOL FromKernelMode,
- PPATH_POINT DirectoryPathPoint,
- PPATH_POINT FilePathPoint
- )
- /*++
- Routine Description:
- This routine performs a permission check for the current user at the given
- path point, in preparation for removing a directory entry during a rename
- or unlink operation.
- Arguments:
- FromKernelMode - Supplies a boolean indicating whether or not this
- request actually originated from kernel mode.
- DirectoryPathPoint - Supplies a pointer to the directory path point the
- file resides in.
- FilePathPoint - Supplies a pointer to the file path point being deleted or
- renamed.
- Return Value:
- STATUS_SUCCESS if the user has permission to access the given object in
- the requested way.
- STATUS_ACCESS_DENIED if the permission was not granted.
- --*/
- {
- PFILE_OBJECT DirectoryFileObject;
- PFILE_OBJECT FileObject;
- KSTATUS Status;
- PKTHREAD Thread;
- Thread = KeGetCurrentThread();
- DirectoryFileObject = DirectoryPathPoint->PathEntry->FileObject;
- //
- // First ensure the caller has write access to the directory.
- //
- Status = IopCheckPermissions(FromKernelMode,
- DirectoryPathPoint,
- IO_ACCESS_WRITE);
- if (!KSUCCESS(Status)) {
- goto CheckDeletePermissionEnd;
- }
- //
- // If the restricted bit is set, then only the file owner can rename or
- // delete the file, even though the caller has write permission in the
- // directory. This is often used on temporary directories to prevent users
- // from deleting each others files.
- //
- if ((DirectoryFileObject->Properties.Permissions &
- FILE_PERMISSION_RESTRICTED) != 0) {
- FileObject = FilePathPoint->PathEntry->FileObject;
- if (Thread->Identity.EffectiveUserId != FileObject->Properties.UserId) {
- if (!KSUCCESS(PsCheckPermission(PERMISSION_FILE_ACCESS))) {
- Status = STATUS_ACCESS_DENIED;
- goto CheckDeletePermissionEnd;
- }
- }
- }
- Status = STATUS_SUCCESS;
- CheckDeletePermissionEnd:
- return Status;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
|