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 |
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 --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[])
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(-)