diff options
| author | Thomas Liu <tliu@redhat.com> | 2009-07-14 12:14:09 -0400 |
|---|---|---|
| committer | James Morris <jmorris@namei.org> | 2009-08-16 18:37:18 -0400 |
| commit | 2bf49690325b62480a42f7afed5e9f164173c570 (patch) | |
| tree | bc8525f6a45ea3ffaed9449084df7644bcd4e3c2 | |
| parent | f322abf83feddc3c37c3a91794e0c5aece4af18e (diff) | |
SELinux: Convert avc_audit to use lsm_audit.h
Convert avc_audit in security/selinux/avc.c to use lsm_audit.h,
for better maintainability.
- changed selinux to use common_audit_data instead of
avc_audit_data
- eliminated code in avc.c and used code from lsm_audit.h instead.
Had to add a LSM_AUDIT_NO_AUDIT to lsm_audit.h so that avc_audit
can call common_lsm_audit and do the pre and post callbacks without
doing the actual dump. This makes it so that the patched version
behaves the same way as the unpatched version.
Also added a denied field to the selinux_audit_data private space,
once again to make it so that the patched version behaves like the
unpatched.
I've tested and confirmed that AVCs look the same before and after
this patch.
Signed-off-by: Thomas Liu <tliu@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
| -rw-r--r-- | include/linux/lsm_audit.h | 2 | ||||
| -rw-r--r-- | security/Makefile | 4 | ||||
| -rw-r--r-- | security/lsm_audit.c | 2 | ||||
| -rw-r--r-- | security/selinux/avc.c | 197 | ||||
| -rw-r--r-- | security/selinux/hooks.c | 142 | ||||
| -rw-r--r-- | security/selinux/include/avc.h | 49 | ||||
| -rw-r--r-- | security/selinux/include/netlabel.h | 4 | ||||
| -rw-r--r-- | security/selinux/include/xfrm.h | 8 | ||||
| -rw-r--r-- | security/selinux/netlabel.c | 2 | ||||
| -rw-r--r-- | security/selinux/xfrm.c | 4 |
10 files changed, 131 insertions, 283 deletions
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h index a5514a3a4f17..190c37854870 100644 --- a/include/linux/lsm_audit.h +++ b/include/linux/lsm_audit.h | |||
| @@ -33,6 +33,7 @@ struct common_audit_data { | |||
| 33 | #define LSM_AUDIT_DATA_IPC 4 | 33 | #define LSM_AUDIT_DATA_IPC 4 |
| 34 | #define LSM_AUDIT_DATA_TASK 5 | 34 | #define LSM_AUDIT_DATA_TASK 5 |
| 35 | #define LSM_AUDIT_DATA_KEY 6 | 35 | #define LSM_AUDIT_DATA_KEY 6 |
| 36 | #define LSM_AUDIT_NO_AUDIT 7 | ||
| 36 | struct task_struct *tsk; | 37 | struct task_struct *tsk; |
| 37 | union { | 38 | union { |
| 38 | struct { | 39 | struct { |
| @@ -86,6 +87,7 @@ struct common_audit_data { | |||
| 86 | u16 tclass; | 87 | u16 tclass; |
| 87 | u32 requested; | 88 | u32 requested; |
| 88 | u32 audited; | 89 | u32 audited; |
| 90 | u32 denied; | ||
| 89 | struct av_decision *avd; | 91 | struct av_decision *avd; |
| 90 | int result; | 92 | int result; |
| 91 | } selinux_audit_data; | 93 | } selinux_audit_data; |
diff --git a/security/Makefile b/security/Makefile index b56e7f9ecbc2..95ecc06392d7 100644 --- a/security/Makefile +++ b/security/Makefile | |||
| @@ -16,9 +16,7 @@ obj-$(CONFIG_SECURITYFS) += inode.o | |||
| 16 | # Must precede capability.o in order to stack properly. | 16 | # Must precede capability.o in order to stack properly. |
| 17 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o | 17 | obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o |
| 18 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o | 18 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o |
| 19 | ifeq ($(CONFIG_AUDIT),y) | 19 | obj-$(CONFIG_AUDIT) += lsm_audit.o |
| 20 | obj-$(CONFIG_SECURITY_SMACK) += lsm_audit.o | ||
| 21 | endif | ||
| 22 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o | 20 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o |
| 23 | obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o | 21 | obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o |
| 24 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o | 22 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 94b868494b31..500aad0ebd6a 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
| @@ -220,6 +220,8 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | switch (a->type) { | 222 | switch (a->type) { |
| 223 | case LSM_AUDIT_NO_AUDIT: | ||
| 224 | return; | ||
| 223 | case LSM_AUDIT_DATA_IPC: | 225 | case LSM_AUDIT_DATA_IPC: |
| 224 | audit_log_format(ab, " key=%d ", a->u.ipc_id); | 226 | audit_log_format(ab, " key=%d ", a->u.ipc_id); |
| 225 | break; | 227 | break; |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index 236aaa2ea86d..e3d19014259b 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
| @@ -492,23 +492,35 @@ out: | |||
| 492 | return node; | 492 | return node; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, | 495 | /** |
| 496 | struct in6_addr *addr, __be16 port, | 496 | * avc_audit_pre_callback - SELinux specific information |
| 497 | char *name1, char *name2) | 497 | * will be called by generic audit code |
| 498 | * @ab: the audit buffer | ||
| 499 | * @a: audit_data | ||
| 500 | */ | ||
| 501 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
| 498 | { | 502 | { |
| 499 | if (!ipv6_addr_any(addr)) | 503 | struct common_audit_data *ad = a; |
| 500 | audit_log_format(ab, " %s=%pI6", name1, addr); | 504 | audit_log_format(ab, "avc: %s ", |
| 501 | if (port) | 505 | ad->selinux_audit_data.denied ? "denied" : "granted"); |
| 502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 506 | avc_dump_av(ab, ad->selinux_audit_data.tclass, |
| 507 | ad->selinux_audit_data.audited); | ||
| 508 | audit_log_format(ab, " for "); | ||
| 503 | } | 509 | } |
| 504 | 510 | ||
| 505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | 511 | /** |
| 506 | __be16 port, char *name1, char *name2) | 512 | * avc_audit_post_callback - SELinux specific information |
| 513 | * will be called by generic audit code | ||
| 514 | * @ab: the audit buffer | ||
| 515 | * @a: audit_data | ||
| 516 | */ | ||
| 517 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
| 507 | { | 518 | { |
| 508 | if (addr) | 519 | struct common_audit_data *ad = a; |
| 509 | audit_log_format(ab, " %s=%pI4", name1, &addr); | 520 | audit_log_format(ab, " "); |
| 510 | if (port) | 521 | avc_dump_query(ab, ad->selinux_audit_data.ssid, |
| 511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); | 522 | ad->selinux_audit_data.tsid, |
| 523 | ad->selinux_audit_data.tclass); | ||
| 512 | } | 524 | } |
| 513 | 525 | ||
| 514 | /** | 526 | /** |
| @@ -532,13 +544,10 @@ static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, | |||
| 532 | */ | 544 | */ |
| 533 | void avc_audit(u32 ssid, u32 tsid, | 545 | void avc_audit(u32 ssid, u32 tsid, |
| 534 | u16 tclass, u32 requested, | 546 | u16 tclass, u32 requested, |
| 535 | struct av_decision *avd, int result, struct avc_audit_data *a) | 547 | struct av_decision *avd, int result, struct common_audit_data *a) |
| 536 | { | 548 | { |
| 537 | struct task_struct *tsk = current; | 549 | struct common_audit_data stack_data; |
| 538 | struct inode *inode = NULL; | ||
| 539 | u32 denied, audited; | 550 | u32 denied, audited; |
| 540 | struct audit_buffer *ab; | ||
| 541 | |||
| 542 | denied = requested & ~avd->allowed; | 551 | denied = requested & ~avd->allowed; |
| 543 | if (denied) { | 552 | if (denied) { |
| 544 | audited = denied; | 553 | audited = denied; |
| @@ -551,144 +560,20 @@ void avc_audit(u32 ssid, u32 tsid, | |||
| 551 | if (!(audited & avd->auditallow)) | 560 | if (!(audited & avd->auditallow)) |
| 552 | return; | 561 | return; |
| 553 | } | 562 | } |
| 554 | 563 | if (!a) { | |
| 555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 564 | a = &stack_data; |
| 556 | if (!ab) | 565 | memset(a, 0, sizeof(*a)); |
| 557 | return; /* audit_panic has been called */ | 566 | a->type = LSM_AUDIT_NO_AUDIT; |
| 558 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
| 559 | avc_dump_av(ab, tclass, audited); | ||
| 560 | audit_log_format(ab, " for "); | ||
| 561 | if (a && a->tsk) | ||
| 562 | tsk = a->tsk; | ||
| 563 | if (tsk && tsk->pid) { | ||
| 564 | audit_log_format(ab, " pid=%d comm=", tsk->pid); | ||
| 565 | audit_log_untrustedstring(ab, tsk->comm); | ||
| 566 | } | ||
| 567 | if (a) { | ||
| 568 | switch (a->type) { | ||
| 569 | case AVC_AUDIT_DATA_IPC: | ||
| 570 | audit_log_format(ab, " key=%d", a->u.ipc_id); | ||
| 571 | break; | ||
| 572 | case AVC_AUDIT_DATA_CAP: | ||
| 573 | audit_log_format(ab, " capability=%d", a->u.cap); | ||
| 574 | break; | ||
| 575 | case AVC_AUDIT_DATA_FS: | ||
| 576 | if (a->u.fs.path.dentry) { | ||
| 577 | struct dentry *dentry = a->u.fs.path.dentry; | ||
| 578 | if (a->u.fs.path.mnt) { | ||
| 579 | audit_log_d_path(ab, "path=", | ||
| 580 | &a->u.fs.path); | ||
| 581 | } else { | ||
| 582 | audit_log_format(ab, " name="); | ||
| 583 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
| 584 | } | ||
| 585 | inode = dentry->d_inode; | ||
| 586 | } else if (a->u.fs.inode) { | ||
| 587 | struct dentry *dentry; | ||
| 588 | inode = a->u.fs.inode; | ||
| 589 | dentry = d_find_alias(inode); | ||
| 590 | if (dentry) { | ||
| 591 | audit_log_format(ab, " name="); | ||
| 592 | audit_log_untrustedstring(ab, dentry->d_name.name); | ||
| 593 | dput(dentry); | ||
| 594 | } | ||
| 595 | } | ||
| 596 | if (inode) | ||
| 597 | audit_log_format(ab, " dev=%s ino=%lu", | ||
| 598 | inode->i_sb->s_id, | ||
| 599 | inode->i_ino); | ||
| 600 | break; | ||
