diff options
| author | Paul Moore <pmoore@redhat.com> | 2014-06-26 14:33:56 -0400 |
|---|---|---|
| committer | Paul Moore <pmoore@redhat.com> | 2014-06-26 14:33:56 -0400 |
| commit | 615e51fdda6f274e94b1e905fcaf6111e0d9aa20 (patch) | |
| tree | d0ce12f9f5e086c293a7255e3e712d2a42be02b9 /security | |
| parent | f31e799459659ae88c341aeac16a8a5efb1271d4 (diff) | |
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.
Reported-by: Jaejyn Shin <flagon22bass@gmail.com>
Signed-off-by: Paul Moore <pmoore@redhat.com>
Diffstat (limited to 'security')
| -rw-r--r-- | security/selinux/hooks.c | 14 | ||||
| -rw-r--r-- | security/selinux/include/netif.h | 2 | ||||
| -rw-r--r-- | security/selinux/include/netnode.h | 2 | ||||
| -rw-r--r-- | security/selinux/include/netport.h | 2 | ||||
| -rw-r--r-- | security/selinux/netif.c | 15 | ||||
| -rw-r--r-- | security/selinux/netnode.c | 15 | ||||
| -rw-r--r-- | security/selinux/netport.c | 15 |
7 files changed, 23 insertions, 42 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 336f0a04450e..39bc8c94b969 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
| @@ -161,6 +161,17 @@ static int selinux_peerlbl_enabled(void) | |||
| 161 | return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled()); | 161 | return (selinux_policycap_alwaysnetwork || netlbl_enabled() || selinux_xfrm_enabled()); |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | static int selinux_netcache_avc_callback(u32 event) | ||
| 165 | { | ||
| 166 | if (event == AVC_CALLBACK_RESET) { | ||
| 167 | sel_netif_flush(); | ||
| 168 | sel_netnode_flush(); | ||
| 169 | sel_netport_flush(); | ||
| 170 | synchronize_net(); | ||
| 171 | } | ||
| 172 | return 0; | ||
| 173 | } | ||
| 174 | |||
| 164 | /* | 175 | /* |
| 165 | * initialise the security for the init task | 176 | * initialise the security for the init task |
| 166 | */ | 177 | */ |
| @@ -5993,6 +6004,9 @@ static __init int selinux_init(void) | |||
| 5993 | if (register_security(&selinux_ops)) | 6004 | if (register_security(&selinux_ops)) |
| 5994 | panic("SELinux: Unable to register with kernel.\n"); | 6005 | panic("SELinux: Unable to register with kernel.\n"); |
| 5995 | 6006 | ||
| 6007 | if (avc_add_callback(selinux_netcache_avc_callback, AVC_CALLBACK_RESET)) | ||
| 6008 | panic("SELinux: Unable to register AVC netcache callback\n"); | ||
| 6009 | |||
| 5996 | if (selinux_enforcing) | 6010 | if (selinux_enforcing) |
| 5997 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); | 6011 | printk(KERN_DEBUG "SELinux: Starting in enforcing mode\n"); |
| 5998 | else | 6012 | else |
diff --git a/security/selinux/include/netif.h b/security/selinux/include/netif.h index 43d507242b42..57c6eae81eac 100644 --- a/security/selinux/include/netif.h +++ b/security/selinux/include/netif.h | |||
| @@ -17,6 +17,8 @@ | |||
| 17 | #ifndef _SELINUX_NETIF_H_ | 17 | #ifndef _SELINUX_NETIF_H_ |
| 18 | #define _SELINUX_NETIF_H_ | 18 | #define _SELINUX_NETIF_H_ |
| 19 | 19 | ||
| 20 | void sel_netif_flush(void); | ||
| 21 | |||
| 20 | int sel_netif_sid(int ifindex, u32 *sid); | 22 | int sel_netif_sid(int ifindex, u32 *sid); |
| 21 | 23 | ||
| 22 | #endif /* _SELINUX_NETIF_H_ */ | 24 | #endif /* _SELINUX_NETIF_H_ */ |
diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h index df7a5ed6c694..937668dd3024 100644 --- a/security/selinux/include/netnode.h +++ b/security/selinux/include/netnode.h | |||
| @@ -27,6 +27,8 @@ | |||
| 27 | #ifndef _SELINUX_NETNODE_H | 27 | #ifndef _SELINUX_NETNODE_H |
| 28 | #define _SELINUX_NETNODE_H | 28 | #define _SELINUX_NETNODE_H |
| 29 | 29 | ||
| 30 | void sel_netnode_flush(void); | ||
| 31 | |||
| 30 | int sel_netnode_sid(void *addr, u16 family, u32 *sid); | 32 | int sel_netnode_sid(void *addr, u16 family, u32 *sid); |
| 31 | 33 | ||
| 32 | #endif | 34 | #endif |
diff --git a/security/selinux/include/netport.h b/security/selinux/include/netport.h index 4d965b83d735..d1ce896b2cb0 100644 --- a/security/selinux/include/netport.h +++ b/security/selinux/include/netport.h | |||
| @@ -26,6 +26,8 @@ | |||
| 26 | #ifndef _SELINUX_NETPORT_H | 26 | #ifndef _SELINUX_NETPORT_H |
| 27 | #define _SELINUX_NETPORT_H | 27 | #define _SELINUX_NETPORT_H |
| 28 | 28 | ||
| 29 | void sel_netport_flush(void); | ||
| 30 | |||
| 29 | int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid); | 31 | int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid); |
| 30 | 32 | ||
| 31 | #endif | 33 | #endif |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index 694e9e43855f..3c3de4ca0ebc 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
| @@ -240,7 +240,7 @@ static void sel_netif_kill(int ifindex) | |||
| 240 | * Remove all entries from the network interface table. | 240 | * Remove all entries from the network interface table. |
| 241 | * | 241 | * |
| 242 | */ | 242 | */ |
| 243 | static void sel_netif_flush(void) | 243 | void sel_netif_flush(void) |
| 244 | { | 244 | { |
| 245 | int idx; | 245 | int idx; |
| 246 | struct sel_netif *netif; | 246 | struct sel_netif *netif; |
| @@ -252,15 +252,6 @@ static void sel_netif_flush(void) | |||
| 252 | spin_unlock_bh(&sel_netif_lock); | 252 | spin_unlock_bh(&sel_netif_lock); |
| 253 | } | 253 | } |
| 254 | 254 | ||
| 255 | static int sel_netif_avc_callback(u32 event) | ||
| 256 | { | ||
| 257 | if (event == AVC_CALLBACK_RESET) { | ||
| 258 | sel_netif_flush(); | ||
| 259 | synchronize_net(); | ||
| 260 | } | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int sel_netif_netdev_notifier_handler(struct notifier_block *this, | 255 | static int sel_netif_netdev_notifier_handler(struct notifier_block *this, |
| 265 | unsigned long event, void *ptr) | 256 | unsigned long event, void *ptr) |
| 266 | { | 257 | { |
| @@ -291,10 +282,6 @@ static __init int sel_netif_init(void) | |||
| 291 | 282 | ||
| 292 | register_netdevice_notifier(&sel_netif_netdev_notifier); | 283 | register_netdevice_notifier(&sel_netif_netdev_notifier); |
| 293 | 284 | ||
| 294 | err = avc_add_callback(sel_netif_avc_callback, AVC_CALLBACK_RESET); | ||
| 295 | if (err) | ||
| 296 | panic("avc_add_callback() failed, error %d\n", err); | ||
| 297 | |||
| 298 | return err; | 285 | return err; |
| 299 | } | 286 | } |
| 300 | 287 | ||
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 03a72c32afd7..ddf315260839 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
| @@ -283,7 +283,7 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid) | |||
| 283 | * Remove all entries from the network address table. | 283 | * Remove all entries from the network address table. |
| 284 | * | 284 | * |
| 285 | */ | 285 | */ |
| 286 | static void sel_netnode_flush(void) | 286 | void sel_netnode_flush(void) |
| 287 | { | 287 | { |
| 288 | unsigned int idx; | 288 | unsigned int idx; |
| 289 | struct sel_netnode *node, *node_tmp; | 289 | struct sel_netnode *node, *node_tmp; |
| @@ -300,15 +300,6 @@ static void sel_netnode_flush(void) | |||
| 300 | spin_unlock_bh(&sel_netnode_lock); | 300 | spin_unlock_bh(&sel_netnode_lock); |
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | static int sel_netnode_avc_callback(u32 event) | ||
| 304 | { | ||
| 305 | if (event == AVC_CALLBACK_RESET) { | ||
| 306 | sel_netnode_flush(); | ||
| 307 | synchronize_net(); | ||
| 308 | } | ||
| 309 | return 0; | ||
| 310 | } | ||
| 311 | |||
| 312 | static __init int sel_netnode_init(void) | 303 | static __init int sel_netnode_init(void) |
| 313 | { | 304 | { |
| 314 | int iter; | 305 | int iter; |
| @@ -322,10 +313,6 @@ static __init int sel_netnode_init(void) | |||
| 322 | sel_netnode_hash[iter].size = 0; | 313 | sel_netnode_hash[iter].size = 0; |
| 323 | } | 314 | } |
| 324 | 315 | ||
| 325 | ret = avc_add_callback(sel_netnode_avc_callback, AVC_CALLBACK_RESET); | ||
| 326 | if (ret != 0) | ||
| 327 | panic("avc_add_callback() failed, error %d\n", ret); | ||
| 328 | |||
| 329 | return ret; | 316 | return ret; |
| 330 | } | 317 | } |
| 331 | 318 | ||
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index d35379781c2c..73ac6784d091 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
| @@ -217,7 +217,7 @@ int sel_netport_sid(u8 protocol, u16 pnum, u32 *sid) | |||
| 217 | * Remove all entries from the network address table. | 217 | * Remove all entries from the network address table. |
| 218 | * | 218 | * |
| 219 | */ | 219 | */ |
| 220 | static void sel_netport_flush(void) | 220 | void sel_netport_flush(void) |
| 221 | { | 221 | { |
| 222 | unsigned int idx; | 222 | unsigned int idx; |
| 223 | struct sel_netport *port, *port_tmp; | 223 | struct sel_netport *port, *port_tmp; |
| @@ -234,15 +234,6 @@ static void sel_netport_flush(void) | |||
| 234 | spin_unlock_bh(&sel_netport_lock); | 234 | spin_unlock_bh(&sel_netport_lock); |
| 235 | } | 235 | } |
| 236 | 236 | ||
| 237 | static int sel_netport_avc_callback(u32 event) | ||
| 238 | { | ||
| 239 | if (event == AVC_CALLBACK_RESET) { | ||
| 240 | sel_netport_flush(); | ||
| 241 | synchronize_net(); | ||
| 242 | } | ||
| 243 | return 0; | ||
| 244 | } | ||
| 245 | |||
| 246 | static __init int sel_netport_init(void) | 237 | static __init int sel_netport_init(void) |
| 247 | { | 238 | { |
| 248 | int iter; | 239 | int iter; |
| @@ -256,10 +247,6 @@ static __init int sel_netport_init(void) | |||
| 256 | sel_netport_hash[iter].size = 0; | 247 | sel_netport_hash[iter].size = 0; |
| 257 | } | 248 | } |
| 258 | 249 | ||
| 259 | ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET); | ||
| 260 | if (ret != 0) | ||
| 261 | panic("avc_add_callback() failed, error %d\n", ret); | ||
| 262 | |||
| 263 | return ret; | 250 | return ret; |
| 264 | } | 251 | } |
| 265 | 252 | ||
