Merge tag 'rpmsg-v6.4' of git://git.kernel.org/pub/scm/linux/kernel/git/remoteproc...
[linux-block.git] / security / apparmor / audit.c
CommitLineData
b886d83c 1// SPDX-License-Identifier: GPL-2.0-only
67012e82
JJ
2/*
3 * AppArmor security module
4 *
5 * This file contains AppArmor auditing functions
6 *
7 * Copyright (C) 1998-2008 Novell/SUSE
8 * Copyright 2009-2010 Canonical Ltd.
67012e82
JJ
9 */
10
11#include <linux/audit.h>
12#include <linux/socket.h>
13
14#include "include/apparmor.h"
15#include "include/audit.h"
16#include "include/policy.h"
cff281f6 17#include "include/policy_ns.h"
e79c26d0 18#include "include/secid.h"
67012e82 19
2d4cee7e 20const char *const audit_mode_names[] = {
67012e82
JJ
21 "normal",
22 "quiet_denied",
23 "quiet",
24 "noquiet",
25 "all"
26};
27
2d4cee7e 28static const char *const aa_audit_type[] = {
67012e82
JJ
29 "AUDIT",
30 "ALLOWED",
31 "DENIED",
32 "HINT",
33 "STATUS",
34 "ERROR",
b492d50b 35 "KILLED",
ade3ddc0 36 "AUTO"
67012e82
JJ
37};
38
8c4b785a
JJ
39static const char *const aa_class_names[] = {
40 "none",
41 "unknown",
42 "file",
43 "cap",
44 "net",
45 "rlimits",
46 "domain",
47 "mount",
48 "unknown",
49 "ptrace",
50 "signal",
961f3e3d 51 "xmatch",
8c4b785a
JJ
52 "unknown",
53 "unknown",
54 "net",
55 "unknown",
56 "label",
961f3e3d
JJ
57 "posix_mqueue",
58 "io_uring",
59 "module",
8c4b785a 60 "lsm",
961f3e3d
JJ
61 "unknown",
62 "unknown",
63 "unknown",
64 "unknown",
65 "unknown",
66 "unknown",
67 "unknown",
68 "unknown",
69 "unknown",
70 "unknown",
71 "X",
72 "dbus",
8c4b785a
JJ
73};
74
75
67012e82
JJ
76/*
77 * Currently AppArmor auditing is fed straight into the audit framework.
78 *
79 * TODO:
80 * netlink interface for complain mode
81 * user auditing, - send user auditing to netlink interface
82 * system control of whether user audit messages go to system log
83 */
84
85/**
64a27ba9 86 * audit_pre() - core AppArmor function.
67012e82
JJ
87 * @ab: audit buffer to fill (NOT NULL)
88 * @ca: audit structure containing data to audit (NOT NULL)
89 *
90 * Record common AppArmor audit data from @sa
91 */
92static void audit_pre(struct audit_buffer *ab, void *ca)
93{
94 struct common_audit_data *sa = ca;
67012e82
JJ
95
96 if (aa_g_audit_header) {
f1d9b23c
RGB
97 audit_log_format(ab, "apparmor=\"%s\"",
98 aa_audit_type[aad(sa)->type]);
67012e82
JJ
99 }
100
ef88a7ac 101 if (aad(sa)->op) {
f1d9b23c 102 audit_log_format(ab, " operation=\"%s\"", aad(sa)->op);
67012e82
JJ
103 }
104
8c4b785a
JJ
105 if (aad(sa)->class)
106 audit_log_format(ab, " class=\"%s\"",
107 aad(sa)->class <= AA_CLASS_LAST ?
108 aa_class_names[aad(sa)->class] :
109 "unknown");
110
ef88a7ac 111 if (aad(sa)->info) {
f1d9b23c 112 audit_log_format(ab, " info=\"%s\"", aad(sa)->info);
ef88a7ac
JJ
113 if (aad(sa)->error)
114 audit_log_format(ab, " error=%d", aad(sa)->error);
67012e82
JJ
115 }
116
637f688d
JJ
117 if (aad(sa)->label) {
118 struct aa_label *label = aad(sa)->label;
119
120 if (label_isprofile(label)) {
121 struct aa_profile *profile = labels_profile(label);
122
123 if (profile->ns != root_ns) {
124 audit_log_format(ab, " namespace=");
125 audit_log_untrustedstring(ab,
126 profile->ns->base.hname);
127 }
128 audit_log_format(ab, " profile=");
129 audit_log_untrustedstring(ab, profile->base.hname);
130 } else {
131 audit_log_format(ab, " label=");
132 aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS,
133 GFP_ATOMIC);
67012e82 134 }
67012e82
JJ
135 }
136
ef88a7ac 137 if (aad(sa)->name) {
67012e82 138 audit_log_format(ab, " name=");
ef88a7ac 139 audit_log_untrustedstring(ab, aad(sa)->name);
67012e82
JJ
140 }
141}
142
143/**
144 * aa_audit_msg - Log a message to the audit subsystem
145 * @sa: audit event structure (NOT NULL)
146 * @cb: optional callback fn for type specific fields (MAYBE NULL)
147 */
148void aa_audit_msg(int type, struct common_audit_data *sa,
149 void (*cb) (struct audit_buffer *, void *))
150{
ef88a7ac 151 aad(sa)->type = type;
b61c37f5 152 common_lsm_audit(sa, audit_pre, cb);
67012e82
JJ
153}
154
155/**
156 * aa_audit - Log a profile based audit event to the audit subsystem
157 * @type: audit type for the message
158 * @profile: profile to check against (NOT NULL)
67012e82
JJ
159 * @sa: audit event (NOT NULL)
160 * @cb: optional callback fn for type specific fields (MAYBE NULL)
161 *
162 * Handle default message switching based off of audit mode flags
163 *
164 * Returns: error on failure
165 */
ef88a7ac 166int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
67012e82
JJ
167 void (*cb) (struct audit_buffer *, void *))
168{
e6bfa25d 169 AA_BUG(!profile);
67012e82
JJ
170
171 if (type == AUDIT_APPARMOR_AUTO) {
ef88a7ac 172 if (likely(!aad(sa)->error)) {
67012e82
JJ
173 if (AUDIT_MODE(profile) != AUDIT_ALL)
174 return 0;
175 type = AUDIT_APPARMOR_AUDIT;
176 } else if (COMPLAIN_MODE(profile))
177 type = AUDIT_APPARMOR_ALLOWED;
178 else
179 type = AUDIT_APPARMOR_DENIED;
180 }
181 if (AUDIT_MODE(profile) == AUDIT_QUIET ||
182 (type == AUDIT_APPARMOR_DENIED &&
68ff8540 183 AUDIT_MODE(profile) == AUDIT_QUIET_DENIED))
ef88a7ac 184 return aad(sa)->error;
67012e82
JJ
185
186 if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
187 type = AUDIT_APPARMOR_KILL;
188
637f688d 189 aad(sa)->label = &profile->label;
67012e82
JJ
190
191 aa_audit_msg(type, sa, cb);
192
ef88a7ac 193 if (aad(sa)->type == AUDIT_APPARMOR_KILL)
0972c74e 194 (void)send_sig_info(SIGKILL, NULL,
b6b1b81b
JJ
195 sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
196 sa->u.tsk : current);
67012e82 197
ef88a7ac
JJ
198 if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
199 return complain_error(aad(sa)->error);
67012e82 200
ef88a7ac 201 return aad(sa)->error;
67012e82 202}
e79c26d0
MG
203
204struct aa_audit_rule {
2ab47dae 205 struct aa_label *label;
e79c26d0
MG
206};
207
208void aa_audit_rule_free(void *vrule)
209{
210 struct aa_audit_rule *rule = vrule;
211
212 if (rule) {
2ab47dae
JJ
213 if (!IS_ERR(rule->label))
214 aa_put_label(rule->label);
e79c26d0
MG
215 kfree(rule);
216 }
217}
218
219int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
220{
221 struct aa_audit_rule *rule;
222
223 switch (field) {
224 case AUDIT_SUBJ_ROLE:
225 if (op != Audit_equal && op != Audit_not_equal)
226 return -EINVAL;
227 break;
228 default:
229 return -EINVAL;
230 }
231
232 rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL);
233
234 if (!rule)
235 return -ENOMEM;
236
2ab47dae
JJ
237 /* Currently rules are treated as coming from the root ns */
238 rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr,
239 GFP_KERNEL, true, false);
52e8c380 240 if (IS_ERR(rule->label)) {
c54d481d 241 int err = PTR_ERR(rule->label);
52e8c380 242 aa_audit_rule_free(rule);
c54d481d 243 return err;
52e8c380 244 }
e79c26d0 245
52e8c380 246 *vrule = rule;
e79c26d0
MG
247 return 0;
248}
249
250int aa_audit_rule_known(struct audit_krule *rule)
251{
252 int i;
253
254 for (i = 0; i < rule->field_count; i++) {
255 struct audit_field *f = &rule->fields[i];
256
257 switch (f->type) {
258 case AUDIT_SUBJ_ROLE:
259 return 1;
260 }
261 }
262
263 return 0;
264}
265
90462a5b 266int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
e79c26d0
MG
267{
268 struct aa_audit_rule *rule = vrule;
269 struct aa_label *label;
e79c26d0
MG
270 int found = 0;
271
272 label = aa_secid_to_label(sid);
273
274 if (!label)
275 return -ENOENT;
276
2ab47dae
JJ
277 if (aa_label_is_subset(label, rule->label))
278 found = 1;
e79c26d0
MG
279
280 switch (field) {
281 case AUDIT_SUBJ_ROLE:
282 switch (op) {
283 case Audit_equal:
284 return found;
285 case Audit_not_equal:
286 return !found;
287 }
288 }
289 return 0;
290}