aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-03-31 13:58:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-03-31 14:24:22 -0400
commita554bea89948dfb6d2f9c4c62ce2b12b2dac18ad (patch)
treef84e38fa7a54c1a678a14d7a65e583efac1cafa3 /security
parentfa2a4519cb6ad94224eb56a1341fff570fd44ea1 (diff)
selinux: don't inline slow-path code into avc_has_perm_noaudit()
The selinux AVC paths remain some of the hottest (and deepest) codepaths at filename lookup time, and we make it worse by having the slow path cases take up I$ and stack space even when they don't trigger. Gcc tends to always want to inline functions that are just called once - never mind that this might make for slower and worse code in the caller. So this tries to improve on it a bit by making the slow-path cases explicitly separate functions that are marked noinline, causing gcc to at least no longer allocate stack space for them unless they are actually called. It also seems to help register allocation a tiny bit, since gcc now doesn't take the slow case code into account. Uninlining the slow path may also allow us to inline the remaining hot path into the one caller that actually matters: avc_has_perm_flags(). I'll have to look at that separately, but both avc_audit() and avc_has_perm_noaudit() are now small and lean enough that inlining them may make sense. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/avc.c52
1 files changed, 38 insertions, 14 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 6989472d0957..07620bc94e2a 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -741,6 +741,41 @@ int avc_ss_reset(u32 seqno)
741 return rc; 741 return rc;
742} 742}
743 743
744/*
745 * Slow-path helper function for avc_has_perm_noaudit,
746 * when the avc_node lookup fails. We get called with
747 * the RCU read lock held, and need to return with it
748 * still held, but drop if for the security compute.
749 *
750 * Don't inline this, since it's the slow-path and just
751 * results in a bigger stack frame.
752 */
753static noinline struct avc_node *avc_compute_av(u32 ssid, u32 tsid,
754 u16 tclass, struct av_decision *avd)
755{
756 rcu_read_unlock();
757 security_compute_av(ssid, tsid, tclass, avd);
758 rcu_read_lock();
759 return avc_insert(ssid, tsid, tclass, avd);
760}
761
762static noinline int avc_denied(u32 ssid, u32 tsid,
763 u16 tclass, u32 requested,
764 unsigned flags,
765 struct av_decision *avd)
766{
767 if (flags & AVC_STRICT)
768 return -EACCES;
769
770 if (selinux_enforcing && !(avd->flags & AVD_FLAGS_PERMISSIVE))
771 return -EACCES;
772
773 avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
774 tsid, tclass, avd->seqno);
775 return 0;
776}
777
778
744/** 779/**
745 * avc_has_perm_noaudit - Check permissions but perform no auditing. 780 * avc_has_perm_noaudit - Check permissions but perform no auditing.
746 * @ssid: source security identifier 781 * @ssid: source security identifier
@@ -776,26 +811,15 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
776 811
777 node = avc_lookup(ssid, tsid, tclass); 812 node = avc_lookup(ssid, tsid, tclass);
778 if (unlikely(!node)) { 813 if (unlikely(!node)) {
779 rcu_read_unlock(); 814 node = avc_compute_av(ssid, tsid, tclass, avd);
780 security_compute_av(ssid, tsid, tclass, avd);
781 rcu_read_lock();
782 node = avc_insert(ssid, tsid, tclass, avd);
783 } else { 815 } else {
784 memcpy(avd, &node->ae.avd, sizeof(*avd)); 816 memcpy(avd, &node->ae.avd, sizeof(*avd));
785 avd = &node->ae.avd; 817 avd = &node->ae.avd;
786 } 818 }
787 819
788 denied = requested & ~(avd->allowed); 820 denied = requested & ~(avd->allowed);
789 821 if (unlikely(denied))
790 if (denied) { 822 rc = avc_denied(ssid, tsid, tclass, requested, flags, avd);
791 if (flags & AVC_STRICT)
792 rc = -EACCES;
793 else if (!selinux_enforcing || (avd->flags & AVD_FLAGS_PERMISSIVE))
794 avc_update_node(AVC_CALLBACK_GRANT, requested, ssid,
795 tsid, tclass, avd->seqno);
796 else
797 rc = -EACCES;
798 }
799 823
800 rcu_read_unlock(); 824 rcu_read_unlock();
801 return rc; 825 return rc;