Re: [PATCH v2 2/2] libsepol: implement POLICYDB_VERSION_COMP_FTRANS

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

 



On Tue, Apr 28, 2020 at 4:49 AM Ondrej Mosnacek <omosnace@xxxxxxxxxx> wrote:
>
> On Mon, Apr 27, 2020 at 9:39 PM James Carter <jwcart2@xxxxxxxxx> wrote:
> > On Tue, Mar 31, 2020 at 4:30 PM James Carter <jwcart2@xxxxxxxxx> wrote:
> > >
> > > On Sat, Mar 28, 2020 at 8:46 AM Ondrej Mosnacek <omosnace@xxxxxxxxxx> wrote:
> > > >
> > > > Implement a new, more space-efficient form 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 representation 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.
> > > >
> > > > Signed-off-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
> > >
> > > Acked-by: James Carter <jwcart2@xxxxxxxxx>
> > >
> >
> > Sorry, it has been a while.
>
> No problem. I would've merged it myself, I just wasn't sure if we
> shouldn't try to do something about the setools issue somehow... But I
> really don't feel like touching that code, so if the consensus is that
> this is worth the breakage then I'm fine with it :)
>

I thought the consensus was to apply this now, but it would be nice to
not break setools, so I am going to hold off merging for day or two
and take a look at how much work it would be to export what setools
needs.

> >
> > I was going to merge these today, but upon further testing, I noticed
> > a couple of problems.
> >
> > First, creating a policy.conf from a binary like this:
> > ~/local/usr/bin/checkpolicy -F -M -b -o policy.31.conf policy.31
> > give the following error:
> > libsepol.avtab_read_item: invalid item count
>
> Hm... I can't reproduce that on my side. Are you sure you're not using
> a broken policy generated by the buggy v1 of this series?
>

No, it wasn't that. It turns out that I didn't do "make clean" between
building master and building the branch with this patch series. I
don't see any problems now.

Jim

> >
> > Second, creating a binary from a policy.conf and then trying to create
> > a policy.conf from that binary:
> > ~/local/usr/bin/checkpolicy -o policy.bin policy.conf
> > ~/local/usr/bin/checkpolicy -F -b -o policy.bin.conf policy.bin
> > gives the following error:
> > security: ebitmap: high bit (32) is not a multiple of the map size (64)
>
> Likewise, couldn't reproduce it with the conf file I tried... Can you
> share the policy.conf that triggers this?
>
> >
> > I don't know if this is related to the problems you had on the kernel
> > side or not. I'll keep looking into this, but, for now, I'll have to
> > remove my Acked-by.
> >
> > Jim
> >
> >
> > > > ---
> > > >  libsepol/include/sepol/policydb/policydb.h |   3 +-
> > > >  libsepol/src/policydb.c                    | 218 +++++++++++++++++----
> > > >  libsepol/src/write.c                       |  72 ++++++-
> > > >  3 files changed, 242 insertions(+), 51 deletions(-)
> > > >
> > > > diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h
> > > > index c3180c61..9ef43abc 100644
> > > > --- a/libsepol/include/sepol/policydb/policydb.h
> > > > +++ b/libsepol/include/sepol/policydb/policydb.h
> > > > @@ -755,10 +755,11 @@ extern int policydb_set_target_platform(policydb_t *p, int platform);
> > > >  #define POLICYDB_VERSION_XPERMS_IOCTL  30 /* Linux-specific */
> > > >  #define POLICYDB_VERSION_INFINIBAND            31 /* Linux-specific */
> > > >  #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
> > > >
> > > >  /* Module versions and specific changes*/
> > > >  #define MOD_POLICYDB_VERSION_BASE              4
> > > > diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c
> > > > index 6b121d66..18ce1912 100644
> > > > --- a/libsepol/src/policydb.c
> > > > +++ b/libsepol/src/policydb.c
> > > > @@ -200,6 +200,13 @@ static struct policydb_compat_info policydb_compat[] = {
> > > >          .ocon_num = OCON_IBENDPORT + 1,
> > > >          .target_platform = SEPOL_TARGET_SELINUX,
> > > >         },
> > > > +       {
> > > > +        .type = POLICY_KERN,
> > > > +        .version = POLICYDB_VERSION_COMP_FTRANS,
> > > > +        .sym_num = SYM_NUM,
> > > > +        .ocon_num = OCON_IBENDPORT + 1,
> > > > +        .target_platform = SEPOL_TARGET_SELINUX,
> > > > +       },
> > > >         {
> > > >          .type = POLICY_BASE,
> > > >          .version = MOD_POLICYDB_VERSION_BASE,
> > > > @@ -2661,73 +2668,202 @@ int policydb_filetrans_insert(policydb_t *p, uint32_t stype, uint32_t ttype,
> > > >         return ebitmap_set_bit(&datum->stypes, stype - 1, 1);
> > > >  }
> > > >
> > > > -int filename_trans_read(policydb_t *p, struct policy_file *fp)
> > > > +static int filename_trans_read_one_old(policydb_t *p, struct policy_file *fp)
> > > >  {
> > > > -       unsigned int i;
> > > > -       uint32_t buf[4], nel, len, stype, ttype, tclass, otype;
> > > > +       uint32_t buf[4], len, stype, ttype, tclass, otype;
> > > > +       char *name = NULL;
> > > >         int rc;
> > > > -       char *name;
> > > >
> > > >         rc = next_entry(buf, fp, sizeof(uint32_t));
> > > >         if (rc < 0)
> > > >                 return -1;
> > > > -       nel = le32_to_cpu(buf[0]);
> > > > +       len = le32_to_cpu(buf[0]);
> > > > +       if (zero_or_saturated(len))
> > > > +               return -1;
> > > >
> > > > -       for (i = 0; i < nel; i++) {
> > > > -               name = NULL;
> > > > +       name = calloc(len + 1, sizeof(*name));
> > > > +       if (!name)
> > > > +               return -1;
> > > >
> > > > -               rc = next_entry(buf, fp, sizeof(uint32_t));
> > > > -               if (rc < 0)
> > > > -                       goto err;
> > > > -               len = le32_to_cpu(buf[0]);
> > > > -               if (zero_or_saturated(len))
> > > > +       rc = next_entry(name, fp, len);
> > > > +       if (rc < 0)
> > > > +               goto err;
> > > > +
> > > > +       rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
> > > > +       if (rc < 0)
> > > > +               goto err;
> > > > +
> > > > +       stype  = le32_to_cpu(buf[0]);
> > > > +       ttype  = le32_to_cpu(buf[1]);
> > > > +       tclass = le32_to_cpu(buf[2]);
> > > > +       otype  = le32_to_cpu(buf[3]);
> > > > +
> > > > +       rc = policydb_filetrans_insert(p, stype, ttype, tclass, name, &name,
> > > > +                                      otype, NULL);
> > > > +       if (rc) {
> > > > +               if (rc != SEPOL_EEXIST)
> > > >                         goto err;
> > > > +               /*
> > > > +                * Some old policies were wrongly generated with
> > > > +                * duplicate filename transition rules.  For backward
> > > > +                * compatibility, do not reject such policies, just
> > > > +                * issue a warning and ignore the duplicate.
> > > > +                */
> > > > +               WARN(fp->handle,
> > > > +                    "Duplicate name-based type_transition %s %s:%s \"%s\":  %s, ignoring",
> > > > +                    p->p_type_val_to_name[stype - 1],
> > > > +                    p->p_type_val_to_name[ttype - 1],
> > > > +                    p->p_class_val_to_name[tclass - 1],
> > > > +                    name,
> > > > +                    p->p_type_val_to_name[otype - 1]);
> > > > +               /* continue, ignoring this one */
> > > > +       }
> > > > +       free(name);
> > > > +       return 0;
> > > > +err:
> > > > +       free(name);
> > > > +       return -1;
> > > > +}
> > > > +
> > > > +static int filename_trans_check_datum(filename_trans_datum_t *datum)
> > > > +{
> > > > +       ebitmap_t stypes, otypes;
> > > > +
> > > > +       ebitmap_init(&stypes);
> > > > +       ebitmap_init(&otypes);
> > > > +
> > > > +       while (datum) {
> > > > +               if (ebitmap_get_bit(&otypes, datum->otype))
> > > > +                       return -1;
> > > > +
> > > > +               if (ebitmap_set_bit(&otypes, datum->otype, 1))
> > > > +                       return -1;
> > > >
> > > > -               name = calloc(len + 1, sizeof(*name));
> > > > -               if (!name)
> > > > +               if (ebitmap_match_any(&stypes, &datum->stypes))
> > > > +                       return -1;
> > > > +
> > > > +               if (ebitmap_union(&stypes, &datum->stypes))
> > > > +                       return -1;
> > > > +       }
> > > > +       return 0;
> > > > +}
> > > > +
> > > > +static int filename_trans_read_one_new(policydb_t *p, struct policy_file *fp)
> > > > +{
> > > > +       filename_trans_key_t *ft = NULL;
> > > > +       filename_trans_datum_t **dst, *datum, *first = NULL;
> > > > +       unsigned int i;
> > > > +       uint32_t buf[3], len, ttype, tclass, ndatum;
> > > > +       char *name = NULL;
> > > > +       int rc;
> > > > +
> > > > +       rc = next_entry(buf, fp, sizeof(uint32_t));
> > > > +       if (rc < 0)
> > > > +               return -1;
> > > > +       len = le32_to_cpu(buf[0]);
> > > > +       if (zero_or_saturated(len))
> > > > +               return -1;
> > > > +
> > > > +       name = calloc(len + 1, sizeof(*name));
> > > > +       if (!name)
> > > > +               return -1;
> > > > +
> > > > +       rc = next_entry(name, fp, len);
> > > > +       if (rc < 0)
> > > > +               goto err;
> > > > +
> > > > +       rc = next_entry(buf, fp, sizeof(uint32_t) * 3);
> > > > +       if (rc < 0)
> > > > +               goto err;
> > > > +
> > > > +       ttype = le32_to_cpu(buf[0]);
> > > > +       tclass = le32_to_cpu(buf[1]);
> > > > +       ndatum = le32_to_cpu(buf[2]);
> > > > +       if (ndatum == 0)
> > > > +               goto err;
> > > > +
> > > > +       dst = &first;
> > > > +       for (i = 0; i < ndatum; i++) {
> > > > +               datum = malloc(sizeof(*datum));
> > > > +               if (!datum)
> > > >                         goto err;
> > > >
> > > > -               rc = next_entry(name, fp, len);
> > > > +               *dst = datum;
> > > > +
> > > > +               /* ebitmap_read() will at least init the bitmap */
> > > > +               rc = ebitmap_read(&datum->stypes, fp);
> > > >                 if (rc < 0)
> > > >                         goto err;
> > > >
> > > > -               rc = next_entry(buf, fp, sizeof(uint32_t) * 4);
> > > > +               rc = next_entry(buf, fp, sizeof(uint32_t));
> > > >                 if (rc < 0)
> > > >                         goto err;
> > > >
> > > > -               stype  = le32_to_cpu(buf[0]);
> > > > -               ttype  = le32_to_cpu(buf[1]);
> > > > -               tclass = le32_to_cpu(buf[2]);
> > > > -               otype  = le32_to_cpu(buf[3]);
> > > > +               datum->otype = le32_to_cpu(buf[0]);
> > > >
> > > > -               rc = policydb_filetrans_insert(p, stype, ttype, tclass, name,
> > > > -                                              &name, otype, NULL);
> > > > -               if (rc) {
> > > > -                       if (rc != SEPOL_EEXIST)
> > > > -                               goto err;
> > > > -                       /*
> > > > -                        * Some old policies were wrongly generated with
> > > > -                        * duplicate filename transition rules.  For backward
> > > > -                        * compatibility, do not reject such policies, just
> > > > -                        * issue a warning and ignore the duplicate.
> > > > -                        */
> > > > -                       WARN(fp->handle,
> > > > -                            "Duplicate name-based type_transition %s %s:%s \"%s\":  %s, ignoring",
> > > > -                            p->p_type_val_to_name[stype - 1],
> > > > -                            p->p_type_val_to_name[ttype - 1],
> > > > -                            p->p_class_val_to_name[tclass - 1],
> > > > -                            name,
> > > > -                            p->p_type_val_to_name[otype - 1]);
> > > > -                       /* continue, ignoring this one */
> > > > -               }
> > > > -               free(name);
> > > > +               p->filename_trans_count += ebitmap_cardinality(&datum->stypes);
> > > > +
> > > > +               dst = &datum->next;
> > > >         }
> > > > +       *dst = NULL;
> > > > +
> > > > +       if (ndatum > 1 && filename_trans_check_datum(first))
> > > > +               goto err;
> > > > +
> > > > +       ft = malloc(sizeof(*ft));
> > > > +       if (!ft)
> > > > +               goto err;
> > > > +
> > > > +       ft->ttype = ttype;
> > > > +       ft->tclass = tclass;
> > > > +       ft->name = name;
> > > > +
> > > > +       rc = hashtab_insert(p->filename_trans, (hashtab_key_t)ft,
> > > > +                           (hashtab_datum_t)first);
> > > > +       if (rc)
> > > > +               goto err;
> > > > +
> > > >         return 0;
> > > >  err:
> > > > +       free(ft);
> > > >         free(name);
> > > > +       while (first) {
> > > > +               datum = first;
> > > > +               first = first->next;
> > > > +
> > > > +               ebitmap_destroy(&datum->stypes);
> > > > +               free(datum);
> > > > +       }
> > > >         return -1;
> > > >  }
> > > >
> > > > +int filename_trans_read(policydb_t *p, struct policy_file *fp)
> > > > +{
> > > > +       unsigned int i;
> > > > +       uint32_t buf[1], nel;
> > > > +       int rc;
> > > > +
> > > > +       rc = next_entry(buf, fp, sizeof(uint32_t));
> > > > +       if (rc < 0)
> > > > +               return -1;
> > > > +       nel = le32_to_cpu(buf[0]);
> > > > +
> > > > +       if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
> > > > +               for (i = 0; i < nel; i++) {
> > > > +                       rc = filename_trans_read_one_old(p, fp);
> > > > +                       if (rc < 0)
> > > > +                               return -1;
> > > > +               }
> > > > +       } else {
> > > > +               for (i = 0; i < nel; i++) {
> > > > +                       rc = filename_trans_read_one_new(p, fp);
> > > > +                       if (rc < 0)
> > > > +                               return -1;
> > > > +               }
> > > > +       }
> > > > +       return 0;
> > > > +}
> > > > +
> > > >  static int ocontext_read_xen(struct policydb_compat_info *info,
> > > >         policydb_t *p, struct policy_file *fp)
> > > >  {
> > > > diff --git a/libsepol/src/write.c b/libsepol/src/write.c
> > > > index d3aee8d5..9c74d9f5 100644
> > > > --- a/libsepol/src/write.c
> > > > +++ b/libsepol/src/write.c
> > > > @@ -569,7 +569,7 @@ static int role_allow_write(role_allow_t * r, struct policy_file *fp)
> > > >         return POLICYDB_SUCCESS;
> > > >  }
> > > >
> > > > -static int filename_write_helper(hashtab_key_t key, void *data, void *ptr)
> > > > +static int filename_write_one_old(hashtab_key_t key, void *data, void *ptr)
> > > >  {
> > > >         uint32_t bit, buf[4];
> > > >         size_t items, len;
> > > > @@ -605,6 +605,54 @@ static int filename_write_helper(hashtab_key_t key, void *data, void *ptr)
> > > >         return 0;
> > > >  }
> > > >
> > > > +static int filename_write_one_new(hashtab_key_t key, void *data, void *ptr)
> > > > +{
> > > > +       uint32_t buf[3];
> > > > +       size_t items, len, ndatum;
> > > > +       filename_trans_key_t *ft = (filename_trans_key_t *)key;
> > > > +       filename_trans_datum_t *datum;
> > > > +       void *fp = ptr;
> > > > +
> > > > +       len = strlen(ft->name);
> > > > +       buf[0] = cpu_to_le32(len);
> > > > +       items = put_entry(buf, sizeof(uint32_t), 1, fp);
> > > > +       if (items != 1)
> > > > +               return POLICYDB_ERROR;
> > > > +
> > > > +       items = put_entry(ft->name, sizeof(char), len, fp);
> > > > +       if (items != len)
> > > > +               return POLICYDB_ERROR;
> > > > +
> > > > +       ndatum = 0;
> > > > +       datum = data;
> > > > +       do {
> > > > +               ndatum++;
> > > > +               datum = datum->next;
> > > > +       } while (datum);
> > > > +
> > > > +       buf[0] = cpu_to_le32(ft->ttype);
> > > > +       buf[1] = cpu_to_le32(ft->tclass);
> > > > +       buf[2] = cpu_to_le32(ndatum);
> > > > +       items = put_entry(buf, sizeof(uint32_t), 3, fp);
> > > > +       if (items != 3)
> > > > +               return POLICYDB_ERROR;
> > > > +
> > > > +       datum = data;
> > > > +       do {
> > > > +               if (ebitmap_write(&datum->stypes, fp))
> > > > +                       return POLICYDB_ERROR;
> > > > +
> > > > +               buf[0] = cpu_to_le32(datum->otype);
> > > > +               items = put_entry(buf, sizeof(uint32_t), 1, fp);
> > > > +               if (items != 1)
> > > > +                       return POLICYDB_ERROR;
> > > > +
> > > > +               datum = datum->next;
> > > > +       } while (datum);
> > > > +
> > > > +       return 0;
> > > > +}
> > > > +
> > > >  static int filename_trans_write(struct policydb *p, void *fp)
> > > >  {
> > > >         size_t items;
> > > > @@ -614,16 +662,22 @@ static int filename_trans_write(struct policydb *p, void *fp)
> > > >         if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
> > > >                 return 0;
> > > >
> > > > -       buf[0] = cpu_to_le32(p->filename_trans_count);
> > > > -       items = put_entry(buf, sizeof(uint32_t), 1, fp);
> > > > -       if (items != 1)
> > > > -               return POLICYDB_ERROR;
> > > > +       if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
> > > > +               buf[0] = cpu_to_le32(p->filename_trans_count);
> > > > +               items = put_entry(buf, sizeof(uint32_t), 1, fp);
> > > > +               if (items != 1)
> > > > +                       return POLICYDB_ERROR;
> > > >
> > > > -       rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
> > > > -       if (rc)
> > > > -               return rc;
> > > > +               rc = hashtab_map(p->filename_trans, filename_write_one_old, fp);
> > > > +       } else {
> > > > +               buf[0] = cpu_to_le32(p->filename_trans->nel);
> > > > +               items = put_entry(buf, sizeof(uint32_t), 1, fp);
> > > > +               if (items != 1)
> > > > +                       return POLICYDB_ERROR;
> > > >
> > > > -       return 0;
> > > > +               rc = hashtab_map(p->filename_trans, filename_write_one_new, fp);
> > > > +       }
> > > > +       return rc;
> > > >  }
> > > >
> > > >  static int role_set_write(role_set_t * x, struct policy_file *fp)
> > > > --
> > > > 2.25.1
> > > >
> >
>
>
> --
> Ondrej Mosnacek <omosnace at redhat dot com>
> Software Engineer, Security Technologies
> Red Hat, Inc.
>



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

  Powered by Linux