Branch data Line data Source code
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 : :
16 : : #include "include/apparmor.h"
17 : : #include "include/capability.h"
18 : : #include "include/cred.h"
19 : : #include "include/policy.h"
20 : : #include "include/audit.h"
21 : :
22 : : /*
23 : : * Table of capability names: we generate it from capabilities.h.
24 : : */
25 : : #include "capability_names.h"
26 : :
27 : : struct aa_sfs_entry aa_sfs_entry_caps[] = {
28 : : AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK),
29 : : { }
30 : : };
31 : :
32 : : struct audit_cache {
33 : : struct aa_profile *profile;
34 : : kernel_cap_t caps;
35 : : };
36 : :
37 : : static DEFINE_PER_CPU(struct audit_cache, audit_cache);
38 : :
39 : : /**
40 : : * audit_cb - call back for capability components of audit struct
41 : : * @ab - audit buffer (NOT NULL)
42 : : * @va - audit struct to audit data from (NOT NULL)
43 : : */
44 : 0 : static void audit_cb(struct audit_buffer *ab, void *va)
45 : : {
46 : : struct common_audit_data *sa = va;
47 : :
48 : 0 : audit_log_format(ab, " capname=");
49 : 0 : audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
50 : 0 : }
51 : :
52 : : /**
53 : : * audit_caps - audit a capability
54 : : * @sa: audit data
55 : : * @profile: profile being tested for confinement (NOT NULL)
56 : : * @cap: capability tested
57 : : * @error: error code returned by test
58 : : *
59 : : * Do auditing of capability and handle, audit/complain/kill modes switching
60 : : * and duplicate message elimination.
61 : : *
62 : : * Returns: 0 or sa->error on success, error code on failure
63 : : */
64 : 0 : static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile,
65 : : int cap, int error)
66 : : {
67 : : struct audit_cache *ent;
68 : : int type = AUDIT_APPARMOR_AUTO;
69 : :
70 : 0 : aad(sa)->error = error;
71 : :
72 [ # # ]: 0 : if (likely(!error)) {
73 : : /* test if auditing is being forced */
74 [ # # # # ]: 0 : if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
75 : : !cap_raised(profile->caps.audit, cap)))
76 : : return 0;
77 : : type = AUDIT_APPARMOR_AUDIT;
78 [ # # # # : 0 : } else if (KILL_MODE(profile) ||
# # ]
79 : 0 : cap_raised(profile->caps.kill, cap)) {
80 : : type = AUDIT_APPARMOR_KILL;
81 [ # # # # ]: 0 : } else if (cap_raised(profile->caps.quiet, cap) &&
82 [ # # ]: 0 : AUDIT_MODE(profile) != AUDIT_NOQUIET &&
83 : : AUDIT_MODE(profile) != AUDIT_ALL) {
84 : : /* quiet auditing */
85 : : return error;
86 : : }
87 : :
88 : : /* Do simple duplicate message elimination */
89 : 0 : ent = &get_cpu_var(audit_cache);
90 [ # # # # ]: 0 : if (profile == ent->profile && cap_raised(ent->caps, cap)) {
91 : 0 : put_cpu_var(audit_cache);
92 [ # # # # ]: 0 : if (COMPLAIN_MODE(profile))
93 : 0 : return complain_error(error);
94 : : return error;
95 : : } else {
96 : : aa_put_profile(ent->profile);
97 : 0 : ent->profile = aa_get_profile(profile);
98 : 0 : cap_raise(ent->caps, cap);
99 : : }
100 : 0 : put_cpu_var(audit_cache);
101 : :
102 : 0 : return aa_audit(type, profile, sa, audit_cb);
103 : : }
104 : :
105 : : /**
106 : : * profile_capable - test if profile allows use of capability @cap
107 : : * @profile: profile being enforced (NOT NULL, NOT unconfined)
108 : : * @cap: capability to test if allowed
109 : : * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
110 : : * @sa: audit data (MAY BE NULL indicating no auditing)
111 : : *
112 : : * Returns: 0 if allowed else -EPERM
113 : : */
114 : 0 : static int profile_capable(struct aa_profile *profile, int cap,
115 : : unsigned int opts, struct common_audit_data *sa)
116 : : {
117 : : int error;
118 : :
119 [ # # # # ]: 0 : if (cap_raised(profile->caps.allow, cap) &&
120 : 0 : !cap_raised(profile->caps.denied, cap))
121 : : error = 0;
122 : : else
123 : : error = -EPERM;
124 : :
125 [ # # ]: 0 : if (opts & CAP_OPT_NOAUDIT) {
126 [ # # # # ]: 0 : if (!COMPLAIN_MODE(profile))
127 : : return error;
128 : : /* audit the cap request in complain mode but note that it
129 : : * should be optional.
130 : : */
131 : 0 : aad(sa)->info = "optional: no audit";
132 : : }
133 : :
134 : 0 : return audit_caps(sa, profile, cap, error);
135 : : }
136 : :
137 : : /**
138 : : * aa_capable - test permission to use capability
139 : : * @label: label being tested for capability (NOT NULL)
140 : : * @cap: capability to be tested
141 : : * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
142 : : *
143 : : * Look up capability in profile capability set.
144 : : *
145 : : * Returns: 0 on success, or else an error code.
146 : : */
147 : 0 : int aa_capable(struct aa_label *label, int cap, unsigned int opts)
148 : : {
149 : : struct aa_profile *profile;
150 : : int error = 0;
151 : 0 : DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
152 : :
153 : 0 : sa.u.cap = cap;
154 [ # # # # ]: 0 : error = fn_for_each_confined(label, profile,
155 : : profile_capable(profile, cap, opts, &sa));
156 : :
157 : 0 : return error;
158 : : }
|