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 auditing functions
6 : : *
7 : : * Copyright (C) 1998-2008 Novell/SUSE
8 : : * Copyright 2009-2010 Canonical Ltd.
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"
17 : : #include "include/policy_ns.h"
18 : : #include "include/secid.h"
19 : :
20 : : const char *const audit_mode_names[] = {
21 : : "normal",
22 : : "quiet_denied",
23 : : "quiet",
24 : : "noquiet",
25 : : "all"
26 : : };
27 : :
28 : : static const char *const aa_audit_type[] = {
29 : : "AUDIT",
30 : : "ALLOWED",
31 : : "DENIED",
32 : : "HINT",
33 : : "STATUS",
34 : : "ERROR",
35 : : "KILLED",
36 : : "AUTO"
37 : : };
38 : :
39 : : /*
40 : : * Currently AppArmor auditing is fed straight into the audit framework.
41 : : *
42 : : * TODO:
43 : : * netlink interface for complain mode
44 : : * user auditing, - send user auditing to netlink interface
45 : : * system control of whether user audit messages go to system log
46 : : */
47 : :
48 : : /**
49 : : * audit_base - core AppArmor function.
50 : : * @ab: audit buffer to fill (NOT NULL)
51 : : * @ca: audit structure containing data to audit (NOT NULL)
52 : : *
53 : : * Record common AppArmor audit data from @sa
54 : : */
55 : 0 : static void audit_pre(struct audit_buffer *ab, void *ca)
56 : : {
57 : : struct common_audit_data *sa = ca;
58 : :
59 [ # # ]: 0 : if (aa_g_audit_header) {
60 : 0 : audit_log_format(ab, "apparmor=");
61 : 0 : audit_log_string(ab, aa_audit_type[aad(sa)->type]);
62 : : }
63 : :
64 [ # # ]: 0 : if (aad(sa)->op) {
65 : 0 : audit_log_format(ab, " operation=");
66 : 0 : audit_log_string(ab, aad(sa)->op);
67 : : }
68 : :
69 [ # # ]: 0 : if (aad(sa)->info) {
70 : 0 : audit_log_format(ab, " info=");
71 : 0 : audit_log_string(ab, aad(sa)->info);
72 [ # # ]: 0 : if (aad(sa)->error)
73 : 0 : audit_log_format(ab, " error=%d", aad(sa)->error);
74 : : }
75 : :
76 [ # # ]: 0 : if (aad(sa)->label) {
77 : : struct aa_label *label = aad(sa)->label;
78 : :
79 [ # # ]: 0 : if (label_isprofile(label)) {
80 : 0 : struct aa_profile *profile = labels_profile(label);
81 : :
82 [ # # ]: 0 : if (profile->ns != root_ns) {
83 : 0 : audit_log_format(ab, " namespace=");
84 : 0 : audit_log_untrustedstring(ab,
85 : 0 : profile->ns->base.hname);
86 : : }
87 : 0 : audit_log_format(ab, " profile=");
88 : 0 : audit_log_untrustedstring(ab, profile->base.hname);
89 : : } else {
90 : 0 : audit_log_format(ab, " label=");
91 : 0 : aa_label_xaudit(ab, root_ns, label, FLAG_VIEW_SUBNS,
92 : : GFP_ATOMIC);
93 : : }
94 : : }
95 : :
96 [ # # ]: 0 : if (aad(sa)->name) {
97 : 0 : audit_log_format(ab, " name=");
98 : 0 : audit_log_untrustedstring(ab, aad(sa)->name);
99 : : }
100 : 0 : }
101 : :
102 : : /**
103 : : * aa_audit_msg - Log a message to the audit subsystem
104 : : * @sa: audit event structure (NOT NULL)
105 : : * @cb: optional callback fn for type specific fields (MAYBE NULL)
106 : : */
107 : 0 : void aa_audit_msg(int type, struct common_audit_data *sa,
108 : : void (*cb) (struct audit_buffer *, void *))
109 : : {
110 : 0 : aad(sa)->type = type;
111 : 0 : common_lsm_audit(sa, audit_pre, cb);
112 : 0 : }
113 : :
114 : : /**
115 : : * aa_audit - Log a profile based audit event to the audit subsystem
116 : : * @type: audit type for the message
117 : : * @profile: profile to check against (NOT NULL)
118 : : * @sa: audit event (NOT NULL)
119 : : * @cb: optional callback fn for type specific fields (MAYBE NULL)
120 : : *
121 : : * Handle default message switching based off of audit mode flags
122 : : *
123 : : * Returns: error on failure
124 : : */
125 : 0 : int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
126 : : void (*cb) (struct audit_buffer *, void *))
127 : : {
128 : : AA_BUG(!profile);
129 : :
130 [ # # ]: 0 : if (type == AUDIT_APPARMOR_AUTO) {
131 [ # # ]: 0 : if (likely(!aad(sa)->error)) {
132 [ # # ]: 0 : if (AUDIT_MODE(profile) != AUDIT_ALL)
133 : : return 0;
134 : : type = AUDIT_APPARMOR_AUDIT;
135 [ # # # # ]: 0 : } else if (COMPLAIN_MODE(profile))
136 : : type = AUDIT_APPARMOR_ALLOWED;
137 : : else
138 : : type = AUDIT_APPARMOR_DENIED;
139 : : }
140 [ # # # # ]: 0 : if (AUDIT_MODE(profile) == AUDIT_QUIET ||
141 [ # # ]: 0 : (type == AUDIT_APPARMOR_DENIED &&
142 : : AUDIT_MODE(profile) == AUDIT_QUIET))
143 : 0 : return aad(sa)->error;
144 : :
145 [ # # # # : 0 : if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
# # ]
146 : : type = AUDIT_APPARMOR_KILL;
147 : :
148 : 0 : aad(sa)->label = &profile->label;
149 : :
150 : : aa_audit_msg(type, sa, cb);
151 : :
152 [ # # ]: 0 : if (aad(sa)->type == AUDIT_APPARMOR_KILL)
153 [ # # ]: 0 : (void)send_sig_info(SIGKILL, NULL,
154 [ # # ]: 0 : sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
155 : : sa->u.tsk : current);
156 : :
157 [ # # ]: 0 : if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
158 : 0 : return complain_error(aad(sa)->error);
159 : :
160 : 0 : return aad(sa)->error;
161 : : }
162 : :
163 : : struct aa_audit_rule {
164 : : struct aa_label *label;
165 : : };
166 : :
167 : 0 : void aa_audit_rule_free(void *vrule)
168 : : {
169 : : struct aa_audit_rule *rule = vrule;
170 : :
171 [ # # ]: 0 : if (rule) {
172 [ # # ]: 0 : if (!IS_ERR(rule->label))
173 : : aa_put_label(rule->label);
174 : 0 : kfree(rule);
175 : : }
176 : 0 : }
177 : :
178 : 0 : int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
179 : : {
180 : : struct aa_audit_rule *rule;
181 : :
182 [ # # ]: 0 : switch (field) {
183 : : case AUDIT_SUBJ_ROLE:
184 [ # # ]: 0 : if (op != Audit_equal && op != Audit_not_equal)
185 : : return -EINVAL;
186 : : break;
187 : : default:
188 : : return -EINVAL;
189 : : }
190 : :
191 : 0 : rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL);
192 : :
193 [ # # ]: 0 : if (!rule)
194 : : return -ENOMEM;
195 : :
196 : : /* Currently rules are treated as coming from the root ns */
197 : 0 : rule->label = aa_label_parse(&root_ns->unconfined->label, rulestr,
198 : : GFP_KERNEL, true, false);
199 [ # # ]: 0 : if (IS_ERR(rule->label)) {
200 : : int err = PTR_ERR(rule->label);
201 : 0 : aa_audit_rule_free(rule);
202 : 0 : return err;
203 : : }
204 : :
205 : 0 : *vrule = rule;
206 : 0 : return 0;
207 : : }
208 : :
209 : 0 : int aa_audit_rule_known(struct audit_krule *rule)
210 : : {
211 : : int i;
212 : :
213 [ # # ]: 0 : for (i = 0; i < rule->field_count; i++) {
214 : 0 : struct audit_field *f = &rule->fields[i];
215 : :
216 [ # # ]: 0 : switch (f->type) {
217 : : case AUDIT_SUBJ_ROLE:
218 : : return 1;
219 : : }
220 : : }
221 : :
222 : : return 0;
223 : : }
224 : :
225 : 0 : int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
226 : : {
227 : : struct aa_audit_rule *rule = vrule;
228 : : struct aa_label *label;
229 : : int found = 0;
230 : :
231 : 0 : label = aa_secid_to_label(sid);
232 : :
233 [ # # ]: 0 : if (!label)
234 : : return -ENOENT;
235 : :
236 [ # # ]: 0 : if (aa_label_is_subset(label, rule->label))
237 : : found = 1;
238 : :
239 [ # # ]: 0 : switch (field) {
240 : : case AUDIT_SUBJ_ROLE:
241 [ # # # ]: 0 : switch (op) {
242 : : case Audit_equal:
243 : 0 : return found;
244 : : case Audit_not_equal:
245 : 0 : return !found;
246 : : }
247 : : }
248 : : return 0;
249 : : }
|