Skip to content

Commit 4300590

Browse files
WOnder93pcmoore
authored andcommitted
selinux: implement new format of filename transitions
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 <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 225621c commit 4300590

File tree

2 files changed

+189
-26
lines changed

2 files changed

+189
-26
lines changed

security/selinux/include/security.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,11 @@
4141
#define POLICYDB_VERSION_XPERMS_IOCTL 30
4242
#define POLICYDB_VERSION_INFINIBAND 31
4343
#define POLICYDB_VERSION_GLBLUB 32
44+
#define POLICYDB_VERSION_COMP_FTRANS 33 /* compressed filename transitions */
4445

4546
/* Range of policy versions we understand*/
4647
#define POLICYDB_VERSION_MIN POLICYDB_VERSION_BASE
47-
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_GLBLUB
48+
#define POLICYDB_VERSION_MAX POLICYDB_VERSION_COMP_FTRANS
4849

4950
/* Mask for just the mount related flags */
5051
#define SE_MNTMASK 0x0f

security/selinux/ss/policydb.c

Lines changed: 187 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@ static struct policydb_compat_info policydb_compat[] = {
154154
.sym_num = SYM_NUM,
155155
.ocon_num = OCON_NUM,
156156
},
157+
{
158+
.version = POLICYDB_VERSION_COMP_FTRANS,
159+
.sym_num = SYM_NUM,
160+
.ocon_num = OCON_NUM,
161+
},
157162
};
158163

159164
static struct policydb_compat_info *policydb_lookup_compat(int version)
@@ -492,23 +497,16 @@ static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
492497
/*
493498
* Initialize a policy database structure.
494499
*/
495-
static int policydb_init(struct policydb *p)
500+
static void policydb_init(struct policydb *p)
496501
{
497502
memset(p, 0, sizeof(*p));
498503

499504
avtab_init(&p->te_avtab);
500505
cond_policydb_init(p);
501506

502-
p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp,
503-
(1 << 11));
504-
if (!p->filename_trans)
505-
return -ENOMEM;
506-
507507
ebitmap_init(&p->filename_trans_ttypes);
508508
ebitmap_init(&p->policycaps);
509509
ebitmap_init(&p->permissive_map);
510-
511-
return 0;
512510
}
513511

514512
/*
@@ -1862,7 +1860,7 @@ static int range_read(struct policydb *p, void *fp)
18621860
return rc;
18631861
}
18641862

1865-
static int filename_trans_read_one(struct policydb *p, void *fp)
1863+
static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
18661864
{
18671865
struct filename_trans_key key, *ft = NULL;
18681866
struct filename_trans_datum *last, *datum = NULL;
@@ -1945,6 +1943,99 @@ static int filename_trans_read_one(struct policydb *p, void *fp)
19451943
return rc;
19461944
}
19471945

1946+
static int filename_trans_read_helper(struct policydb *p, void *fp)
1947+
{
1948+
struct filename_trans_key *ft = NULL;
1949+
struct filename_trans_datum **dst, *datum, *first = NULL;
1950+
char *name = NULL;
1951+
u32 len, ttype, tclass, ndatum, i;
1952+
__le32 buf[3];
1953+
int rc;
1954+
1955+
/* length of the path component string */
1956+
rc = next_entry(buf, fp, sizeof(u32));
1957+
if (rc)
1958+
return rc;
1959+
len = le32_to_cpu(buf[0]);
1960+
1961+
/* path component string */
1962+
rc = str_read(&name, GFP_KERNEL, fp, len);
1963+
if (rc)
1964+
return rc;
1965+
1966+
rc = next_entry(buf, fp, sizeof(u32) * 3);
1967+
if (rc)
1968+
goto out;
1969+
1970+
ttype = le32_to_cpu(buf[0]);
1971+
tclass = le32_to_cpu(buf[1]);
1972+
1973+
ndatum = le32_to_cpu(buf[2]);
1974+
if (ndatum == 0) {
1975+
pr_err("SELinux: Filename transition key with no datum\n");
1976+
rc = -ENOENT;
1977+
goto out;
1978+
}
1979+
1980+
dst = &first;
1981+
for (i = 0; i < ndatum; i++) {
1982+
rc = -ENOMEM;
1983+
datum = kmalloc(sizeof(*datum), GFP_KERNEL);
1984+
if (!datum)
1985+
goto out;
1986+
1987+
*dst = datum;
1988+
1989+
/* ebitmap_read() will at least init the bitmap */
1990+
rc = ebitmap_read(&datum->stypes, fp);
1991+
if (rc)
1992+
goto out;
1993+
1994+
rc = next_entry(buf, fp, sizeof(u32));
1995+
if (rc)
1996+
goto out;
1997+
1998+
datum->otype = le32_to_cpu(buf[0]);
1999+
datum->next = NULL;
2000+
2001+
dst = &datum->next;
2002+
}
2003+
2004+
rc = -ENOMEM;
2005+
ft = kmalloc(sizeof(*ft), GFP_KERNEL);
2006+
if (!ft)
2007+
goto out;
2008+
2009+
ft->ttype = ttype;
2010+
ft->tclass = tclass;
2011+
ft->name = name;
2012+
2013+
rc = hashtab_insert(p->filename_trans, ft, first);
2014+
if (rc == -EEXIST)
2015+
pr_err("SELinux: Duplicate filename transition key\n");
2016+
if (rc)
2017+
goto out;
2018+
2019+
rc = ebitmap_set_bit(&p->filename_trans_ttypes, ttype, 1);
2020+
if (rc)
2021+
return rc;
2022+
2023+
p->filename_trans_count += ndatum;
2024+
return 0;
2025+
2026+
out:
2027+
kfree(ft);
2028+
kfree(name);
2029+
while (first) {
2030+
datum = first;
2031+
first = first->next;
2032+
2033+
ebitmap_destroy(&datum->stypes);
2034+
kfree(datum);
2035+
}
2036+
return rc;
2037+
}
2038+
19482039
static int filename_trans_read(struct policydb *p, void *fp)
19492040
{
19502041
u32 nel;
@@ -1959,12 +2050,29 @@ static int filename_trans_read(struct policydb *p, void *fp)
19592050
return rc;
19602051
nel = le32_to_cpu(buf[0]);
19612052

1962-
p->filename_trans_count = nel;
2053+
if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
2054+
p->filename_trans_count = nel;
2055+
p->filename_trans = hashtab_create(filenametr_hash,
2056+
filenametr_cmp, (1 << 11));
2057+
if (!p->filename_trans)
2058+
return -ENOMEM;
19632059

1964-
for (i = 0; i < nel; i++) {
1965-
rc = filename_trans_read_one(p, fp);
1966-
if (rc)
1967-
return rc;
2060+
for (i = 0; i < nel; i++) {
2061+
rc = filename_trans_read_helper_compat(p, fp);
2062+
if (rc)
2063+
return rc;
2064+
}
2065+
} else {
2066+
p->filename_trans = hashtab_create(filenametr_hash,
2067+
filenametr_cmp, nel);
2068+
if (!p->filename_trans)
2069+
return -ENOMEM;
2070+
2071+
for (i = 0; i < nel; i++) {
2072+
rc = filename_trans_read_helper(p, fp);
2073+
if (rc)
2074+
return rc;
2075+
}
19682076
}
19692077
hash_eval(p->filename_trans, "filenametr");
19702078
return 0;
@@ -2281,9 +2389,7 @@ int policydb_read(struct policydb *p, void *fp)
22812389
char *policydb_str;
22822390
struct policydb_compat_info *info;
22832391

2284-
rc = policydb_init(p);
2285-
if (rc)
2286-
return rc;
2392+
policydb_init(p);
22872393

22882394
/* Read the magic number and string length. */
22892395
rc = next_entry(buf, fp, sizeof(u32) * 2);
@@ -3367,7 +3473,7 @@ static int range_write(struct policydb *p, void *fp)
33673473
return 0;
33683474
}
33693475

3370-
static int filename_write_helper(void *key, void *data, void *ptr)
3476+
static int filename_write_helper_compat(void *key, void *data, void *ptr)
33713477
{
33723478
struct filename_trans_key *ft = key;
33733479
struct filename_trans_datum *datum = data;
@@ -3404,26 +3510,82 @@ static int filename_write_helper(void *key, void *data, void *ptr)
34043510
return 0;
34053511
}
34063512

3407-
static int filename_trans_write(struct policydb *p, void *fp)
3513+
static int filename_write_helper(void *key, void *data, void *ptr)
34083514
{
3409-
__le32 buf[1];
3515+
struct filename_trans_key *ft = key;
3516+
struct filename_trans_datum *datum;
3517+
void *fp = ptr;
3518+
__le32 buf[3];
34103519
int rc;
3520+
u32 ndatum, len = strlen(ft->name);
34113521

3412-
if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
3413-
return 0;
3414-
3415-
buf[0] = cpu_to_le32(p->filename_trans_count);
3522+
buf[0] = cpu_to_le32(len);
34163523
rc = put_entry(buf, sizeof(u32), 1, fp);
34173524
if (rc)
34183525
return rc;
34193526

3420-
rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
3527+
rc = put_entry(ft->name, sizeof(char), len, fp);
34213528
if (rc)
34223529
return rc;
34233530

3531+
ndatum = 0;
3532+
datum = data;
3533+
do {
3534+
ndatum++;
3535+
datum = datum->next;
3536+
} while (unlikely(datum));
3537+
3538+
buf[0] = cpu_to_le32(ft->ttype);
3539+
buf[1] = cpu_to_le32(ft->tclass);
3540+
buf[2] = cpu_to_le32(ndatum);
3541+
rc = put_entry(buf, sizeof(u32), 3, fp);
3542+
if (rc)
3543+
return rc;
3544+
3545+
datum = data;
3546+
do {
3547+
rc = ebitmap_write(&datum->stypes, fp);
3548+
if (rc)
3549+
return rc;
3550+
3551+
buf[0] = cpu_to_le32(datum->otype);
3552+
rc = put_entry(buf, sizeof(u32), 1, fp);
3553+
if (rc)
3554+
return rc;
3555+
3556+
datum = datum->next;
3557+
} while (unlikely(datum));
3558+
34243559
return 0;
34253560
}
34263561

3562+
static int filename_trans_write(struct policydb *p, void *fp)
3563+
{
3564+
__le32 buf[1];
3565+
int rc;
3566+
3567+
if (p->policyvers < POLICYDB_VERSION_FILENAME_TRANS)
3568+
return 0;
3569+
3570+
if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
3571+
buf[0] = cpu_to_le32(p->filename_trans_count);
3572+
rc = put_entry(buf, sizeof(u32), 1, fp);
3573+
if (rc)
3574+
return rc;
3575+
3576+
rc = hashtab_map(p->filename_trans,
3577+
filename_write_helper_compat, fp);
3578+
} else {
3579+
buf[0] = cpu_to_le32(p->filename_trans->nel);
3580+
rc = put_entry(buf, sizeof(u32), 1, fp);
3581+
if (rc)
3582+
return rc;
3583+
3584+
rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
3585+
}
3586+
return rc;
3587+
}
3588+
34273589
/*
34283590
* Write the configuration data in a policy database
34293591
* structure to a policy database binary representation

0 commit comments

Comments
 (0)