Re: [PATCH v3] libsepol: handle type gaps

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Jan 25, 2022 at 2:43 PM Christian Göttsche
<cgzones@xxxxxxxxxxxxxx> wrote:
>
> For policy versions between 20 and 23 the type_val_to_struct array might
> contain gaps. Skip those gaps to avoid NULL pointer dereferences:
>
>     ==1250==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000008 (pc 0x00000058560b bp 0x7ffdca60c110 sp 0x7ffdca60bfc0 T0)
>     ==1250==The signal is caused by a READ memory access.
>     ==1250==Hint: address points to the zero page.
>         #0 0x58560b in build_type_map selinux/libsepol/src/optimize.c:107:33
>         #1 0x58560b in policydb_optimize selinux/libsepol/src/optimize.c:441:13
>         #2 0x55e63e in LLVMFuzzerTestOneInput selinux/libsepol/fuzz/binpolicy-fuzzer.c:42:10
>         #3 0x455283 in fuzzer::Fuzzer::ExecuteCallback(unsigned char const*, unsigned long) cxa_noexception.cpp:0
>         #4 0x440ec2 in fuzzer::RunOneTest(fuzzer::Fuzzer*, char const*, unsigned long) /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerDriver.cpp:324:6
>         #5 0x44671c in fuzzer::FuzzerDriver(int*, char***, int (*)(unsigned char const*, unsigned long)) cxa_noexception.cpp:0
>         #6 0x46f522 in main /src/llvm-project/compiler-rt/lib/fuzzer/FuzzerMain.cpp:20:10
>         #7 0x7f9c160d00b2 in __libc_start_main /build/glibc-eX1tMB/glibc-2.31/csu/libc-start.c:308:16
>         #8 0x41f67d in _start
>
> Found by oss-fuzz (#42697)
>
> Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx>
>

Acked-by: James Carter <jwcart2@xxxxxxxxx>

> ---
> v3:
>    - drop extra error blocks in kernel_to_(cil|conf).c in favor of a
>      simple non-NULL check, as writing policies between version 20 and
>      23 is not supported and previously checked
>    - refuse to optimize policies between version 20 and 23 altogether
>      and simplify NULL checks
>
> Signed-off-by: Christian Göttsche <cgzones@xxxxxxxxxxxxxx>
> ---
>  libsepol/src/kernel_to_cil.c  | 10 +++++-----
>  libsepol/src/kernel_to_conf.c |  8 ++++----
>  libsepol/src/optimize.c       | 21 +++++++++++++++++++--
>  3 files changed, 28 insertions(+), 11 deletions(-)
>
> diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c
> index 18294a9a..693206d2 100644
> --- a/libsepol/src/kernel_to_cil.c
> +++ b/libsepol/src/kernel_to_cil.c
> @@ -1227,7 +1227,7 @@ static int write_type_attributes_to_cil(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_ATTRIB) {
> +               if (type && type->flavor == TYPE_ATTRIB) {
>                         rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                         if (rc != 0) {
>                                 goto exit;
> @@ -1357,7 +1357,7 @@ static int write_type_decl_rules_to_cil(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_TYPE && type->primary) {
> +               if (type && type->flavor == TYPE_TYPE && type->primary) {
>                         rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                         if (rc != 0) {
>                                 goto exit;
> @@ -1486,7 +1486,7 @@ static int write_type_bounds_rules_to_cil(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_TYPE) {
> +               if (type && type->flavor == TYPE_TYPE) {
>                         if (type->bounds > 0) {
>                                 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                                 if (rc != 0) {
> @@ -1540,7 +1540,7 @@ static int write_type_attribute_sets_to_cil(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 attr = pdb->type_val_to_struct[i];
> -               if (attr->flavor != TYPE_ATTRIB) continue;
> +               if (!attr || attr->flavor != TYPE_ATTRIB) continue;
>                 name = pdb->p_type_val_to_name[i];
>                 typemap = &pdb->attr_type_map[i];
>                 if (ebitmap_is_empty(typemap)) continue;
> @@ -2273,7 +2273,7 @@ static int write_role_decl_rules_to_cil(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type_datum = pdb->type_val_to_struct[i];
> -               if (type_datum->flavor == TYPE_TYPE && type_datum->primary) {
> +               if (type_datum && type_datum->flavor == TYPE_TYPE && type_datum->primary) {
>                         rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                         if (rc != 0) {
>                                 goto exit;
> diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c
> index a92ba9fd..52b6c60f 100644
> --- a/libsepol/src/kernel_to_conf.c
> +++ b/libsepol/src/kernel_to_conf.c
> @@ -1210,7 +1210,7 @@ static int write_type_attributes_to_conf(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_ATTRIB) {
> +               if (type && type->flavor == TYPE_ATTRIB) {
>                         rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                         if (rc != 0) {
>                                 goto exit;
> @@ -1340,7 +1340,7 @@ static int write_type_decl_rules_to_conf(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_TYPE && type->primary) {
> +               if (type && type->flavor == TYPE_TYPE && type->primary) {
>                         rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                         if (rc != 0) {
>                                 goto exit;
> @@ -1460,7 +1460,7 @@ static int write_type_bounds_rules_to_conf(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor == TYPE_TYPE) {
> +               if (type && type->flavor == TYPE_TYPE) {
>                         if (type->bounds > 0) {
>                                 rc = strs_add(strs, pdb->p_type_val_to_name[i]);
>                                 if (rc != 0) {
> @@ -1583,7 +1583,7 @@ static int write_type_attribute_sets_to_conf(FILE *out, struct policydb *pdb)
>
>         for (i=0; i < pdb->p_types.nprim; i++) {
>                 type = pdb->type_val_to_struct[i];
> -               if (type->flavor != TYPE_TYPE || !type->primary) continue;
> +               if (!type || type->flavor != TYPE_TYPE || !type->primary) continue;
>                 if (ebitmap_cardinality(&pdb->type_attr_map[i]) == 1) continue;
>
>                 rc = ebitmap_cpy(&attrmap, &pdb->type_attr_map[i]);
> diff --git a/libsepol/src/optimize.c b/libsepol/src/optimize.c
> index 8a048702..93ff2116 100644
> --- a/libsepol/src/optimize.c
> +++ b/libsepol/src/optimize.c
> @@ -31,6 +31,7 @@
>  #include <sepol/policydb/policydb.h>
>  #include <sepol/policydb/conditional.h>
>
> +#include "debug.h"
>  #include "private.h"
>
>  #define TYPE_VEC_INIT_SIZE 16
> @@ -104,6 +105,9 @@ static struct type_vec *build_type_map(const policydb_t *p)
>                 if (type_vec_init(&map[i]))
>                         goto err;
>
> +               if (!p->type_val_to_struct[i])
> +                       continue;
> +
>                 if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB) {
>                         ebitmap_for_each_positive_bit(&p->type_attr_map[i],
>                                                       n, k) {
> @@ -114,11 +118,13 @@ static struct type_vec *build_type_map(const policydb_t *p)
>                         ebitmap_t *types_i = &p->attr_type_map[i];
>
>                         for (k = 0; k < p->p_types.nprim; k++) {
> -                               ebitmap_t *types_k = &p->attr_type_map[k];
> +                               const ebitmap_t *types_k;
>
> -                               if (p->type_val_to_struct[k]->flavor != TYPE_ATTRIB)
> +                               if (!p->type_val_to_struct[k] || p->type_val_to_struct[k]->flavor != TYPE_ATTRIB)
>                                         continue;
>
> +                               types_k = &p->attr_type_map[k];
> +
>                                 if (ebitmap_contains(types_k, types_i)) {
>                                         if (type_vec_append(&map[i], k))
>                                                 goto err;
> @@ -438,6 +444,17 @@ int policydb_optimize(policydb_t *p)
>         if (p->policy_type != POLICY_KERN)
>                 return -1;
>
> +       if (p->policyvers >= POLICYDB_VERSION_AVTAB && p->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
> +               /*
> +                * For policy versions between 20 and 23, attributes exist in the policy,
> +                * but only in the type_attr_map. This means that there are gaps in both
> +                * the type_val_to_struct and p_type_val_to_name arrays and policy rules
> +                * can refer to those gaps.
> +                */
> +               ERR(NULL, "Optimizing policy versions between 20 and 23 is not supported");
> +               return -1;
> +       }
> +
>         type_map = build_type_map(p);
>         if (!type_map)
>                 return -1;
> --
> 2.34.1
>




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux