NTSTATUS NTAPI NpCommonSetSecurityInfo(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NODE_TYPE_CODE NodeTypeCode; PIO_STACK_LOCATION IoStack; NTSTATUS Status; PNP_FCB Fcb; PNP_CCB Ccb; ULONG NamedPipeEnd; PSECURITY_DESCRIPTOR OldSecurityDescriptor; PSECURITY_DESCRIPTOR TempSecurityDescriptor; PSECURITY_DESCRIPTOR NewSecurityDescriptor; PAGED_CODE(); IoStack = IoGetCurrentIrpStackLocation(Irp); NodeTypeCode = NpDecodeFileObject(IoStack->FileObject, (PVOID*)&Fcb, &Ccb, &NamedPipeEnd); if (!NodeTypeCode) return STATUS_PIPE_DISCONNECTED; if (NodeTypeCode != NPFS_NTC_CCB) return STATUS_INVALID_PARAMETER; OldSecurityDescriptor = TempSecurityDescriptor = Fcb->SecurityDescriptor; Status = SeSetSecurityDescriptorInfo(NULL, &IoStack->Parameters.SetSecurity.SecurityInformation, IoStack->Parameters.SetSecurity.SecurityDescriptor, &TempSecurityDescriptor, TRUE, IoGetFileObjectGenericMapping()); if (!NT_SUCCESS(Status)) return Status; Status = ObLogSecurityDescriptor(TempSecurityDescriptor, &NewSecurityDescriptor, 1); ASSERT(TempSecurityDescriptor != OldSecurityDescriptor); ExFreePoolWithTag(TempSecurityDescriptor, 0); if (!NT_SUCCESS(Status)) return Status; Fcb->SecurityDescriptor = NewSecurityDescriptor; ObDereferenceSecurityDescriptor(OldSecurityDescriptor, 1); return Status; }
NTSTATUS NTAPI ObAssignObjectSecurityDescriptor(IN PVOID Object, IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL, IN POOL_TYPE PoolType) { POBJECT_HEADER ObjectHeader; NTSTATUS Status; PSECURITY_DESCRIPTOR NewSd; PEX_FAST_REF FastRef; PAGED_CODE(); /* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); FastRef = (PEX_FAST_REF)&ObjectHeader->SecurityDescriptor; if (!SecurityDescriptor) { /* Nothing to assign */ ExInitializeFastReference(FastRef, NULL); return STATUS_SUCCESS; } /* Add it to our internal cache */ Status = ObLogSecurityDescriptor(SecurityDescriptor, &NewSd, MAX_FAST_REFS + 1); if (NT_SUCCESS(Status)) { /* Free the old copy */ ExFreePoolWithTag(SecurityDescriptor, TAG_SD); /* Set the new pointer */ ASSERT(NewSd); ExInitializeFastReference(FastRef, NewSd); } /* Return status */ return Status; }
NTSTATUS NTAPI ObSetSecurityDescriptorInfo(IN PVOID Object, IN PSECURITY_INFORMATION SecurityInformation, IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor, IN OUT PSECURITY_DESCRIPTOR *OutputSecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping) { NTSTATUS Status; POBJECT_HEADER ObjectHeader; PSECURITY_DESCRIPTOR OldDescriptor, NewDescriptor, CachedDescriptor; PEX_FAST_REF FastRef; EX_FAST_REF OldValue; ULONG_PTR Count; PAGED_CODE(); /* Get the object header */ ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object); while (TRUE) { /* Reference the old descriptor */ OldDescriptor = ObpReferenceSecurityDescriptor(ObjectHeader); NewDescriptor = OldDescriptor; /* Set the SD information */ Status = SeSetSecurityDescriptorInfo(Object, SecurityInformation, SecurityDescriptor, &NewDescriptor, PoolType, GenericMapping); if (NT_SUCCESS(Status)) { /* Now add this to the cache */ Status = ObLogSecurityDescriptor(NewDescriptor, &CachedDescriptor, MAX_FAST_REFS + 1); /* Let go of our uncached copy */ ExFreePool(NewDescriptor); /* Check for success */ if (NT_SUCCESS(Status)) { /* Do the swap */ FastRef = (PEX_FAST_REF)OutputSecurityDescriptor; OldValue = ExCompareSwapFastReference(FastRef, CachedDescriptor, OldDescriptor); /* Get the security descriptor */ SecurityDescriptor = ExGetObjectFastReference(OldValue); Count = ExGetCountFastReference(OldValue); /* Make sure the swap worked */ if (SecurityDescriptor == OldDescriptor) { /* Flush waiters */ ObpAcquireObjectLock(ObjectHeader); ObpReleaseObjectLock(ObjectHeader); /* And dereference the old one */ ObDereferenceSecurityDescriptor(OldDescriptor, Count + 2); break; } else { /* Someone changed it behind our back -- try again */ ObDereferenceSecurityDescriptor(OldDescriptor, 1); ObDereferenceSecurityDescriptor(CachedDescriptor, MAX_FAST_REFS + 1); } } else { /* We failed, dereference the old one */ ObDereferenceSecurityDescriptor(OldDescriptor, 1); break; } } else { /* We failed, dereference the old one */ if (OldDescriptor) ObDereferenceSecurityDescriptor(OldDescriptor, 1); break; } } /* Return status */ return Status; }