Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 19: Auditing


audit_log_format(ab, " success=%s exit=%ld",
(context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
context->return_code);
...
audit_log_format(ab,
" a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
" pid=%d auid=%u uid=%u gid=%u"
" euid=%u suid=%u fsuid=%u"
" egid=%u sgid=%u fsgid=%u",
context->argv[0],
context->argv[1],
context->argv[2],
context->argv[3],
context->name_count,
context->pid,
context->loginuid,
context->uid,
context->gid,
context->euid, context->suid, context->fsuid,
context->egid, context->sgid, context->fsgid);
...
}

The system call number, the system call return code,and some generic information about the process are
logged by the preceding code. Afterwards,audit_syscall_exithas to make sure that the previous audit
context (should one exist) is restored as the active context; additionally, several now-unused resources
need to be deallocated.

Access VectorCache Auditing


A very prominent example where auditing is a rathercrucial requirement is the SELinux access vector
cache. Granting or denying permissions is performed by the functionavc_audit, which is called from
avc_has_perm, that is, whenever a permission query is passed to the security server. First, the function
needs to check if auditing is required for the current case (i.e., granting or denial is supposed to be audited
or not) as follows:

security/selinux/avc.c
void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *a)
{
struct task_struct *tsk = current;
struct inode *inode = NULL;
u32 denied, audited;
struct audit_buffer *ab;

denied = requested & ̃avd->allowed;
if (denied) {
audited = denied;
if (!(audited & avd->auditdeny))
return;
} else if (result) {
audited = denied = requested;
Free download pdf