1*0ed3b28aSJohn Johansen /* 2*0ed3b28aSJohn Johansen * AppArmor security module 3*0ed3b28aSJohn Johansen * 4*0ed3b28aSJohn Johansen * This file contains AppArmor capability mediation functions 5*0ed3b28aSJohn Johansen * 6*0ed3b28aSJohn Johansen * Copyright (C) 1998-2008 Novell/SUSE 7*0ed3b28aSJohn Johansen * Copyright 2009-2010 Canonical Ltd. 8*0ed3b28aSJohn Johansen * 9*0ed3b28aSJohn Johansen * This program is free software; you can redistribute it and/or 10*0ed3b28aSJohn Johansen * modify it under the terms of the GNU General Public License as 11*0ed3b28aSJohn Johansen * published by the Free Software Foundation, version 2 of the 12*0ed3b28aSJohn Johansen * License. 13*0ed3b28aSJohn Johansen */ 14*0ed3b28aSJohn Johansen 15*0ed3b28aSJohn Johansen #include <linux/capability.h> 16*0ed3b28aSJohn Johansen #include <linux/errno.h> 17*0ed3b28aSJohn Johansen #include <linux/gfp.h> 18*0ed3b28aSJohn Johansen 19*0ed3b28aSJohn Johansen #include "include/apparmor.h" 20*0ed3b28aSJohn Johansen #include "include/capability.h" 21*0ed3b28aSJohn Johansen #include "include/context.h" 22*0ed3b28aSJohn Johansen #include "include/policy.h" 23*0ed3b28aSJohn Johansen #include "include/audit.h" 24*0ed3b28aSJohn Johansen 25*0ed3b28aSJohn Johansen /* 26*0ed3b28aSJohn Johansen * Table of capability names: we generate it from capabilities.h. 27*0ed3b28aSJohn Johansen */ 28*0ed3b28aSJohn Johansen #include "capability_names.h" 29*0ed3b28aSJohn Johansen 30*0ed3b28aSJohn Johansen struct audit_cache { 31*0ed3b28aSJohn Johansen struct aa_profile *profile; 32*0ed3b28aSJohn Johansen kernel_cap_t caps; 33*0ed3b28aSJohn Johansen }; 34*0ed3b28aSJohn Johansen 35*0ed3b28aSJohn Johansen static DEFINE_PER_CPU(struct audit_cache, audit_cache); 36*0ed3b28aSJohn Johansen 37*0ed3b28aSJohn Johansen /** 38*0ed3b28aSJohn Johansen * audit_cb - call back for capability components of audit struct 39*0ed3b28aSJohn Johansen * @ab - audit buffer (NOT NULL) 40*0ed3b28aSJohn Johansen * @va - audit struct to audit data from (NOT NULL) 41*0ed3b28aSJohn Johansen */ 42*0ed3b28aSJohn Johansen static void audit_cb(struct audit_buffer *ab, void *va) 43*0ed3b28aSJohn Johansen { 44*0ed3b28aSJohn Johansen struct common_audit_data *sa = va; 45*0ed3b28aSJohn Johansen audit_log_format(ab, " capname="); 46*0ed3b28aSJohn Johansen audit_log_untrustedstring(ab, capability_names[sa->u.cap]); 47*0ed3b28aSJohn Johansen } 48*0ed3b28aSJohn Johansen 49*0ed3b28aSJohn Johansen /** 50*0ed3b28aSJohn Johansen * audit_caps - audit a capability 51*0ed3b28aSJohn Johansen * @profile: profile confining task (NOT NULL) 52*0ed3b28aSJohn Johansen * @task: task capability test was performed against (NOT NULL) 53*0ed3b28aSJohn Johansen * @cap: capability tested 54*0ed3b28aSJohn Johansen * @error: error code returned by test 55*0ed3b28aSJohn Johansen * 56*0ed3b28aSJohn Johansen * Do auditing of capability and handle, audit/complain/kill modes switching 57*0ed3b28aSJohn Johansen * and duplicate message elimination. 58*0ed3b28aSJohn Johansen * 59*0ed3b28aSJohn Johansen * Returns: 0 or sa->error on success, error code on failure 60*0ed3b28aSJohn Johansen */ 61*0ed3b28aSJohn Johansen static int audit_caps(struct aa_profile *profile, struct task_struct *task, 62*0ed3b28aSJohn Johansen int cap, int error) 63*0ed3b28aSJohn Johansen { 64*0ed3b28aSJohn Johansen struct audit_cache *ent; 65*0ed3b28aSJohn Johansen int type = AUDIT_APPARMOR_AUTO; 66*0ed3b28aSJohn Johansen struct common_audit_data sa; 67*0ed3b28aSJohn Johansen COMMON_AUDIT_DATA_INIT(&sa, CAP); 68*0ed3b28aSJohn Johansen sa.tsk = task; 69*0ed3b28aSJohn Johansen sa.u.cap = cap; 70*0ed3b28aSJohn Johansen sa.aad.op = OP_CAPABLE; 71*0ed3b28aSJohn Johansen sa.aad.error = error; 72*0ed3b28aSJohn Johansen 73*0ed3b28aSJohn Johansen if (likely(!error)) { 74*0ed3b28aSJohn Johansen /* test if auditing is being forced */ 75*0ed3b28aSJohn Johansen if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && 76*0ed3b28aSJohn Johansen !cap_raised(profile->caps.audit, cap))) 77*0ed3b28aSJohn Johansen return 0; 78*0ed3b28aSJohn Johansen type = AUDIT_APPARMOR_AUDIT; 79*0ed3b28aSJohn Johansen } else if (KILL_MODE(profile) || 80*0ed3b28aSJohn Johansen cap_raised(profile->caps.kill, cap)) { 81*0ed3b28aSJohn Johansen type = AUDIT_APPARMOR_KILL; 82*0ed3b28aSJohn Johansen } else if (cap_raised(profile->caps.quiet, cap) && 83*0ed3b28aSJohn Johansen AUDIT_MODE(profile) != AUDIT_NOQUIET && 84*0ed3b28aSJohn Johansen AUDIT_MODE(profile) != AUDIT_ALL) { 85*0ed3b28aSJohn Johansen /* quiet auditing */ 86*0ed3b28aSJohn Johansen return error; 87*0ed3b28aSJohn Johansen } 88*0ed3b28aSJohn Johansen 89*0ed3b28aSJohn Johansen /* Do simple duplicate message elimination */ 90*0ed3b28aSJohn Johansen ent = &get_cpu_var(audit_cache); 91*0ed3b28aSJohn Johansen if (profile == ent->profile && cap_raised(ent->caps, cap)) { 92*0ed3b28aSJohn Johansen put_cpu_var(audit_cache); 93*0ed3b28aSJohn Johansen if (COMPLAIN_MODE(profile)) 94*0ed3b28aSJohn Johansen return complain_error(error); 95*0ed3b28aSJohn Johansen return error; 96*0ed3b28aSJohn Johansen } else { 97*0ed3b28aSJohn Johansen aa_put_profile(ent->profile); 98*0ed3b28aSJohn Johansen ent->profile = aa_get_profile(profile); 99*0ed3b28aSJohn Johansen cap_raise(ent->caps, cap); 100*0ed3b28aSJohn Johansen } 101*0ed3b28aSJohn Johansen put_cpu_var(audit_cache); 102*0ed3b28aSJohn Johansen 103*0ed3b28aSJohn Johansen return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb); 104*0ed3b28aSJohn Johansen } 105*0ed3b28aSJohn Johansen 106*0ed3b28aSJohn Johansen /** 107*0ed3b28aSJohn Johansen * profile_capable - test if profile allows use of capability @cap 108*0ed3b28aSJohn Johansen * @profile: profile being enforced (NOT NULL, NOT unconfined) 109*0ed3b28aSJohn Johansen * @cap: capability to test if allowed 110*0ed3b28aSJohn Johansen * 111*0ed3b28aSJohn Johansen * Returns: 0 if allowed else -EPERM 112*0ed3b28aSJohn Johansen */ 113*0ed3b28aSJohn Johansen static int profile_capable(struct aa_profile *profile, int cap) 114*0ed3b28aSJohn Johansen { 115*0ed3b28aSJohn Johansen return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM; 116*0ed3b28aSJohn Johansen } 117*0ed3b28aSJohn Johansen 118*0ed3b28aSJohn Johansen /** 119*0ed3b28aSJohn Johansen * aa_capable - test permission to use capability 120*0ed3b28aSJohn Johansen * @task: task doing capability test against (NOT NULL) 121*0ed3b28aSJohn Johansen * @profile: profile confining @task (NOT NULL) 122*0ed3b28aSJohn Johansen * @cap: capability to be tested 123*0ed3b28aSJohn Johansen * @audit: whether an audit record should be generated 124*0ed3b28aSJohn Johansen * 125*0ed3b28aSJohn Johansen * Look up capability in profile capability set. 126*0ed3b28aSJohn Johansen * 127*0ed3b28aSJohn Johansen * Returns: 0 on success, or else an error code. 128*0ed3b28aSJohn Johansen */ 129*0ed3b28aSJohn Johansen int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap, 130*0ed3b28aSJohn Johansen int audit) 131*0ed3b28aSJohn Johansen { 132*0ed3b28aSJohn Johansen int error = profile_capable(profile, cap); 133*0ed3b28aSJohn Johansen 134*0ed3b28aSJohn Johansen if (!audit) { 135*0ed3b28aSJohn Johansen if (COMPLAIN_MODE(profile)) 136*0ed3b28aSJohn Johansen return complain_error(error); 137*0ed3b28aSJohn Johansen return error; 138*0ed3b28aSJohn Johansen } 139*0ed3b28aSJohn Johansen 140*0ed3b28aSJohn Johansen return audit_caps(profile, task, cap, error); 141*0ed3b28aSJohn Johansen } 142