Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2463c26d authored by Eric Paris's avatar Eric Paris
Browse files

SELinux: put name based create rules in a hashtable



To shorten the list we need to run if filename trans rules exist for the type
of the given parent directory I put them in a hashtable.  Given the policy we
are expecting to use in Fedora this takes the worst case list run from about
5,000 entries to 17.

Signed-off-by: default avatarEric Paris <eparis@redhat.com>
Reviewed-by: default avatarJames Morris <jmorris@namei.org>
parent 3f058ef7
Loading
Loading
Loading
Loading
+119 −48
Original line number Diff line number Diff line
@@ -184,6 +184,43 @@ static int roles_init(struct policydb *p)
	return rc;
}

static u32 filenametr_hash(struct hashtab *h, const void *k)
{
	const struct filename_trans *ft = k;
	unsigned long hash;
	unsigned int byte_num;
	unsigned char focus;

	hash = ft->stype ^ ft->ttype ^ ft->tclass;

	byte_num = 0;
	while ((focus = ft->name[byte_num++]))
		hash = partial_name_hash(focus, hash);
	return hash & (h->size - 1);
}

static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
{
	const struct filename_trans *ft1 = k1;
	const struct filename_trans *ft2 = k2;
	int v;

	v = ft1->stype - ft2->stype;
	if (v)
		return v;

	v = ft1->ttype - ft2->ttype;
	if (v)
		return v;

	v = ft1->tclass - ft2->tclass;
	if (v)
		return v;

	return strcmp(ft1->name, ft2->name);

}

static u32 rangetr_hash(struct hashtab *h, const void *k)
{
	const struct range_trans *key = k;
@@ -236,6 +273,10 @@ static int policydb_init(struct policydb *p)
	if (rc)
		goto out;

	p->filename_trans = hashtab_create(filenametr_hash, filenametr_cmp, (1 << 10));
	if (!p->filename_trans)
		goto out;

	p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256);
	if (!p->range_tr)
		goto out;
@@ -246,6 +287,8 @@ static int policydb_init(struct policydb *p)

	return 0;
out:
	hashtab_destroy(p->filename_trans);
	hashtab_destroy(p->range_tr);
	for (i = 0; i < SYM_NUM; i++)
		hashtab_destroy(p->symtab[i].table);
	return rc;
@@ -675,6 +718,16 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) =
	cat_destroy,
};

static int filenametr_destroy(void *key, void *datum, void *p)
{
	struct filename_trans *ft = key;
	kfree(ft->name);
	kfree(key);
	kfree(datum);
	cond_resched();
	return 0;
}

static int range_tr_destroy(void *key, void *datum, void *p)
{
	struct mls_range *rt = datum;
@@ -709,7 +762,6 @@ void policydb_destroy(struct policydb *p)
	int i;
	struct role_allow *ra, *lra = NULL;
	struct role_trans *tr, *ltr = NULL;
	struct filename_trans *ft, *nft;

	for (i = 0; i < SYM_NUM; i++) {
		cond_resched();
@@ -773,6 +825,9 @@ void policydb_destroy(struct policydb *p)
	}
	kfree(lra);

	hashtab_map(p->filename_trans, filenametr_destroy, NULL);
	hashtab_destroy(p->filename_trans);

	hashtab_map(p->range_tr, range_tr_destroy, NULL);
	hashtab_destroy(p->range_tr);

@@ -788,14 +843,6 @@ void policydb_destroy(struct policydb *p)
		flex_array_free(p->type_attr_map_array);
	}

	ft = p->filename_trans;
	while (ft) {
		nft = ft->next;
		kfree(ft->name);
		kfree(ft);
		ft = nft;
	}

	ebitmap_destroy(&p->filename_trans_ttypes);
	ebitmap_destroy(&p->policycaps);
	ebitmap_destroy(&p->permissive_map);
@@ -1806,9 +1853,10 @@ static int range_read(struct policydb *p, void *fp)

static int filename_trans_read(struct policydb *p, void *fp)
{
	struct filename_trans *ft, *last;
	u32 nel, len;
	struct filename_trans *ft;
	struct filename_trans_datum *otype;
	char *name;
	u32 nel, len;
	__le32 buf[4];
	int rc, i;

@@ -1817,25 +1865,23 @@ static int filename_trans_read(struct policydb *p, void *fp)

	rc = next_entry(buf, fp, sizeof(u32));
	if (rc)
		goto out;
		return rc;
	nel = le32_to_cpu(buf[0]);

	last = p->filename_trans;
	while (last && last->next)
		last = last->next;

	for (i = 0; i < nel; i++) {
		ft = NULL;
		otype = NULL;
		name = NULL;

		rc = -ENOMEM;
		ft = kzalloc(sizeof(*ft), GFP_KERNEL);
		if (!ft)
			goto out;

		/* add it to the tail of the list */
		if (!last)
			p->filename_trans = ft;
		else
			last->next = ft;
		last = ft;
		rc = -ENOMEM;
		otype = kmalloc(sizeof(*otype), GFP_KERNEL);
		if (!otype)
			goto out;

		/* length of the path component string */
		rc = next_entry(buf, fp, sizeof(u32));
@@ -1863,14 +1909,22 @@ static int filename_trans_read(struct policydb *p, void *fp)
		ft->stype = le32_to_cpu(buf[0]);
		ft->ttype = le32_to_cpu(buf[1]);
		ft->tclass = le32_to_cpu(buf[2]);
		ft->otype = le32_to_cpu(buf[3]);

		otype->otype = le32_to_cpu(buf[3]);

		rc = ebitmap_set_bit(&p->filename_trans_ttypes, ft->ttype, 1);
		if (rc)
			goto out;

		hashtab_insert(p->filename_trans, ft, otype);
	}
	rc = 0;
	hash_eval(p->filename_trans, "filenametr");
	return 0;
out:
	kfree(ft);
	kfree(name);
	kfree(otype);

	return rc;
}

@@ -3131,22 +3185,15 @@ static int range_write(struct policydb *p, void *fp)
	return 0;
}

static int filename_trans_write(struct policydb *p, void *fp)
static int filename_write_helper(void *key, void *data, void *ptr)
{
	struct filename_trans *ft;
	u32 len, nel = 0;
	__le32 buf[4];
	struct filename_trans *ft = key;
	struct filename_trans_datum *otype = data;
	void *fp = ptr;
	int rc;
	u32 len;

	for (ft = p->filename_trans; ft; ft = ft->next)
		nel++;

	buf[0] = cpu_to_le32(nel);
	rc = put_entry(buf, sizeof(u32), 1, fp);
	if (rc)
		return rc;

	for (ft = p->filename_trans; ft; ft = ft->next) {
	len = strlen(ft->name);
	buf[0] = cpu_to_le32(len);
	rc = put_entry(buf, sizeof(u32), 1, fp);
@@ -3160,14 +3207,38 @@ static int filename_trans_write(struct policydb *p, void *fp)
	buf[0] = ft->stype;
	buf[1] = ft->ttype;
	buf[2] = ft->tclass;
		buf[3] = ft->otype;
	buf[3] = otype->otype;

	rc = put_entry(buf, sizeof(u32), 4, fp);
	if (rc)
		return rc;

	return 0;
}

static int filename_trans_write(struct policydb *p, void *fp)
{
	u32 nel;
	__le32 buf[1];
	int rc;

	nel = 0;
	rc = hashtab_map(p->filename_trans, hashtab_cnt, &nel);
	if (rc)
		return rc;

	buf[0] = cpu_to_le32(nel);
	rc = put_entry(buf, sizeof(u32), 1, fp);
	if (rc)
		return rc;

	rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
	if (rc)
		return rc;

	return 0;
}

/*
 * Write the configuration data in a policy database
 * structure to a policy database binary representation
+6 −3
Original line number Diff line number Diff line
@@ -79,11 +79,13 @@ struct role_trans {
};

struct filename_trans {
	struct filename_trans *next;
	u32 stype;		/* current process */
	u32 ttype;		/* parent dir context */
	u16 tclass;		/* class of new object */
	const char *name;	/* last path component */
};

struct filename_trans_datum {
	u32 otype;		/* expected of new object */
};

@@ -227,10 +229,11 @@ struct policydb {
	/* role transitions */
	struct role_trans *role_tr;

	/* file transitions with the last path component */
	/* quickly exclude lookups when parent ttype has no rules */
	struct ebitmap filename_trans_ttypes;
	/* file transitions with the last path component */
	struct filename_trans *filename_trans;
	/* actual set of filename_trans rules */
	struct hashtab *filename_trans;

	/* bools indexed by (value - 1) */
	struct cond_bool_datum **bool_val_to_struct;
+10 −10
Original line number Diff line number Diff line
@@ -1362,7 +1362,8 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext
				  u32 stype, u32 ttype, u16 tclass,
				  const char *objname)
{
	struct filename_trans *ft;
	struct filename_trans ft;
	struct filename_trans_datum *otype;

	/*
	 * Most filename trans rules are going to live in specific directories
@@ -1372,15 +1373,14 @@ static void filename_compute_type(struct policydb *p, struct context *newcontext
	if (!ebitmap_get_bit(&p->filename_trans_ttypes, ttype))
		return;

	for (ft = p->filename_trans; ft; ft = ft->next) {
		if (ft->stype == stype &&
		    ft->ttype == ttype &&
		    ft->tclass == tclass &&
		    !strcmp(ft->name, objname)) {
			newcontext->type = ft->otype;
			return;
		}
	}
	ft.stype = stype;
	ft.ttype = ttype;
	ft.tclass = tclass;
	ft.name = objname;

	otype = hashtab_search(p->filename_trans, &ft);
	if (otype)
		newcontext->type = otype->otype;
}

static int security_compute_sid(u32 ssid,