diff --git a/xtoskrnl/includes/ob/security.hh b/xtoskrnl/includes/ob/security.hh index 8398b82..b1b5e3e 100644 --- a/xtoskrnl/includes/ob/security.hh +++ b/xtoskrnl/includes/ob/security.hh @@ -18,6 +18,10 @@ namespace OB class Security { public: + STATIC XTAPI VOID AuditObjectAccess(IN HANDLE Handle, + IN PHANDLE_TABLE_ENTRY_INFO ObjectTableEntryInfo, + IN PUNICODE_STRING ObjectTypeName, + IN ACCESS_MASK DesiredAccess); STATIC XTAPI XTSTATUS ProcessObjectSecurityDescriptor(IN PVOID Object, IN SECURITY_OPERATION_CODE OperationCode, IN PSECURITY_INFORMATION SecurityInformation, diff --git a/xtoskrnl/ob/security.cc b/xtoskrnl/ob/security.cc index 6b73c4c..fba5c30 100644 --- a/xtoskrnl/ob/security.cc +++ b/xtoskrnl/ob/security.cc @@ -9,6 +9,75 @@ #include +/** + * Consumes the audit mask for a handle table entry and triggers a security audit alarm if the requested access + * rights match the audit requirements. + * + * @param Handle + * Supplies the handle being accessed. + * + * @param ObjectTableEntryInfo + * Supplies a pointer to the extended handle table entry information containing the volatile audit mask. + * + * @param ObjectTypeName + * Supplies a pointer to the Unicode string representing the object's type name. + * + * @param AccessMask + * Supplies the access mask requested by the caller to be evaluated against the audit mask. + * + * @return This routine does not return a value. + * + * @since XT 1.0 + */ +XTAPI +VOID +OB::Security::AuditObjectAccess(IN HANDLE Handle, + IN PHANDLE_TABLE_ENTRY_INFO ObjectTableEntryInfo, + IN PUNICODE_STRING ObjectTypeName, + IN ACCESS_MASK AccessMask) +{ + ACCESS_MASK BitsToAudit, CurrentAuditMask, PreviousAuditMask, RemainingAuditMask; + + /* Enter a CAS loop */ + while(ObjectTableEntryInfo->AuditMask) + { + /* Capture the current state of the audit mask */ + CurrentAuditMask = ObjectTableEntryInfo->AuditMask; + + /* Mask out the access rights */ + RemainingAuditMask = CurrentAuditMask & ~AccessMask; + + /* Check if the requested access intersects with the audit mask */ + if(RemainingAuditMask == CurrentAuditMask) + { + /* No overlapping bits, return */ + return; + } + + /* Attempt to update the audit mask */ + PreviousAuditMask = (ACCESS_MASK)RTL::Atomic::CompareExchange32((VOLATILE PLONG)&ObjectTableEntryInfo->AuditMask, + (LONG)RemainingAuditMask, + (LONG)CurrentAuditMask); + + /* Verify if the update succeeded */ + if(PreviousAuditMask == CurrentAuditMask) + { + /* Extract the access bits */ + BitsToAudit = PreviousAuditMask & AccessMask; + + /* Check if there are active bits */ + if(BitsToAudit) + { + /* Dispatch the audit event */ + SE::Audit::OperationAuditAlarm(NULLPTR, Handle, ObjectTypeName, BitsToAudit, NULLPTR); + } + + /* Auditing completed, return */ + return; + } + } +} + /** * Provides the default security procedure for handling object security descriptors. *