Re: [PATCH] selinux: implement new format of filename transitions

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

 



On Fri, Mar 27, 2020 at 11:19 AM Ondrej Mosnacek <omosnace@xxxxxxxxxx> wrote:
>
> Implement a new, more space-efficient way of storing filename
> transitions in the binary policy. The internal structures have already
> been converted to this new representation; this patch just implements
> reading/writing an equivalent represntation from/to the binary policy.
>
> This new format reduces the size of Fedora policy from 7.6 MB to only
> 3.3 MB (with policy optimization enabled in both cases). With the
> unconfined module disabled, the size is reduced from 3.3 MB to 2.4 MB.
>
> The time to load policy into kernel is also shorter with the new format.
> On Fedora Rawhide x86_64 it dropped from 157 ms to 106 ms; without the
> unconfined module from 115 ms to 105 ms.
>
> Signed-off-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
> ---
>  security/selinux/include/security.h |   3 +-
>  security/selinux/ss/policydb.c      | 212 ++++++++++++++++++++++++----
>  2 files changed, 189 insertions(+), 26 deletions(-)

...

> diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
> index d6036c018cf2..b0e02cfe3ce1 100644
> --- a/security/selinux/include/security.h
> +++ b/security/selinux/include/security.h
> @@ -41,10 +41,11 @@
>  #define POLICYDB_VERSION_XPERMS_IOCTL  30
>  #define POLICYDB_VERSION_INFINIBAND            31
>  #define POLICYDB_VERSION_GLBLUB                32
> +#define POLICYDB_VERSION_COMP_FTRANS   33 /* compressed filename transitions */
>
>  /* Range of policy versions we understand*/
>  #define POLICYDB_VERSION_MIN   POLICYDB_VERSION_BASE
> -#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_GLBLUB
> +#define POLICYDB_VERSION_MAX   POLICYDB_VERSION_COMP_FTRANS
>
>  /* Mask for just the mount related flags */
>  #define SE_MNTMASK     0x0f
> diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c
> index 932b2b9bcdb2..f355876ed793 100644
> --- a/security/selinux/ss/policydb.c
> +++ b/security/selinux/ss/policydb.c
> @@ -154,6 +154,11 @@ static struct policydb_compat_info policydb_compat[] = {
>                 .sym_num        = SYM_NUM,
>                 .ocon_num       = OCON_NUM,
>         },
> +       {
> +               .version        = POLICYDB_VERSION_COMP_FTRANS,
> +               .sym_num        = SYM_NUM,
> +               .ocon_num       = OCON_NUM,
> +       },
>  };
>
>  static struct policydb_compat_info *policydb_lookup_compat(int version)
> @@ -461,23 +466,16 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
>  /*
>   * Initialize a policy database structure.
>   */
> -static int policydb_init(struct policydb *p)
> +static void policydb_init(struct policydb *p)
>  {
>         memset(p, 0, sizeof(*p));
>
>         avtab_init(&p->te_avtab);
>         cond_policydb_init(p);
>
> -       p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp,
> -                                          (1 << 11));
> -       if (!p->filename_trans)
> -               return -ENOMEM;
> -
>         ebitmap_init(&p->filename_trans_ttypes);
>         ebitmap_init(&p->policycaps);
>         ebitmap_init(&p->permissive_map);
> -
> -       return 0;
>  }
>
>  /*
> @@ -1842,7 +1840,7 @@ out:
>         return rc;
>  }
>
> -static int filename_trans_read_one(struct policydb *p, void *fp)
> +static int filename_trans_read_one_old(struct policydb *p, void *fp)

If you have to respin this patch, please change from XXX_old(...) to
XXX_compat(...); there is some precedence for using _compat in the
SELinux kernel code.

Same thing with the _write_ code.

>  {
>         struct filename_trans_key key, *ft = NULL;
>         struct filename_trans_datum *last, *datum = NULL;
> @@ -1925,6 +1923,99 @@ out:
>         return rc;
>  }
>
> +static int filename_trans_read_one_new(struct policydb *p, void *fp)

No need to call this XXX_new(), just stick to the original name and
XXX_compat().

Same thing with the _write_ code.

> +{
> +       struct filename_trans_key *ft = NULL;
> +       struct filename_trans_datum **dst, *datum, *first = NULL;
> +       char *name = NULL;
> +       u32 len, ttype, tclass, ndatum, i;
> +       __le32 buf[3];
> +       int rc;
> +
> +       /* length of the path component string */
> +       rc = next_entry(buf, fp, sizeof(u32));
> +       if (rc)
> +               return rc;
> +       len = le32_to_cpu(buf[0]);
> +
> +       /* path component string */
> +       rc = str_read(&name, GFP_KERNEL, fp, len);
> +       if (rc)
> +               return rc;
> +
> +       rc = next_entry(buf, fp, sizeof(u32) * 3);
> +       if (rc)
> +               goto out;
> +
> +       ttype = le32_to_cpu(buf[0]);
> +       tclass = le32_to_cpu(buf[1]);
> +
> +       rc = ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1);
> +       if (rc)
> +               goto out;

Should we move the p->filename_trans_ttypes update to the bottom of
the function where we increment filename_trans_count?

> +       ndatum = le32_to_cpu(buf[2]);
> +       if (ndatum == 0) {
> +               pr_err("SELinux:  Filename transition key with no datum\n");
> +               rc = -ENOENT;
> +               goto out;
> +       }
> +
> +       dst = &first;
> +       for (i = 0; i < ndatum; i++) {
> +               rc = -ENOMEM;
> +               datum = kmalloc(sizeof(*datum), GFP_KERNEL);
> +               if (!datum)
> +                       goto out;
> +
> +               *dst = datum;
> +
> +               /* ebitmap_read() will at least init the bitmap */
> +               rc = ebitmap_read(&datum->stypes, fp);
> +               if (rc)
> +                       goto out;
> +
> +               rc = next_entry(buf, fp, sizeof(u32));
> +               if (rc)
> +                       goto out;
> +
> +               datum->otype = le32_to_cpu(buf[0]);
> +               datum->next = NULL;
> +
> +               dst = &datum->next;
> +       }
> +
> +       rc = -ENOMEM;
> +       ft = kmalloc(sizeof(*ft), GFP_KERNEL);
> +       if (!ft)
> +               goto out;
> +
> +       ft->ttype = ttype;
> +       ft->tclass = tclass;
> +       ft->name = name;
> +
> +       rc = hashtab_insert(p->filename_trans, ft, first);
> +       if (rc == -EEXIST)
> +               pr_err("SELinux:  Duplicate filename transition key\n");
> +       if (rc)
> +               goto out;
> +
> +       p->filename_trans_count++;
> +       return 0;
> +
> +out:
> +       kfree(ft);
> +       kfree(name);
> +       while (first) {
> +               datum = first;
> +               first = first->next;
> +
> +               ebitmap_destroy(&datum->stypes);
> +               kfree(datum);
> +       }
> +       return rc;
> +}

-- 
paul moore
www.paul-moore.com



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

  Powered by Linux