Yuichi Nakamura | 1 Feb 2008 05:59
Picon

Re: [patch] Tuning avtab to reduce memory usage

Hi.

On Thu, 31 Jan 2008 16:00:50 -0500
Stephen Smalley  wrote:
> 
> On Fri, 2007-08-24 at 11:55 +0900, Yuichi Nakamura wrote:
> > On Thu, 23 Aug 2007 09:15:25 -0400
> > Stephen Smalley  wrote:
> > > On Thu, 2007-08-23 at 09:57 +0900, Yuichi Nakamura wrote:
> > > > Following is updated patch to 2.6.22.
> > > > 
> > > > Signed-off-by: Yuichi Nakamura<ynakam@...>
> > > > ---
> > > >  security/selinux/ss/avtab.c       |   78 +++++++++++++++++++++++++++-----------
> > > >  security/selinux/ss/avtab.h       |   16 +++++--
> > > >  security/selinux/ss/conditional.c |    4 +
> > > >  security/selinux/ss/policydb.c    |    7 ---
> > > >  4 files changed, 73 insertions(+), 32 deletions(-)
> > > > diff -purN -X linux-2.6.22/Documentation/dontdiff
linux-2.6.22.orig/security/selinux/ss/avtab.c linux-2.6.22/security/selinux/ss/avtab.c
> > > > --- linux-2.6.22.orig/security/selinux/ss/avtab.c	2007-07-09 08:32:17.000000000 +0900
> > > > +++ linux-2.6.22/security/selinux/ss/avtab.c	2007-08-23 09:30:03.000000000 +0900
> > > > +int avtab_alloc(struct avtab *h, int nrules)
> > > 
> > > nrules should be u32 too.
> > Fixed.
> > 
> > > 
> > > And you should likely test for the degenerate case (nrules == 0) and
> > > bail on it.
(Continue reading)

Justin Mattock | 1 Feb 2008 07:36
Picon

usb_hcd_poll_rh_status (rh_timer_func)

Hello; Im in need of some help, first things first; thank you far for all the help so far, I need to find a good mailing.list for a problem that I have with power consumption on my laptop; to give you an idea of what im facing; running linux on a macbook pro the battery life is a whole 1:30hr, I've managed to move it up to 2:50hr with the kernel boot option of uhci-hcd.ignore=1, and radeontool power low, but seem to be at a wall with trying to figure out why usb_hcd_poll_rh_status (rh_timer_func) keeps waking the cpu from going into a deep sleep.  With using lsusb -vv I noticed remote wakeup with some of the devices? but still am unsure of what or where the Watts are being taken from, and why the wakeups keep occuring.
regards;
              --Justin P. Mattock
                   

Stephen Smalley | 1 Feb 2008 14:58
Picon

[patch] libsepol: tune avtab to reduce memory usage

Port of Yuichi Nakamura's tune avtab to reduce memory usage patch
from the kernel avtab to libsepol.

This patch decides the number of hash slots dynamically based on the
number of rules.  It also avoids allocating the avtab altogether when
reading policy modules, as they don't need it.

Signed-off-by:  Stephen Smalley <sds@...>

---

 checkpolicy/test/dispol.c               |    2 
 libsepol/include/sepol/policydb/avtab.h |   18 ++++--
 libsepol/src/avtab.c                    |   88 +++++++++++++++++++++++---------
 libsepol/src/conditional.c              |    4 +
 libsepol/src/expand.c                   |   20 +++++++
 libsepol/src/policydb.c                 |    7 --
 libsepol/src/write.c                    |   11 ++--
 7 files changed, 109 insertions(+), 41 deletions(-)

Index: trunk/libsepol/include/sepol/policydb/avtab.h
===================================================================
--- trunk/libsepol/include/sepol/policydb/avtab.h	(revision 2774)
+++ trunk/libsepol/include/sepol/policydb/avtab.h	(working copy)
 <at>  <at>  -1,6 +1,11  <at>  <at> 

 /* Author : Stephen Smalley, <sds@...> */

+/*
+ * Updated: Yuichi Nakamura <ynakam@...>
+ * 	Tuned number of hash slots for avtab to reduce memory usage
+ */
+
 /* Updated: Frank Mayer <mayerf@...> and Karl MacMillan <kmacmillan@...>
  *
  * 	Added conditional policy language extensions
 <at>  <at>  -75,10 +80,12  <at>  <at> 
 typedef struct avtab {
 	avtab_ptr_t *htable;
 	uint32_t nel;		/* number of elements */
+	uint32_t nslot;         /* number of hash slots */
+	uint16_t mask;          /* mask to compute hash func */
 } avtab_t;

 extern int avtab_init(avtab_t *);
-
+extern int avtab_alloc(avtab_t *, uint32_t);
 extern int avtab_insert(avtab_t * h, avtab_key_t * k, avtab_datum_t * d);

 extern avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k);
 <at>  <at>  -110,12 +117,11  <at>  <at> 

 extern avtab_ptr_t avtab_search_node_next(avtab_ptr_t node, int specified);

-#define AVTAB_HASH_BITS 15
-#define AVTAB_HASH_BUCKETS (1 << AVTAB_HASH_BITS)
-#define AVTAB_HASH_MASK (AVTAB_HASH_BUCKETS-1)
+#define MAX_AVTAB_HASH_BITS 13
+#define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS)
+#define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1)
+#define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS

-#define AVTAB_SIZE AVTAB_HASH_BUCKETS
-
 #endif				/* _AVTAB_H_ */

 /* FLASK */
Index: trunk/libsepol/src/conditional.c
===================================================================
--- trunk/libsepol/src/conditional.c	(revision 2774)
+++ trunk/libsepol/src/conditional.c	(working copy)
 <at>  <at>  -829,6 +829,10  <at>  <at> 

 	len = le32_to_cpu(buf[0]);

+	rc = avtab_alloc(&p->te_cond_avtab, p->te_avtab.nel);
+	if (rc)
+		goto err;
+
 	for (i = 0; i < len; i++) {
 		node = malloc(sizeof(cond_node_t));
 		if (!node)
Index: trunk/libsepol/src/policydb.c
===================================================================
--- trunk/libsepol/src/policydb.c	(revision 2774)
+++ trunk/libsepol/src/policydb.c	(working copy)
 <at>  <at>  -492,17 +492,14  <at>  <at> 

 	rc = roles_init(p);
 	if (rc)
-		goto out_free_avtab;
+		goto out_free_symtab;

 	rc = cond_policydb_init(p);
 	if (rc)
-		goto out_free_avtab;
+		goto out_free_symtab;
       out:
 	return rc;

-      out_free_avtab:
-	avtab_destroy(&p->te_avtab);
-
       out_free_symtab:
 	for (i = 0; i < SYM_NUM; i++) {
 		hashtab_destroy(p->symtab[i].table);
Index: trunk/libsepol/src/expand.c
===================================================================
--- trunk/libsepol/src/expand.c	(revision 2774)
+++ trunk/libsepol/src/expand.c	(working copy)
 <at>  <at>  -2137,6 +2137,16  <at>  <at> 
 	avrule_block_t *curblock;
 	int retval = -1;

+	if (avtab_alloc(&state->out->te_avtab, MAX_AVTAB_SIZE)) {
+		ERR(state->handle, "Out of Memory!");
+		return -1;
+	}
+
+	if (avtab_alloc(&state->out->te_cond_avtab, MAX_AVTAB_SIZE)) {
+		ERR(state->handle, "Out of Memory!");
+		return -1;
+	}
+
 	for (curblock = state->base->global; curblock != NULL;
 	     curblock = curblock->next) {
 		avrule_decl_t *decl = curblock->enabled;
 <at>  <at>  -2548,6 +2558,11  <at>  <at> 
 {
 	struct expand_avtab_data data;

+	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
+		ERR(NULL, "Out of memory!");
+		return -1;
+	}
+
 	data.expa = expa;
 	data.p = p;
 	return avtab_map(a, expand_avtab_node, &data);
 <at>  <at>  -2676,6 +2691,11  <at>  <at> 
 	avtab_ptr_t node;
 	int rc;

+	if (avtab_alloc(expa, MAX_AVTAB_SIZE)) {
+		ERR(NULL, "Out of memory!");
+		return -1;
+	}
+
 	*newl = NULL;
 	for (cur = l; cur; cur = cur->next) {
 		node = cur->node;
Index: trunk/libsepol/src/write.c
===================================================================
--- trunk/libsepol/src/write.c	(revision 2774)
+++ trunk/libsepol/src/write.c	(working copy)
 <at>  <at>  -229,9 +229,9  <at>  <at> 

 static inline void avtab_reset_merged(avtab_t * a)
 {
-	int i;
+	unsigned int i;
 	avtab_ptr_t cur;
-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < a->nslot; i++) {
 		for (cur = a->htable[i]; cur; cur = cur->next)
 			cur->merged = 0;
 	}
 <at>  <at>  -239,7 +239,8  <at>  <at> 

 static int avtab_write(struct policydb *p, avtab_t * a, struct policy_file *fp)
 {
-	int i, rc;
+	unsigned int i;
+	int rc;
 	avtab_t expa;
 	avtab_ptr_t cur;
 	uint32_t nel;
 <at>  <at>  -269,7 +270,7  <at>  <at> 
 			return POLICYDB_ERROR;
 	}

-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < a->nslot; i++) {
 		for (cur = a->htable[i]; cur; cur = cur->next) {
 			/* If old format, compute final nel.
 			   If new format, write out the items. */
 <at>  <at>  -290,7 +291,7  <at>  <at> 
 			goto out;
 		}
 		avtab_reset_merged(a);
-		for (i = 0; i < AVTAB_SIZE; i++) {
+		for (i = 0; i < a->nslot; i++) {
 			for (cur = a->htable[i]; cur; cur = cur->next) {
 				if (avtab_write_item(p, cur, fp, 1, 1, NULL)) {
 					rc = -1;
Index: trunk/libsepol/src/avtab.c
===================================================================
--- trunk/libsepol/src/avtab.c	(revision 2774)
+++ trunk/libsepol/src/avtab.c	(working copy)
 <at>  <at>  -1,6 +1,11  <at>  <at> 

 /* Author : Stephen Smalley, <sds@...> */

+/*
+ * Updated: Yuichi Nakamura <ynakam@...>
+ * 	Tuned number of hash slots for avtab to reduce memory usage
+ */
+
 /* Updated: Frank Mayer <mayerf@...>
  *          and Karl MacMillan <kmacmillan@...>
  *
 <at>  <at>  -44,11 +49,11  <at>  <at> 
 #include "debug.h"
 #include "private.h"

-#define AVTAB_HASH(keyp) \
-((keyp->target_class + \
- (keyp->target_type << 2) + \
- (keyp->source_type << 9)) & \
- AVTAB_HASH_MASK)
+static inline int avtab_hash(struct avtab_key *keyp, uint16_t mask)
+{
+	return ((keyp->target_class + (keyp->target_type << 2) +
+		 (keyp->source_type << 9)) & mask);
+}

 static avtab_ptr_t
 avtab_insert_node(avtab_t * h, int hvalue, avtab_ptr_t prev, avtab_key_t * key,
 <at>  <at>  -80,10 +85,10  <at>  <at> 
 	uint16_t specified =
 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);

-	if (!h)
+	if (!h || !h->htable)
 		return SEPOL_ENOMEM;

-	hvalue = AVTAB_HASH(key);
+	hvalue = avtab_hash(key, h->mask);
 	for (prev = NULL, cur = h->htable[hvalue];
 	     cur; prev = cur, cur = cur->next) {
 		if (key->source_type == cur->key.source_type &&
 <at>  <at>  -121,9 +126,9  <at>  <at> 
 	uint16_t specified =
 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);

-	if (!h)
+	if (!h || !h->htable)
 		return NULL;
-	hvalue = AVTAB_HASH(key);
+	hvalue = avtab_hash(key, h->mask);
 	for (prev = NULL, cur = h->htable[hvalue];
 	     cur; prev = cur, cur = cur->next) {
 		if (key->source_type == cur->key.source_type &&
 <at>  <at>  -153,10 +158,10  <at>  <at> 
 	uint16_t specified =
 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);

-	if (!h)
+	if (!h || !h->htable)
 		return NULL;

-	hvalue = AVTAB_HASH(key);
+	hvalue = avtab_hash(key, h->mask);
 	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
 		if (key->source_type == cur->key.source_type &&
 		    key->target_type == cur->key.target_type &&
 <at>  <at>  -188,10 +193,10  <at>  <at> 
 	uint16_t specified =
 	    key->specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);

-	if (!h)
+	if (!h || !h->htable)
 		return NULL;

-	hvalue = AVTAB_HASH(key);
+	hvalue = avtab_hash(key, h->mask);
 	for (cur = h->htable[hvalue]; cur; cur = cur->next) {
 		if (key->source_type == cur->key.source_type &&
 		    key->target_type == cur->key.target_type &&
 <at>  <at>  -242,13 +247,13  <at>  <at> 

 void avtab_destroy(avtab_t * h)
 {
-	int i;
+	unsigned int i;
 	avtab_ptr_t cur, temp;

 	if (!h || !h->htable)
 		return;

-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < h->nslot; i++) {
 		cur = h->htable[i];
 		while (cur != NULL) {
 			temp = cur;
 <at>  <at>  -259,19 +264,22  <at>  <at> 
 	}
 	free(h->htable);
 	h->htable = NULL;
+	h->nslot = 0;
+	h->mask = 0;
 }

 int avtab_map(avtab_t * h,
 	      int (*apply) (avtab_key_t * k,
 			    avtab_datum_t * d, void *args), void *args)
 {
-	int i, ret;
+	unsigned int i;
+	int ret;
 	avtab_ptr_t cur;

 	if (!h)
 		return 0;

-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < h->nslot; i++) {
 		cur = h->htable[i];
 		while (cur != NULL) {
 			ret = apply(&cur->key, &cur->datum, args);
 <at>  <at>  -285,25 +293,50  <at>  <at> 

 int avtab_init(avtab_t * h)
 {
-	int i;
+	h->htable = NULL;
+	h->nel = 0;
+	return 0;
+}

-	h->htable = malloc(sizeof(avtab_ptr_t) * AVTAB_SIZE);
+int avtab_alloc(avtab_t *h, uint32_t nrules)
+{
+	uint16_t mask = 0;
+	uint32_t shift = 0;
+	uint32_t work = nrules;
+	uint32_t nslot = 0;
+
+	if (nrules == 0)
+		goto out;
+
+	while (work) {
+		work  = work >> 1;
+		shift++;
+	}
+	if (shift > 2)
+		shift = shift - 2;
+	nslot = 1 << shift;
+	if (nslot > MAX_AVTAB_SIZE)
+		nslot = MAX_AVTAB_SIZE;
+	mask = nslot - 1;
+
+	h->htable = calloc(nslot, sizeof(avtab_ptr_t));
 	if (!h->htable)
 		return -1;
-	for (i = 0; i < AVTAB_SIZE; i++)
-		h->htable[i] = (avtab_ptr_t) NULL;
+out:
 	h->nel = 0;
+	h->nslot = nslot;
+	h->mask = mask;
 	return 0;
 }

 void avtab_hash_eval(avtab_t * h, char *tag)
 {
-	int i, chain_len, slots_used, max_chain_len;
+	unsigned int i, chain_len, slots_used, max_chain_len;
 	avtab_ptr_t cur;

 	slots_used = 0;
 	max_chain_len = 0;
-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < h->nslot; i++) {
 		cur = h->htable[i];
 		if (cur) {
 			slots_used++;
 <at>  <at>  -320,7 +353,7  <at>  <at> 

 	printf
 	    ("%s:  %d entries and %d/%d buckets used, longest chain length %d\n",
-	     tag, h->nel, slots_used, AVTAB_SIZE, max_chain_len);
+	     tag, h->nel, slots_used, h->nslot, max_chain_len);
 }

 /* Ordering of datums in the original avtab format in the policy file. */
 <at>  <at>  -471,6 +504,13  <at>  <at> 
 		ERR(fp->handle, "table is empty");
 		goto bad;
 	}
+
+	rc = avtab_alloc(a, nel);
+	if (rc) {
+		ERR(fp->handle, "out of memory");
+		goto bad;
+	}
+
 	for (i = 0; i < nel; i++) {
 		rc = avtab_read_item(fp, vers, a, avtab_insertf, NULL);
 		if (rc) {
Index: trunk/checkpolicy/test/dispol.c
===================================================================
--- trunk/checkpolicy/test/dispol.c	(revision 2774)
+++ trunk/checkpolicy/test/dispol.c	(working copy)
 <at>  <at>  -169,7 +169,7  <at>  <at> 
 	}

 	/* hmm...should have used avtab_map. */
-	for (i = 0; i < AVTAB_SIZE; i++) {
+	for (i = 0; i < expa.nslot; i++) {
 		for (cur = expa.htable[i]; cur; cur = cur->next) {
 			render_av_rule(&cur->key, &cur->datum, what, p, fp);
 		}

--

-- 
Stephen Smalley
National Security Agency

Stephen Smalley | 1 Feb 2008 15:11
Picon

[patch] libsemanage: free base immediately after expand

Drop the base module immediately after expanding, so that the memory can
be reused for the remainder of the transaction.

Signed-off-by:  Stephen Smalley <sds@...>

---

 libsemanage/src/direct_api.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

Index: trunk/libsemanage/src/direct_api.c
===================================================================
--- trunk/libsemanage/src/direct_api.c	(revision 2774)
+++ trunk/libsemanage/src/direct_api.c	(working copy)
 <at>  <at>  -642,6 +642,9  <at>  <at> 
 		retval = semanage_expand_sandbox(sh, base, &out);
 		if (retval < 0)
 			goto cleanup;
+	
+		sepol_module_package_free(base);
+		base = NULL;

 		dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase,
 				      out);
 <at>  <at>  -718,7 +721,6  <at>  <at> 
 	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);

 	free(mod_filenames);
-	sepol_module_package_free(base);
 	sepol_policydb_free(out);
 	semanage_release_trans_lock(sh);

--

-- 
Stephen Smalley
National Security Agency

Joshua Brindle | 1 Feb 2008 15:12

[PATCH] optionally consume input at expand time to save memory

This patch should reduce the amount of peak memory required to expand 
the policy by consuming part of the input policy during expansion. It 
reduced the rss of semodule_expand with a full refpolicy from 86 to 66 meg.

On a side note, if anyone knows of a good tool for profiling heap usage 
I'd like to hear, I've tried valgrind massif, google-perftools, and 
smaps and none of them seem to work that well...

Signed-off-by: Joshua Brindle <method@...>

Index: libsemanage/src/semanage_store.c
===================================================================
--- libsemanage/src/semanage_store.c    (revision 2774)
+++ libsemanage/src/semanage_store.c    (working copy)
 <at>  <at>  -1636,6 +1636,8  <at>  <at> 
        if (sepol_policydb_create(&out))
                goto err;

+       sepol_set_expand_consume_base(sh->sepolh, 1);
+
        if (sepol_expand_module(sh->sepolh,
                                sepol_module_package_get_policy(base), out, 0,
                                expand_check)
Index: libsepol/include/sepol/handle.h
===================================================================
--- libsepol/include/sepol/handle.h     (revision 2774)
+++ libsepol/include/sepol/handle.h     (working copy)
 <at>  <at>  -11,6 +11,10  <at>  <at> 
  * not disable dontaudits, 1 disables them */
 void sepol_set_disable_dontaudit(sepol_handle_t * sh, int disable_dontaudit);

+/* Set whether module_expand() should consume the base policy passed in.
+ * This should reduce the amount of memory required to expand the policy. */
+void sepol_set_expand_consume_base(sepol_handle_t * sh, int consume_base);
+
 /* Destroy a sepol handle. */
 void sepol_handle_destroy(sepol_handle_t *);

Index: libsepol/src/handle.h
===================================================================
--- libsepol/src/handle.h       (revision 2774)
+++ libsepol/src/handle.h       (working copy)
 <at>  <at>  -16,6 +16,7  <at>  <at> 
        void *msg_callback_arg;

        int disable_dontaudit;
+       int expand_consume_base;

 };

Index: libsepol/src/libsepol.map
===================================================================
--- libsepol/src/libsepol.map   (revision 2774)
+++ libsepol/src/libsepol.map   (working copy)
 <at>  <at>  -13,5 +13,6  <at>  <at> 
        sepol_policy_kern_*;
        sepol_policy_file_*;
        sepol_set_disable_dontaudit;
+       sepol_set_expand_consume_base;
   local: *;
 };
Index: libsepol/src/expand.c
===================================================================
--- libsepol/src/expand.c       (revision 2774)
+++ libsepol/src/expand.c       (working copy)
 <at>  <at>  -2134,17 +2134,17  <at>  <at> 
  */
 static int copy_and_expand_avrule_block(expand_state_t * state)
 {
-       avrule_block_t *curblock;
+       avrule_block_t *curblock = state->base->global;
+       avrule_block_t *prevblock;
        int retval = -1;

-       for (curblock = state->base->global; curblock != NULL;
-            curblock = curblock->next) {
+       while (curblock) {
                avrule_decl_t *decl = curblock->enabled;
                avrule_t *cur_avrule;

                if (decl == NULL) {
                        /* nothing was enabled within this block */
-                       continue;
+                       goto cont;
                }

                /* copy role allows and role trans */
 <at>  <at>  -2186,6 +2186,18  <at>  <at> 
                /* copy conditional rules */
                if (cond_node_copy(state, decl->cond_list))
                        goto cleanup;
+
+      cont:
+               prevblock = curblock;
+               curblock = curblock->next;
+
+               if (state->handle && state->handle->expand_consume_base) {
+                       /* set base top avrule block in case there
+                        * is an error condition and the policy needs 
+                        * to be destroyed */
+                       state->base->global = curblock;
+                       avrule_block_destroy(prevblock);
+               }
        }

        retval = 0;
Index: libsepol/src/handle.c
===================================================================
--- libsepol/src/handle.c       (revision 2774)
+++ libsepol/src/handle.c       (working copy)
 <at>  <at>  -16,6 +16,7  <at>  <at> 

        /* by default do not disable dontaudits */
        sh->disable_dontaudit = 0;
+       sh->expand_consume_base = 0;

        return sh;
 }
 <at>  <at>  -26,6 +27,12  <at>  <at> 
        sh->disable_dontaudit = disable_dontaudit;
 }

+void sepol_set_expand_consume_base(sepol_handle_t *sh, int consume_base)
+{
+       assert(sh != NULL);
+       sh->expand_consume_base = consume_base;
+}
+
 void sepol_handle_destroy(sepol_handle_t * sh)
 {
        free(sh);
Index: policycoreutils/semodule_expand/semodule_expand.c
===================================================================
--- policycoreutils/semodule_expand/semodule_expand.c   (revision 2774)
+++ policycoreutils/semodule_expand/semodule_expand.c   (working copy)
 <at>  <at>  -44,6 +44,7  <at>  <at> 
        sepol_policydb_t *out, *p;
        FILE *fp, *outfile;
        int check_assertions = 1;
+       sepol_handle_t *handle;

        while ((ch = getopt(argc, argv, "c:Vva")) != EOF) {
                switch (ch) {
 <at>  <at>  -105,6 +106,10  <at>  <at> 
        basename = argv[optind++];
        outname = argv[optind];

+       handle = sepol_handle_create();
+       if (!handle)
+               exit(1);
+
        if (sepol_policy_file_create(&pf)) {
                fprintf(stderr, "%s:  Out of memory\n", argv[0]);
                exit(1);
 <at>  <at>  -132,7 +137,7  <at>  <at> 

        /* linking the base takes care of enabling optional avrules */
        p = sepol_module_package_get_policy(base);
-       if (sepol_link_modules(NULL, p, NULL, 0, 0)) {
+       if (sepol_link_modules(handle, p, NULL, 0, 0)) {
                fprintf(stderr, "%s:  Error while enabling avrules\n", argv[0]);
                exit(1);
        }
 <at>  <at>  -144,7 +149,9  <at>  <at> 
                exit(1);
        }

-       if (sepol_expand_module(NULL, p, out, verbose, check_assertions)) {
+       sepol_set_expand_consume_base(handle, 1);
+
+       if (sepol_expand_module(handle, p, out, verbose, check_assertions)) {
                fprintf(stderr, "%s:  Error while expanding policy\n", argv[0]);
                exit(1);
        }
 <at>  <at>  -174,6 +181,7  <at>  <at> 
                exit(1);
        }
        fclose(outfile);
+       sepol_handle_destroy(handle);
        sepol_policydb_free(out);
        sepol_policy_file_free(pf);

James Antill | 1 Feb 2008 15:23
Picon
Favicon
Gravatar

Re: genhomedircon is broken in libsemanage


 Mostly FYI, although there is one minor error dealing with a malloc()
error case.

On Thu, 2008-01-31 at 10:13 -0500, Todd C. Miller wrote:

> Index: trunk/libsemanage/src/genhomedircon.c
> ===================================================================
> --- trunk/libsemanage/src/genhomedircon.c	(revision 2771)
> +++ trunk/libsemanage/src/genhomedircon.c	(working copy)
>  <at>  <at>  -24,6 +24,8  <at>  <at> 
>  #include <semanage/seusers_policy.h>
>  #include <semanage/users_policy.h>
>  #include <semanage/user_record.h>
> +#include <semanage/fcontext_record.h>
> +#include <semanage/fcontexts_policy.h>
>  #include <sepol/context.h>
>  #include <sepol/context_record.h>
>  #include "semanage_store.h"
>  <at>  <at>  -45,6 +47,7  <at>  <at> 
>  #include <pwd.h>
>  #include <errno.h>
>  #include <unistd.h>
> +#include <regex.h>
>  
>  /* paths used in get_home_dirs() */
>  #define PATH_ETC_USERADD "/etc/default/useradd"
>  <at>  <at>  -101,6 +104,11  <at>  <at> 
>  	const char *replace_with;
>  } replacement_pair_t;
>  
> +typedef struct {
> +	const char *dir;
> +	int matched;
> +} fc_match_handle_t;
> +
>  static semanage_list_t *default_shell_list(void)
>  {
>  	semanage_list_t *list = NULL;
>  <at>  <at>  -150,10 +158,70  <at>  <at> 
>  	return list;
>  }
>  
> +/* Helper function called via semanage_fcontext_iterate() */
> +static int fcontext_matches(const semanage_fcontext_t *fcontext, void *varg)
> +{
> +	const char *oexpr = semanage_fcontext_get_expr(fcontext);
> +	fc_match_handle_t *handp = varg;
> +	struct Ustr *expr;
> +	regex_t re;
> +	size_t n;
> +	int type, retval = -1;
> +
> +	/* Only match ALL or DIR */
> +	type = semanage_fcontext_get_type(fcontext);
> +	if (type != SEMANAGE_FCONTEXT_ALL && type != SEMANAGE_FCONTEXT_ALL)
> +		return 0;
> +
> +	/* Convert oexpr into a Ustr and anchor it at the beginning */
> +	expr = ustr_dup_cstr("^");
> +	if (expr == USTR_NULL)
> +		goto done;
> +	ustr_ins_cstr(&expr, 1, oexpr);

 This works fine, but you can use:

          ustr_add_cstr(&expr, oexpr)

...which appends data, so you don't need to keep track of the offset.

> +	if (expr == USTR_NULL)

 This will never be true, you either want to test the return value or
use the "has had a memory error" flag:

          if (ustr_enomem(expr))

> +		goto done;
> +	n = ustr_len(expr);
> +
> +	/* Strip off trailing ".+" or ".*" */
> +	if (ustr_cmp_suffix_cstr_eq(expr, ".+") ||
> +	    ustr_cmp_suffix_cstr_eq(expr, ".*")) {
> +		if (!ustr_del_subustr(&expr, n - 1, 2))

 This works fine, but you can use:

                  if (!ustr_del(&expr, 2))

...which always removes the last X bytes.

> +			goto done;
> +		n -= 2;
> +	}
> +
> +	/* Strip off trailing "(/.*)?" */
> +	if (ustr_cmp_suffix_cstr_eq(expr, "(/.*)?")) {
> +		if (!ustr_del_subustr(&expr, n - 5, 6))
> +			goto done;
> +		n -= 6;
> +	}
> +
> +	/* Append pattern to eat up trailing slashes */
> +	if (!ustr_ins_cstr(&expr, n, "/*$"))
> +		goto done;
> +
> +	/* Check dir against expr */
> +	if (regcomp(&re, ustr_cstr(expr), REG_EXTENDED) != 0)
> +		goto done;
> +	if (regexec(&re, handp->dir, 0, NULL, 0) == 0)
> +		handp->matched = 1;
> +	regfree(&re);
> +
> +	retval = 0;
> +
> +done:
> +	if (expr)
> +		ustr_free(expr);

 This works fine, but:

 ustr_free(NULL);

...is guaranteed to be a noop, much like libc free(NULL).

> +
> +	return retval;
> +}

--

-- 
James Antill <james.antill@...>
Red Hat
Daniel J Walsh | 1 Feb 2008 16:01
Picon
Favicon
Gravatar

I have spit out my current diffs in policy on fedoraproject.org


http://people.fedoraproject.org/~dwalsh/Policy/

Patch is now up to 28000 lines.

I have it split into 147 patches.

Kernel patches should be fairly easy to merge,
System patches other than userdomain should not be difficult.

Then we get to service/apps ...

Going forward this is going to get more difficult.  I think we need more
people with the ability to update the reference policy.  Even if they
just cherry pick through the differences in my patches and upstream.  I
don't believe one person can keep up with the volume of changes.

Stephen Smalley | 1 Feb 2008 16:05
Picon

Re: I have spit out my current diffs in policy on fedoraproject.org


On Fri, 2008-02-01 at 10:01 -0500, Daniel J Walsh wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> http://people.fedoraproject.org/~dwalsh/Policy/
> 
> Patch is now up to 28000 lines.
> 
> I have it split into 147 patches.
> 
> Kernel patches should be fairly easy to merge,
> System patches other than userdomain should not be difficult.
> 
> Then we get to service/apps ...
> 
> 
> Going forward this is going to get more difficult.  I think we need more
> people with the ability to update the reference policy.  Even if they
> just cherry pick through the differences in my patches and upstream.  I
> don't believe one person can keep up with the volume of changes.

Maybe create a fedora branch of refpolicy?

--

-- 
Stephen Smalley
National Security Agency

Stephen Smalley | 1 Feb 2008 16:31
Picon

RE: UNCLASSIFIED - Realtime Scheduling...


On Thu, 2008-01-31 at 19:03 +0000, HAWKER, Dan 2 (external) wrote:
> 
> > 
> > At present, SELinux acts as an orthogonal mechanism to Linux 
> > discretionary controls, and thus you must be authorized by 
> > both Linux DAC and by SELinux MAC checks to perform any 
> > operation.  So to invoke a call that requires privilege (in 
> > Linux, "capability"), your program has to at least start with 
> > uid 0 in addition to running in a SELinux domain that is 
> > allowed the capability by policy.  The program can shed uid 0 
> > upon startup while retaining certain capabilities; you can 
> > see an example of that in newrole.  If your kernel supports 
> > file capabilities, you could try using that instead of setuid 0.
> > 
> > We have previously proposed a patch to selinux that would 
> > allow it to authoritatively grant a capability to a non-uid-0 
> > process based on policy (see mailing list archives), and we 
> > may proceed with that patch to support that kind of need, but 
> > it isn't in any distro kernels today.
> 
> Hi Stephen,
> 
> Thanks for that, its as I thought. I'll pass on the info to the
> developer.
> 
> Regarding the patch, I see that was back in June 07, (not that far back
> admitedly, but SELinux moves apace), however I presume it *does what it
> says on the tin* and applies simply enough???
> 
> I'll take a look and see how we get on.

I deferred submitting it for mainline because there was a fair amount of
concern from others about the implications of the change, as you can see
from the responses.

Nonetheless, I think it would be a useful feature for certain user
communities, so we should likely re-base and submit it.

It won't apply cleanly against the latest kernel because the class value
I used for it has since been taken for another class.

Unless you are already using a patched kernel for some reason, I think
you'd be better off just using the mechanisms present in your existing
kernel, e.g. make the program setuid, have it shed unnecessary
capabilities and uid 0 at startup, and use policy to protect and confine
it.  See newrole for an example.  Otherwise you have to carry the patch
yourself, deal with any side effects, invalidate any support agreements
you might have with the vendor, etc.

--

-- 
Stephen Smalley
National Security Agency

Joshua Brindle | 1 Feb 2008 16:39

Re: [patch] libsemanage: free base immediately after expand

Stephen Smalley wrote:
> Drop the base module immediately after expanding, so that the memory can
> be reused for the remainder of the transaction.
>
> Signed-off-by:  Stephen Smalley <sds@...>
>
>   

Acked-By: Joshua Brindle <method@...>

> ---
>
>  libsemanage/src/direct_api.c |    4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
>
> Index: trunk/libsemanage/src/direct_api.c
> ===================================================================
> --- trunk/libsemanage/src/direct_api.c	(revision 2774)
> +++ trunk/libsemanage/src/direct_api.c	(working copy)
>  <at>  <at>  -642,6 +642,9  <at>  <at> 
>  		retval = semanage_expand_sandbox(sh, base, &out);
>  		if (retval < 0)
>  			goto cleanup;
> +	
> +		sepol_module_package_free(base);
> +		base = NULL;
>  
>  		dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase,
>  				      out);
>  <at>  <at>  -718,7 +721,6  <at>  <at> 
>  	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
>  
>  	free(mod_filenames);
> -	sepol_module_package_free(base);
>  	sepol_policydb_free(out);
>  	semanage_release_trans_lock(sh);
>  
>
>   


Gmane