https://git.reactos.org/?p=reactos.git;a=commitdiff;h=389a2da7ff94cfcefff322...
commit 389a2da7ff94cfcefff3220797f61311519d6fa0 Author: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org AuthorDate: Thu May 19 23:43:18 2022 +0200 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Mon May 23 19:30:34 2022 +0200
[NTOS:SE] SepCaptureAcl(): Add missing validation of the captured ACL (#4523)
- The ACL is however not validated when the function is called within kernel mode and no capture is actually being done.
- Simplify aspects of the function (returning early when possible). --- ntoskrnl/se/acl.c | 85 ++++++++++++++++++++++++++++------------------------- ntoskrnl/se/token.c | 2 +- 2 files changed, 46 insertions(+), 41 deletions(-)
diff --git a/ntoskrnl/se/acl.c b/ntoskrnl/se/acl.c index e160b34c429..d7c53d4ac17 100644 --- a/ntoskrnl/se/acl.c +++ b/ntoskrnl/se/acl.c @@ -329,15 +329,15 @@ SepCreateImpersonationTokenDacl( * * @param[in] AccessMode * Processor level access mode. The processor mode determines how - * are the input arguments probed. + * the input arguments are probed. * * @param[in] PoolType * Pool type for new captured ACL for creation. The pool type determines - * how the ACL data should reside in the pool memory. + * in which memory pool the ACL data should reside. * * @param[in] CaptureIfKernel - * If set to TRUE and the processor access mode being KernelMode, we're - * capturing an ACL directly in the kernel. Otherwise we're capturing + * If set to TRUE and the processor access mode being KernelMode, we are + * capturing an ACL directly in the kernel. Otherwise we are capturing * within a kernel mode driver. * * @param[out] CapturedAcl @@ -357,11 +357,19 @@ SepCaptureAcl( _Out_ PACL *CapturedAcl) { PACL NewAcl; - ULONG AclSize = 0; - NTSTATUS Status = STATUS_SUCCESS; + ULONG AclSize;
PAGED_CODE();
+ /* If in kernel mode and we do not capture, just + * return the given ACL and don't validate it. */ + if ((AccessMode == KernelMode) && !CaptureIfKernel) + { + *CapturedAcl = InputAcl; + return STATUS_SUCCESS; + } + + /* Otherwise, capture and validate the ACL, depending on the access mode */ if (AccessMode != KernelMode) { _SEH2_TRY @@ -381,59 +389,56 @@ SepCaptureAcl( } _SEH2_END;
+ /* Validate the minimal size an ACL can have */ + if (AclSize < sizeof(ACL)) + return STATUS_INVALID_ACL; + NewAcl = ExAllocatePoolWithTag(PoolType, AclSize, TAG_ACL); - if (NewAcl != NULL) - { - _SEH2_TRY - { - RtlCopyMemory(NewAcl, - InputAcl, - AclSize); + if (!NewAcl) + return STATUS_INSUFFICIENT_RESOURCES;
- *CapturedAcl = NewAcl; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Free the ACL and return the exception code */ - ExFreePoolWithTag(NewAcl, TAG_ACL); - _SEH2_YIELD(return _SEH2_GetExceptionCode()); - } - _SEH2_END; + _SEH2_TRY + { + RtlCopyMemory(NewAcl, InputAcl, AclSize); } - else + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) { - Status = STATUS_INSUFFICIENT_RESOURCES; + /* Free the ACL and return the exception code */ + ExFreePoolWithTag(NewAcl, TAG_ACL); + _SEH2_YIELD(return _SEH2_GetExceptionCode()); } - } - else if (!CaptureIfKernel) - { - *CapturedAcl = InputAcl; + _SEH2_END; } else { AclSize = InputAcl->AclSize;
+ /* Validate the minimal size an ACL can have */ + if (AclSize < sizeof(ACL)) + return STATUS_INVALID_ACL; + NewAcl = ExAllocatePoolWithTag(PoolType, AclSize, TAG_ACL); + if (!NewAcl) + return STATUS_INSUFFICIENT_RESOURCES;
- if (NewAcl != NULL) - { - RtlCopyMemory(NewAcl, - InputAcl, - AclSize); + RtlCopyMemory(NewAcl, InputAcl, AclSize); + }
- *CapturedAcl = NewAcl; - } - else - { - Status = STATUS_INSUFFICIENT_RESOURCES; - } + /* Validate the captured ACL */ + if (!RtlValidAcl(NewAcl)) + { + /* Free the ACL and fail */ + ExFreePoolWithTag(NewAcl, TAG_ACL); + return STATUS_INVALID_ACL; }
- return Status; + /* It's valid, return it */ + *CapturedAcl = NewAcl; + return STATUS_SUCCESS; }
/** diff --git a/ntoskrnl/se/token.c b/ntoskrnl/se/token.c index 1415e36009d..f215f4c1fe2 100644 --- a/ntoskrnl/se/token.c +++ b/ntoskrnl/se/token.c @@ -4518,7 +4518,7 @@ NtSetInformationToken( { PACL CapturedAcl;
- /* Capture and copy the dacl */ + /* Capture, validate, and copy the DACL */ Status = SepCaptureAcl(InputAcl, PreviousMode, PagedPool,