Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/apparmor/capability.c
10814 views
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
30
struct audit_cache {
31
struct aa_profile *profile;
32
kernel_cap_t caps;
33
};
34
35
static 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
*/
42
static 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
*/
61
static 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
*/
113
static 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
*/
129
int 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
}
142
143