selinux: reduce the number of calls to synchronize_net() when flushing caches
authorPaul Moore <pmoore@redhat.com>
Thu, 26 Jun 2014 18:33:56 +0000 (14:33 -0400)
committerStephen Smalley <sds@tycho.nsa.gov>
Tue, 20 Jan 2015 19:27:41 +0000 (14:27 -0500)
commit 615e51fdda6f274e94b1e905fcaf6111e0d9aa20 upstream.

When flushing the AVC, such as during a policy load, the various
network caches are also flushed, with each making a call to
synchronize_net() which has shown to be expensive in some cases.
This patch consolidates the network cache flushes into a single AVC
callback which only calls synchronize_net() once for each AVC cache
flush.

Change-Id: I2a7f020748d1adf2b68246f6ef86d0c871adffb7
Reported-by: Jaejyn Shin <flagon22bass@gmail.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
security/selinux/hooks.c
security/selinux/include/netif.h
security/selinux/include/netnode.h
security/selinux/include/netport.h
security/selinux/netif.c
security/selinux/netnode.c
security/selinux/netport.c

index 0fa3195626a903a3fb2f310e765ac4e38102ca23..8923208b4be7fde4d8bffd0d99b34fe060cf5216 100644 (file)
@@ -146,6 +146,17 @@ static int selinux_secmark_enabled(void)
        return (atomic_read(&selinux_secmark_refcount) > 0);
 }
 
+static int selinux_netcache_avc_callback(u32 event)
+{
+       if (event == AVC_CALLBACK_RESET) {
+               sel_netif_flush();
+               sel_netnode_flush();
+               sel_netport_flush();
+               synchronize_net();
+       }
+       return 0;
+}
+
 /*
  * initialise the security for the init task
  */
@@ -5844,6 +5855,9 @@ static __init int selinux_init(void)
        if (register_security(&selinux_ops))
                panic("SELinux: Unable to register with kernel.\n");
 
+       if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET))
+               panic("SELinux: Unable to register AVC netcache callback\n");
+
        if (selinux_enforcing)
                printk(KERN_DEBUG "SELinux:  Starting in enforcing mode\n");
        else
index 43d507242b42f1ecdbe0f2971074d5d7b80165c5..57c6eae81eacac6226273963ee89602cdf736983 100644 (file)
@@ -17,6 +17,8 @@
 #ifndef _SELINUX_NETIF_H_
 #define _SELINUX_NETIF_H_
 
+void sel_netif_flush(void);
+
 int sel_netif_sid(int ifindex, u32 *sid);
 
 #endif /* _SELINUX_NETIF_H_ */
index df7a5ed6c6943e01008b010acb9782c2b727d824..937668dd30247731dbb416e162c105d29f6e3253 100644 (file)
@@ -27,6 +27,8 @@
 #ifndef _SELINUX_NETNODE_H
 #define _SELINUX_NETNODE_H
 
+void sel_netnode_flush(void);
+
 int sel_netnode_sid(void *addr, u16 family, u32 *sid);
 
 #endif
index 4d965b83d735b976029231274c2ace509b498e1f..d1ce896b2cb0f84bdef2e72ce282cc040f206e64 100644 (file)
@@ -26,6 +26,8 @@
 #ifndef _SELINUX_NETPORT_H
 #define _SELINUX_NETPORT_H
 
+void sel_netport_flush(void);
+
 int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid);
 
 #endif
index 47a49d1a6f6adf7b60873fcfb1249b1ee023f5b9..6c814ec4b01ae9f1fae1f3909167ae0c24c9f002 100644 (file)
@@ -240,7 +240,7 @@ static void sel_netif_kill(int ifindex)
  * Remove all entries from the network interface table.
  *
  */
-static void sel_netif_flush(void)
+void sel_netif_flush(void)
 {
        int idx;
        struct sel_netif *netif;
@@ -252,15 +252,6 @@ static void sel_netif_flush(void)
        spin_unlock_bh(&sel_netif_lock);
 }
 
-static int sel_netif_avc_callback(u32 event)
-{
-       if (event == AVC_CALLBACK_RESET) {
-               sel_netif_flush();
-               synchronize_net();
-       }
-       return 0;
-}
-
 static int sel_netif_netdev_notifier_handler(struct notifier_block *this,
                                             unsigned long event, void *ptr)
 {
@@ -291,10 +282,6 @@ static __init int sel_netif_init(void)
 
        register_netdevice_notifier(&sel_netif_netdev_notifier);
 
-       err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET);
-       if (err)
-               panic("avc_add_callback() failed, error %d\n", err);
-
        return err;
 }
 
index c5454c0477c346e4d814f5ff209feba86e5b86ad..bb8de9d9b429468337ca36cb766a237c8427fed5 100644 (file)
@@ -281,7 +281,7 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid)
  * Remove all entries from the network address table.
  *
  */
-static void sel_netnode_flush(void)
+void sel_netnode_flush(void)
 {
        unsigned int idx;
        struct sel_netnode *node, *node_tmp;
@@ -298,15 +298,6 @@ static void sel_netnode_flush(void)
        spin_unlock_bh(&sel_netnode_lock);
 }
 
-static int sel_netnode_avc_callback(u32 event)
-{
-       if (event == AVC_CALLBACK_RESET) {
-               sel_netnode_flush();
-               synchronize_net();
-       }
-       return 0;
-}
-
 static __init int sel_netnode_init(void)
 {
        int iter;
@@ -320,10 +311,6 @@ static __init int sel_netnode_init(void)
                sel_netnode_hash[iter].size = 0;
        }
 
-       ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET);
-       if (ret != 0)
-               panic("avc_add_callback() failed, error %d\n", ret);
-
        return ret;
 }
 
index d35379781c2c44ab188cb7aed071579da189bb53..73ac6784d091574fc756f01a569ad087a0611869 100644 (file)
@@ -217,7 +217,7 @@ int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid)
  * Remove all entries from the network address table.
  *
  */
-static void sel_netport_flush(void)
+void sel_netport_flush(void)
 {
        unsigned int idx;
        struct sel_netport *port, *port_tmp;
@@ -234,15 +234,6 @@ static void sel_netport_flush(void)
        spin_unlock_bh(&sel_netport_lock);
 }
 
-static int sel_netport_avc_callback(u32 event)
-{
-       if (event == AVC_CALLBACK_RESET) {
-               sel_netport_flush();
-               synchronize_net();
-       }
-       return 0;
-}
-
 static __init int sel_netport_init(void)
 {
        int iter;
@@ -256,10 +247,6 @@ static __init int sel_netport_init(void)
                sel_netport_hash[iter].size = 0;
        }
 
-       ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET);
-       if (ret != 0)
-               panic("avc_add_callback() failed, error %d\n", ret);
-
        return ret;
 }