https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4b4638dc5599d5061a01a…
commit 4b4638dc5599d5061a01a21ed04a1ce9b68e732d
Author: George Bișoc <george.bisoc(a)reactos.org>
AuthorDate: Sat Sep 30 20:51:12 2023 +0200
Commit: George Bișoc <george.bisoc(a)reactos.org>
CommitDate: Wed Oct 4 18:04:29 2023 +0200
[NTOS:SE] HACK: Temporarily grant access to the client if empty generic mapping was
passed
Certain apps such as AIM installer passes an empty generic mapping (this can
be understood with their generic masks set to 0) and our code tries to map
the access right from an ACE with the mapping provided by AccessCheck.
This can lead to a bug where we would not be able to decode the generic right
from an ACE as we need a proper generic mapping in order to do so. A mask
right that is not decoded it cannot be used to mask out the remaining rights,
further resulting into a denied access right.
What Windows does instead is they are mapping the ACE's rights in another place,
presumably when setting security data to an object, and they are using the
generic mapping passed by the kernel.
What we can do for the time being is to temporarily grant access to the client,
but only if they are an administrator.
CORE-18576
---
ntoskrnl/se/accesschk.c | 28 ++++++++++++++++++++++++++++
1 file changed, 28 insertions(+)
diff --git a/ntoskrnl/se/accesschk.c b/ntoskrnl/se/accesschk.c
index eaf159f8ce1..858bfeef994 100644
--- a/ntoskrnl/se/accesschk.c
+++ b/ntoskrnl/se/accesschk.c
@@ -1058,6 +1058,34 @@ SepAccessCheckWorker(
goto ReturnCommonStatus;
}
+ /*
+ * HACK: Temporary hack that checks if the caller passed an empty
+ * generic mapping. In such cases we cannot mask out the remaining
+ * access rights without a proper mapping so the only option we
+ * can do is to check if the client is an administrator,
+ * since they are powerful users.
+ *
+ * See CORE-18576 for information.
+ */
+ if (GenericMapping->GenericRead == 0 &&
+ GenericMapping->GenericWrite == 0 &&
+ GenericMapping->GenericExecute == 0 &&
+ GenericMapping->GenericAll == 0)
+ {
+ if (SeTokenIsAdmin(Token))
+ {
+ /* Grant him access */
+ PreviouslyGrantedAccess |= RemainingAccess;
+ Status = STATUS_SUCCESS;
+ goto ReturnCommonStatus;
+ }
+
+ /* It's not an admin so bail out */
+ PreviouslyGrantedAccess = 0;
+ Status = STATUS_ACCESS_DENIED;
+ goto ReturnCommonStatus;
+ }
+
/* Get the DACL */
Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
&Present,