protect access to buffers with SEH in NtSetSecurityObject and NtQuerySecurityObject and ask for the proper access rights Modified: trunk/reactos/ntoskrnl/include/internal/se.h Modified: trunk/reactos/ntoskrnl/ob/security.c Modified: trunk/reactos/ntoskrnl/se/semgr.c _____
Modified: trunk/reactos/ntoskrnl/include/internal/se.h --- trunk/reactos/ntoskrnl/include/internal/se.h 2005-12-30 01:39:34 UTC (rev 20454) +++ trunk/reactos/ntoskrnl/include/internal/se.h 2005-12-30 01:41:02 UTC (rev 20455) @@ -274,6 +274,14 @@
KeLeaveCriticalRegion(); \ while(0)
+VOID STDCALL +SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, + OUT PACCESS_MASK DesiredAccess); + +VOID STDCALL +SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, + OUT PACCESS_MASK DesiredAccess); + #endif /* __NTOSKRNL_INCLUDE_INTERNAL_SE_H */
/* EOF */ _____
Modified: trunk/reactos/ntoskrnl/ob/security.c --- trunk/reactos/ntoskrnl/ob/security.c 2005-12-30 01:39:34 UTC (rev 20454) +++ trunk/reactos/ntoskrnl/ob/security.c 2005-12-30 01:41:02 UTC (rev 20455) @@ -159,47 +159,74 @@
IN ULONG Length, OUT PULONG ResultLength) { - POBJECT_HEADER Header; - PVOID Object; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + PVOID Object; + POBJECT_HEADER Header; + ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; + NTSTATUS Status = STATUS_SUCCESS;
- PAGED_CODE(); + PAGED_CODE();
- DPRINT("NtQuerySecurityObject() called\n"); + PreviousMode = ExGetPreviousMode();
- Status = ObReferenceObjectByHandle(Handle, - (SecurityInformation & SACL_SECURITY_INFORMATION) ? ACCESS_SYSTEM_SECURITY : 0, - NULL, - KeGetPreviousMode(), - &Object, - NULL); - if (!NT_SUCCESS(Status)) + if (PreviousMode != KernelMode) { - DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status); - return Status; + _SEH_TRY + { + ProbeForWrite(SecurityDescriptor, + Length, + sizeof(ULONG)); + ProbeForWriteUlong(ResultLength); + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if (!NT_SUCCESS(Status)) return Status; }
- Header = BODY_TO_HEADER(Object); - if (Header->Type == NULL) + /* get the required access rights for the operation */ + SeQuerySecurityAccessMask(SecurityInformation, + &DesiredAccess); + + Status = ObReferenceObjectByHandle(Handle, + DesiredAccess, + NULL, + PreviousMode, + &Object, + NULL); + + if (NT_SUCCESS(Status)) { - DPRINT1("Invalid object type\n"); - ObDereferenceObject(Object); - return STATUS_UNSUCCESSFUL; - } + Header = BODY_TO_HEADER(Object); + ASSERT(Header->Type != NULL);
- *ResultLength = Length; - Status = Header->Type->TypeInfo.SecurityProcedure(Object, - QuerySecurityDescriptor, - SecurityInformation, - SecurityDescriptor, - ResultLength, - NULL, - NonPagedPool, - NULL); + Status = Header->Type->TypeInfo.SecurityProcedure(Object, + QuerySecurityDescriptor, + SecurityInformation, + SecurityDescriptor, + &Length, + &Header->SecurityDescriptor, + Header->Type->TypeInfo.PoolType, + &Header->Type->TypeInfo.GenericMapping);
- ObDereferenceObject(Object); + ObDereferenceObject(Object);
- return Status; + /* return the required length */ + _SEH_TRY + { + *ResultLength = Length; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + } + + return Status; }
@@ -211,46 +238,81 @@ IN SECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor) { - POBJECT_HEADER Header; - PVOID Object; - NTSTATUS Status; + KPROCESSOR_MODE PreviousMode; + PVOID Object; + POBJECT_HEADER Header; + SECURITY_DESCRIPTOR_RELATIVE *CapturedSecurityDescriptor; + ACCESS_MASK DesiredAccess = (ACCESS_MASK)0; + NTSTATUS Status;
- PAGED_CODE(); + PAGED_CODE();
- DPRINT("NtSetSecurityObject() called\n"); + /* make sure the caller doesn't pass a NULL security descriptor! */ + if (SecurityDescriptor == NULL) + { + return STATUS_ACCESS_DENIED; + }
- Status = ObReferenceObjectByHandle(Handle, - (SecurityInformation & SACL_SECURITY_INFORMATION) ? ACCESS_SYSTEM_SECURITY : 0, - NULL, - KeGetPreviousMode(), - &Object, - NULL); - if (!NT_SUCCESS(Status)) + PreviousMode = ExGetPreviousMode(); + + /* capture and make a copy of the security descriptor */ + Status = SeCaptureSecurityDescriptor(SecurityDescriptor, + PreviousMode, + PagedPool, + TRUE, + (PSECURITY_DESCRIPTOR*)&CapturedSecurityDescriptor); + if (!NT_SUCCESS(Status)) { - DPRINT1("ObReferenceObjectByHandle() failed (Status %lx)\n", Status); - return Status; + DPRINT1("Capturing the security descriptor failed! Status: 0x%lx\n", Status); + return Status; }
- Header = BODY_TO_HEADER(Object); - if (Header->Type == NULL) + /* make sure the security descriptor passed by the caller + is valid for the operation we're about to perform */ + if (((SecurityInformation & OWNER_SECURITY_INFORMATION) && + (CapturedSecurityDescriptor->Owner == 0)) || + ((SecurityInformation & GROUP_SECURITY_INFORMATION) && + (CapturedSecurityDescriptor->Group == 0))) { - DPRINT1("Invalid object type\n"); - ObDereferenceObject(Object); - return STATUS_UNSUCCESSFUL; + Status = STATUS_INVALID_SECURITY_DESCR; } + else + { + /* get the required access rights for the operation */ + SeSetSecurityAccessMask(SecurityInformation, + &DesiredAccess);
- Status = Header->Type->TypeInfo.SecurityProcedure(Object, - SetSecurityDescriptor, - SecurityInformation, - SecurityDescriptor, - NULL, - NULL, - NonPagedPool, - NULL); + Status = ObReferenceObjectByHandle(Handle, + DesiredAccess, + NULL, + PreviousMode, + &Object, + NULL);
- ObDereferenceObject(Object); + if (NT_SUCCESS(Status)) + { + Header = BODY_TO_HEADER(Object); + ASSERT(Header->Type != NULL);
- return Status; + Status = Header->Type->TypeInfo.SecurityProcedure(Object, + SetSecurityDescriptor, + SecurityInformation, + (PSECURITY_DESCRIPTOR)SecurityDescriptor, + NULL, + &Header->SecurityDescriptor, + Header->Type->TypeInfo.PoolType, + &Header->Type->TypeInfo.GenericMapping); + + ObDereferenceObject(Object); + } + } + + /* release the descriptor */ + SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR)CapturedSecurityDescri ptor, + PreviousMode, + TRUE); + + return Status; }
_____
Modified: trunk/reactos/ntoskrnl/se/semgr.c --- trunk/reactos/ntoskrnl/se/semgr.c 2005-12-30 01:39:34 UTC (rev 20454) +++ trunk/reactos/ntoskrnl/se/semgr.c 2005-12-30 01:41:02 UTC (rev 20455) @@ -1037,7 +1037,7 @@
OUT PACCESS_MASK GrantedAccess, OUT PNTSTATUS AccessStatus) { - SECURITY_SUBJECT_CONTEXT SubjectSecurityContext; + SECURITY_SUBJECT_CONTEXT SubjectSecurityContext = {0}; KPROCESSOR_MODE PreviousMode; PTOKEN Token; NTSTATUS Status; @@ -1082,8 +1082,6 @@ return STATUS_ACCESS_VIOLATION; }
- RtlZeroMemory(&SubjectSecurityContext, - sizeof(SECURITY_SUBJECT_CONTEXT)); SubjectSecurityContext.ClientToken = Token; SubjectSecurityContext.ImpersonationLevel = Token->ImpersonationLevel;
@@ -1118,4 +1116,37 @@ return Status; }
+VOID STDCALL +SeQuerySecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, + OUT PACCESS_MASK DesiredAccess) +{ + if (SecurityInformation & (OWNER_SECURITY_INFORMATION | + GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION)) + { + *DesiredAccess |= READ_CONTROL; + } + if (SecurityInformation & SACL_SECURITY_INFORMATION) + { + *DesiredAccess |= ACCESS_SYSTEM_SECURITY; + } +} + +VOID STDCALL +SeSetSecurityAccessMask(IN SECURITY_INFORMATION SecurityInformation, + OUT PACCESS_MASK DesiredAccess) +{ + if (SecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION)) + { + *DesiredAccess |= WRITE_OWNER; + } + if (SecurityInformation & DACL_SECURITY_INFORMATION) + { + *DesiredAccess |= WRITE_DAC; + } + if (SecurityInformation & SACL_SECURITY_INFORMATION) + { + *DesiredAccess |= ACCESS_SYSTEM_SECURITY; + } +} + /* EOF */