/** * aa_apply_modes_to_perms - apply namespace and profile flags to perms * @profile: that perms where computed from * @perms: perms to apply mode modifiers to * * TODO: split into profile and ns based flags for when accumulating perms */ void aa_apply_modes_to_perms(struct aa_profile *profile, struct aa_perms *perms) { switch (AUDIT_MODE(profile)) { case AUDIT_ALL: perms->audit = ALL_PERMS_MASK; /* fall through */ case AUDIT_NOQUIET: perms->quiet = 0; break; case AUDIT_QUIET: perms->audit = 0; /* fall through */ case AUDIT_QUIET_DENIED: perms->quiet = ALL_PERMS_MASK; break; } if (KILL_MODE(profile)) perms->kill = ALL_PERMS_MASK; else if (COMPLAIN_MODE(profile)) perms->complain = ALL_PERMS_MASK; /* TODO: else if (PROMPT_MODE(profile)) perms->prompt = ALL_PERMS_MASK; */ }
/** * audit_caps - audit a capability * @profile: profile confining task (NOT NULL) * @task: task capability test was performed against (NOT NULL) * @cap: capability tested * @error: error code returned by test * * Do auditing of capability and handle, audit/complain/kill modes switching * and duplicate message elimination. * * Returns: 0 or sa->error on success, error code on failure */ static int audit_caps(struct aa_profile *profile, struct task_struct *task, int cap, int error) { struct audit_cache *ent; int type = AUDIT_APPARMOR_AUTO; struct common_audit_data sa; struct apparmor_audit_data aad = {0,}; COMMON_AUDIT_DATA_INIT(&sa, CAP); sa.aad = &aad; sa.tsk = task; sa.u.cap = cap; sa.aad->op = OP_CAPABLE; sa.aad->error = error; if (likely(!error)) { /* test if auditing is being forced */ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && !cap_raised(profile->caps.audit, cap))) return 0; type = AUDIT_APPARMOR_AUDIT; } else if (KILL_MODE(profile) || cap_raised(profile->caps.kill, cap)) { type = AUDIT_APPARMOR_KILL; } else if (cap_raised(profile->caps.quiet, cap) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) { /* quiet auditing */ return error; } /* Do simple duplicate message elimination */ ent = &get_cpu_var(audit_cache); if (profile == ent->profile && cap_raised(ent->caps, cap)) { put_cpu_var(audit_cache); if (COMPLAIN_MODE(profile)) return complain_error(error); return error; } else { aa_put_profile(ent->profile); ent->profile = aa_get_profile(profile); cap_raise(ent->caps, cap); } put_cpu_var(audit_cache); return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb); }
/** * audit_caps - audit a capability * @sa: audit data * @profile: profile being tested for confinement (NOT NULL) * @cap: capability tested * @error: error code returned by test * * Do auditing of capability and handle, audit/complain/kill modes switching * and duplicate message elimination. * * Returns: 0 or sa->error on success, error code on failure */ static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, int cap, int error) { struct audit_cache *ent; int type = AUDIT_APPARMOR_AUTO; aad(sa)->error = error; if (likely(!error)) { /* test if auditing is being forced */ if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && !cap_raised(profile->caps.audit, cap))) return 0; type = AUDIT_APPARMOR_AUDIT; } else if (KILL_MODE(profile) || cap_raised(profile->caps.kill, cap)) { type = AUDIT_APPARMOR_KILL; } else if (cap_raised(profile->caps.quiet, cap) && AUDIT_MODE(profile) != AUDIT_NOQUIET && AUDIT_MODE(profile) != AUDIT_ALL) { /* quiet auditing */ return error; } /* Do simple duplicate message elimination */ ent = &get_cpu_var(audit_cache); if (profile == ent->profile && cap_raised(ent->caps, cap)) { put_cpu_var(audit_cache); if (COMPLAIN_MODE(profile)) return complain_error(error); return error; } else { aa_put_profile(ent->profile); ent->profile = aa_get_profile(profile); cap_raise(ent->caps, cap); } put_cpu_var(audit_cache); return aa_audit(type, profile, sa, audit_cb); }
/** * aa_audit - Log a profile based audit event to the audit subsystem * @type: audit type for the message * @profile: profile to check against (NOT NULL) * @gfp: allocation flags to use * @sa: audit event (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) * * Handle default message switching based off of audit mode flags * * Returns: error on failure */ int aa_audit(int type, struct aa_profile *profile, gfp_t gfp, struct common_audit_data *sa, void (*cb) (struct audit_buffer *, void *)) { BUG_ON(!profile); if (type == AUDIT_APPARMOR_AUTO) { if (likely(!sa->aad->error)) { if (AUDIT_MODE(profile) != AUDIT_ALL) return 0; type = AUDIT_APPARMOR_AUDIT; } else if (COMPLAIN_MODE(profile)) type = AUDIT_APPARMOR_ALLOWED; else type = AUDIT_APPARMOR_DENIED; } if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && AUDIT_MODE(profile) == AUDIT_QUIET)) return sa->aad->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; if (!unconfined(profile)) sa->aad->profile = profile; aa_audit_msg(type, sa, cb); if (sa->aad->type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, sa->u.tsk ? sa->u.tsk : current); if (sa->aad->type == AUDIT_APPARMOR_ALLOWED) return complain_error(sa->aad->error); return sa->aad->error; }
/** * aa_audit - Log a profile based audit event to the audit subsystem * @type: audit type for the message * @profile: profile to check against (NOT NULL) * @sa: audit event (NOT NULL) * @cb: optional callback fn for type specific fields (MAYBE NULL) * * Handle default message switching based off of audit mode flags * * Returns: error on failure */ int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa, void (*cb) (struct audit_buffer *, void *)) { BUG_ON(!profile); if (type == AUDIT_APPARMOR_AUTO) { if (likely(!aad(sa)->error)) { if (AUDIT_MODE(profile) != AUDIT_ALL) return 0; type = AUDIT_APPARMOR_AUDIT; } else if (COMPLAIN_MODE(profile)) type = AUDIT_APPARMOR_ALLOWED; else type = AUDIT_APPARMOR_DENIED; } if (AUDIT_MODE(profile) == AUDIT_QUIET || (type == AUDIT_APPARMOR_DENIED && AUDIT_MODE(profile) == AUDIT_QUIET)) return aad(sa)->error; if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED) type = AUDIT_APPARMOR_KILL; aad(sa)->label = &profile->label; aa_audit_msg(type, sa, cb); if (aad(sa)->type == AUDIT_APPARMOR_KILL) (void)send_sig_info(SIGKILL, NULL, sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ? sa->u.tsk : current); if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED) return complain_error(aad(sa)->error); return aad(sa)->error; }