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 | |||
