/*1* AppArmor security module2*3* This file contains AppArmor capability mediation functions4*5* Copyright (C) 1998-2008 Novell/SUSE6* Copyright 2009-2010 Canonical Ltd.7*8* This program is free software; you can redistribute it and/or9* modify it under the terms of the GNU General Public License as10* published by the Free Software Foundation, version 2 of the11* License.12*/1314#include <linux/capability.h>15#include <linux/errno.h>16#include <linux/gfp.h>1718#include "include/apparmor.h"19#include "include/capability.h"20#include "include/context.h"21#include "include/policy.h"22#include "include/audit.h"2324/*25* Table of capability names: we generate it from capabilities.h.26*/27#include "capability_names.h"2829struct audit_cache {30struct aa_profile *profile;31kernel_cap_t caps;32};3334static DEFINE_PER_CPU(struct audit_cache, audit_cache);3536/**37* audit_cb - call back for capability components of audit struct38* @ab - audit buffer (NOT NULL)39* @va - audit struct to audit data from (NOT NULL)40*/41static void audit_cb(struct audit_buffer *ab, void *va)42{43struct common_audit_data *sa = va;44audit_log_format(ab, " capname=");45audit_log_untrustedstring(ab, capability_names[sa->u.cap]);46}4748/**49* audit_caps - audit a capability50* @profile: profile confining task (NOT NULL)51* @task: task capability test was performed against (NOT NULL)52* @cap: capability tested53* @error: error code returned by test54*55* Do auditing of capability and handle, audit/complain/kill modes switching56* and duplicate message elimination.57*58* Returns: 0 or sa->error on success, error code on failure59*/60static int audit_caps(struct aa_profile *profile, struct task_struct *task,61int cap, int error)62{63struct audit_cache *ent;64int type = AUDIT_APPARMOR_AUTO;65struct common_audit_data sa;66COMMON_AUDIT_DATA_INIT(&sa, CAP);67sa.tsk = task;68sa.u.cap = cap;69sa.aad.op = OP_CAPABLE;70sa.aad.error = error;7172if (likely(!error)) {73/* test if auditing is being forced */74if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&75!cap_raised(profile->caps.audit, cap)))76return 0;77type = AUDIT_APPARMOR_AUDIT;78} else if (KILL_MODE(profile) ||79cap_raised(profile->caps.kill, cap)) {80type = AUDIT_APPARMOR_KILL;81} else if (cap_raised(profile->caps.quiet, cap) &&82AUDIT_MODE(profile) != AUDIT_NOQUIET &&83AUDIT_MODE(profile) != AUDIT_ALL) {84/* quiet auditing */85return error;86}8788/* Do simple duplicate message elimination */89ent = &get_cpu_var(audit_cache);90if (profile == ent->profile && cap_raised(ent->caps, cap)) {91put_cpu_var(audit_cache);92if (COMPLAIN_MODE(profile))93return complain_error(error);94return error;95} else {96aa_put_profile(ent->profile);97ent->profile = aa_get_profile(profile);98cap_raise(ent->caps, cap);99}100put_cpu_var(audit_cache);101102return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);103}104105/**106* profile_capable - test if profile allows use of capability @cap107* @profile: profile being enforced (NOT NULL, NOT unconfined)108* @cap: capability to test if allowed109*110* Returns: 0 if allowed else -EPERM111*/112static int profile_capable(struct aa_profile *profile, int cap)113{114return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;115}116117/**118* aa_capable - test permission to use capability119* @task: task doing capability test against (NOT NULL)120* @profile: profile confining @task (NOT NULL)121* @cap: capability to be tested122* @audit: whether an audit record should be generated123*124* Look up capability in profile capability set.125*126* Returns: 0 on success, or else an error code.127*/128int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,129int audit)130{131int error = profile_capable(profile, cap);132133if (!audit) {134if (COMPLAIN_MODE(profile))135return complain_error(error);136return error;137}138139return audit_caps(profile, task, cap, error);140}141142143