diff mbox series

[RFC] libsepol/cil: support parallel neverallow checks

Message ID 20230706141329.57661-1-cgzones@googlemail.com (mailing list archive)
State Changes Requested
Delegated to: Petr Lautrbach
Headers show
Series [RFC] libsepol/cil: support parallel neverallow checks | expand

Commit Message

Christian Göttsche July 6, 2023, 2:13 p.m. UTC
Add support to check for neverallow assertions in parallel.  Since the
policy is not modified during those checks there needs to be no
extensive locking.

The checks are run by semodule(8) if the semanage.conf(5) setting
expand-check is set.

Implement the parallel procedure via OpenMP, to minimize code changes
and to allow users a simple way to enable or disable the functionality
at build time.  Currently the support opt-in.

Example benchmark:

    Benchmark 1: ./test_load_wip.sh (serial)
      Time (mean ± σ):      3.485 s ±  0.019 s    [User: 0.003 s, System: 0.002 s]
      Range (min … max):    3.455 s …  3.501 s    5 runs

    Benchmark 1: ./test_load_wip.sh (parallel)
      Time (mean ± σ):      2.443 s ±  0.035 s    [User: 0.004 s, System: 0.001 s]
      Range (min … max):    2.411 s …  2.500 s    5 runs

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libsepol/cil/src/cil_binary.c | 60 ++++++++++++++++++++++++++++-------
 1 file changed, 48 insertions(+), 12 deletions(-)

Comments

James Carter July 31, 2023, 1:51 p.m. UTC | #1
On Thu, Jul 6, 2023 at 10:22 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Add support to check for neverallow assertions in parallel.  Since the
> policy is not modified during those checks there needs to be no
> extensive locking.
>
> The checks are run by semodule(8) if the semanage.conf(5) setting
> expand-check is set.
>
> Implement the parallel procedure via OpenMP, to minimize code changes
> and to allow users a simple way to enable or disable the functionality
> at build time.  Currently the support opt-in.
>
> Example benchmark:
>
>     Benchmark 1: ./test_load_wip.sh (serial)
>       Time (mean ± σ):      3.485 s ±  0.019 s    [User: 0.003 s, System: 0.002 s]
>       Range (min … max):    3.455 s …  3.501 s    5 runs
>
>     Benchmark 1: ./test_load_wip.sh (parallel)
>       Time (mean ± σ):      2.443 s ±  0.035 s    [User: 0.004 s, System: 0.001 s]
>       Range (min … max):    2.411 s …  2.500 s    5 runs
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Needs a "-fopenmp" when building.

I am not seeing very much change (1.8 sec originally, 1.6 sec with this patch).
Jim

> ---
>  libsepol/cil/src/cil_binary.c | 60 ++++++++++++++++++++++++++++-------
>  1 file changed, 48 insertions(+), 12 deletions(-)
>
> diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
> index c4ee2380..7f6212e3 100644
> --- a/libsepol/cil/src/cil_binary.c
> +++ b/libsepol/cil/src/cil_binary.c
> @@ -4828,8 +4828,11 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
>
>                 rc = check_assertion(pdb, rule);
>                 if (rc == CIL_TRUE) {
> -                       *violation = CIL_TRUE;
> -                       rc = __cil_print_neverallow_failure(db, node);
> +                       #pragma omp critical (output)
> +                       {
> +                               *violation = CIL_TRUE;
> +                               rc = __cil_print_neverallow_failure(db, node);
> +                       }
>                         if (rc != SEPOL_OK) {
>                                 goto exit;
>                         }
> @@ -4850,8 +4853,11 @@ static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
>                         rule->xperms = item->data;
>                         rc = check_assertion(pdb, rule);
>                         if (rc == CIL_TRUE) {
> -                               *violation = CIL_TRUE;
> -                               rc = __cil_print_neverallow_failure(db, node);
> +                               #pragma omp critical (output)
> +                               {
> +                                       *violation = CIL_TRUE;
> +                                       rc = __cil_print_neverallow_failure(db, node);
> +                               }
>                                 if (rc != SEPOL_OK) {
>                                         goto exit;
>                                 }
> @@ -4876,18 +4882,48 @@ exit:
>
>  static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows, int *violation)
>  {
> -       int rc = SEPOL_OK;
> -       struct cil_list_item *item;
> +       int rc_sync = SEPOL_OK;
> +
> +       #pragma omp parallel
> +       {
> +
> +               #pragma omp single
> +               {
> +
> +                       struct cil_list_item *item;
> +                       cil_list_for_each(item, neverallows) {
> +
> +                               struct cil_tree_node *node = item->data;
> +                               int rc_test;
> +
> +                               #pragma omp task default(none) firstprivate(node, db, pdb, violation) shared(rc_sync) untied
> +                               {
> +                                       int rc_task = cil_check_neverallow(
> +                                               db,
> +                                               pdb,
> +                                               node,
> +                                               violation);
> +
> +                                       if (rc_task != SEPOL_OK) {
> +                                               #pragma omp atomic write
> +                                               rc_sync = rc_task;
> +                                       }
> +                               }
> +
> +                               #pragma omp atomic read
> +                               rc_test = rc_sync;
> +
> +                               if (rc_test != SEPOL_OK)
> +                                       break;
> +
> +                       }
>
> -       cil_list_for_each(item, neverallows) {
> -               rc = cil_check_neverallow(db, pdb, item->data, violation);
> -               if (rc != SEPOL_OK) {
> -                       goto exit;
>                 }
> +
> +               #pragma omp taskwait
>         }
>
> -exit:
> -       return rc;
> +       return rc_sync;
>  }
>
>  static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[])
> --
> 2.40.1
>
diff mbox series

Patch

diff --git a/libsepol/cil/src/cil_binary.c b/libsepol/cil/src/cil_binary.c
index c4ee2380..7f6212e3 100644
--- a/libsepol/cil/src/cil_binary.c
+++ b/libsepol/cil/src/cil_binary.c
@@ -4828,8 +4828,11 @@  static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
 
 		rc = check_assertion(pdb, rule);
 		if (rc == CIL_TRUE) {
-			*violation = CIL_TRUE;
-			rc = __cil_print_neverallow_failure(db, node);
+			#pragma omp critical (output)
+			{
+				*violation = CIL_TRUE;
+				rc = __cil_print_neverallow_failure(db, node);
+			}
 			if (rc != SEPOL_OK) {
 				goto exit;
 			}
@@ -4850,8 +4853,11 @@  static int cil_check_neverallow(const struct cil_db *db, policydb_t *pdb, struct
 			rule->xperms = item->data;
 			rc = check_assertion(pdb, rule);
 			if (rc == CIL_TRUE) {
-				*violation = CIL_TRUE;
-				rc = __cil_print_neverallow_failure(db, node);
+				#pragma omp critical (output)
+				{
+					*violation = CIL_TRUE;
+					rc = __cil_print_neverallow_failure(db, node);
+				}
 				if (rc != SEPOL_OK) {
 					goto exit;
 				}
@@ -4876,18 +4882,48 @@  exit:
 
 static int cil_check_neverallows(const struct cil_db *db, policydb_t *pdb, struct cil_list *neverallows, int *violation)
 {
-	int rc = SEPOL_OK;
-	struct cil_list_item *item;
+	int rc_sync = SEPOL_OK;
+
+	#pragma omp parallel
+	{
+
+		#pragma omp single
+		{
+
+			struct cil_list_item *item;
+			cil_list_for_each(item, neverallows) {
+
+				struct cil_tree_node *node = item->data;
+				int rc_test;
+
+				#pragma omp task default(none) firstprivate(node, db, pdb, violation) shared(rc_sync) untied
+				{
+					int rc_task = cil_check_neverallow(
+						db,
+						pdb,
+						node,
+						violation);
+
+					if (rc_task != SEPOL_OK) {
+						#pragma omp atomic write
+						rc_sync = rc_task;
+					}
+				}
+
+				#pragma omp atomic read
+				rc_test = rc_sync;
+
+				if (rc_test != SEPOL_OK)
+					break;
+
+			}
 
-	cil_list_for_each(item, neverallows) {
-		rc = cil_check_neverallow(db, pdb, item->data, violation);
-		if (rc != SEPOL_OK) {
-			goto exit;
 		}
+
+		#pragma omp taskwait
 	}
 
-exit:
-	return rc;
+	return rc_sync;
 }
 
 static struct cil_list *cil_classperms_from_sepol(policydb_t *pdb, uint16_t class, uint32_t data, struct cil_class *class_value_to_cil[], struct cil_perm **perm_value_to_cil[])