diff options
author | James Morris <jmorris@namei.org> | 2009-07-12 20:39:36 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-07-12 20:39:36 -0400 |
commit | be940d6279c30a2d7c4e8d1d5435f957f594d66d (patch) | |
tree | 965805d563cb756879fd3595230c3ca205da76d1 /security/selinux/avc.c | |
parent | b3a633c8527ef155b1a4e22e8f5abc58f7af54c9 (diff) |
Revert "SELinux: Convert avc_audit to use lsm_audit.h"
This reverts commit 8113a8d80f4c6a3dc3724b39b470f3fee9c426b6.
The patch causes a stack overflow on my system during boot.
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/selinux/avc.c')
-rw-r--r-- | security/selinux/avc.c | 218 |
1 files changed, 170 insertions, 48 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index d9fd22488ef8..236aaa2ea86d 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -492,50 +492,23 @@ out: | |||
492 | return node; | 492 | return node; |
493 | } | 493 | } |
494 | 494 | ||
495 | /** | 495 | static inline void avc_print_ipv6_addr(struct audit_buffer *ab, |
496 | * avc_audit_pre_callback - SELinux specific information | 496 | struct in6_addr *addr, __be16 port, |
497 | * will be called by generic audit code | 497 | char *name1, char *name2) |
498 | * @ab: the audit buffer | ||
499 | * @a: audit_data | ||
500 | */ | ||
501 | static void avc_audit_pre_callback(struct audit_buffer *ab, void *a) | ||
502 | { | 498 | { |
503 | struct common_audit_data *ad = a; | 499 | if (!ipv6_addr_any(addr)) |
504 | struct av_decision *avd = ad->selinux_audit_data.avd; | 500 | audit_log_format(ab, " %s=%pI6", name1, addr); |
505 | u32 requested = ad->selinux_audit_data.requested; | 501 | if (port) |
506 | int result = ad->selinux_audit_data.result; | 502 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
507 | u32 denied, audited; | ||
508 | denied = requested & ~avd->allowed; | ||
509 | if (denied) { | ||
510 | audited = denied; | ||
511 | if (!(audited & avd->auditdeny)) | ||
512 | return; | ||
513 | } else if (result) { | ||
514 | audited = denied = requested; | ||
515 | } else { | ||
516 | audited = requested; | ||
517 | if (!(audited & avd->auditallow)) | ||
518 | return; | ||
519 | } | ||
520 | audit_log_format(ab, "avc: %s ", denied ? "denied" : "granted"); | ||
521 | avc_dump_av(ab, ad->selinux_audit_data.tclass, | ||
522 | ad->selinux_audit_data.audited); | ||
523 | audit_log_format(ab, " for "); | ||
524 | } | 503 | } |
525 | 504 | ||
526 | /** | 505 | static inline void avc_print_ipv4_addr(struct audit_buffer *ab, __be32 addr, |
527 | * avc_audit_post_callback - SELinux specific information | 506 | __be16 port, char *name1, char *name2) |
528 | * will be called by generic audit code | ||
529 | * @ab: the audit buffer | ||
530 | * @a: audit_data | ||
531 | */ | ||
532 | static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | ||
533 | { | 507 | { |
534 | struct common_audit_data *ad = a; | 508 | if (addr) |
535 | audit_log_format(ab, " "); | 509 | audit_log_format(ab, " %s=%pI4", name1, &addr); |
536 | avc_dump_query(ab, ad->selinux_audit_data.ssid, | 510 | if (port) |
537 | ad->selinux_audit_data.tsid, | 511 | audit_log_format(ab, " %s=%d", name2, ntohs(port)); |
538 | ad->selinux_audit_data.tclass); | ||
539 | } | 512 | } |
540 | 513 | ||
541 | /** | 514 | /** |
@@ -559,14 +532,163 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a) | |||
559 | */ | 532 | */ |
560 | void avc_audit(u32 ssid, u32 tsid, | 533 | void avc_audit(u32 ssid, u32 tsid, |
561 | u16 tclass, u32 requested, | 534 | u16 tclass, u32 requested, |
562 | struct av_decision *avd, int result, struct common_audit_data *a) | 535 | struct av_decision *avd, int result, struct avc_audit_data *a) |
563 | { | 536 | { |
564 | a->selinux_audit_data.avd = avd; | 537 | struct task_struct *tsk = current; |
565 | a->selinux_audit_data.tclass = tclass; | 538 | struct inode *inode = NULL; |
566 | a->selinux_audit_data.requested = requested; | 539 | u32 denied, audited; |
567 | a->lsm_pre_audit = avc_audit_pre_callback; | 540 | struct audit_buffer *ab; |
568 | a->lsm_post_audit = avc_audit_post_callback; | 541 | |
569 | common_lsm_audit(a); | 542 | denied = requested & ~avd->allowed; |
543 | if (denied) { | ||
544 | audited = denied; | ||
545 | if (!(audited & avd->auditdeny)) | ||
546 | return; | ||
547 | } else if (result) { | ||
548 | audited = denied = requested; | ||
549 | } else { | ||
550 | audited = requested; | ||
551 | if (!(audited & avd->auditallow)) | ||
552 | return; | ||
553 | } | ||
554 | |||
555 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | ||
556 | if (!ab) | ||
557 | return; /* audit_panic has been called */ | ||
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; | ||
601 | case AVC_AUDIT_DATA_NET: | ||
602 | if (a->u.net.sk) { | ||
603 | struct sock *sk = a->u.net.sk; | ||
604 | struct unix_sock *u; | ||
605 | int len = 0; | ||
606 | char *p = NULL; | ||
607 | |||
608 | switch (sk->sk_family) { | ||
609 | case AF_INET: { | ||
610 | struct inet_sock *inet = inet_sk(sk); | ||
611 | |||
612 | avc_print_ipv4_addr(ab, inet->rcv_saddr, | ||
613 | inet->sport, | ||
614 | "laddr", "lport"); | ||
615 | avc_print_ipv4_addr(ab, inet->daddr, | ||
616 | inet->dport, | ||
617 | "faddr", "fport"); | ||
618 | break; | ||
619 | } | ||
620 | case AF_INET6: { | ||
621 | struct inet_sock *inet = inet_sk(sk); | ||
622 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
623 | |||
624 | avc_print_ipv6_addr(ab, &inet6->rcv_saddr, | ||
625 | inet->sport, | ||
626 | "laddr", "lport"); | ||
627 | avc_print_ipv6_addr(ab, &inet6->daddr, | ||
628 | inet->dport, | ||
629 | "faddr", "fport"); | ||
630 | break; | ||
631 | } | ||
632 | case AF_UNIX: | ||
633 | u = unix_sk(sk); | ||
634 | if (u->dentry) { | ||
635 | struct path path = { | ||
636 | .dentry = u->dentry, | ||
637 | .mnt = u->mnt | ||
638 | }; | ||
639 | audit_log_d_path(ab, "path=", | ||
640 | &path); | ||
641 | break; | ||
642 | } | ||
643 | if (!u->addr) | ||
644 | break; | ||
645 | len = u->addr->len-sizeof(short); | ||
646 | p = &u->addr->name->sun_path[0]; | ||
647 | audit_log_format(ab, " path="); | ||
648 | if (*p) | ||
649 | audit_log_untrustedstring(ab, p); | ||
650 | else | ||
651 | audit_log_n_hex(ab, p, len); | ||
652 | break; | ||
653 | } | ||
654 | } | ||
655 | |||
656 | switch (a->u.net.family) { | ||
657 | case AF_INET: | ||
658 | avc_print_ipv4_addr(ab, a->u.net.v4info.saddr, | ||
659 | a->u.net.sport, | ||
660 | "saddr", "src"); | ||
661 | avc_print_ipv4_addr(ab, a->u.net.v4info.daddr, | ||
662 | a->u.net.dport, | ||
663 | "daddr", "dest"); | ||
664 | break; | ||
665 | case AF_INET6: | ||
666 | avc_print_ipv6_addr(ab, &a->u.net.v6info.saddr, | ||
667 | a->u.net.sport, | ||
668 | "saddr", "src"); | ||
669 | avc_print_ipv6_addr(ab, &a->u.net.v6info.daddr, | ||
670 | a->u.net.dport, | ||
671 | "daddr", "dest"); | ||
672 | break; | ||
673 | } | ||
674 | if (a->u.net.netif > 0) { | ||
675 | struct net_device *dev; | ||
676 | |||
677 | /* NOTE: we always use init's namespace */ | ||
678 | dev = dev_get_by_index(&init_net, | ||
679 | a->u.net.netif); | ||
680 | if (dev) { | ||
681 | audit_log_format(ab, " netif=%s", | ||
682 | dev->name); | ||
683 | dev_put(dev); | ||
684 | } | ||
685 | } | ||
686 | break; | ||
687 | } | ||
688 | } | ||
689 | audit_log_format(ab, " "); | ||
690 | avc_dump_query(ab, ssid, tsid, tclass); | ||
691 | audit_log_end(ab); | ||
570 | } | 692 | } |
571 | 693 | ||
572 | /** | 694 | /** |
@@ -834,7 +956,7 @@ out: | |||
834 | * another -errno upon other errors. | 956 | * another -errno upon other errors. |
835 | */ | 957 | */ |
836 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, | 958 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
837 | u32 requested, struct common_audit_data *auditdata) | 959 | u32 requested, struct avc_audit_data *auditdata) |
838 | { | 960 | { |
839 | struct av_decision avd; | 961 | struct av_decision avd; |
840 | int rc; | 962 | int rc; |