Re: [PATCH] libsepol: Prevent OOB access of array when copying scope information

Stephen Smalley <[email protected]>
Newsgroups org.kernel.vger.selinux
Message-ID <CAEjxPJ5Mcz8ECLWS6mmjfbx+YsBF2tPNZVVyeGRjhQFMN-VN4w@mail.gmail.com>
On Fri, Jul 17, 2026 at 1:35 PM James Carter <[email protected]> wrote:
>
> The function copy_scope_index() in link.c copies information about
> what declarations are in scope for the current block. This is tracked
> in the "scope" field of the scope_index struct in an array of ebitmaps.
> A second field called "class_perms_map" is used to track which
> permissions are in scope for each class. The "class_perms_len" field is
> the length of the permissions array. As the function is copying scoping
> information from the module to the base policy, the index values are
> translated as well. When the information for classes is translated and
> copied the largest new index value for a class is determined. This value
> is used to allocate the class_perms_map array. For each source class in
> that array, the bits in the source ebitmap are translated and set in the
> destination bitmap.
>
> A maliciously crafted policy could set permissions in the module's
> class_perms_map for a class that is not in scope. If that class has
> a new index that is greater than the largest index of a valid class,
> then there will be an OOB write when copying the class_perms_map.
>
> When copying the class_perms_map, check that the index is not going to
> result in an OOB write when converting. In addition, if there were no
> classes, then just set class_perms_map to NULL and return. Also, don't
> bother trying to copy permissions if the ebitmap is empty. Finally,
> just use array notation when copying the scope and class_perms_map
> data since they are both arrays of ebitmaps.
>
> Signed-off-by: James Carter <[email protected]>

Acked-by: Stephen Smalley <[email protected]>

> ---
>  libsepol/src/link.c | 27 +++++++++++++++++++--------
>  1 file changed, 19 insertions(+), 8 deletions(-)
>
> diff --git a/libsepol/src/link.c b/libsepol/src/link.c
> index 70742fc8..868e0a7a 100644
> --- a/libsepol/src/link.c
> +++ b/libsepol/src/link.c
> @@ -1652,8 +1652,9 @@ static int copy_scope_index(scope_index_t *src, scope_index_t *dest,
>         ebitmap_node_t *node;
>         /* copy the scoping information for this avrule decl block */
>         for (i = 0; i < SYM_NUM; i++) {
> -               ebitmap_t *srcmap = src->scope + i;
> -               ebitmap_t *destmap = dest->scope + i;
> +               ebitmap_t *srcmap = &src->scope[i];
> +               ebitmap_t *destmap = &dest->scope[i];
> +
>                 if (copy_callback_f[i] == NULL) {
>                         continue;
>                 }
> @@ -1672,18 +1673,28 @@ static int copy_scope_index(scope_index_t *src, scope_index_t *dest,
>                 }
>         }
>
> +       dest->class_perms_len = largest_mapped_class_value;
> +       if (largest_mapped_class_value == 0) {
> +               dest->class_perms_map = NULL;
> +               return 0;
> +       }
> +
>         /* next copy the enabled permissions data  */
>         if ((dest->class_perms_map = calloc(largest_mapped_class_value,
>                                             sizeof(*dest->class_perms_map))) ==
>             NULL) {
>                 goto cleanup;
>         }
> -       dest->class_perms_len = largest_mapped_class_value;
> -       for (i = 0; i < src->class_perms_len; i++) {
> -               const ebitmap_t *srcmap = src->class_perms_map + i;
> -               ebitmap_t *destmap =
> -                       dest->class_perms_map + module->map[SYM_CLASSES][i] - 1;
>
> +       for (i = 0; i < src->class_perms_len; i++) {
> +               const ebitmap_t *srcmap = &src->class_perms_map[i];
> +               ebitmap_t *destmap;
> +               if (ebitmap_is_empty(srcmap))
> +                       continue;
> +               j = module->map[SYM_CLASSES][i] - 1;
> +               if (j >= largest_mapped_class_value)
> +                       goto cleanup;
> +               destmap = &dest->class_perms_map[j];
>                 if (ebitmap_convert(srcmap, destmap, module->perm_map[i]))
>                         goto cleanup;
>         }
> @@ -1691,7 +1702,7 @@ static int copy_scope_index(scope_index_t *src, scope_index_t *dest,
>         return 0;
>
>  cleanup:
> -       ERR(state->handle, "Out of memory!");
> +       ERR(state->handle, "Error copying scope index");
>         return -1;
>  }
>
> --
> 2.55.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.