Linux Audio

Check our new training course

Loading...
v3.1
 
  1/*
  2 * AppArmor security module
  3 *
  4 * This file contains AppArmor capability mediation functions
  5 *
  6 * Copyright (C) 1998-2008 Novell/SUSE
  7 * Copyright 2009-2010 Canonical Ltd.
  8 *
  9 * This program is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU General Public License as
 11 * published by the Free Software Foundation, version 2 of the
 12 * License.
 13 */
 14
 15#include <linux/capability.h>
 16#include <linux/errno.h>
 17#include <linux/gfp.h>
 
 
 18
 19#include "include/apparmor.h"
 20#include "include/capability.h"
 21#include "include/context.h"
 22#include "include/policy.h"
 23#include "include/audit.h"
 24
 25/*
 26 * Table of capability names: we generate it from capabilities.h.
 27 */
 28#include "capability_names.h"
 29
 
 
 
 
 
 30struct audit_cache {
 31	struct aa_profile *profile;
 32	kernel_cap_t caps;
 
 33};
 34
 35static DEFINE_PER_CPU(struct audit_cache, audit_cache);
 36
 37/**
 38 * audit_cb - call back for capability components of audit struct
 39 * @ab - audit buffer   (NOT NULL)
 40 * @va - audit struct to audit data from  (NOT NULL)
 41 */
 42static void audit_cb(struct audit_buffer *ab, void *va)
 43{
 44	struct common_audit_data *sa = va;
 
 45	audit_log_format(ab, " capname=");
 46	audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
 47}
 48
 49/**
 50 * audit_caps - audit a capability
 51 * @profile: profile confining task (NOT NULL)
 52 * @task: task capability test was performed against (NOT NULL)
 53 * @cap: capability tested
 54 * @error: error code returned by test
 55 *
 56 * Do auditing of capability and handle, audit/complain/kill modes switching
 57 * and duplicate message elimination.
 58 *
 59 * Returns: 0 or sa->error on success,  error code on failure
 60 */
 61static int audit_caps(struct aa_profile *profile, struct task_struct *task,
 62		      int cap, int error)
 63{
 
 
 
 
 64	struct audit_cache *ent;
 65	int type = AUDIT_APPARMOR_AUTO;
 66	struct common_audit_data sa;
 67	COMMON_AUDIT_DATA_INIT(&sa, CAP);
 68	sa.tsk = task;
 69	sa.u.cap = cap;
 70	sa.aad.op = OP_CAPABLE;
 71	sa.aad.error = error;
 72
 73	if (likely(!error)) {
 74		/* test if auditing is being forced */
 75		if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
 76			   !cap_raised(profile->caps.audit, cap)))
 77			return 0;
 78		type = AUDIT_APPARMOR_AUDIT;
 79	} else if (KILL_MODE(profile) ||
 80		   cap_raised(profile->caps.kill, cap)) {
 81		type = AUDIT_APPARMOR_KILL;
 82	} else if (cap_raised(profile->caps.quiet, cap) &&
 83		   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
 84		   AUDIT_MODE(profile) != AUDIT_ALL) {
 85		/* quiet auditing */
 86		return error;
 87	}
 88
 89	/* Do simple duplicate message elimination */
 90	ent = &get_cpu_var(audit_cache);
 91	if (profile == ent->profile && cap_raised(ent->caps, cap)) {
 
 92		put_cpu_var(audit_cache);
 93		if (COMPLAIN_MODE(profile))
 94			return complain_error(error);
 95		return error;
 96	} else {
 97		aa_put_profile(ent->profile);
 98		ent->profile = aa_get_profile(profile);
 99		cap_raise(ent->caps, cap);
100	}
101	put_cpu_var(audit_cache);
102
103	return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
104}
105
106/**
107 * profile_capable - test if profile allows use of capability @cap
108 * @profile: profile being enforced    (NOT NULL, NOT unconfined)
109 * @cap: capability to test if allowed
 
 
110 *
111 * Returns: 0 if allowed else -EPERM
112 */
113static int profile_capable(struct aa_profile *profile, int cap)
 
114{
115	return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116}
117
118/**
119 * aa_capable - test permission to use capability
120 * @task: task doing capability test against (NOT NULL)
121 * @profile: profile confining @task (NOT NULL)
122 * @cap: capability to be tested
123 * @audit: whether an audit record should be generated
124 *
125 * Look up capability in profile capability set.
126 *
127 * Returns: 0 on success, or else an error code.
128 */
129int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
130	       int audit)
131{
132	int error = profile_capable(profile, cap);
 
 
133
134	if (!audit) {
135		if (COMPLAIN_MODE(profile))
136			return complain_error(error);
137		return error;
138	}
139
140	return audit_caps(profile, task, cap, error);
141}
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * AppArmor security module
  4 *
  5 * This file contains AppArmor capability mediation functions
  6 *
  7 * Copyright (C) 1998-2008 Novell/SUSE
  8 * Copyright 2009-2010 Canonical Ltd.
 
 
 
 
 
  9 */
 10
 11#include <linux/capability.h>
 12#include <linux/errno.h>
 13#include <linux/gfp.h>
 14#include <linux/security.h>
 15#include <linux/timekeeping.h>
 16
 17#include "include/apparmor.h"
 18#include "include/capability.h"
 19#include "include/cred.h"
 20#include "include/policy.h"
 21#include "include/audit.h"
 22
 23/*
 24 * Table of capability names: we generate it from capabilities.h.
 25 */
 26#include "capability_names.h"
 27
 28struct aa_sfs_entry aa_sfs_entry_caps[] = {
 29	AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK),
 30	{ }
 31};
 32
 33struct audit_cache {
 34	const struct cred *ad_subj_cred;
 35	/* Capabilities go from 0 to CAP_LAST_CAP */
 36	u64 ktime_ns_expiration[CAP_LAST_CAP+1];
 37};
 38
 39static DEFINE_PER_CPU(struct audit_cache, audit_cache);
 40
 41/**
 42 * audit_cb - call back for capability components of audit struct
 43 * @ab: audit buffer   (NOT NULL)
 44 * @va: audit struct to audit data from  (NOT NULL)
 45 */
 46static void audit_cb(struct audit_buffer *ab, void *va)
 47{
 48	struct common_audit_data *sa = va;
 49
 50	audit_log_format(ab, " capname=");
 51	audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
 52}
 53
 54/**
 55 * audit_caps - audit a capability
 56 * @ad: audit data
 57 * @profile: profile being tested for confinement (NOT NULL)
 58 * @cap: capability tested
 59 * @error: error code returned by test
 60 *
 61 * Do auditing of capability and handle, audit/complain/kill modes switching
 62 * and duplicate message elimination.
 63 *
 64 * Returns: 0 or ad->error on success,  error code on failure
 65 */
 66static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile,
 67		      int cap, int error)
 68{
 69	const u64 AUDIT_CACHE_TIMEOUT_NS = 1000*1000*1000; /* 1 second */
 70
 71	struct aa_ruleset *rules = list_first_entry(&profile->rules,
 72						    typeof(*rules), list);
 73	struct audit_cache *ent;
 74	int type = AUDIT_APPARMOR_AUTO;
 75
 76	ad->error = error;
 
 
 
 
 77
 78	if (likely(!error)) {
 79		/* test if auditing is being forced */
 80		if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
 81			   !cap_raised(rules->caps.audit, cap)))
 82			return 0;
 83		type = AUDIT_APPARMOR_AUDIT;
 84	} else if (KILL_MODE(profile) ||
 85		   cap_raised(rules->caps.kill, cap)) {
 86		type = AUDIT_APPARMOR_KILL;
 87	} else if (cap_raised(rules->caps.quiet, cap) &&
 88		   AUDIT_MODE(profile) != AUDIT_NOQUIET &&
 89		   AUDIT_MODE(profile) != AUDIT_ALL) {
 90		/* quiet auditing */
 91		return error;
 92	}
 93
 94	/* Do simple duplicate message elimination */
 95	ent = &get_cpu_var(audit_cache);
 96	/* If the capability was never raised the timestamp check would also catch that */
 97	if (ad->subj_cred == ent->ad_subj_cred && ktime_get_ns() <= ent->ktime_ns_expiration[cap]) {
 98		put_cpu_var(audit_cache);
 99		if (COMPLAIN_MODE(profile))
100			return complain_error(error);
101		return error;
102	} else {
103		put_cred(ent->ad_subj_cred);
104		ent->ad_subj_cred = get_cred(ad->subj_cred);
105		ent->ktime_ns_expiration[cap] = ktime_get_ns() + AUDIT_CACHE_TIMEOUT_NS;
106	}
107	put_cpu_var(audit_cache);
108
109	return aa_audit(type, profile, ad, audit_cb);
110}
111
112/**
113 * profile_capable - test if profile allows use of capability @cap
114 * @profile: profile being enforced    (NOT NULL, NOT unconfined)
115 * @cap: capability to test if allowed
116 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
117 * @ad: audit data (NOT NULL)
118 *
119 * Returns: 0 if allowed else -EPERM
120 */
121static int profile_capable(struct aa_profile *profile, int cap,
122			   unsigned int opts, struct apparmor_audit_data *ad)
123{
124	struct aa_ruleset *rules = list_first_entry(&profile->rules,
125						    typeof(*rules), list);
126	int error;
127
128	if (cap_raised(rules->caps.allow, cap) &&
129	    !cap_raised(rules->caps.denied, cap))
130		error = 0;
131	else
132		error = -EPERM;
133
134	if (opts & CAP_OPT_NOAUDIT) {
135		if (!COMPLAIN_MODE(profile))
136			return error;
137		/* audit the cap request in complain mode but note that it
138		 * should be optional.
139		 */
140		ad->info = "optional: no audit";
141	}
142
143	return audit_caps(ad, profile, cap, error);
144}
145
146/**
147 * aa_capable - test permission to use capability
148 * @subj_cred: cred we are testing capability against
149 * @label: label being tested for capability (NOT NULL)
150 * @cap: capability to be tested
151 * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
152 *
153 * Look up capability in profile capability set.
154 *
155 * Returns: 0 on success, or else an error code.
156 */
157int aa_capable(const struct cred *subj_cred, struct aa_label *label,
158	       int cap, unsigned int opts)
159{
160	struct aa_profile *profile;
161	int error = 0;
162	DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);
163
164	ad.subj_cred = subj_cred;
165	ad.common.u.cap = cap;
166	error = fn_for_each_confined(label, profile,
167			profile_capable(profile, cap, opts, &ad));
 
168
169	return error;
170}