[PATCH 5/6] SELinux: improve performance when AVC misses

Previous thread: TPM driver changes to support multiple locality by Agarwal, Lomesh on Tuesday, October 9, 2007 - 3:51 pm. (13 messages)

Next thread: [PATCH] Reserve N process to root by Gustavo Chain on Tuesday, October 9, 2007 - 4:48 pm. (9 messages)
From: James Morris
Date: Tuesday, October 9, 2007 - 4:18 pm

Please pull.


The following changes since commit bbf25010f1a6b761914430f5fca081ec8c7accd1:
  Linus Torvalds (1):
        Linux 2.6.23

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6.git for-linus

Eric Paris (2):
      SELinux: change Kconfig to use select instead of depends
      SELinux: policy selectable handling of unknown classes and perms

KaiGai Kohei (2):
      SELinux: improve performance when AVC misses.
      SELinux: kills warnings in Improve SELinux performance when AVC misses

Yuichi Nakamura (2):
      SELinux: tune avtab to reduce memory usage
      SELinux: Improve read/write performance

 fs/open.c                           |    4 +
 include/linux/security.h            |   18 +++
 security/dummy.c                    |    6 +
 security/selinux/Kconfig            |    7 +-
 security/selinux/avc.c              |    5 +
 security/selinux/hooks.c            |   53 +++++++-
 security/selinux/include/avc.h      |    2 +
 security/selinux/include/objsec.h   |    2 +
 security/selinux/include/security.h |    2 +
 security/selinux/selinuxfs.c        |   26 ++++
 security/selinux/ss/avtab.c         |   91 ++++++++----
 security/selinux/ss/avtab.h         |   16 ++-
 security/selinux/ss/conditional.c   |    4 +
 security/selinux/ss/ebitmap.c       |  282 +++++++++++++++++++---------------
 security/selinux/ss/ebitmap.h       |   89 +++++++++---
 security/selinux/ss/mls.c           |  156 +++++++++----------
 security/selinux/ss/policydb.c      |   11 +-
 security/selinux/ss/policydb.h      |    8 +
 security/selinux/ss/services.c      |   91 +++++++++---
 19 files changed, 588 insertions(+), 285 deletions(-)
-

From: James Morris
Date: Tuesday, October 9, 2007 - 4:20 pm

From: Yuichi Nakamura <ynakam@hitachisoft.jp>

This patch reduces memory usage of SELinux by tuning avtab. Number of hash
slots in avtab was 32768. Unused slots used memory when number of rules is
fewer. This patch decides number of hash slots dynamically based on number
of rules. (chain length)^2 is also printed out in avtab_hash_eval to see
standard deviation of avtab hash table.

Signed-off-by: Yuichi Nakamura<ynakam@hitachisoft.jp>
Acked-by:  Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@e.namei>
---
 security/selinux/ss/avtab.c       |   91 ++++++++++++++++++++++++++-----------
 security/selinux/ss/avtab.h       |   16 +++++--
 security/selinux/ss/conditional.c |    4 ++
 security/selinux/ss/policydb.c    |    7 +--
 4 files changed, 82 insertions(+), 36 deletions(-)

diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 85705eb..7551af1 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -12,24 +12,25 @@
  *	This program is free software; you can redistribute it and/or modify
  *  	it under the terms of the GNU General Public License as published by
  *	the Free Software Foundation, version 2.
+ *
+ * Updated: Yuichi Nakamura <ynakam@hitachisoft.jp>
+ * 	Tuned number of hash slots for avtab to reduce memory usage
  */
 
 #include <linux/kernel.h>
 #include <linux/slab.h>
-#include <linux/vmalloc.h>
 #include <linux/errno.h>
-
 #include "avtab.h"
 #include "policydb.h"
 
-#define AVTAB_HASH(keyp) \
-((keyp->target_class + \
- (keyp->target_type << 2) + \
- (keyp->source_type << 9)) & \
- AVTAB_HASH_MASK)
-
 static struct kmem_cache *avtab_node_cachep;
 
+static inline int avtab_hash(struct avtab_key *keyp, u16 mask)
+{
+	return ((keyp->target_class + (keyp->target_type << 2) +
+		 (keyp->source_type << 9)) & mask);
+}
+
 static struct avtab_node*
 avtab_insert_node(struct avtab *h, int hvalue,
 		  struct avtab_node * prev, struct avtab_node * cur,
@@ -59,10 +60,10 @@ static ...
From: James Morris
Date: Tuesday, October 9, 2007 - 4:21 pm

From: Yuichi Nakamura <ynakam@hitachisoft.jp>

It reduces the selinux overhead on read/write by only revalidating
permissions in selinux_file_permission if the task or inode labels have
changed or the policy has changed since the open-time check.  A new LSM
hook, security_dentry_open, is added to capture the necessary state at open
time to allow this optimization.

(see http://marc.info/?l=selinux&m=118972995207740&w=2)

Signed-off-by: Yuichi Nakamura<ynakam@hitachisoft.jp>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@localhost.localdomain>
---
 fs/open.c                         |    4 +++
 include/linux/security.h          |   18 ++++++++++++
 security/dummy.c                  |    6 ++++
 security/selinux/avc.c            |    5 +++
 security/selinux/hooks.c          |   53 ++++++++++++++++++++++++++++++++++++-
 security/selinux/include/avc.h    |    2 +
 security/selinux/include/objsec.h |    2 +
 7 files changed, 89 insertions(+), 1 deletions(-)

diff --git a/fs/open.c b/fs/open.c
index 1d9e5e9..044bfa8 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -757,6 +757,10 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt,
 	f->f_op = fops_get(inode->i_fop);
 	file_move(f, &inode->i_sb->s_files);
 
+	error = security_dentry_open(f);
+	if (error)
+		goto cleanup_all;
+
 	if (!open && f->f_op)
 		open = f->f_op->open;
 	if (open) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 1a15526..928d479 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -504,6 +504,13 @@ struct request_sock;
  *	@file contains the file structure being received.
  *	Return 0 if permission is granted.
  *
+ * Security hook for dentry
+ *
+ * @dentry_open
+ *	Save open-time permission checking state for later use upon
+ *	file_permission, and recheck access if anything has changed
+ *	since inode_permission.
+ *
  * Security hooks for task operations.
  *
  * @task_create:
@@ ...
From: James Morris
Date: Tuesday, October 9, 2007 - 4:19 pm

From: Eric Paris <eparis@redhat.com>

Changes the security/selinux/Kconfig to use select instead of depends
for most of the SELinux requirements.  This allows the SELinux option to
show up when people do a make config without already knowing they had to
enable audit and other non-obvious choices.  Added a depends on SECURITY
(which previously existed through SECURITY_NETWORK) so that SELinux
would not always show up, but would be easy and intuitive to find.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@e.namei>
---
 security/selinux/Kconfig |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/security/selinux/Kconfig b/security/selinux/Kconfig
index b32a459..40b97e6 100644
--- a/security/selinux/Kconfig
+++ b/security/selinux/Kconfig
@@ -1,6 +1,10 @@
 config SECURITY_SELINUX
 	bool "NSA SELinux Support"
-	depends on SECURITY_NETWORK && AUDIT && NET && INET
+	depends on SECURITY
+	select SECURITY_NETWORK
+	select AUDIT
+	select NET
+	select INET
 	select NETWORK_SECMARK
 	default n
 	help
@@ -9,6 +13,7 @@ config SECURITY_SELINUX
 	  You can obtain the policy compiler (checkpolicy), the utility for
 	  labeling filesystems (setfiles), and an example policy configuration
 	  from <http://www.nsa.gov/selinux/>.
+
 	  If you are unsure how to answer this question, answer N.
 
 config SECURITY_SELINUX_BOOTPARAM
-- 
1.5.2.4

-

From: Randy Dunlap
Date: Tuesday, October 9, 2007 - 4:28 pm

I doth protest.  Enabling the entire NET subsystem thru a hidden
select is awful.  Select should be used (sparingly) to enable
library code only.  If someone wants NET enabled, they should



---
~Randy
-

From: James Morris
Date: Tuesday, October 9, 2007 - 4:50 pm

Ok, fair enough.

I've dropped the patch and rebased the branch.  Please pull per:


The following changes since commit bbf25010f1a6b761914430f5fca081ec8c7accd1:
  Linus Torvalds (1):
        Linux 2.6.23

are available in the git repository at:

ssh://master.kernel.org/pub/scm/linux/kernel/git/jmorris/selinux-2.6.git for-linus

Eric Paris (1):
      SELinux: policy selectable handling of unknown classes and perms

KaiGai Kohei (2):
      SELinux: improve performance when AVC misses.
      SELinux: kills warnings in Improve SELinux performance when AVC misses

Yuichi Nakamura (2):
      SELinux: tune avtab to reduce memory usage
      SELinux: Improve read/write performance

 fs/open.c                           |    4 +
 include/linux/security.h            |   18 +++
 security/dummy.c                    |    6 +
 security/selinux/avc.c              |    5 +
 security/selinux/hooks.c            |   53 +++++++-
 security/selinux/include/avc.h      |    2 +
 security/selinux/include/objsec.h   |    2 +
 security/selinux/include/security.h |    2 +
 security/selinux/selinuxfs.c        |   26 ++++
 security/selinux/ss/avtab.c         |   91 ++++++++----
 security/selinux/ss/avtab.h         |   16 ++-
 security/selinux/ss/conditional.c   |    4 +
 security/selinux/ss/ebitmap.c       |  282 +++++++++++++++++++---------------
 security/selinux/ss/ebitmap.h       |   89 +++++++++---
 security/selinux/ss/mls.c           |  156 +++++++++----------
 security/selinux/ss/policydb.c      |   11 +-
 security/selinux/ss/policydb.h      |    8 +
 security/selinux/ss/services.c      |   91 +++++++++---
 18 files changed, 582 insertions(+), 284 deletions(-)
 



-- 
James Morris
<jmorris@namei.org>
-

From: Randy Dunlap
Date: Tuesday, October 9, 2007 - 5:16 pm

Great, thanks.

---
~Randy
-

From: Stephen Smalley
Date: Wednesday, October 10, 2007 - 5:12 am

Does that apply to all the options, or only to NET (e.g. is it ok to
select AUDIT)?  I thought that this patch came out of earlier
discussions about proper use of select vs. depends.  It may have gone
-- 
Stephen Smalley
National Security Agency

-

From: Randy Dunlap
Date: Wednesday, October 10, 2007 - 8:40 am

AUDIT isn't quite library code, still I don't have a (big) problem with
selecting it or NETWORK_SECMARK.  (other than select is evil :)

OTOH, NET and INET are large config options, not library-like code, and
should not be selected.

-- 
~Randy
-

From: Valdis.Kletnieks
Date: Wednesday, October 10, 2007 - 12:53 pm

If it does a 'select SECURITY_NETWORK' but NET=n, does the resulting kernel
actually build?  The problem seems to be that select isn't transitive - if
you select something, it won't automagically select that something's pre-reqs
(modulo the recent patches I've seen posted, have those been mainlined?).

From: Randy Dunlap
Date: Wednesday, October 10, 2007 - 12:57 pm

Good point.

I haven't tested that, but it's most likely still a problem.
"select" does not follow its dependency chain...


-- 
~Randy
-

From: James Morris
Date: Tuesday, October 9, 2007 - 4:22 pm

From: Eric Paris <eparis@redhat.com>

Allow policy to select, in much the same way as it selects MLS support, how
the kernel should handle access decisions which contain either unknown
classes or unknown permissions in known classes.  The three choices for the
policy flags are

0 - Deny unknown security access. (default)
2 - reject loading policy if it does not contain all definitions
4 - allow unknown security access

The policy's choice is exported through 2 booleans in
selinuxfs.  /selinux/deny_unknown and /selinux/reject_unknown.

Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/include/security.h |    2 +
 security/selinux/selinuxfs.c        |   26 ++++++++++++
 security/selinux/ss/policydb.c      |    4 ++
 security/selinux/ss/policydb.h      |    8 ++++
 security/selinux/ss/services.c      |   75 ++++++++++++++++++++++++++++++----
 5 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index 83bdd4d..39337af 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -90,6 +90,8 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid);
 
 int security_get_classes(char ***classes, int *nclasses);
 int security_get_permissions(char *class, char ***perms, int *nperms);
+int security_get_reject_unknown(void);
+int security_get_allow_unknown(void);
 
 #define SECURITY_FS_USE_XATTR		1 /* use xattr */
 #define SECURITY_FS_USE_TRANS		2 /* use transition SIDs, e.g. devpts/tmpfs */
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c
index c9e92da..f5f3e6d 100644
--- a/security/selinux/selinuxfs.c
+++ b/security/selinux/selinuxfs.c
@@ -103,6 +103,8 @@ enum sel_inos {
 	SEL_MEMBER,	/* compute polyinstantiation membership decision */
 	SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
 ...
From: James Morris
Date: Tuesday, October 9, 2007 - 4:23 pm

From: KaiGai Kohei <kaigai@kaigai.gr.jp>

This patch kills ugly warnings when the "Improve SELinux performance when 
AVC misses" patch.

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/ss/ebitmap.c |   11 +++++------
 security/selinux/ss/ebitmap.h |    2 ++
 2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c
index ae44c0c..c1a6b22 100644
--- a/security/selinux/ss/ebitmap.c
+++ b/security/selinux/ss/ebitmap.c
@@ -193,7 +193,7 @@ int ebitmap_netlbl_import(struct ebitmap *ebmap,
 			e_sft = delta % EBITMAP_UNIT_SIZE;
 			while (map) {
 				e_iter->maps[e_idx++] |= map & (-1UL);
-				map >>= EBITMAP_UNIT_SIZE;
+				map = EBITMAP_SHIFT_UNIT_SIZE(map);
 			}
 		}
 		c_iter = c_iter->next;
@@ -389,13 +389,13 @@ int ebitmap_read(struct ebitmap *e, void *fp)
 
 		if (startbit & (mapunit - 1)) {
 			printk(KERN_ERR "security: ebitmap start bit (%d) is "
-			       "not a multiple of the map unit size (%Zd)\n",
+			       "not a multiple of the map unit size (%u)\n",
 			       startbit, mapunit);
 			goto bad;
 		}
 		if (startbit > e->highbit - mapunit) {
 			printk(KERN_ERR "security: ebitmap start bit (%d) is "
-			       "beyond the end of the bitmap (%Zd)\n",
+			       "beyond the end of the bitmap (%u)\n",
 			       startbit, (e->highbit - mapunit));
 			goto bad;
 		}
@@ -433,9 +433,8 @@ int ebitmap_read(struct ebitmap *e, void *fp)
 
 		index = (startbit - n->startbit) / EBITMAP_UNIT_SIZE;
 		while (map) {
-			n->maps[index] = map & (-1UL);
-			map = map >> EBITMAP_UNIT_SIZE;
-			index++;
+			n->maps[index++] = map & (-1UL);
+			map = EBITMAP_SHIFT_UNIT_SIZE(map);
 		}
 	}
 ok:
diff --git a/security/selinux/ss/ebitmap.h b/security/selinux/ss/ebitmap.h
index e38a327..f283b43 100644
--- a/security/selinux/ss/ebitmap.h
+++ b/security/selinux/ss/ebitmap.h
@@ -21,6 +21,8 @@
 #define ...
From: James Morris
Date: Tuesday, October 9, 2007 - 4:23 pm

From: KaiGai Kohei <kaigai@ak.jp.nec.com>

* We add ebitmap_for_each_positive_bit() which enables to walk on
  any positive bit on the given ebitmap, to improve its performance
  using common bit-operations defined in linux/bitops.h.
  In the previous version, this logic was implemented using a combination
  of ebitmap_for_each_bit() and ebitmap_node_get_bit(), but is was worse
  in performance aspect.
  This logic is most frequestly used to compute a new AVC entry,
  so this patch can improve SELinux performance when AVC misses are happen.
* struct ebitmap_node is redefined as an array of "unsigned long", to get
  suitable for using find_next_bit() which is fasted than iteration of
  shift and logical operation, and to maximize memory usage allocated
  from general purpose slab.
* Any ebitmap_for_each_bit() are repleced by the new implementation
  in ss/service.c and ss/mls.c. Some of related implementation are
  changed, however, there is no incompatibility with the previous
  version.
* The width of any new line are less or equal than 80-chars.

The following benchmark shows the effect of this patch, when we
access many files which have different security context one after
another. The number is more than /selinux/avc/cache_threshold, so
any access always causes AVC misses.

      selinux-2.6      selinux-2.6-ebitmap
AVG:   22.763 [s]          8.750 [s]
STD:    0.265              0.019
------------------------------------------
1st:   22.558 [s]          8.786 [s]
2nd:   22.458 [s]          8.750 [s]
3rd:   22.478 [s]          8.754 [s]
4th:   22.724 [s]          8.745 [s]
5th:   22.918 [s]          8.748 [s]
6th:   22.905 [s]          8.764 [s]
7th:   23.238 [s]          8.726 [s]
8th:   22.822 [s]          8.729 [s]

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
---
 security/selinux/ss/ebitmap.c  |  281 ++++++++++++++++++++++-----------------
 ...
Previous thread: TPM driver changes to support multiple locality by Agarwal, Lomesh on Tuesday, October 9, 2007 - 3:51 pm. (13 messages)

Next thread: [PATCH] Reserve N process to root by Gustavo Chain on Tuesday, October 9, 2007 - 4:48 pm. (9 messages)