Commit 6575328c authored by James Morris's avatar James Morris Committed by Linus Torvalds

[PATCH] SELinux scalability: convert AVC to RCU

The following patch improves the scalability of SELinux by replacing the
global avc_lock with an RCU based scheme by Kaigai Kohei.  The size of the
cache is made tunable, to allow administrators to tune systems for different
workloads, while statistics are exported via selinuxfs to allow AVC
performance to be monitored at a low level.

AVC nodes are also allocated now via a slab cache, and AVC references have
been removed from the code.

This code has been extensively tested and benchmarked (see benchmark results
below).  Baseline performance is not improved, although it is clear that
dramatic scalability improvements are achieved.

Baseline performance and networking scalability are areas where work is
ongoing (in particular, we need to add caching of some network security
objects so that we don't fallback to policy database lookups on each
permission call).

Benchmark results:

===============================================================================================

System: 4 node 16-way IA64 NUMA

- 'Stream' is based on http://www.cs.virginia.edu/stream/ , HPC memory bandwidth test,
  higher result is better.
- Hackbench: scheduler scalability benchmark by Rusty, lower is better.

Standard kernel:
  2.6.9-1.648_EL  SELINUX=0 : Stream 6159.987MB/s HackBench 53.144
  2.6.9-1.648_EL  SELINUX=1 : Stream 5872.529MB/s HackBench 1043.132

Kernel with RCU/AVC patches:
  2.6.9-1.689_avcrcu.root SELINUX=0 : Stream 8829.647MB/s HackBench 53.976
  2.6.9-1.689_avcrcu.root SELINUX=1 : Stream 8817.117MB/s HackBench 50.975

===============================================================================================

System: 8-way PIII 900Mhz Xeon with 9GB RAM
Fileystem: ext2 for all testing.

Notes:
    AVC was reset before tests, so avc was flushed.
    System was run in enforcing mode.

Key:
    std-nolsm:      standard kernel with LSM disabled
    std-lsmcap:     standard kernel with LSM enabled, capabilities LSM
    std-sel-strict: standard kernel with SELinux enabled, capabilities secondary LSM
    rcu-sel-strict: as above with RCU & AVC stats patches
parent b0f31274
This diff is collapsed.
This diff is collapsed.
...@@ -29,19 +29,6 @@ extern int selinux_enforcing; ...@@ -29,19 +29,6 @@ extern int selinux_enforcing;
*/ */
struct avc_entry; struct avc_entry;
/*
* A reference to an AVC entry.
*/
struct avc_entry_ref {
struct avc_entry *ae;
};
/* Initialize an AVC entry reference before first use. */
static inline void avc_entry_ref_init(struct avc_entry_ref *h)
{
h->ae = NULL;
}
struct task_struct; struct task_struct;
struct vfsmount; struct vfsmount;
struct dentry; struct dentry;
...@@ -118,23 +105,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass); ...@@ -118,23 +105,17 @@ void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tclass);
void __init avc_init(void); void __init avc_init(void);
int avc_lookup(u32 ssid, u32 tsid, u16 tclass,
u32 requested, struct avc_entry_ref *aeref);
int avc_insert(u32 ssid, u32 tsid, u16 tclass,
struct avc_entry *ae, struct avc_entry_ref *out_aeref);
void avc_audit(u32 ssid, u32 tsid, void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata); struct av_decision *avd, int result, struct avc_audit_data *auditdata);
int avc_has_perm_noaudit(u32 ssid, u32 tsid, int avc_has_perm_noaudit(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct avc_entry_ref *aeref, struct av_decision *avd); struct av_decision *avd);
int avc_has_perm(u32 ssid, u32 tsid, int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested, u16 tclass, u32 requested,
struct avc_entry_ref *aeref, struct avc_audit_data *auditdata); struct avc_audit_data *auditdata);
#define AVC_CALLBACK_GRANT 1 #define AVC_CALLBACK_GRANT 1
#define AVC_CALLBACK_TRY_REVOKE 2 #define AVC_CALLBACK_TRY_REVOKE 2
......
...@@ -33,7 +33,6 @@ struct task_security_struct { ...@@ -33,7 +33,6 @@ struct task_security_struct {
u32 sid; /* current SID */ u32 sid; /* current SID */
u32 exec_sid; /* exec SID */ u32 exec_sid; /* exec SID */
u32 create_sid; /* fscreate SID */ u32 create_sid; /* fscreate SID */
struct avc_entry_ref avcr; /* reference to process permissions */
u32 ptrace_sid; /* SID of ptrace parent */ u32 ptrace_sid; /* SID of ptrace parent */
}; };
...@@ -44,7 +43,6 @@ struct inode_security_struct { ...@@ -44,7 +43,6 @@ struct inode_security_struct {
u32 task_sid; /* SID of creating task */ u32 task_sid; /* SID of creating task */
u32 sid; /* SID of this object */ u32 sid; /* SID of this object */
u16 sclass; /* security class of this object */ u16 sclass; /* security class of this object */
struct avc_entry_ref avcr; /* reference to object permissions */
unsigned char initialized; /* initialization flag */ unsigned char initialized; /* initialization flag */
struct semaphore sem; struct semaphore sem;
unsigned char inherit; /* inherit SID from parent entry */ unsigned char inherit; /* inherit SID from parent entry */
...@@ -55,8 +53,6 @@ struct file_security_struct { ...@@ -55,8 +53,6 @@ struct file_security_struct {
struct file *file; /* back pointer to file object */ struct file *file; /* back pointer to file object */
u32 sid; /* SID of open file description */ u32 sid; /* SID of open file description */
u32 fown_sid; /* SID of file owner (for SIGIO) */ u32 fown_sid; /* SID of file owner (for SIGIO) */
struct avc_entry_ref avcr; /* reference to fd permissions */
struct avc_entry_ref inode_avcr; /* reference to object permissions */
}; };
struct superblock_security_struct { struct superblock_security_struct {
...@@ -77,7 +73,6 @@ struct msg_security_struct { ...@@ -77,7 +73,6 @@ struct msg_security_struct {
unsigned long magic; /* magic number for this module */ unsigned long magic; /* magic number for this module */
struct msg_msg *msg; /* back pointer */ struct msg_msg *msg; /* back pointer */
u32 sid; /* SID of message */ u32 sid; /* SID of message */
struct avc_entry_ref avcr; /* reference to permissions */
}; };
struct ipc_security_struct { struct ipc_security_struct {
...@@ -85,7 +80,6 @@ struct ipc_security_struct { ...@@ -85,7 +80,6 @@ struct ipc_security_struct {
struct kern_ipc_perm *ipc_perm; /* back pointer */ struct kern_ipc_perm *ipc_perm; /* back pointer */
u16 sclass; /* security class of this object */ u16 sclass; /* security class of this object */
u32 sid; /* SID of IPC resource */ u32 sid; /* SID of IPC resource */
struct avc_entry_ref avcr; /* reference to permissions */
}; };
struct bprm_security_struct { struct bprm_security_struct {
......
...@@ -51,7 +51,7 @@ int task_has_security(struct task_struct *tsk, ...@@ -51,7 +51,7 @@ int task_has_security(struct task_struct *tsk,
return -EACCES; return -EACCES;
return avc_has_perm(tsec->sid, SECINITSID_SECURITY, return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
SECCLASS_SECURITY, perms, NULL, NULL); SECCLASS_SECURITY, perms, NULL);
} }
enum sel_inos { enum sel_inos {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment