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 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; }
NTSTATUS IopSetDeviceSecurityDescriptors( IN PDEVICE_OBJECT DeviceObject, IN PSECURITY_INFORMATION SecurityInformation, IN PSECURITY_DESCRIPTOR SecurityDescriptor, IN POOL_TYPE PoolType, IN PGENERIC_MAPPING GenericMapping, IN BOOLEAN DoAttachedDevices ) /*++ Routine Description: Call this routine to set device security descriptor Arguments: DeviceObject - pointer to base device object (first one to set) SecurityInformation )_ passed directly from IopGetSetSecurityObject SecurityDescriptor ) PoolType ) GenericMapping ) DoAttachedDevices - if true, iterate the AttachedDevice list ReturnValue: success, or error from first failure --*/ { PDEVICE_OBJECT NewDeviceObject = NULL; PSECURITY_DESCRIPTOR OldSecurityDescriptor; KIRQL irql; NTSTATUS status; NTSTATUS firsterr = STATUS_SUCCESS; BOOLEAN first = TRUE; ASSERT(DeviceObject); IopAcquireEnumerationLock(NULL); // ensure we have acquired P&P locks // // pre-reference this object to match the dereference later // ObReferenceObject( DeviceObject ); do { KeEnterCriticalRegion(); ExAcquireResourceExclusive( &IopSecurityResource, TRUE ); OldSecurityDescriptor = DeviceObject->SecurityDescriptor; if (OldSecurityDescriptor || first) { // // always call this on the first object, only do it for others that have a security descriptor // status = SeSetSecurityDescriptorInfo( NULL, SecurityInformation, SecurityDescriptor, &DeviceObject->SecurityDescriptor, PoolType, GenericMapping ); if (NT_SUCCESS(firsterr)) { firsterr = status; } if (NT_SUCCESS( status )) { ASSERT(OldSecurityDescriptor); ExFreePool( OldSecurityDescriptor ); } first = FALSE; } ExReleaseResource( &IopSecurityResource ); KeLeaveCriticalRegion(); // // get next device on attachment chain // ExAcquireSpinLock(&IopDatabaseLock,&irql); NewDeviceObject = DeviceObject->AttachedDevice; if ( NewDeviceObject != NULL ) { ObReferenceObject( NewDeviceObject ); } else { DoAttachedDevices = FALSE; } ExReleaseSpinLock(&IopDatabaseLock,irql); ObDereferenceObject( DeviceObject ); DeviceObject = NewDeviceObject; } while(DoAttachedDevices); IopReleaseEnumerationLock(NULL); return firsterr; // of the PDO / single object }
NTSTATUS AfdCreateRawSecurityDescriptor( VOID ) /*++ Routine Description: This routine creates a security descriptor which gives access only to Administrtors and LocalSystem. This descriptor is used to access check raw endpoint opens. Arguments: None. Return Value: STATUS_SUCCESS or an appropriate error code. --*/ { PACL rawAcl; NTSTATUS status; BOOLEAN memoryAllocated = FALSE; PSECURITY_DESCRIPTOR afdSecurityDescriptor; ULONG afdSecurityDescriptorLength; CHAR buffer[SECURITY_DESCRIPTOR_MIN_LENGTH]; PSECURITY_DESCRIPTOR localSecurityDescriptor = (PSECURITY_DESCRIPTOR) &buffer; SECURITY_INFORMATION securityInformation = DACL_SECURITY_INFORMATION; // // Get a pointer to the security descriptor from the AFD device object. // status = ObGetObjectSecurity( AfdDeviceObject, &afdSecurityDescriptor, &memoryAllocated ); if (!NT_SUCCESS(status)) { KdPrint(( "AFD: Unable to get security descriptor, error: %x\n", status )); ASSERT(memoryAllocated == FALSE); return(status); } // // Build a local security descriptor with an ACL giving only // administrators and system access. // status = AfdBuildDeviceAcl(&rawAcl); if (!NT_SUCCESS(status)) { KdPrint(("AFD: Unable to create Raw ACL, error: %x\n", status)); goto error_exit; } (VOID) RtlCreateSecurityDescriptor( localSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION ); (VOID) RtlSetDaclSecurityDescriptor( localSecurityDescriptor, TRUE, rawAcl, FALSE ); // // Make a copy of the AFD descriptor. This copy will be the raw descriptor. // afdSecurityDescriptorLength = RtlLengthSecurityDescriptor( afdSecurityDescriptor ); AfdRawSecurityDescriptor = AFD_ALLOCATE_POOL( PagedPool, afdSecurityDescriptorLength, AFD_SECURITY_POOL_TAG ); if (AfdRawSecurityDescriptor == NULL) { KdPrint(("AFD: couldn't allocate security descriptor\n")); goto error_exit; } RtlMoveMemory( AfdRawSecurityDescriptor, afdSecurityDescriptor, afdSecurityDescriptorLength ); // // Now apply the local descriptor to the raw descriptor. // status = SeSetSecurityDescriptorInfo( NULL, &securityInformation, localSecurityDescriptor, &AfdRawSecurityDescriptor, PagedPool, IoGetFileObjectGenericMapping() ); if (!NT_SUCCESS(status)) { KdPrint(("AFD: SeSetSecurity failed, %lx\n", status)); AFD_FREE_POOL( AfdRawSecurityDescriptor, AFD_SECURITY_POOL_TAG ); AFD_FREE_POOL( rawAcl, AFD_SECURITY_POOL_TAG ); AfdRawSecurityDescriptor = NULL; goto error_exit; } status = STATUS_SUCCESS; error_exit: ObReleaseObjectSecurity( afdSecurityDescriptor, memoryAllocated ); return(status); }