Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: Add support for audit rule filtering

This patch adds support to Apparmor for integrating with audit rule
filtering. Right now it only handles SUBJ_ROLE, interpreting it as a
single component of a label. This is sufficient to get Apparmor working
with IMA's appraisal rules without any modifications on the IMA side.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>

authored by

Matthew Garrett and committed by
John Johansen
e79c26d0 b896c54e

+107 -1
+94 -1
security/apparmor/audit.c
··· 19 19 #include "include/audit.h" 20 20 #include "include/policy.h" 21 21 #include "include/policy_ns.h" 22 - 22 + #include "include/secid.h" 23 23 24 24 const char *const audit_mode_names[] = { 25 25 "normal", ··· 162 162 return complain_error(aad(sa)->error); 163 163 164 164 return aad(sa)->error; 165 + } 166 + 167 + struct aa_audit_rule { 168 + char *profile; 169 + }; 170 + 171 + void aa_audit_rule_free(void *vrule) 172 + { 173 + struct aa_audit_rule *rule = vrule; 174 + 175 + if (rule) { 176 + kfree(rule->profile); 177 + kfree(rule); 178 + } 179 + } 180 + 181 + int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) 182 + { 183 + struct aa_audit_rule *rule; 184 + 185 + switch (field) { 186 + case AUDIT_SUBJ_ROLE: 187 + if (op != Audit_equal && op != Audit_not_equal) 188 + return -EINVAL; 189 + break; 190 + default: 191 + return -EINVAL; 192 + } 193 + 194 + rule = kzalloc(sizeof(struct aa_audit_rule), GFP_KERNEL); 195 + 196 + if (!rule) 197 + return -ENOMEM; 198 + 199 + rule->profile = kstrdup(rulestr, GFP_KERNEL); 200 + 201 + if (!rule->profile) { 202 + kfree(rule); 203 + return -ENOMEM; 204 + } 205 + 206 + *vrule = rule; 207 + 208 + return 0; 209 + } 210 + 211 + int aa_audit_rule_known(struct audit_krule *rule) 212 + { 213 + int i; 214 + 215 + for (i = 0; i < rule->field_count; i++) { 216 + struct audit_field *f = &rule->fields[i]; 217 + 218 + switch (f->type) { 219 + case AUDIT_SUBJ_ROLE: 220 + return 1; 221 + } 222 + } 223 + 224 + return 0; 225 + } 226 + 227 + int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, 228 + struct audit_context *actx) 229 + { 230 + struct aa_audit_rule *rule = vrule; 231 + struct aa_label *label; 232 + struct label_it i; 233 + struct aa_profile *profile; 234 + int found = 0; 235 + 236 + label = aa_secid_to_label(sid); 237 + 238 + if (!label) 239 + return -ENOENT; 240 + 241 + label_for_each(i, label, profile) { 242 + if (strcmp(rule->profile, profile->base.hname) == 0) { 243 + found = 1; 244 + break; 245 + } 246 + } 247 + 248 + switch (field) { 249 + case AUDIT_SUBJ_ROLE: 250 + switch (op) { 251 + case Audit_equal: 252 + return found; 253 + case Audit_not_equal: 254 + return !found; 255 + } 256 + } 257 + return 0; 165 258 }
+6
security/apparmor/include/audit.h
··· 189 189 return error; 190 190 } 191 191 192 + void aa_audit_rule_free(void *vrule); 193 + int aa_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule); 194 + int aa_audit_rule_known(struct audit_krule *rule); 195 + int aa_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, 196 + struct audit_context *actx); 197 + 192 198 #endif /* __AA_AUDIT_H */
+7
security/apparmor/lsm.c
··· 1198 1198 LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), 1199 1199 LSM_HOOK_INIT(task_kill, apparmor_task_kill), 1200 1200 1201 + #ifdef CONFIG_AUDIT 1202 + LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init), 1203 + LSM_HOOK_INIT(audit_rule_known, aa_audit_rule_known), 1204 + LSM_HOOK_INIT(audit_rule_match, aa_audit_rule_match), 1205 + LSM_HOOK_INIT(audit_rule_free, aa_audit_rule_free), 1206 + #endif 1207 + 1201 1208 LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), 1202 1209 LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid), 1203 1210 LSM_HOOK_INIT(release_secctx, apparmor_release_secctx),