diff options
-rw-r--r-- | include/linux/audit.h | 4 | ||||
-rw-r--r-- | kernel/auditfilter.c | 40 | ||||
-rw-r--r-- | kernel/auditsc.c | 12 | ||||
-rw-r--r-- | security/selinux/include/audit.h | 65 |
4 files changed, 93 insertions, 28 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index 04869c96016b..4ccb048cae1d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -377,8 +377,8 @@ struct audit_field { | |||
377 | u32 type; | 377 | u32 type; |
378 | u32 val; | 378 | u32 val; |
379 | u32 op; | 379 | u32 op; |
380 | char *se_str; | 380 | char *lsm_str; |
381 | void *se_rule; | 381 | void *lsm_rule; |
382 | }; | 382 | }; |
383 | 383 | ||
384 | #define AUDITSC_INVALID 0 | 384 | #define AUDITSC_INVALID 0 |
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c index 7c69cb5e44fb..28fef6bf8534 100644 --- a/kernel/auditfilter.c +++ b/kernel/auditfilter.c | |||
@@ -139,8 +139,8 @@ static inline void audit_free_rule(struct audit_entry *e) | |||
139 | if (e->rule.fields) | 139 | if (e->rule.fields) |
140 | for (i = 0; i < e->rule.field_count; i++) { | 140 | for (i = 0; i < e->rule.field_count; i++) { |
141 | struct audit_field *f = &e->rule.fields[i]; | 141 | struct audit_field *f = &e->rule.fields[i]; |
142 | kfree(f->se_str); | 142 | kfree(f->lsm_str); |
143 | security_audit_rule_free(f->se_rule); | 143 | security_audit_rule_free(f->lsm_rule); |
144 | } | 144 | } |
145 | kfree(e->rule.fields); | 145 | kfree(e->rule.fields); |
146 | kfree(e->rule.filterkey); | 146 | kfree(e->rule.filterkey); |
@@ -554,8 +554,8 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
554 | f->op = data->fieldflags[i] & AUDIT_OPERATORS; | 554 | f->op = data->fieldflags[i] & AUDIT_OPERATORS; |
555 | f->type = data->fields[i]; | 555 | f->type = data->fields[i]; |
556 | f->val = data->values[i]; | 556 | f->val = data->values[i]; |
557 | f->se_str = NULL; | 557 | f->lsm_str = NULL; |
558 | f->se_rule = NULL; | 558 | f->lsm_rule = NULL; |
559 | switch(f->type) { | 559 | switch(f->type) { |
560 | case AUDIT_PID: | 560 | case AUDIT_PID: |
561 | case AUDIT_UID: | 561 | case AUDIT_UID: |
@@ -598,7 +598,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
598 | entry->rule.buflen += f->val; | 598 | entry->rule.buflen += f->val; |
599 | 599 | ||
600 | err = security_audit_rule_init(f->type, f->op, str, | 600 | err = security_audit_rule_init(f->type, f->op, str, |
601 | (void **)&f->se_rule); | 601 | (void **)&f->lsm_rule); |
602 | /* Keep currently invalid fields around in case they | 602 | /* Keep currently invalid fields around in case they |
603 | * become valid after a policy reload. */ | 603 | * become valid after a policy reload. */ |
604 | if (err == -EINVAL) { | 604 | if (err == -EINVAL) { |
@@ -610,7 +610,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, | |||
610 | kfree(str); | 610 | kfree(str); |
611 | goto exit_free; | 611 | goto exit_free; |
612 | } else | 612 | } else |
613 | f->se_str = str; | 613 | f->lsm_str = str; |
614 | break; | 614 | break; |
615 | case AUDIT_WATCH: | 615 | case AUDIT_WATCH: |
616 | str = audit_unpack_string(&bufp, &remain, f->val); | 616 | str = audit_unpack_string(&bufp, &remain, f->val); |
@@ -754,7 +754,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) | |||
754 | case AUDIT_OBJ_LEV_LOW: | 754 | case AUDIT_OBJ_LEV_LOW: |
755 | case AUDIT_OBJ_LEV_HIGH: | 755 | case AUDIT_OBJ_LEV_HIGH: |
756 | data->buflen += data->values[i] = | 756 | data->buflen += data->values[i] = |
757 | audit_pack_string(&bufp, f->se_str); | 757 | audit_pack_string(&bufp, f->lsm_str); |
758 | break; | 758 | break; |
759 | case AUDIT_WATCH: | 759 | case AUDIT_WATCH: |
760 | data->buflen += data->values[i] = | 760 | data->buflen += data->values[i] = |
@@ -806,7 +806,7 @@ static int audit_compare_rule(struct audit_krule *a, struct audit_krule *b) | |||
806 | case AUDIT_OBJ_TYPE: | 806 | case AUDIT_OBJ_TYPE: |
807 | case AUDIT_OBJ_LEV_LOW: | 807 | case AUDIT_OBJ_LEV_LOW: |
808 | case AUDIT_OBJ_LEV_HIGH: | 808 | case AUDIT_OBJ_LEV_HIGH: |
809 | if (strcmp(a->fields[i].se_str, b->fields[i].se_str)) | 809 | if (strcmp(a->fields[i].lsm_str, b->fields[i].lsm_str)) |
810 | return 1; | 810 | return 1; |
811 | break; | 811 | break; |
812 | case AUDIT_WATCH: | 812 | case AUDIT_WATCH: |
@@ -862,28 +862,28 @@ out: | |||
862 | return new; | 862 | return new; |
863 | } | 863 | } |
864 | 864 | ||
865 | /* Duplicate LSM field information. The se_rule is opaque, so must be | 865 | /* Duplicate LSM field information. The lsm_rule is opaque, so must be |
866 | * re-initialized. */ | 866 | * re-initialized. */ |
867 | static inline int audit_dupe_lsm_field(struct audit_field *df, | 867 | static inline int audit_dupe_lsm_field(struct audit_field *df, |
868 | struct audit_field *sf) | 868 | struct audit_field *sf) |
869 | { | 869 | { |
870 | int ret = 0; | 870 | int ret = 0; |
871 | char *se_str; | 871 | char *lsm_str; |
872 | 872 | ||
873 | /* our own copy of se_str */ | 873 | /* our own copy of lsm_str */ |
874 | se_str = kstrdup(sf->se_str, GFP_KERNEL); | 874 | lsm_str = kstrdup(sf->lsm_str, GFP_KERNEL); |
875 | if (unlikely(!se_str)) | 875 | if (unlikely(!lsm_str)) |
876 | return -ENOMEM; | 876 | return -ENOMEM; |
877 | df->se_str = se_str; | 877 | df->lsm_str = lsm_str; |
878 | 878 | ||
879 | /* our own (refreshed) copy of se_rule */ | 879 | /* our own (refreshed) copy of lsm_rule */ |
880 | ret = security_audit_rule_init(df->type, df->op, df->se_str, | 880 | ret = security_audit_rule_init(df->type, df->op, df->lsm_str, |
881 | (void **)&df->se_rule); | 881 | (void **)&df->lsm_rule); |
882 | /* Keep currently invalid fields around in case they | 882 | /* Keep currently invalid fields around in case they |
883 | * become valid after a policy reload. */ | 883 | * become valid after a policy reload. */ |
884 | if (ret == -EINVAL) { | 884 | if (ret == -EINVAL) { |
885 | printk(KERN_WARNING "audit rule for LSM \'%s\' is " | 885 | printk(KERN_WARNING "audit rule for LSM \'%s\' is " |
886 | "invalid\n", df->se_str); | 886 | "invalid\n", df->lsm_str); |
887 | ret = 0; | 887 | ret = 0; |
888 | } | 888 | } |
889 | 889 | ||
@@ -930,7 +930,7 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, | |||
930 | new->tree = old->tree; | 930 | new->tree = old->tree; |
931 | memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount); | 931 | memcpy(new->fields, old->fields, sizeof(struct audit_field) * fcount); |
932 | 932 | ||
933 | /* deep copy this information, updating the se_rule fields, because | 933 | /* deep copy this information, updating the lsm_rule fields, because |
934 | * the originals will all be freed when the old rule is freed. */ | 934 | * the originals will all be freed when the old rule is freed. */ |
935 | for (i = 0; i < fcount; i++) { | 935 | for (i = 0; i < fcount; i++) { |
936 | switch (new->fields[i].type) { | 936 | switch (new->fields[i].type) { |
@@ -1762,7 +1762,7 @@ unlock_and_return: | |||
1762 | return result; | 1762 | return result; |
1763 | } | 1763 | } |
1764 | 1764 | ||
1765 | /* This function will re-initialize the se_rule field of all applicable rules. | 1765 | /* This function will re-initialize the lsm_rule field of all applicable rules. |
1766 | * It will traverse the filter lists serarching for rules that contain LSM | 1766 | * It will traverse the filter lists serarching for rules that contain LSM |
1767 | * specific filter fields. When such a rule is found, it is copied, the | 1767 | * specific filter fields. When such a rule is found, it is copied, the |
1768 | * LSM field is re-initialized, and the old rule is replaced with the | 1768 | * LSM field is re-initialized, and the old rule is replaced with the |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index c0700535e5c5..56e56ed594a8 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -527,14 +527,14 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
527 | match for now to avoid losing information that | 527 | match for now to avoid losing information that |
528 | may be wanted. An error message will also be | 528 | may be wanted. An error message will also be |
529 | logged upon error */ | 529 | logged upon error */ |
530 | if (f->se_rule) { | 530 | if (f->lsm_rule) { |
531 | if (need_sid) { | 531 | if (need_sid) { |
532 | security_task_getsecid(tsk, &sid); | 532 | security_task_getsecid(tsk, &sid); |
533 | need_sid = 0; | 533 | need_sid = 0; |
534 | } | 534 | } |
535 | result = security_audit_rule_match(sid, f->type, | 535 | result = security_audit_rule_match(sid, f->type, |
536 | f->op, | 536 | f->op, |
537 | f->se_rule, | 537 | f->lsm_rule, |
538 | ctx); | 538 | ctx); |
539 | } | 539 | } |
540 | break; | 540 | break; |
@@ -545,18 +545,18 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
545 | case AUDIT_OBJ_LEV_HIGH: | 545 | case AUDIT_OBJ_LEV_HIGH: |
546 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR | 546 | /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR |
547 | also applies here */ | 547 | also applies here */ |
548 | if (f->se_rule) { | 548 | if (f->lsm_rule) { |
549 | /* Find files that match */ | 549 | /* Find files that match */ |
550 | if (name) { | 550 | if (name) { |
551 | result = security_audit_rule_match( | 551 | result = security_audit_rule_match( |
552 | name->osid, f->type, f->op, | 552 | name->osid, f->type, f->op, |
553 | f->se_rule, ctx); | 553 | f->lsm_rule, ctx); |
554 | } else if (ctx) { | 554 | } else if (ctx) { |
555 | for (j = 0; j < ctx->name_count; j++) { | 555 | for (j = 0; j < ctx->name_count; j++) { |
556 | if (security_audit_rule_match( | 556 | if (security_audit_rule_match( |
557 | ctx->names[j].osid, | 557 | ctx->names[j].osid, |
558 | f->type, f->op, | 558 | f->type, f->op, |
559 | f->se_rule, ctx)) { | 559 | f->lsm_rule, ctx)) { |
560 | ++result; | 560 | ++result; |
561 | break; | 561 | break; |
562 | } | 562 | } |
@@ -569,7 +569,7 @@ static int audit_filter_rules(struct task_struct *tsk, | |||
569 | aux = aux->next) { | 569 | aux = aux->next) { |
570 | if (aux->type == AUDIT_IPC) { | 570 | if (aux->type == AUDIT_IPC) { |
571 | struct audit_aux_data_ipcctl *axi = (void *)aux; | 571 | struct audit_aux_data_ipcctl *axi = (void *)aux; |
572 | if (security_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) { | 572 | if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) { |
573 | ++result; | 573 | ++result; |
574 | break; | 574 | break; |
575 | } | 575 | } |
diff --git a/security/selinux/include/audit.h b/security/selinux/include/audit.h new file mode 100644 index 000000000000..6c8b9ef15579 --- /dev/null +++ b/security/selinux/include/audit.h | |||
@@ -0,0 +1,65 @@ | |||
1 | /* | ||
2 | * SELinux support for the Audit LSM hooks | ||
3 | * | ||
4 | * Most of below header was moved from include/linux/selinux.h which | ||
5 | * is released under below copyrights: | ||
6 | * | ||
7 | * Author: James Morris <jmorris@redhat.com> | ||
8 | * | ||
9 | * Copyright (C) 2005 Red Hat, Inc., James Morris <jmorris@redhat.com> | ||
10 | * Copyright (C) 2006 Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> | ||
11 | * Copyright (C) 2006 IBM Corporation, Timothy R. Chavez <tinytim@us.ibm.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify | ||
14 | * it under the terms of the GNU General Public License version 2, | ||
15 | * as published by the Free Software Foundation. | ||
16 | */ | ||
17 | |||
18 | #ifndef _SELINUX_AUDIT_H | ||
19 | #define _SELINUX_AUDIT_H | ||
20 | |||
21 | /** | ||
22 | * selinux_audit_rule_init - alloc/init an selinux audit rule structure. | ||
23 | * @field: the field this rule refers to | ||
24 | * @op: the operater the rule uses | ||
25 | * @rulestr: the text "target" of the rule | ||
26 | * @rule: pointer to the new rule structure returned via this | ||
27 | * | ||
28 | * Returns 0 if successful, -errno if not. On success, the rule structure | ||
29 | * will be allocated internally. The caller must free this structure with | ||
30 | * selinux_audit_rule_free() after use. | ||
31 | */ | ||
32 | int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **rule); | ||
33 | |||
34 | /** | ||
35 | * selinux_audit_rule_free - free an selinux audit rule structure. | ||
36 | * @rule: pointer to the audit rule to be freed | ||
37 | * | ||
38 | * This will free all memory associated with the given rule. | ||
39 | * If @rule is NULL, no operation is performed. | ||
40 | */ | ||
41 | void selinux_audit_rule_free(void *rule); | ||
42 | |||
43 | /** | ||
44 | * selinux_audit_rule_match - determine if a context ID matches a rule. | ||
45 | * @sid: the context ID to check | ||
46 | * @field: the field this rule refers to | ||
47 | * @op: the operater the rule uses | ||
48 | * @rule: pointer to the audit rule to check against | ||
49 | * @actx: the audit context (can be NULL) associated with the check | ||
50 | * | ||
51 | * Returns 1 if the context id matches the rule, 0 if it does not, and | ||
52 | * -errno on failure. | ||
53 | */ | ||
54 | int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule, | ||
55 | struct audit_context *actx); | ||
56 | |||
57 | /** | ||
58 | * selinux_audit_rule_known - check to see if rule contains selinux fields. | ||
59 | * @rule: rule to be checked | ||
60 | * Returns 1 if there are selinux fields specified in the rule, 0 otherwise. | ||
61 | */ | ||
62 | int selinux_audit_rule_known(struct audit_krule *krule); | ||
63 | |||
64 | #endif /* _SELINUX_AUDIT_H */ | ||
65 | |||