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