selinux: reduce the number of calls to synchronize_net() when flushing caches
RFC PATCH 1/1 selinux: reduce the number of calls to synchronize_net() when flushing caches
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.
--- security/selinux/hooks.c | 14 ++++++++++++++ security/selinux/include/netif.h | 2 ++ security/selinux/include/netnode.h | 2 ++ security/selinux/include/netport.h | 2 ++ security/selinux/netif.c | 15 +-------------- security/selinux/netnode.c | 15 +-------------- security/selinux/netport.c | 15 +-------------- 7 files changed, 23 insertions(+), 42 deletions(-)
security/selinux/hooks.c +14 -0
@@ -161,6 +161,17 @@ static int selinux_peerlbl_enabled(void)return (selinux_policycap_alwaysnetwork ||netlbl_enabled () ||selinux_xfrm_enabled ()); } +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 */
@@ -5993,6 +6004,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
security/selinux/include/netif.h +2 -0
@@ -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_ */
security/selinux/include/netnode.h +2 -0
@@ -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
security/selinux/include/netport.h +2 -0
@@ -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
security/selinux/netif.c +1 -14
@@ -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; }
security/selinux/netnode.c +1 -14
@@ -283,7 +283,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;
@@ -300,15 +300,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;
@@ -322,10 +313,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; }
security/selinux/netport.c +1 -14
@@ -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; }
Thank you for your effort !!
The booting time might not be a problem for other people, but it was a serious problem for me.
Thank you~
Best regards
2014-06-28 5:41 GMT+09:00 Paul Moore <[email protected]>:
Quoted 222 lines
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 callssynchronize_net()once for each AVC cache flush.Reported-by Jaejyn Shin <[email protected]>Signed-off-by Paul Moore <[email protected]>--- security/selinux/hooks.c | 14 ++++++++++++++ security/selinux/include/netif.h | 2 ++ security/selinux/include/netnode.h | 2 ++ security/selinux/include/netport.h | 2 ++ security/selinux/netif.c | 15 +-------------- security/selinux/netnode.c | 15 +-------------- security/selinux/netport.c | 15 +-------------- 7 files changed, 23 insertions(+), 42 deletions(-)security/selinux/hooks.c +11
-0@@ -161,6 +161,17 @@ static int selinux_peerlbl_enabled(void)return (selinux_policycap_alwaysnetwork ||netlbl_enabled () ||selinux_xfrm_enabled ()); } +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 */
security/selinux/hooks.c +3
-0@@ -5993,6 +6004,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");
elsesecurity/selinux/include/netif.h +2
-0@@ -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_ */ security/selinux/include/netnode.h +2
-0@@ -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 security/selinux/include/netport.h +2
-0@@ -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 security/selinux/netif.c +1
-10@@ -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){
security/selinux/netif.c +0
-4@@ -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; }security/selinux/netnode.c +1
-14@@ -283,7 +283,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;@@ -300,15 +300,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;@@ -322,10 +313,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; }security/selinux/netport.c +1
-14@@ -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; }
Quoted 4 lines · Jaejyn Shin
Thank you for your effort !!
The booting time might not be a problem for other people, but it was a serious problem for me.
I haven't heard any comments so I'm going to go ahead and move this into SELinux #next.
Quoted 286 lines
2014-06-28 5:41 GMT+09:00 Paul Moore <[email protected]>:
Quoted 285 lines
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 callssynchronize_net()once for each AVC cache flush.Reported-by Jaejyn Shin <[email protected]>Signed-off-by Paul Moore <[email protected]>---
security/selinux/hooks.c | 14 ++++++++++++++ security/selinux/include/netif.h | 2 ++ security/selinux/include/netnode.h | 2 ++ security/selinux/include/netport.h | 2 ++ security/selinux/netif.c | 15 +-------------- security/selinux/netnode.c | 15 +-------------- security/selinux/netport.c | 15 +-------------- 7 files changed, 23 insertions(+), 42 deletions(-)security/selinux/hooks.c +13
-0@@ -161,6 +161,17 @@ static int selinux_peerlbl_enabled(void)return (selinux_policycap_alwaysnetwork ||netlbl_enabled () ||selinux_xfrm_enabled ()); } +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 */ @@ -5993,6 +6004,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 netcachecallback\n");
+if (
selinux_enforcing)printk(KERN_DEBUG "SELinux: Starting in enforcing
mode\n");
else
security/selinux/include/netif.h +2
-0@@ -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_ */
security/selinux/include/netnode.h +2
-0@@ -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
security/selinux/include/netport.h +2
-0@@ -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
security/selinux/netif.c +1
-1@@ -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;security/selinux/netif.c +0
-9@@ -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)
{
security/selinux/netif.c +0
-4@@ -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;}
security/selinux/netnode.c +1
-1@@ -283,7 +283,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;security/selinux/netnode.c +0
-9@@ -300,15 +300,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
__initintsel_netnode_init(void)
{int iter;security/selinux/netnode.c +0
-4@@ -322,10 +313,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;}
security/selinux/netport.c +1
-1@@ -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;security/selinux/netport.c +0
-9@@ -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
__initintsel_netport_init(void)
{int iter;security/selinux/netport.c +0
-4@@ -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;}
Signature · 2 lines
paul moore security and virtualization @ redhat