diff mbox series

[3/4] selinux: avtab iteration macros

Message ID 20230929195617.65120-4-jsatterfield.linux@gmail.com (mailing list archive)
State Changes Requested
Delegated to: Paul Moore
Headers show
Series selinux: avtab arrays and refactors | expand

Commit Message

Jacob Satterfield Sept. 29, 2023, 7:56 p.m. UTC
Similar to the list_for_each macros in list.h, this patch adds two
macros that iterates an avtab_node linked list (avtab_chain_for_each and
avtab_chain_for_each_prev). This has two benefits: it reduces the amount
of duplicative code for iteration and it makes changes to the underlying
hashtable data structure easier as there are fewer places to update.

Signed-off-by: Jacob Satterfield <jsatterfield.linux@gmail.com>
---
 security/selinux/ss/avtab.c | 40 ++++++++++++++++---------------------
 1 file changed, 17 insertions(+), 23 deletions(-)

Comments

Stephen Smalley Oct. 2, 2023, 2:58 p.m. UTC | #1
On Fri, Sep 29, 2023 at 3:56 PM Jacob Satterfield
<jsatterfield.linux@gmail.com> wrote:
>
> Similar to the list_for_each macros in list.h, this patch adds two
> macros that iterates an avtab_node linked list (avtab_chain_for_each and
> avtab_chain_for_each_prev). This has two benefits: it reduces the amount
> of duplicative code for iteration and it makes changes to the underlying
> hashtable data structure easier as there are fewer places to update.

You will need/want an equivalent to list_for_each_safe() or open-code
it to handle avtab_destroy() below.

>
> Signed-off-by: Jacob Satterfield <jsatterfield.linux@gmail.com>
> ---
>  security/selinux/ss/avtab.c | 40 ++++++++++++++++---------------------
>  1 file changed, 17 insertions(+), 23 deletions(-)
>
> diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
> index 1cd4fed30bf7..e8046eda7140 100644
> --- a/security/selinux/ss/avtab.c
> +++ b/security/selinux/ss/avtab.c
> @@ -223,20 +223,17 @@ avtab_search_node_next(struct avtab_node *node, u16 specified)
>  void avtab_destroy(struct avtab *h)
>  {
>         u32 i;
> -       struct avtab_node *cur, *temp;
> +       struct avtab_node *cur;
>
>         if (!h)
>                 return;
>
>         for (i = 0; i < h->nslot; i++) {
> -               cur = h->htable[i];
> -               while (cur) {
> -                       temp = cur;
> -                       cur = cur->next;
> -                       if (temp->key.specified & AVTAB_XPERMS)
> +               avtab_chain_for_each(cur, h, i) {
> +                       if (cur->key.specified & AVTAB_XPERMS)
>                                 kmem_cache_free(avtab_xperms_cachep,
> -                                               temp->datum.u.xperms);
> -                       kmem_cache_free(avtab_node_cachep, temp);
> +                                               cur->datum.u.xperms);
> +                       kmem_cache_free(avtab_node_cachep, cur);
>                 }
>         }
>         kvfree(h->htable);

This requires an avtab_chain_for_each_safe() or similar since it frees the node.
Jacob Satterfield Oct. 4, 2023, 5:03 p.m. UTC | #2
On Mon, Oct 2, 2023 at 10:58 AM Stephen Smalley
<stephen.smalley.work@gmail.com> wrote:
>
> On Fri, Sep 29, 2023 at 3:56 PM Jacob Satterfield
> <jsatterfield.linux@gmail.com> wrote:
> >
> > Similar to the list_for_each macros in list.h, this patch adds two
> > macros that iterates an avtab_node linked list (avtab_chain_for_each and
> > avtab_chain_for_each_prev). This has two benefits: it reduces the amount
> > of duplicative code for iteration and it makes changes to the underlying
> > hashtable data structure easier as there are fewer places to update.
>
> You will need/want an equivalent to list_for_each_safe() or open-code
> it to handle avtab_destroy() below.
>
> >
> > Signed-off-by: Jacob Satterfield <jsatterfield.linux@gmail.com>
> > ---
> >  security/selinux/ss/avtab.c | 40 ++++++++++++++++---------------------
> >  1 file changed, 17 insertions(+), 23 deletions(-)
> >
> > diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
> > index 1cd4fed30bf7..e8046eda7140 100644
> > --- a/security/selinux/ss/avtab.c
> > +++ b/security/selinux/ss/avtab.c
> > @@ -223,20 +223,17 @@ avtab_search_node_next(struct avtab_node *node, u16 specified)
> >  void avtab_destroy(struct avtab *h)
> >  {
> >         u32 i;
> > -       struct avtab_node *cur, *temp;
> > +       struct avtab_node *cur;
> >
> >         if (!h)
> >                 return;
> >
> >         for (i = 0; i < h->nslot; i++) {
> > -               cur = h->htable[i];
> > -               while (cur) {
> > -                       temp = cur;
> > -                       cur = cur->next;
> > -                       if (temp->key.specified & AVTAB_XPERMS)
> > +               avtab_chain_for_each(cur, h, i) {
> > +                       if (cur->key.specified & AVTAB_XPERMS)
> >                                 kmem_cache_free(avtab_xperms_cachep,
> > -                                               temp->datum.u.xperms);
> > -                       kmem_cache_free(avtab_node_cachep, temp);
> > +                                               cur->datum.u.xperms);
> > +                       kmem_cache_free(avtab_node_cachep, cur);
> >                 }
> >         }
> >         kvfree(h->htable);
>
> This requires an avtab_chain_for_each_safe() or similar since it frees the node.

Great catch! Since this separate macro would only have one invocation,
it would make the code less readable without any benefit. I have
reverted the changes to avtab_destroy() for the next spin.

Thanks!
-Jacob
diff mbox series

Patch

diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c
index 1cd4fed30bf7..e8046eda7140 100644
--- a/security/selinux/ss/avtab.c
+++ b/security/selinux/ss/avtab.c
@@ -27,6 +27,13 @@ 
 static struct kmem_cache *avtab_node_cachep __ro_after_init;
 static struct kmem_cache *avtab_xperms_cachep __ro_after_init;
 
+#define avtab_chain_for_each(pos, tab, slot) \
+	for (pos = (tab)->htable[slot]; pos; pos = pos->next)
+
+#define avtab_chain_for_each_prev(pos, prev, tab, slot) \
+	for (prev = NULL, pos = (tab)->htable[slot]; pos; \
+	prev = pos, pos = pos->next)
+
 /* Based on MurmurHash3, written by Austin Appleby and placed in the
  * public domain.
  */
@@ -129,9 +136,7 @@  static int avtab_insert(struct avtab *h, const struct avtab_key *key,
 		return -EINVAL;
 
 	hvalue = avtab_hash(key, h->mask);
-	for (prev = NULL, cur = h->htable[hvalue];
-	     cur;
-	     prev = cur, cur = cur->next) {
+	avtab_chain_for_each_prev(cur, prev, h, hvalue) {
 		cmp = avtab_node_cmp(key, &cur->key);
 		/* extended perms may not be unique */
 		if (unlikely(cmp == 0 && !(key->specified & AVTAB_XPERMS)))
@@ -163,9 +168,7 @@  struct avtab_node *avtab_insert_nonunique(struct avtab *h,
 	if (!h || !h->nslot || h->nel == U32_MAX)
 		return NULL;
 	hvalue = avtab_hash(key, h->mask);
-	for (prev = NULL, cur = h->htable[hvalue];
-	     cur;
-	     prev = cur, cur = cur->next) {
+	avtab_chain_for_each_prev(cur, prev, h, hvalue) {
 		cmp = avtab_node_cmp(key, &cur->key);
 		if (cmp <= 0)
 			break;
@@ -180,16 +183,13 @@  struct avtab_node *avtab_insert_nonunique(struct avtab *h,
 struct avtab_node *avtab_search_node(struct avtab *h,
 				     const struct avtab_key *key)
 {
-	u32 hvalue;
 	struct avtab_node *cur;
 	int cmp;
 
 	if (!h || !h->nslot)
 		return NULL;
 
-	hvalue = avtab_hash(key, h->mask);
-	for (cur = h->htable[hvalue]; cur;
-	     cur = cur->next) {
+	avtab_chain_for_each(cur, h, avtab_hash(key, h->mask)) {
 		cmp = avtab_node_cmp(key, &cur->key);
 		if (cmp == 0)
 			return cur;
@@ -223,20 +223,17 @@  avtab_search_node_next(struct avtab_node *node, u16 specified)
 void avtab_destroy(struct avtab *h)
 {
 	u32 i;
-	struct avtab_node *cur, *temp;
+	struct avtab_node *cur;
 
 	if (!h)
 		return;
 
 	for (i = 0; i < h->nslot; i++) {
-		cur = h->htable[i];
-		while (cur) {
-			temp = cur;
-			cur = cur->next;
-			if (temp->key.specified & AVTAB_XPERMS)
+		avtab_chain_for_each(cur, h, i) {
+			if (cur->key.specified & AVTAB_XPERMS)
 				kmem_cache_free(avtab_xperms_cachep,
-						temp->datum.u.xperms);
-			kmem_cache_free(avtab_node_cachep, temp);
+						cur->datum.u.xperms);
+			kmem_cache_free(avtab_node_cachep, cur);
 		}
 	}
 	kvfree(h->htable);
@@ -307,10 +304,8 @@  void avtab_hash_eval(struct avtab *h, const char *tag)
 		if (cur) {
 			slots_used++;
 			chain_len = 0;
-			while (cur) {
+			avtab_chain_for_each(cur, h, i)
 				chain_len++;
-				cur = cur->next;
-			}
 
 			if (chain_len > max_chain_len)
 				max_chain_len = chain_len;
@@ -593,8 +588,7 @@  int avtab_write(struct policydb *p, struct avtab *a, void *fp)
 		return rc;
 
 	for (i = 0; i < a->nslot; i++) {
-		for (cur = a->htable[i]; cur;
-		     cur = cur->next) {
+		avtab_chain_for_each(cur, a, i) {
 			rc = avtab_write_item(p, cur, fp);
 			if (rc)
 				return rc;