Messages in this thread Patch in this message | | | Date | Mon, 7 Mar 2011 13:06:56 -0800 | From | Tony Jones <> | Subject | PATCH [1/1]: audit: acquire creds selectively to reduce atomic op overhead |
| |
Commit c69e8d9c01db added calls to get_task_cred and put_cred in audit_filter_rules. Profiling with a large number of audit rules active on the exit chain shows that we are spending upto 48% in this routine for syscall intensive tests, most of which is in the atomic ops.
The following patch acquires the cred if a rule requires it. In our particular case above, most rules had no cred requirement and this dropped the time spent in audit_filter_rules down to ~12%. An alternative would be for the caller to acquire the cred just once for the whole chain and pass into audit_filter_rules. I can create an alternate patch doing this if required.
Signed-off-by: Tony Jones <tonyj@suse.de> ---
kernel/auditsc.c | 24 +++++++++++++++++++++--- 1 files changed, 21 insertions(+), 3 deletions(-)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index f49a031..4a930a1 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -450,7 +450,7 @@ static int audit_filter_rules(struct task_struct *tsk, struct audit_names *name, enum audit_state *state) { - const struct cred *cred = get_task_cred(tsk); + const struct cred *cred=NULL; int i, j, need_sid = 1; u32 sid; @@ -470,27 +470,43 @@ static int audit_filter_rules(struct task_struct *tsk, } break; case AUDIT_UID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->uid, f->op, f->val); break; case AUDIT_EUID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->euid, f->op, f->val); break; case AUDIT_SUID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->suid, f->op, f->val); break; case AUDIT_FSUID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->fsuid, f->op, f->val); break; case AUDIT_GID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->gid, f->op, f->val); break; case AUDIT_EGID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->egid, f->op, f->val); break; case AUDIT_SGID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->sgid, f->op, f->val); break; case AUDIT_FSGID: + if (!cred) + cred=get_task_cred(tsk); result = audit_comparator(cred->fsgid, f->op, f->val); break; case AUDIT_PERS: @@ -638,7 +654,8 @@ static int audit_filter_rules(struct task_struct *tsk, } if (!result) { - put_cred(cred); + if (cred) + put_cred(cred); return 0; } } @@ -656,7 +673,8 @@ static int audit_filter_rules(struct task_struct *tsk, case AUDIT_NEVER: *state = AUDIT_DISABLED; break; case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; } - put_cred(cred); + if (cred) + put_cred(cred); return 1; }
| |