Commit 03414a49 authored by Ondrej Mosnacek's avatar Ondrej Mosnacek Committed by Paul Moore
Browse files

selinux: do not allocate hashtabs dynamically



It is simpler to allocate them statically in the corresponding
structure, avoiding unnecessary kmalloc() calls and pointer
dereferencing.

Signed-off-by: default avatarOndrej Mosnacek <omosnace@redhat.com>
[PM: manual merging required in policydb.c]
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 46619b44
Loading
Loading
Loading
Loading
+15 −36
Original line number Diff line number Diff line
@@ -29,34 +29,21 @@ static u32 hashtab_compute_size(u32 nel)
	return nel == 0 ? 0 : roundup_pow_of_two(nel);
}

struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
			       int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
int hashtab_init(struct hashtab *h,
		 u32 (*hash_value)(struct hashtab *h, const void *key),
		 int (*keycmp)(struct hashtab *h, const void *key1,
			       const void *key2),
		 u32 nel_hint)
{
	struct hashtab *p;
	u32 i, size = hashtab_compute_size(nel_hint);

	p = kzalloc(sizeof(*p), GFP_KERNEL);
	if (!p)
		return p;

	p->size = size;
	p->nel = 0;
	p->hash_value = hash_value;
	p->keycmp = keycmp;
	if (!size)
		return p;

	p->htable = kmalloc_array(size, sizeof(*p->htable), GFP_KERNEL);
	if (!p->htable) {
		kfree(p);
		return NULL;
	}

	for (i = 0; i < size; i++)
		p->htable[i] = NULL;
	h->size = hashtab_compute_size(nel_hint);
	h->nel = 0;
	h->hash_value = hash_value;
	h->keycmp = keycmp;
	if (!h->size)
		return 0;

	return p;
	h->htable = kcalloc(h->size, sizeof(*h->htable), GFP_KERNEL);
	return h->htable ? 0 : -ENOMEM;
}

int hashtab_insert(struct hashtab *h, void *key, void *datum)
@@ -66,7 +53,7 @@ int hashtab_insert(struct hashtab *h, void *key, void *datum)

	cond_resched();

	if (!h || !h->size || h->nel == HASHTAB_MAX_NODES)
	if (!h->size || h->nel == HASHTAB_MAX_NODES)
		return -EINVAL;

	hvalue = h->hash_value(h, key);
@@ -102,7 +89,7 @@ void *hashtab_search(struct hashtab *h, const void *key)
	u32 hvalue;
	struct hashtab_node *cur;

	if (!h || !h->size)
	if (!h->size)
		return NULL;

	hvalue = h->hash_value(h, key);
@@ -121,9 +108,6 @@ void hashtab_destroy(struct hashtab *h)
	u32 i;
	struct hashtab_node *cur, *temp;

	if (!h)
		return;

	for (i = 0; i < h->size; i++) {
		cur = h->htable[i];
		while (cur) {
@@ -136,8 +120,6 @@ void hashtab_destroy(struct hashtab *h)

	kfree(h->htable);
	h->htable = NULL;

	kfree(h);
}

int hashtab_map(struct hashtab *h,
@@ -148,9 +130,6 @@ int hashtab_map(struct hashtab *h,
	int ret;
	struct hashtab_node *cur;

	if (!h)
		return 0;

	for (i = 0; i < h->size; i++) {
		cur = h->htable[i];
		while (cur) {
+7 −6
Original line number Diff line number Diff line
@@ -35,13 +35,14 @@ struct hashtab_info {
};

/*
 * Creates a new hash table with the specified characteristics.
 * Initializes a new hash table with the specified characteristics.
 *
 * Returns NULL if insufficent space is available or
 * the new hash table otherwise.
 * Returns -ENOMEM if insufficient space is available or 0 otherwise.
 */
struct hashtab *hashtab_create(u32 (*hash_value)(struct hashtab *h, const void *key),
			       int (*keycmp)(struct hashtab *h, const void *key1, const void *key2),
int hashtab_init(struct hashtab *h,
		 u32 (*hash_value)(struct hashtab *h, const void *key),
		 int (*keycmp)(struct hashtab *h, const void *key1,
			       const void *key2),
		 u32 nel_hint);

/*
+7 −7
Original line number Diff line number Diff line
@@ -165,7 +165,7 @@ int mls_level_isvalid(struct policydb *p, struct mls_level *l)

	if (!l->sens || l->sens > p->p_levels.nprim)
		return 0;
	levdatum = hashtab_search(p->p_levels.table,
	levdatum = hashtab_search(&p->p_levels.table,
				  sym_name(p, SYM_LEVELS, l->sens - 1));
	if (!levdatum)
		return 0;
@@ -293,7 +293,7 @@ int mls_context_to_sid(struct policydb *pol,
			*(next_cat++) = '\0';

		/* Parse sensitivity. */
		levdatum = hashtab_search(pol->p_levels.table, sensitivity);
		levdatum = hashtab_search(&pol->p_levels.table, sensitivity);
		if (!levdatum)
			return -EINVAL;
		context->range.level[l].sens = levdatum->level->sens;
@@ -312,7 +312,7 @@ int mls_context_to_sid(struct policydb *pol,
				*rngptr++ = '\0';
			}

			catdatum = hashtab_search(pol->p_cats.table, cur_cat);
			catdatum = hashtab_search(&pol->p_cats.table, cur_cat);
			if (!catdatum)
				return -EINVAL;

@@ -325,7 +325,7 @@ int mls_context_to_sid(struct policydb *pol,
			if (rngptr == NULL)
				continue;

			rngdatum = hashtab_search(pol->p_cats.table, rngptr);
			rngdatum = hashtab_search(&pol->p_cats.table, rngptr);
			if (!rngdatum)
				return -EINVAL;

@@ -458,7 +458,7 @@ int mls_convert_context(struct policydb *oldp,
		return 0;

	for (l = 0; l < 2; l++) {
		levdatum = hashtab_search(newp->p_levels.table,
		levdatum = hashtab_search(&newp->p_levels.table,
					  sym_name(oldp, SYM_LEVELS,
						   oldc->range.level[l].sens - 1));

@@ -470,7 +470,7 @@ int mls_convert_context(struct policydb *oldp,
					      node, i) {
			int rc;

			catdatum = hashtab_search(newp->p_cats.table,
			catdatum = hashtab_search(&newp->p_cats.table,
						  sym_name(oldp, SYM_CATS, i));
			if (!catdatum)
				return -EINVAL;
@@ -506,7 +506,7 @@ int mls_compute_sid(struct policydb *p,
		rtr.source_type = scontext->type;
		rtr.target_type = tcontext->type;
		rtr.target_class = tclass;
		r = hashtab_search(p->range_tr, &rtr);
		r = hashtab_search(&p->range_tr, &rtr);
		if (r)
			return mls_range_set(newcontext, r);

+60 −67
Original line number Diff line number Diff line
@@ -195,8 +195,8 @@ static int common_destroy(void *key, void *datum, void *p)
	kfree(key);
	if (datum) {
		comdatum = datum;
		hashtab_map(comdatum->permissions.table, perm_destroy, NULL);
		hashtab_destroy(comdatum->permissions.table);
		hashtab_map(&comdatum->permissions.table, perm_destroy, NULL);
		hashtab_destroy(&comdatum->permissions.table);
	}
	kfree(datum);
	return 0;
@@ -224,8 +224,8 @@ static int cls_destroy(void *key, void *datum, void *p)
	kfree(key);
	if (datum) {
		cladatum = datum;
		hashtab_map(cladatum->permissions.table, perm_destroy, NULL);
		hashtab_destroy(cladatum->permissions.table);
		hashtab_map(&cladatum->permissions.table, perm_destroy, NULL);
		hashtab_destroy(&cladatum->permissions.table);
		constraint = cladatum->constraints;
		while (constraint) {
			e = constraint->expr;
@@ -400,7 +400,7 @@ static int roles_init(struct policydb *p)
	if (!key)
		goto out;

	rc = hashtab_insert(p->p_roles.table, key, role);
	rc = hashtab_insert(&p->p_roles.table, key, role);
	if (rc)
		goto out;

@@ -668,7 +668,7 @@ static void symtab_hash_eval(struct symtab *s)
	int i;

	for (i = 0; i < SYM_NUM; i++)
		hash_eval(s[i].table, symtab_name[i]);
		hash_eval(&s[i].table, symtab_name[i]);
}

#else
@@ -739,7 +739,7 @@ static int policydb_index(struct policydb *p)
		if (!p->sym_val_to_name[i])
			return -ENOMEM;

		rc = hashtab_map(p->symtab[i].table, index_f[i], p);
		rc = hashtab_map(&p->symtab[i].table, index_f[i], p);
		if (rc)
			goto out;
	}
@@ -760,8 +760,8 @@ void policydb_destroy(struct policydb *p)

	for (i = 0; i < SYM_NUM; i++) {
		cond_resched();
		hashtab_map(p->symtab[i].table, destroy_f[i], NULL);
		hashtab_destroy(p->symtab[i].table);
		hashtab_map(&p->symtab[i].table, destroy_f[i], NULL);
		hashtab_destroy(&p->symtab[i].table);
	}

	for (i = 0; i < SYM_NUM; i++)
@@ -803,8 +803,8 @@ void policydb_destroy(struct policydb *p)

	cond_policydb_destroy(p);

	hashtab_map(p->role_tr, role_tr_destroy, NULL);
	hashtab_destroy(p->role_tr);
	hashtab_map(&p->role_tr, role_tr_destroy, NULL);
	hashtab_destroy(&p->role_tr);

	for (ra = p->role_allow; ra; ra = ra->next) {
		cond_resched();
@@ -813,11 +813,11 @@ void policydb_destroy(struct policydb *p)
	}
	kfree(lra);

	hashtab_map(p->filename_trans, filenametr_destroy, NULL);
	hashtab_destroy(p->filename_trans);
	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);
	hashtab_map(&p->range_tr, range_tr_destroy, NULL);
	hashtab_destroy(&p->range_tr);

	if (p->type_attr_map_array) {
		for (i = 0; i < p->p_types.nprim; i++)
@@ -1128,7 +1128,7 @@ static int common_read(struct policydb *p, struct hashtab *h, void *fp)
		goto bad;

	for (i = 0; i < nel; i++) {
		rc = perm_read(p, comdatum->permissions.table, fp);
		rc = perm_read(p, &comdatum->permissions.table, fp);
		if (rc)
			goto bad;
	}
@@ -1300,7 +1300,8 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
			goto bad;

		rc = -EINVAL;
		cladatum->comdatum = hashtab_search(p->p_commons.table, cladatum->comkey);
		cladatum->comdatum = hashtab_search(&p->p_commons.table,
						    cladatum->comkey);
		if (!cladatum->comdatum) {
			pr_err("SELinux:  unknown common %s\n",
			       cladatum->comkey);
@@ -1308,7 +1309,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
		}
	}
	for (i = 0; i < nel; i++) {
		rc = perm_read(p, cladatum->permissions.table, fp);
		rc = perm_read(p, &cladatum->permissions.table, fp);
		if (rc)
			goto bad;
	}
@@ -1731,18 +1732,15 @@ static int policydb_bounds_sanity_check(struct policydb *p)
	if (p->policyvers < POLICYDB_VERSION_BOUNDARY)
		return 0;

	rc = hashtab_map(p->p_users.table,
			 user_bounds_sanity_check, p);
	rc = hashtab_map(&p->p_users.table, user_bounds_sanity_check, p);
	if (rc)
		return rc;

	rc = hashtab_map(p->p_roles.table,
			 role_bounds_sanity_check, p);
	rc = hashtab_map(&p->p_roles.table, role_bounds_sanity_check, p);
	if (rc)
		return rc;

	rc = hashtab_map(p->p_types.table,
			 type_bounds_sanity_check, p);
	rc = hashtab_map(&p->p_types.table, type_bounds_sanity_check, p);
	if (rc)
		return rc;

@@ -1753,7 +1751,7 @@ u16 string_to_security_class(struct policydb *p, const char *name)
{
	struct class_datum *cladatum;

	cladatum = hashtab_search(p->p_classes.table, name);
	cladatum = hashtab_search(&p->p_classes.table, name);
	if (!cladatum)
		return 0;

@@ -1772,11 +1770,9 @@ u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name)
	cladatum = p->class_val_to_struct[tclass-1];
	comdatum = cladatum->comdatum;
	if (comdatum)
		perdatum = hashtab_search(comdatum->permissions.table,
					  name);
		perdatum = hashtab_search(&comdatum->permissions.table, name);
	if (!perdatum)
		perdatum = hashtab_search(cladatum->permissions.table,
					  name);
		perdatum = hashtab_search(&cladatum->permissions.table, name);
	if (!perdatum)
		return 0;

@@ -1800,9 +1796,9 @@ static int range_read(struct policydb *p, void *fp)

	nel = le32_to_cpu(buf[0]);

	p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, nel);
	if (!p->range_tr)
		return -ENOMEM;
	rc = hashtab_init(&p->range_tr, rangetr_hash, rangetr_cmp, nel);
	if (rc)
		return rc;

	for (i = 0; i < nel; i++) {
		rc = -ENOMEM;
@@ -1845,14 +1841,14 @@ static int range_read(struct policydb *p, void *fp)
			goto out;
		}

		rc = hashtab_insert(p->range_tr, rt, r);
		rc = hashtab_insert(&p->range_tr, rt, r);
		if (rc)
			goto out;

		rt = NULL;
		r = NULL;
	}
	hash_eval(p->range_tr, "rangetr");
	hash_eval(&p->range_tr, "rangetr");
	rc = 0;
out:
	kfree(rt);
@@ -1892,7 +1888,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
	otype = le32_to_cpu(buf[3]);

	last = NULL;
	datum = hashtab_search(p->filename_trans, &key);
	datum = hashtab_search(&p->filename_trans, &key);
	while (datum) {
		if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
			/* conflicting/duplicate rules are ignored */
@@ -1922,7 +1918,7 @@ static int filename_trans_read_helper_compat(struct policydb *p, void *fp)
			if (!ft)
				goto out;

			rc = hashtab_insert(p->filename_trans, ft, datum);
			rc = hashtab_insert(&p->filename_trans, ft, datum);
			if (rc)
				goto out;
			name = NULL;
@@ -2010,7 +2006,7 @@ static int filename_trans_read_helper(struct policydb *p, void *fp)
	ft->tclass = tclass;
	ft->name = name;

	rc = hashtab_insert(p->filename_trans, ft, first);
	rc = hashtab_insert(&p->filename_trans, ft, first);
	if (rc == -EEXIST)
		pr_err("SELinux:  Duplicate filename transition key\n");
	if (rc)
@@ -2047,10 +2043,11 @@ static int filename_trans_read(struct policydb *p, void *fp)

	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
		p->compat_filename_trans_count = nel;
		p->filename_trans = hashtab_create(filenametr_hash,

		rc = hashtab_init(&p->filename_trans, filenametr_hash,
				  filenametr_cmp, (1 << 11));
		if (!p->filename_trans)
			return -ENOMEM;
		if (rc)
			return rc;

		for (i = 0; i < nel; i++) {
			rc = filename_trans_read_helper_compat(p, fp);
@@ -2058,10 +2055,10 @@ static int filename_trans_read(struct policydb *p, void *fp)
				return rc;
		}
	} else {
		p->filename_trans = hashtab_create(filenametr_hash,
		rc = hashtab_init(&p->filename_trans, filenametr_hash,
				  filenametr_cmp, nel);
		if (!p->filename_trans)
			return -ENOMEM;
		if (rc)
			return rc;

		for (i = 0; i < nel; i++) {
			rc = filename_trans_read_helper(p, fp);
@@ -2069,7 +2066,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
				return rc;
		}
	}
	hash_eval(p->filename_trans, "filenametr");
	hash_eval(&p->filename_trans, "filenametr");
	return 0;
}

@@ -2512,7 +2509,7 @@ int policydb_read(struct policydb *p, void *fp)
		}

		for (j = 0; j < nel; j++) {
			rc = read_f[i](p, p->symtab[i].table, fp);
			rc = read_f[i](p, &p->symtab[i].table, fp);
			if (rc)
				goto bad;
		}
@@ -2540,9 +2537,8 @@ int policydb_read(struct policydb *p, void *fp)
		goto bad;
	nel = le32_to_cpu(buf[0]);

	rc = -ENOMEM;
	p->role_tr = hashtab_create(role_trans_hash, role_trans_cmp, nel);
	if (!p->role_tr)
	rc = hashtab_init(&p->role_tr, role_trans_hash, role_trans_cmp, nel);
	if (rc)
		goto bad;
	for (i = 0; i < nel; i++) {
		rc = -ENOMEM;
@@ -2578,7 +2574,7 @@ int policydb_read(struct policydb *p, void *fp)
		    !policydb_role_isvalid(p, rtd->new_role))
			goto bad;

		rc = hashtab_insert(p->role_tr, rtk, rtd);
		rc = hashtab_insert(&p->role_tr, rtk, rtd);
		if (rc)
			goto bad;

@@ -2822,12 +2818,12 @@ static int role_trans_write(struct policydb *p, void *fp)
	__le32 buf[1];
	int rc;

	buf[0] = cpu_to_le32(p->role_tr->nel);
	buf[0] = cpu_to_le32(p->role_tr.nel);
	rc = put_entry(buf, sizeof(u32), 1, fp);
	if (rc)
		return rc;

	return hashtab_map(p->role_tr, role_trans_write_one, &pd);
	return hashtab_map(&p->role_tr, role_trans_write_one, &pd);
}

static int role_allow_write(struct role_allow *r, void *fp)
@@ -2921,7 +2917,7 @@ static int common_write(void *vkey, void *datum, void *ptr)
	buf[0] = cpu_to_le32(len);
	buf[1] = cpu_to_le32(comdatum->value);
	buf[2] = cpu_to_le32(comdatum->permissions.nprim);
	buf[3] = cpu_to_le32(comdatum->permissions.table->nel);
	buf[3] = cpu_to_le32(comdatum->permissions.table.nel);
	rc = put_entry(buf, sizeof(u32), 4, fp);
	if (rc)
		return rc;
@@ -2930,7 +2926,7 @@ static int common_write(void *vkey, void *datum, void *ptr)
	if (rc)
		return rc;

	rc = hashtab_map(comdatum->permissions.table, perm_write, fp);
	rc = hashtab_map(&comdatum->permissions.table, perm_write, fp);
	if (rc)
		return rc;

@@ -3029,10 +3025,7 @@ static int class_write(void *vkey, void *datum, void *ptr)
	buf[1] = cpu_to_le32(len2);
	buf[2] = cpu_to_le32(cladatum->value);
	buf[3] = cpu_to_le32(cladatum->permissions.nprim);
	if (cladatum->permissions.table)
		buf[4] = cpu_to_le32(cladatum->permissions.table->nel);
	else
		buf[4] = 0;
	buf[4] = cpu_to_le32(cladatum->permissions.table.nel);
	buf[5] = cpu_to_le32(ncons);
	rc = put_entry(buf, sizeof(u32), 6, fp);
	if (rc)
@@ -3048,7 +3041,7 @@ static int class_write(void *vkey, void *datum, void *ptr)
			return rc;
	}

	rc = hashtab_map(cladatum->permissions.table, perm_write, fp);
	rc = hashtab_map(&cladatum->permissions.table, perm_write, fp);
	if (rc)
		return rc;

@@ -3443,13 +3436,13 @@ static int range_write(struct policydb *p, void *fp)
	pd.p = p;
	pd.fp = fp;

	buf[0] = cpu_to_le32(p->range_tr->nel);
	buf[0] = cpu_to_le32(p->range_tr.nel);
	rc = put_entry(buf, sizeof(u32), 1, fp);
	if (rc)
		return rc;

	/* actually write all of the entries */
	rc = hashtab_map(p->range_tr, range_write_helper, &pd);
	rc = hashtab_map(&p->range_tr, range_write_helper, &pd);
	if (rc)
		return rc;

@@ -3556,15 +3549,15 @@ static int filename_trans_write(struct policydb *p, void *fp)
		if (rc)
			return rc;

		rc = hashtab_map(p->filename_trans,
		rc = hashtab_map(&p->filename_trans,
				 filename_write_helper_compat, fp);
	} else {
		buf[0] = cpu_to_le32(p->filename_trans->nel);
		buf[0] = cpu_to_le32(p->filename_trans.nel);
		rc = put_entry(buf, sizeof(u32), 1, fp);
		if (rc)
			return rc;

		rc = hashtab_map(p->filename_trans, filename_write_helper, fp);
		rc = hashtab_map(&p->filename_trans, filename_write_helper, fp);
	}
	return rc;
}
@@ -3653,12 +3646,12 @@ int policydb_write(struct policydb *p, void *fp)
		pd.p = p;

		buf[0] = cpu_to_le32(p->symtab[i].nprim);
		buf[1] = cpu_to_le32(p->symtab[i].table->nel);
		buf[1] = cpu_to_le32(p->symtab[i].table.nel);

		rc = put_entry(buf, sizeof(u32), 2, fp);
		if (rc)
			return rc;
		rc = hashtab_map(p->symtab[i].table, write_f[i], &pd);
		rc = hashtab_map(&p->symtab[i].table, write_f[i], &pd);
		if (rc)
			return rc;
	}
+3 −3
Original line number Diff line number Diff line
@@ -263,13 +263,13 @@ struct policydb {
	struct avtab te_avtab;

	/* role transitions */
	struct hashtab *role_tr;
	struct hashtab role_tr;

	/* file transitions with the last path component */
	/* quickly exclude lookups when parent ttype has no rules */
	struct ebitmap filename_trans_ttypes;
	/* actual set of filename_trans rules */
	struct hashtab *filename_trans;
	struct hashtab filename_trans;
	/* only used if policyvers < POLICYDB_VERSION_COMP_FTRANS */
	u32 compat_filename_trans_count;

@@ -294,7 +294,7 @@ struct policydb {
	struct genfs *genfs;

	/* range transitions table (range_trans_key -> mls_range) */
	struct hashtab *range_tr;
	struct hashtab range_tr;

	/* type -> attribute reverse mapping */
	struct ebitmap *type_attr_map_array;
Loading