mirror of
				https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
				synced 2025-11-04 07:44:51 +10:00 
			
		
		
		
	selinux/stable-5.9 PR 20200803
-----BEGIN PGP SIGNATURE-----
 
 iQJIBAABCAAyFiEES0KozwfymdVUl37v6iDy2pc3iXMFAl8okmsUHHBhdWxAcGF1
 bC1tb29yZS5jb20ACgkQ6iDy2pc3iXMaRA//XO7JKJEyLcpqRzhQP/QY50JXdQtE
 c9vKeb7y4wlfbTozRgjBN3Xj+tFbqANzX/rVsR1aKV+hExyEuUfNZ0Fl8MbPEccQ
 1RUCW2808/YRTYsl0g0DDZsc+vxVosfouk91pZfld9ZRnZbrNTGXFP7vuVyFKdBy
 wBX1FCL9q31wLc8Jk7f6otSbBvSCG0YXjkkxEM7LQx3oQ59s8dfOed41kDGpLoNk
 TS5BN/W3uuYEDIsIwTRZjU4h42dpc/wbxVMJhBg85rU/2bF4u5sDs2qgwqaa1tXs
 aRDH5J+eBMZRCkF4shxlDrrOWeXvEEtal9yYzQUx664tWDjZazoTLctCAe3PWI1i
 q61cG8PXw/5/oB6RyvPkRMLc5pU8P6/Xdfg6R6kOsGSq8bj+g30J6jqGXnW9FIVr
 5rIaooiw19vqH+ASVuq9oLmhuWJQyn6ImFqOkREJFWVaqufglWw9RWDCGFsLq9Tr
 w6HbA9UYCoWpdQBfRXpa086sSQm1wuCP39fIcY64uHpR5gPJuzyd8Tswz3tbEAtg
 v7vgIRtBpghhdcBLzIJgSIXJKR7W/Y49eFwNf3x0OTSeAIia6Z9paaQjXYl71I9V
 6oUiQgVE3lX2SkgMbOK2V5UsjbVkpjjv7MWxdm0mPQCU0Fmb8W2FN/wVR7FBlCZc
 yhde+bs4zTmPNFw=
 =ocPe
 -----END PGP SIGNATURE-----
Merge tag 'selinux-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux
Pull selinux updates from Paul Moore:
 "Beyond the usual smattering of bug fixes, we've got three small
  improvements worth highlighting:
   - improved SELinux policy symbol table performance due to a reworking
     of the insert and search functions
   - allow reading of SELinux labels before the policy is loaded,
     allowing for some more "exotic" initramfs approaches
   - improved checking an error reporting about process
     class/permissions during SELinux policy load"
* tag 'selinux-pr-20200803' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux:
  selinux: complete the inlining of hashtab functions
  selinux: prepare for inlining of hashtab functions
  selinux: specialize symtab insert and search functions
  selinux: Fix spelling mistakes in the comments
  selinux: fixed a checkpatch warning with the sizeof macro
  selinux: log error messages on required process class / permissions
  scripts/selinux/mdp: fix initial SID handling
  selinux: allow reading labels before policy is loaded
			
			
This commit is contained in:
		
						commit
						49e917deeb
					
				@ -67,8 +67,14 @@ int main(int argc, char *argv[])
 | 
			
		||||
 | 
			
		||||
	initial_sid_to_string_len = sizeof(initial_sid_to_string) / sizeof (char *);
 | 
			
		||||
	/* print out the sids */
 | 
			
		||||
	for (i = 1; i < initial_sid_to_string_len; i++)
 | 
			
		||||
		fprintf(fout, "sid %s\n", initial_sid_to_string[i]);
 | 
			
		||||
	for (i = 1; i < initial_sid_to_string_len; i++) {
 | 
			
		||||
		const char *name = initial_sid_to_string[i];
 | 
			
		||||
 | 
			
		||||
		if (name)
 | 
			
		||||
			fprintf(fout, "sid %s\n", name);
 | 
			
		||||
		else
 | 
			
		||||
			fprintf(fout, "sid unused%d\n", i);
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(fout, "\n");
 | 
			
		||||
 | 
			
		||||
	/* print out the class permissions */
 | 
			
		||||
@ -126,9 +132,16 @@ int main(int argc, char *argv[])
 | 
			
		||||
#define OBJUSERROLETYPE "user_u:object_r:base_t"
 | 
			
		||||
 | 
			
		||||
	/* default sids */
 | 
			
		||||
	for (i = 1; i < initial_sid_to_string_len; i++)
 | 
			
		||||
		fprintf(fout, "sid %s " SUBJUSERROLETYPE "%s\n",
 | 
			
		||||
			initial_sid_to_string[i], mls ? ":" SYSTEMLOW : "");
 | 
			
		||||
	for (i = 1; i < initial_sid_to_string_len; i++) {
 | 
			
		||||
		const char *name = initial_sid_to_string[i];
 | 
			
		||||
 | 
			
		||||
		if (name)
 | 
			
		||||
			fprintf(fout, "sid %s ", name);
 | 
			
		||||
		else
 | 
			
		||||
			fprintf(fout, "sid unused%d\n", i);
 | 
			
		||||
		fprintf(fout, SUBJUSERROLETYPE "%s\n",
 | 
			
		||||
			mls ? ":" SYSTEMLOW : "");
 | 
			
		||||
	}
 | 
			
		||||
	fprintf(fout, "\n");
 | 
			
		||||
 | 
			
		||||
#define FS_USE(behavior, fstype)			    \
 | 
			
		||||
 | 
			
		||||
@ -3332,7 +3332,12 @@ static int selinux_inode_getsecurity(struct inode *inode, const char *name, void
 | 
			
		||||
	char *context = NULL;
 | 
			
		||||
	struct inode_security_struct *isec;
 | 
			
		||||
 | 
			
		||||
	if (strcmp(name, XATTR_SELINUX_SUFFIX))
 | 
			
		||||
	/*
 | 
			
		||||
	 * If we're not initialized yet, then we can't validate contexts, so
 | 
			
		||||
	 * just let vfs_getxattr fall back to using the on-disk xattr.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!selinux_initialized(&selinux_state) ||
 | 
			
		||||
	    strcmp(name, XATTR_SELINUX_SUFFIX))
 | 
			
		||||
		return -EOPNOTSUPP;
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
 | 
			
		||||
@ -124,7 +124,7 @@ static void sel_netif_destroy(struct sel_netif *netif)
 | 
			
		||||
 * @sid: interface SID
 | 
			
		||||
 *
 | 
			
		||||
 * Description:
 | 
			
		||||
 * This function determines the SID of a network interface by quering the
 | 
			
		||||
 * This function determines the SID of a network interface by querying the
 | 
			
		||||
 * security policy.  The result is added to the network interface table to
 | 
			
		||||
 * speedup future queries.  Returns zero on success, negative values on
 | 
			
		||||
 * failure.
 | 
			
		||||
 | 
			
		||||
@ -181,7 +181,7 @@ static void sel_netnode_insert(struct sel_netnode *node)
 | 
			
		||||
 * @sid: node SID
 | 
			
		||||
 *
 | 
			
		||||
 * Description:
 | 
			
		||||
 * This function determines the SID of a network address by quering the
 | 
			
		||||
 * This function determines the SID of a network address by querying the
 | 
			
		||||
 * security policy.  The result is added to the network address table to
 | 
			
		||||
 * speedup future queries.  Returns zero on success, negative values on
 | 
			
		||||
 * failure.
 | 
			
		||||
 | 
			
		||||
@ -130,7 +130,7 @@ static void sel_netport_insert(struct sel_netport *port)
 | 
			
		||||
 * @sid: port SID
 | 
			
		||||
 *
 | 
			
		||||
 * Description:
 | 
			
		||||
 * This function determines the SID of a network port by quering the security
 | 
			
		||||
 * This function determines the SID of a network port by querying the security
 | 
			
		||||
 * policy.  The result is added to the network port table to speedup future
 | 
			
		||||
 * queries.  Returns zero on success, negative values on failure.
 | 
			
		||||
 *
 | 
			
		||||
 | 
			
		||||
@ -203,7 +203,7 @@ static int bool_isvalid(struct cond_bool_datum *b)
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
int cond_read_bool(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct cond_bool_datum *booldatum;
 | 
			
		||||
@ -215,7 +215,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (!booldatum)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
 | 
			
		||||
	rc = next_entry(buf, fp, sizeof buf);
 | 
			
		||||
	rc = next_entry(buf, fp, sizeof(buf));
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
@ -238,7 +238,7 @@ int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto err;
 | 
			
		||||
	key[len] = '\0';
 | 
			
		||||
	rc = hashtab_insert(h, key, booldatum);
 | 
			
		||||
	rc = symtab_insert(s, key, booldatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto err;
 | 
			
		||||
 | 
			
		||||
@ -416,7 +416,7 @@ int cond_read_list(struct policydb *p, void *fp)
 | 
			
		||||
	u32 i, len;
 | 
			
		||||
	int rc;
 | 
			
		||||
 | 
			
		||||
	rc = next_entry(buf, fp, sizeof buf);
 | 
			
		||||
	rc = next_entry(buf, fp, sizeof(buf));
 | 
			
		||||
	if (rc)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -69,7 +69,7 @@ int cond_destroy_bool(void *key, void *datum, void *p);
 | 
			
		||||
 | 
			
		||||
int cond_index_bool(void *key, void *datum, void *datap);
 | 
			
		||||
 | 
			
		||||
int cond_read_bool(struct policydb *p, struct hashtab *h, void *fp);
 | 
			
		||||
int cond_read_bool(struct policydb *p, struct symtab *s, void *fp);
 | 
			
		||||
int cond_read_list(struct policydb *p, void *fp);
 | 
			
		||||
int cond_write_bool(void *key, void *datum, void *ptr);
 | 
			
		||||
int cond_write_list(struct policydb *p, void *fp);
 | 
			
		||||
 | 
			
		||||
@ -7,7 +7,6 @@
 | 
			
		||||
#include <linux/kernel.h>
 | 
			
		||||
#include <linux/slab.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
#include "hashtab.h"
 | 
			
		||||
 | 
			
		||||
static struct kmem_cache *hashtab_node_cachep;
 | 
			
		||||
@ -29,16 +28,10 @@ static u32 hashtab_compute_size(u32 nel)
 | 
			
		||||
	return nel == 0 ? 0 : roundup_pow_of_two(nel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
int hashtab_init(struct hashtab *h, u32 nel_hint)
 | 
			
		||||
{
 | 
			
		||||
	h->size = hashtab_compute_size(nel_hint);
 | 
			
		||||
	h->nel = 0;
 | 
			
		||||
	h->hash_value = hash_value;
 | 
			
		||||
	h->keycmp = keycmp;
 | 
			
		||||
	if (!h->size)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@ -46,63 +39,23 @@ int hashtab_init(struct hashtab *h,
 | 
			
		||||
	return h->htable ? 0 : -ENOMEM;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hashtab_insert(struct hashtab *h, void *key, void *datum)
 | 
			
		||||
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
 | 
			
		||||
		     void *key, void *datum)
 | 
			
		||||
{
 | 
			
		||||
	u32 hvalue;
 | 
			
		||||
	struct hashtab_node *prev, *cur, *newnode;
 | 
			
		||||
 | 
			
		||||
	cond_resched();
 | 
			
		||||
 | 
			
		||||
	if (!h->size || h->nel == HASHTAB_MAX_NODES)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	hvalue = h->hash_value(h, key);
 | 
			
		||||
	prev = NULL;
 | 
			
		||||
	cur = h->htable[hvalue];
 | 
			
		||||
	while (cur && h->keycmp(h, key, cur->key) > 0) {
 | 
			
		||||
		prev = cur;
 | 
			
		||||
		cur = cur->next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cur && (h->keycmp(h, key, cur->key) == 0))
 | 
			
		||||
		return -EEXIST;
 | 
			
		||||
	struct hashtab_node *newnode;
 | 
			
		||||
 | 
			
		||||
	newnode = kmem_cache_zalloc(hashtab_node_cachep, GFP_KERNEL);
 | 
			
		||||
	if (!newnode)
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	newnode->key = key;
 | 
			
		||||
	newnode->datum = datum;
 | 
			
		||||
	if (prev) {
 | 
			
		||||
		newnode->next = prev->next;
 | 
			
		||||
		prev->next = newnode;
 | 
			
		||||
	} else {
 | 
			
		||||
		newnode->next = h->htable[hvalue];
 | 
			
		||||
		h->htable[hvalue] = newnode;
 | 
			
		||||
	}
 | 
			
		||||
	newnode->next = *dst;
 | 
			
		||||
	*dst = newnode;
 | 
			
		||||
 | 
			
		||||
	h->nel++;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *hashtab_search(struct hashtab *h, const void *key)
 | 
			
		||||
{
 | 
			
		||||
	u32 hvalue;
 | 
			
		||||
	struct hashtab_node *cur;
 | 
			
		||||
 | 
			
		||||
	if (!h->size)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	hvalue = h->hash_value(h, key);
 | 
			
		||||
	cur = h->htable[hvalue];
 | 
			
		||||
	while (cur && h->keycmp(h, key, cur->key) > 0)
 | 
			
		||||
		cur = cur->next;
 | 
			
		||||
 | 
			
		||||
	if (!cur || (h->keycmp(h, key, cur->key) != 0))
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	return cur->datum;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hashtab_destroy(struct hashtab *h)
 | 
			
		||||
{
 | 
			
		||||
	u32 i;
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,17 @@
 | 
			
		||||
#ifndef _SS_HASHTAB_H_
 | 
			
		||||
#define _SS_HASHTAB_H_
 | 
			
		||||
 | 
			
		||||
#define HASHTAB_MAX_NODES	0xffffffff
 | 
			
		||||
#include <linux/types.h>
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include <linux/sched.h>
 | 
			
		||||
 | 
			
		||||
#define HASHTAB_MAX_NODES	U32_MAX
 | 
			
		||||
 | 
			
		||||
struct hashtab_key_params {
 | 
			
		||||
	u32 (*hash)(const void *key);	/* hash function */
 | 
			
		||||
	int (*cmp)(const void *key1, const void *key2);
 | 
			
		||||
					/* key comparison function */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hashtab_node {
 | 
			
		||||
	void *key;
 | 
			
		||||
@ -23,10 +33,6 @@ struct hashtab {
 | 
			
		||||
	struct hashtab_node **htable;	/* hash table */
 | 
			
		||||
	u32 size;			/* number of slots in hash table */
 | 
			
		||||
	u32 nel;			/* number of elements in hash table */
 | 
			
		||||
	u32 (*hash_value)(struct hashtab *h, const void *key);
 | 
			
		||||
					/* hash function */
 | 
			
		||||
	int (*keycmp)(struct hashtab *h, const void *key1, const void *key2);
 | 
			
		||||
					/* key comparison function */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct hashtab_info {
 | 
			
		||||
@ -39,11 +45,10 @@ struct hashtab_info {
 | 
			
		||||
 *
 | 
			
		||||
 * Returns -ENOMEM if insufficient space is available or 0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
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);
 | 
			
		||||
int hashtab_init(struct hashtab *h, u32 nel_hint);
 | 
			
		||||
 | 
			
		||||
int __hashtab_insert(struct hashtab *h, struct hashtab_node **dst,
 | 
			
		||||
		     void *key, void *datum);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Inserts the specified (key, datum) pair into the specified hash table.
 | 
			
		||||
@ -53,7 +58,34 @@ int hashtab_init(struct hashtab *h,
 | 
			
		||||
 * -EINVAL for general errors or
 | 
			
		||||
  0 otherwise.
 | 
			
		||||
 */
 | 
			
		||||
int hashtab_insert(struct hashtab *h, void *k, void *d);
 | 
			
		||||
static inline int hashtab_insert(struct hashtab *h, void *key, void *datum,
 | 
			
		||||
				 struct hashtab_key_params key_params)
 | 
			
		||||
{
 | 
			
		||||
	u32 hvalue;
 | 
			
		||||
	struct hashtab_node *prev, *cur;
 | 
			
		||||
 | 
			
		||||
	cond_resched();
 | 
			
		||||
 | 
			
		||||
	if (!h->size || h->nel == HASHTAB_MAX_NODES)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	hvalue = key_params.hash(key) & (h->size - 1);
 | 
			
		||||
	prev = NULL;
 | 
			
		||||
	cur = h->htable[hvalue];
 | 
			
		||||
	while (cur) {
 | 
			
		||||
		int cmp = key_params.cmp(key, cur->key);
 | 
			
		||||
 | 
			
		||||
		if (cmp == 0)
 | 
			
		||||
			return -EEXIST;
 | 
			
		||||
		if (cmp < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		prev = cur;
 | 
			
		||||
		cur = cur->next;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return __hashtab_insert(h, prev ? &prev->next : &h->htable[hvalue],
 | 
			
		||||
				key, datum);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Searches for the entry with the specified key in the hash table.
 | 
			
		||||
@ -61,7 +93,28 @@ int hashtab_insert(struct hashtab *h, void *k, void *d);
 | 
			
		||||
 * Returns NULL if no entry has the specified key or
 | 
			
		||||
 * the datum of the entry otherwise.
 | 
			
		||||
 */
 | 
			
		||||
void *hashtab_search(struct hashtab *h, const void *k);
 | 
			
		||||
static inline void *hashtab_search(struct hashtab *h, const void *key,
 | 
			
		||||
				   struct hashtab_key_params key_params)
 | 
			
		||||
{
 | 
			
		||||
	u32 hvalue;
 | 
			
		||||
	struct hashtab_node *cur;
 | 
			
		||||
 | 
			
		||||
	if (!h->size)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	hvalue = key_params.hash(key) & (h->size - 1);
 | 
			
		||||
	cur = h->htable[hvalue];
 | 
			
		||||
	while (cur) {
 | 
			
		||||
		int cmp = key_params.cmp(key, cur->key);
 | 
			
		||||
 | 
			
		||||
		if (cmp == 0)
 | 
			
		||||
			return cur->datum;
 | 
			
		||||
		if (cmp < 0)
 | 
			
		||||
			break;
 | 
			
		||||
		cur = cur->next;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Destroys the specified hash table.
 | 
			
		||||
 | 
			
		||||
@ -165,8 +165,8 @@ 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,
 | 
			
		||||
				  sym_name(p, SYM_LEVELS, l->sens - 1));
 | 
			
		||||
	levdatum = symtab_search(&p->p_levels,
 | 
			
		||||
				 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 = symtab_search(&pol->p_levels, 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 = symtab_search(&pol->p_cats, 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 = symtab_search(&pol->p_cats, rngptr);
 | 
			
		||||
			if (!rngdatum)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
 | 
			
		||||
@ -458,9 +458,10 @@ int mls_convert_context(struct policydb *oldp,
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	for (l = 0; l < 2; l++) {
 | 
			
		||||
		levdatum = hashtab_search(&newp->p_levels.table,
 | 
			
		||||
					  sym_name(oldp, SYM_LEVELS,
 | 
			
		||||
						   oldc->range.level[l].sens - 1));
 | 
			
		||||
		char *name = sym_name(oldp, SYM_LEVELS,
 | 
			
		||||
				      oldc->range.level[l].sens - 1);
 | 
			
		||||
 | 
			
		||||
		levdatum = symtab_search(&newp->p_levels, name);
 | 
			
		||||
 | 
			
		||||
		if (!levdatum)
 | 
			
		||||
			return -EINVAL;
 | 
			
		||||
@ -470,8 +471,8 @@ int mls_convert_context(struct policydb *oldp,
 | 
			
		||||
					      node, i) {
 | 
			
		||||
			int rc;
 | 
			
		||||
 | 
			
		||||
			catdatum = hashtab_search(&newp->p_cats.table,
 | 
			
		||||
						  sym_name(oldp, SYM_CATS, i));
 | 
			
		||||
			catdatum = symtab_search(&newp->p_cats,
 | 
			
		||||
						 sym_name(oldp, SYM_CATS, i));
 | 
			
		||||
			if (!catdatum)
 | 
			
		||||
				return -EINVAL;
 | 
			
		||||
			rc = ebitmap_set_bit(&newc->range.level[l].cat,
 | 
			
		||||
@ -506,7 +507,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 = policydb_rangetr_search(p, &rtr);
 | 
			
		||||
		if (r)
 | 
			
		||||
			return mls_range_set(newcontext, r);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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 = symtab_insert(&p->p_roles, key, role);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
@ -411,7 +411,7 @@ out:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 filenametr_hash(struct hashtab *h, const void *k)
 | 
			
		||||
static u32 filenametr_hash(const void *k)
 | 
			
		||||
{
 | 
			
		||||
	const struct filename_trans_key *ft = k;
 | 
			
		||||
	unsigned long hash;
 | 
			
		||||
@ -423,10 +423,10 @@ static u32 filenametr_hash(struct hashtab *h, const void *k)
 | 
			
		||||
	byte_num = 0;
 | 
			
		||||
	while ((focus = ft->name[byte_num++]))
 | 
			
		||||
		hash = partial_name_hash(focus, hash);
 | 
			
		||||
	return hash & (h->size - 1);
 | 
			
		||||
	return hash;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
static int filenametr_cmp(const void *k1, const void *k2)
 | 
			
		||||
{
 | 
			
		||||
	const struct filename_trans_key *ft1 = k1;
 | 
			
		||||
	const struct filename_trans_key *ft2 = k2;
 | 
			
		||||
@ -444,15 +444,26 @@ static int filenametr_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 rangetr_hash(struct hashtab *h, const void *k)
 | 
			
		||||
static const struct hashtab_key_params filenametr_key_params = {
 | 
			
		||||
	.hash = filenametr_hash,
 | 
			
		||||
	.cmp = filenametr_cmp,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct filename_trans_datum *policydb_filenametr_search(
 | 
			
		||||
	struct policydb *p, struct filename_trans_key *key)
 | 
			
		||||
{
 | 
			
		||||
	return hashtab_search(&p->filename_trans, key, filenametr_key_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 rangetr_hash(const void *k)
 | 
			
		||||
{
 | 
			
		||||
	const struct range_trans *key = k;
 | 
			
		||||
 | 
			
		||||
	return (key->source_type + (key->target_type << 3) +
 | 
			
		||||
		(key->target_class << 5)) & (h->size - 1);
 | 
			
		||||
	return key->source_type + (key->target_type << 3) +
 | 
			
		||||
		(key->target_class << 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
static int rangetr_cmp(const void *k1, const void *k2)
 | 
			
		||||
{
 | 
			
		||||
	const struct range_trans *key1 = k1, *key2 = k2;
 | 
			
		||||
	int v;
 | 
			
		||||
@ -470,15 +481,25 @@ static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
	return v;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 role_trans_hash(struct hashtab *h, const void *k)
 | 
			
		||||
static const struct hashtab_key_params rangetr_key_params = {
 | 
			
		||||
	.hash = rangetr_hash,
 | 
			
		||||
	.cmp = rangetr_cmp,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct mls_range *policydb_rangetr_search(struct policydb *p,
 | 
			
		||||
					  struct range_trans *key)
 | 
			
		||||
{
 | 
			
		||||
	return hashtab_search(&p->range_tr, key, rangetr_key_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static u32 role_trans_hash(const void *k)
 | 
			
		||||
{
 | 
			
		||||
	const struct role_trans_key *key = k;
 | 
			
		||||
 | 
			
		||||
	return (key->role + (key->type << 3) + (key->tclass << 5)) &
 | 
			
		||||
		(h->size - 1);
 | 
			
		||||
	return key->role + (key->type << 3) + (key->tclass << 5);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
static int role_trans_cmp(const void *k1, const void *k2)
 | 
			
		||||
{
 | 
			
		||||
	const struct role_trans_key *key1 = k1, *key2 = k2;
 | 
			
		||||
	int v;
 | 
			
		||||
@ -494,6 +515,17 @@ static int role_trans_cmp(struct hashtab *h, const void *k1, const void *k2)
 | 
			
		||||
	return key1->tclass - key2->tclass;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct hashtab_key_params roletr_key_params = {
 | 
			
		||||
	.hash = role_trans_hash,
 | 
			
		||||
	.cmp = role_trans_cmp,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct role_trans_datum *policydb_roletr_search(struct policydb *p,
 | 
			
		||||
						struct role_trans_key *key)
 | 
			
		||||
{
 | 
			
		||||
	return hashtab_search(&p->role_tr, key, roletr_key_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Initialize a policy database structure.
 | 
			
		||||
 */
 | 
			
		||||
@ -1065,7 +1097,7 @@ static int str_read(char **strp, gfp_t flags, void *fp, u32 len)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int perm_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct perm_datum *perdatum;
 | 
			
		||||
@ -1088,7 +1120,7 @@ static int perm_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, perdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, perdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
@ -1098,7 +1130,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int common_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int common_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct common_datum *comdatum;
 | 
			
		||||
@ -1128,12 +1160,12 @@ 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, fp);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, comdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, comdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1262,7 +1294,7 @@ static int read_cons_helper(struct policydb *p,
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int class_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct class_datum *cladatum;
 | 
			
		||||
@ -1300,8 +1332,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 = symtab_search(&p->p_commons,
 | 
			
		||||
						   cladatum->comkey);
 | 
			
		||||
		if (!cladatum->comdatum) {
 | 
			
		||||
			pr_err("SELinux:  unknown common %s\n",
 | 
			
		||||
			       cladatum->comkey);
 | 
			
		||||
@ -1309,7 +1341,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, fp);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			goto bad;
 | 
			
		||||
	}
 | 
			
		||||
@ -1347,7 +1379,7 @@ static int class_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
		cladatum->default_type = le32_to_cpu(buf[0]);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, cladatum);
 | 
			
		||||
	rc = symtab_insert(s, key, cladatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
@ -1357,7 +1389,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int role_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int role_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct role_datum *role;
 | 
			
		||||
@ -1404,7 +1436,7 @@ static int role_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, role);
 | 
			
		||||
	rc = symtab_insert(s, key, role);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1413,7 +1445,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int type_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int type_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct type_datum *typdatum;
 | 
			
		||||
@ -1451,7 +1483,7 @@ static int type_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, typdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, typdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1487,7 +1519,7 @@ static int mls_read_level(struct mls_level *lp, void *fp)
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int user_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int user_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct user_datum *usrdatum;
 | 
			
		||||
@ -1528,7 +1560,7 @@ static int user_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
			goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, usrdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, usrdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1537,7 +1569,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int sens_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct level_datum *levdatum;
 | 
			
		||||
@ -1569,7 +1601,7 @@ static int sens_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, levdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, levdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1578,7 +1610,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
static int cat_read(struct policydb *p, struct symtab *s, void *fp)
 | 
			
		||||
{
 | 
			
		||||
	char *key = NULL;
 | 
			
		||||
	struct cat_datum *catdatum;
 | 
			
		||||
@ -1602,7 +1634,7 @@ static int cat_read(struct policydb *p, struct hashtab *h, void *fp)
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_insert(h, key, catdatum);
 | 
			
		||||
	rc = symtab_insert(s, key, catdatum);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	return 0;
 | 
			
		||||
@ -1611,7 +1643,7 @@ bad:
 | 
			
		||||
	return rc;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int (*read_f[SYM_NUM]) (struct policydb *p, struct hashtab *h, void *fp) =
 | 
			
		||||
static int (*read_f[SYM_NUM]) (struct policydb *p, struct symtab *s, void *fp) =
 | 
			
		||||
{
 | 
			
		||||
	common_read,
 | 
			
		||||
	class_read,
 | 
			
		||||
@ -1751,7 +1783,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 = symtab_search(&p->p_classes, name);
 | 
			
		||||
	if (!cladatum)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@ -1770,9 +1802,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 = symtab_search(&comdatum->permissions, name);
 | 
			
		||||
	if (!perdatum)
 | 
			
		||||
		perdatum = hashtab_search(&cladatum->permissions.table, name);
 | 
			
		||||
		perdatum = symtab_search(&cladatum->permissions, name);
 | 
			
		||||
	if (!perdatum)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
@ -1796,7 +1828,7 @@ static int range_read(struct policydb *p, void *fp)
 | 
			
		||||
 | 
			
		||||
	nel = le32_to_cpu(buf[0]);
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_init(&p->range_tr, rangetr_hash, rangetr_cmp, nel);
 | 
			
		||||
	rc = hashtab_init(&p->range_tr, nel);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
@ -1841,7 +1873,7 @@ 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, rangetr_key_params);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			goto out;
 | 
			
		||||
 | 
			
		||||
@ -1888,7 +1920,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 = policydb_filenametr_search(p, &key);
 | 
			
		||||
	while (datum) {
 | 
			
		||||
		if (unlikely(ebitmap_get_bit(&datum->stypes, stype - 1))) {
 | 
			
		||||
			/* conflicting/duplicate rules are ignored */
 | 
			
		||||
@ -1918,7 +1950,8 @@ 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,
 | 
			
		||||
					    filenametr_key_params);
 | 
			
		||||
			if (rc)
 | 
			
		||||
				goto out;
 | 
			
		||||
			name = NULL;
 | 
			
		||||
@ -2006,7 +2039,8 @@ 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,
 | 
			
		||||
			    filenametr_key_params);
 | 
			
		||||
	if (rc == -EEXIST)
 | 
			
		||||
		pr_err("SELinux:  Duplicate filename transition key\n");
 | 
			
		||||
	if (rc)
 | 
			
		||||
@ -2044,8 +2078,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
 | 
			
		||||
	if (p->policyvers < POLICYDB_VERSION_COMP_FTRANS) {
 | 
			
		||||
		p->compat_filename_trans_count = nel;
 | 
			
		||||
 | 
			
		||||
		rc = hashtab_init(&p->filename_trans, filenametr_hash,
 | 
			
		||||
				  filenametr_cmp, (1 << 11));
 | 
			
		||||
		rc = hashtab_init(&p->filename_trans, (1 << 11));
 | 
			
		||||
		if (rc)
 | 
			
		||||
			return rc;
 | 
			
		||||
 | 
			
		||||
@ -2055,8 +2088,7 @@ static int filename_trans_read(struct policydb *p, void *fp)
 | 
			
		||||
				return rc;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		rc = hashtab_init(&p->filename_trans, filenametr_hash,
 | 
			
		||||
				  filenametr_cmp, nel);
 | 
			
		||||
		rc = hashtab_init(&p->filename_trans, nel);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			return rc;
 | 
			
		||||
 | 
			
		||||
@ -2376,7 +2408,7 @@ int policydb_read(struct policydb *p, void *fp)
 | 
			
		||||
	struct role_trans_datum *rtd = NULL;
 | 
			
		||||
	int i, j, rc;
 | 
			
		||||
	__le32 buf[4];
 | 
			
		||||
	u32 len, nprim, nel;
 | 
			
		||||
	u32 len, nprim, nel, perm;
 | 
			
		||||
 | 
			
		||||
	char *policydb_str;
 | 
			
		||||
	struct policydb_compat_info *info;
 | 
			
		||||
@ -2509,7 +2541,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], fp);
 | 
			
		||||
			if (rc)
 | 
			
		||||
				goto bad;
 | 
			
		||||
		}
 | 
			
		||||
@ -2519,8 +2551,10 @@ int policydb_read(struct policydb *p, void *fp)
 | 
			
		||||
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	p->process_class = string_to_security_class(p, "process");
 | 
			
		||||
	if (!p->process_class)
 | 
			
		||||
	if (!p->process_class) {
 | 
			
		||||
		pr_err("SELinux: process class is required, not defined in policy\n");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rc = avtab_read(&p->te_avtab, fp, p);
 | 
			
		||||
	if (rc)
 | 
			
		||||
@ -2537,7 +2571,7 @@ int policydb_read(struct policydb *p, void *fp)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	nel = le32_to_cpu(buf[0]);
 | 
			
		||||
 | 
			
		||||
	rc = hashtab_init(&p->role_tr, role_trans_hash, role_trans_cmp, nel);
 | 
			
		||||
	rc = hashtab_init(&p->role_tr, nel);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	for (i = 0; i < nel; i++) {
 | 
			
		||||
@ -2574,7 +2608,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, roletr_key_params);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			goto bad;
 | 
			
		||||
 | 
			
		||||
@ -2618,10 +2652,18 @@ int policydb_read(struct policydb *p, void *fp)
 | 
			
		||||
		goto bad;
 | 
			
		||||
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	p->process_trans_perms = string_to_av_perm(p, p->process_class, "transition");
 | 
			
		||||
	p->process_trans_perms |= string_to_av_perm(p, p->process_class, "dyntransition");
 | 
			
		||||
	if (!p->process_trans_perms)
 | 
			
		||||
	perm = string_to_av_perm(p, p->process_class, "transition");
 | 
			
		||||
	if (!perm) {
 | 
			
		||||
		pr_err("SELinux: process transition permission is required, not defined in policy\n");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	p->process_trans_perms = perm;
 | 
			
		||||
	perm = string_to_av_perm(p, p->process_class, "dyntransition");
 | 
			
		||||
	if (!perm) {
 | 
			
		||||
		pr_err("SELinux: process dyntransition permission is required, not defined in policy\n");
 | 
			
		||||
		goto bad;
 | 
			
		||||
	}
 | 
			
		||||
	p->process_trans_perms |= perm;
 | 
			
		||||
 | 
			
		||||
	rc = ocontext_read(p, info, fp);
 | 
			
		||||
	if (rc)
 | 
			
		||||
 | 
			
		||||
@ -324,6 +324,15 @@ extern int policydb_role_isvalid(struct policydb *p, unsigned int role);
 | 
			
		||||
extern int policydb_read(struct policydb *p, void *fp);
 | 
			
		||||
extern int policydb_write(struct policydb *p, void *fp);
 | 
			
		||||
 | 
			
		||||
extern struct filename_trans_datum *policydb_filenametr_search(
 | 
			
		||||
	struct policydb *p, struct filename_trans_key *key);
 | 
			
		||||
 | 
			
		||||
extern struct mls_range *policydb_rangetr_search(
 | 
			
		||||
	struct policydb *p, struct range_trans *key);
 | 
			
		||||
 | 
			
		||||
extern struct role_trans_datum *policydb_roletr_search(
 | 
			
		||||
	struct policydb *p, struct role_trans_key *key);
 | 
			
		||||
 | 
			
		||||
#define POLICYDB_CONFIG_MLS    1
 | 
			
		||||
 | 
			
		||||
/* the config flags related to unknown classes/perms are bits 2 and 3 */
 | 
			
		||||
 | 
			
		||||
@ -1441,7 +1441,7 @@ static int string_to_context_struct(struct policydb *pol,
 | 
			
		||||
 | 
			
		||||
	*p++ = 0;
 | 
			
		||||
 | 
			
		||||
	usrdatum = hashtab_search(&pol->p_users.table, scontextp);
 | 
			
		||||
	usrdatum = symtab_search(&pol->p_users, scontextp);
 | 
			
		||||
	if (!usrdatum)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
@ -1457,7 +1457,7 @@ static int string_to_context_struct(struct policydb *pol,
 | 
			
		||||
 | 
			
		||||
	*p++ = 0;
 | 
			
		||||
 | 
			
		||||
	role = hashtab_search(&pol->p_roles.table, scontextp);
 | 
			
		||||
	role = symtab_search(&pol->p_roles, scontextp);
 | 
			
		||||
	if (!role)
 | 
			
		||||
		goto out;
 | 
			
		||||
	ctx->role = role->value;
 | 
			
		||||
@ -1469,7 +1469,7 @@ static int string_to_context_struct(struct policydb *pol,
 | 
			
		||||
	oldc = *p;
 | 
			
		||||
	*p++ = 0;
 | 
			
		||||
 | 
			
		||||
	typdatum = hashtab_search(&pol->p_types.table, scontextp);
 | 
			
		||||
	typdatum = symtab_search(&pol->p_types, scontextp);
 | 
			
		||||
	if (!typdatum || typdatum->attribute)
 | 
			
		||||
		goto out;
 | 
			
		||||
 | 
			
		||||
@ -1671,7 +1671,7 @@ static void filename_compute_type(struct policydb *policydb,
 | 
			
		||||
	ft.tclass = tclass;
 | 
			
		||||
	ft.name = objname;
 | 
			
		||||
 | 
			
		||||
	datum = hashtab_search(&policydb->filename_trans, &ft);
 | 
			
		||||
	datum = policydb_filenametr_search(policydb, &ft);
 | 
			
		||||
	while (datum) {
 | 
			
		||||
		if (ebitmap_get_bit(&datum->stypes, stype - 1)) {
 | 
			
		||||
			newcontext->type = datum->otype;
 | 
			
		||||
@ -1834,7 +1834,7 @@ static int security_compute_sid(struct selinux_state *state,
 | 
			
		||||
			.tclass = tclass,
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		rtd = hashtab_search(&policydb->role_tr, &rtk);
 | 
			
		||||
		rtd = policydb_roletr_search(policydb, &rtk);
 | 
			
		||||
		if (rtd)
 | 
			
		||||
			newcontext.role = rtd->new_role;
 | 
			
		||||
	}
 | 
			
		||||
@ -2024,26 +2024,26 @@ static int convert_context(struct context *oldc, struct context *newc, void *p)
 | 
			
		||||
 | 
			
		||||
	/* Convert the user. */
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	usrdatum = hashtab_search(&args->newp->p_users.table,
 | 
			
		||||
				  sym_name(args->oldp,
 | 
			
		||||
					   SYM_USERS, oldc->user - 1));
 | 
			
		||||
	usrdatum = symtab_search(&args->newp->p_users,
 | 
			
		||||
				 sym_name(args->oldp,
 | 
			
		||||
					  SYM_USERS, oldc->user - 1));
 | 
			
		||||
	if (!usrdatum)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	newc->user = usrdatum->value;
 | 
			
		||||
 | 
			
		||||
	/* Convert the role. */
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	role = hashtab_search(&args->newp->p_roles.table,
 | 
			
		||||
			      sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
 | 
			
		||||
	role = symtab_search(&args->newp->p_roles,
 | 
			
		||||
			     sym_name(args->oldp, SYM_ROLES, oldc->role - 1));
 | 
			
		||||
	if (!role)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	newc->role = role->value;
 | 
			
		||||
 | 
			
		||||
	/* Convert the type. */
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	typdatum = hashtab_search(&args->newp->p_types.table,
 | 
			
		||||
				  sym_name(args->oldp,
 | 
			
		||||
					   SYM_TYPES, oldc->type - 1));
 | 
			
		||||
	typdatum = symtab_search(&args->newp->p_types,
 | 
			
		||||
				 sym_name(args->oldp,
 | 
			
		||||
					  SYM_TYPES, oldc->type - 1));
 | 
			
		||||
	if (!typdatum)
 | 
			
		||||
		goto bad;
 | 
			
		||||
	newc->type = typdatum->value;
 | 
			
		||||
@ -2623,7 +2623,7 @@ int security_get_user_sids(struct selinux_state *state,
 | 
			
		||||
		goto out_unlock;
 | 
			
		||||
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	user = hashtab_search(&policydb->p_users.table, username);
 | 
			
		||||
	user = symtab_search(&policydb->p_users, username);
 | 
			
		||||
	if (!user)
 | 
			
		||||
		goto out_unlock;
 | 
			
		||||
 | 
			
		||||
@ -2979,7 +2979,7 @@ static int security_preserve_bools(struct selinux_state *state,
 | 
			
		||||
	if (rc)
 | 
			
		||||
		goto out;
 | 
			
		||||
	for (i = 0; i < nbools; i++) {
 | 
			
		||||
		booldatum = hashtab_search(&policydb->p_bools.table, bnames[i]);
 | 
			
		||||
		booldatum = symtab_search(&policydb->p_bools, bnames[i]);
 | 
			
		||||
		if (booldatum)
 | 
			
		||||
			booldatum->state = bvalues[i];
 | 
			
		||||
	}
 | 
			
		||||
@ -3230,7 +3230,7 @@ int security_get_permissions(struct selinux_state *state,
 | 
			
		||||
	read_lock(&state->ss->policy_rwlock);
 | 
			
		||||
 | 
			
		||||
	rc = -EINVAL;
 | 
			
		||||
	match = hashtab_search(&policydb->p_classes.table, class);
 | 
			
		||||
	match = symtab_search(&policydb->p_classes, class);
 | 
			
		||||
	if (!match) {
 | 
			
		||||
		pr_err("SELinux: %s:  unrecognized class %s\n",
 | 
			
		||||
			__func__, class);
 | 
			
		||||
@ -3369,7 +3369,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 | 
			
		||||
	case AUDIT_SUBJ_USER:
 | 
			
		||||
	case AUDIT_OBJ_USER:
 | 
			
		||||
		rc = -EINVAL;
 | 
			
		||||
		userdatum = hashtab_search(&policydb->p_users.table, rulestr);
 | 
			
		||||
		userdatum = symtab_search(&policydb->p_users, rulestr);
 | 
			
		||||
		if (!userdatum)
 | 
			
		||||
			goto out;
 | 
			
		||||
		tmprule->au_ctxt.user = userdatum->value;
 | 
			
		||||
@ -3377,7 +3377,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 | 
			
		||||
	case AUDIT_SUBJ_ROLE:
 | 
			
		||||
	case AUDIT_OBJ_ROLE:
 | 
			
		||||
		rc = -EINVAL;
 | 
			
		||||
		roledatum = hashtab_search(&policydb->p_roles.table, rulestr);
 | 
			
		||||
		roledatum = symtab_search(&policydb->p_roles, rulestr);
 | 
			
		||||
		if (!roledatum)
 | 
			
		||||
			goto out;
 | 
			
		||||
		tmprule->au_ctxt.role = roledatum->value;
 | 
			
		||||
@ -3385,7 +3385,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule)
 | 
			
		||||
	case AUDIT_SUBJ_TYPE:
 | 
			
		||||
	case AUDIT_OBJ_TYPE:
 | 
			
		||||
		rc = -EINVAL;
 | 
			
		||||
		typedatum = hashtab_search(&policydb->p_types.table, rulestr);
 | 
			
		||||
		typedatum = symtab_search(&policydb->p_types, rulestr);
 | 
			
		||||
		if (!typedatum)
 | 
			
		||||
			goto out;
 | 
			
		||||
		tmprule->au_ctxt.type = typedatum->value;
 | 
			
		||||
 | 
			
		||||
@ -9,7 +9,7 @@
 | 
			
		||||
#include <linux/errno.h>
 | 
			
		||||
#include "symtab.h"
 | 
			
		||||
 | 
			
		||||
static unsigned int symhash(struct hashtab *h, const void *key)
 | 
			
		||||
static unsigned int symhash(const void *key)
 | 
			
		||||
{
 | 
			
		||||
	const char *p, *keyp;
 | 
			
		||||
	unsigned int size;
 | 
			
		||||
@ -20,10 +20,10 @@ static unsigned int symhash(struct hashtab *h, const void *key)
 | 
			
		||||
	size = strlen(keyp);
 | 
			
		||||
	for (p = keyp; (p - keyp) < size; p++)
 | 
			
		||||
		val = (val << 4 | (val >> (8*sizeof(unsigned int)-4))) ^ (*p);
 | 
			
		||||
	return val & (h->size - 1);
 | 
			
		||||
	return val;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int symcmp(struct hashtab *h, const void *key1, const void *key2)
 | 
			
		||||
static int symcmp(const void *key1, const void *key2)
 | 
			
		||||
{
 | 
			
		||||
	const char *keyp1, *keyp2;
 | 
			
		||||
 | 
			
		||||
@ -32,10 +32,23 @@ static int symcmp(struct hashtab *h, const void *key1, const void *key2)
 | 
			
		||||
	return strcmp(keyp1, keyp2);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct hashtab_key_params symtab_key_params = {
 | 
			
		||||
	.hash = symhash,
 | 
			
		||||
	.cmp = symcmp,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
int symtab_init(struct symtab *s, unsigned int size)
 | 
			
		||||
{
 | 
			
		||||
	s->nprim = 0;
 | 
			
		||||
	return hashtab_init(&s->table, symhash, symcmp, size);
 | 
			
		||||
	return hashtab_init(&s->table, size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int symtab_insert(struct symtab *s, char *name, void *datum)
 | 
			
		||||
{
 | 
			
		||||
	return hashtab_insert(&s->table, name, datum, symtab_key_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void *symtab_search(struct symtab *s, const char *name)
 | 
			
		||||
{
 | 
			
		||||
	return hashtab_search(&s->table, name, symtab_key_params);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,9 @@ struct symtab {
 | 
			
		||||
 | 
			
		||||
int symtab_init(struct symtab *s, unsigned int size);
 | 
			
		||||
 | 
			
		||||
int symtab_insert(struct symtab *s, char *name, void *datum);
 | 
			
		||||
void *symtab_search(struct symtab *s, const char *name);
 | 
			
		||||
 | 
			
		||||
#endif	/* _SS_SYMTAB_H_ */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user