xref: /aosp_15_r20/external/selinux/libselinux/src/avc_sidtab.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * Implementation of the userspace SID hashtable.
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Author : Eamon Walsh, <[email protected]>
5*2d543d20SAndroid Build Coastguard Worker  */
6*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
7*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
8*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
9*2d543d20SAndroid Build Coastguard Worker #include <stdint.h>
10*2d543d20SAndroid Build Coastguard Worker #include <string.h>
11*2d543d20SAndroid Build Coastguard Worker #include "selinux_internal.h"
12*2d543d20SAndroid Build Coastguard Worker #include <selinux/avc.h>
13*2d543d20SAndroid Build Coastguard Worker #include "avc_sidtab.h"
14*2d543d20SAndroid Build Coastguard Worker #include "avc_internal.h"
15*2d543d20SAndroid Build Coastguard Worker 
16*2d543d20SAndroid Build Coastguard Worker ignore_unsigned_overflow_
sidtab_hash(const char * key)17*2d543d20SAndroid Build Coastguard Worker static inline unsigned sidtab_hash(const char * key)
18*2d543d20SAndroid Build Coastguard Worker {
19*2d543d20SAndroid Build Coastguard Worker 	unsigned int hash = 5381;
20*2d543d20SAndroid Build Coastguard Worker 	unsigned char c;
21*2d543d20SAndroid Build Coastguard Worker 
22*2d543d20SAndroid Build Coastguard Worker 	while ((c = *(unsigned const char *)key++))
23*2d543d20SAndroid Build Coastguard Worker 		hash = ((hash << 5) + hash) ^ c;
24*2d543d20SAndroid Build Coastguard Worker 
25*2d543d20SAndroid Build Coastguard Worker 	return hash & (SIDTAB_SIZE - 1);
26*2d543d20SAndroid Build Coastguard Worker }
27*2d543d20SAndroid Build Coastguard Worker 
sidtab_init(struct sidtab * s)28*2d543d20SAndroid Build Coastguard Worker int sidtab_init(struct sidtab *s)
29*2d543d20SAndroid Build Coastguard Worker {
30*2d543d20SAndroid Build Coastguard Worker 	int i, rc = 0;
31*2d543d20SAndroid Build Coastguard Worker 
32*2d543d20SAndroid Build Coastguard Worker 	s->htable = (struct sidtab_node **)avc_malloc
33*2d543d20SAndroid Build Coastguard Worker 	    (sizeof(struct sidtab_node *) * SIDTAB_SIZE);
34*2d543d20SAndroid Build Coastguard Worker 
35*2d543d20SAndroid Build Coastguard Worker 	if (!s->htable) {
36*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
37*2d543d20SAndroid Build Coastguard Worker 		goto out;
38*2d543d20SAndroid Build Coastguard Worker 	}
39*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SIDTAB_SIZE; i++)
40*2d543d20SAndroid Build Coastguard Worker 		s->htable[i] = NULL;
41*2d543d20SAndroid Build Coastguard Worker 	s->nel = 0;
42*2d543d20SAndroid Build Coastguard Worker       out:
43*2d543d20SAndroid Build Coastguard Worker 	return rc;
44*2d543d20SAndroid Build Coastguard Worker }
45*2d543d20SAndroid Build Coastguard Worker 
sidtab_insert(struct sidtab * s,const char * ctx)46*2d543d20SAndroid Build Coastguard Worker int sidtab_insert(struct sidtab *s, const char * ctx)
47*2d543d20SAndroid Build Coastguard Worker {
48*2d543d20SAndroid Build Coastguard Worker 	int hvalue, rc = 0;
49*2d543d20SAndroid Build Coastguard Worker 	struct sidtab_node *newnode;
50*2d543d20SAndroid Build Coastguard Worker 	char * newctx;
51*2d543d20SAndroid Build Coastguard Worker 
52*2d543d20SAndroid Build Coastguard Worker 	newnode = (struct sidtab_node *)avc_malloc(sizeof(*newnode));
53*2d543d20SAndroid Build Coastguard Worker 	if (!newnode) {
54*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
55*2d543d20SAndroid Build Coastguard Worker 		goto out;
56*2d543d20SAndroid Build Coastguard Worker 	}
57*2d543d20SAndroid Build Coastguard Worker 	newctx = strdup(ctx);
58*2d543d20SAndroid Build Coastguard Worker 	if (!newctx) {
59*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
60*2d543d20SAndroid Build Coastguard Worker 		avc_free(newnode);
61*2d543d20SAndroid Build Coastguard Worker 		goto out;
62*2d543d20SAndroid Build Coastguard Worker 	}
63*2d543d20SAndroid Build Coastguard Worker 
64*2d543d20SAndroid Build Coastguard Worker 	hvalue = sidtab_hash(newctx);
65*2d543d20SAndroid Build Coastguard Worker 	newnode->next = s->htable[hvalue];
66*2d543d20SAndroid Build Coastguard Worker 	newnode->sid_s.ctx = newctx;
67*2d543d20SAndroid Build Coastguard Worker 	newnode->sid_s.refcnt = 1;	/* unused */
68*2d543d20SAndroid Build Coastguard Worker 	s->htable[hvalue] = newnode;
69*2d543d20SAndroid Build Coastguard Worker 	s->nel++;
70*2d543d20SAndroid Build Coastguard Worker       out:
71*2d543d20SAndroid Build Coastguard Worker 	return rc;
72*2d543d20SAndroid Build Coastguard Worker }
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker int
sidtab_context_to_sid(struct sidtab * s,const char * ctx,security_id_t * sid)75*2d543d20SAndroid Build Coastguard Worker sidtab_context_to_sid(struct sidtab *s,
76*2d543d20SAndroid Build Coastguard Worker 		      const char * ctx, security_id_t * sid)
77*2d543d20SAndroid Build Coastguard Worker {
78*2d543d20SAndroid Build Coastguard Worker 	int hvalue, rc = 0;
79*2d543d20SAndroid Build Coastguard Worker 	struct sidtab_node *cur;
80*2d543d20SAndroid Build Coastguard Worker 
81*2d543d20SAndroid Build Coastguard Worker 	*sid = NULL;
82*2d543d20SAndroid Build Coastguard Worker 	hvalue = sidtab_hash(ctx);
83*2d543d20SAndroid Build Coastguard Worker 
84*2d543d20SAndroid Build Coastguard Worker       loop:
85*2d543d20SAndroid Build Coastguard Worker 	cur = s->htable[hvalue];
86*2d543d20SAndroid Build Coastguard Worker 	while (cur != NULL && strcmp(cur->sid_s.ctx, ctx))
87*2d543d20SAndroid Build Coastguard Worker 		cur = cur->next;
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	if (cur == NULL) {	/* need to make a new entry */
90*2d543d20SAndroid Build Coastguard Worker 		rc = sidtab_insert(s, ctx);
91*2d543d20SAndroid Build Coastguard Worker 		if (rc)
92*2d543d20SAndroid Build Coastguard Worker 			goto out;
93*2d543d20SAndroid Build Coastguard Worker 		goto loop;	/* find the newly inserted node */
94*2d543d20SAndroid Build Coastguard Worker 	}
95*2d543d20SAndroid Build Coastguard Worker 
96*2d543d20SAndroid Build Coastguard Worker 	*sid = &cur->sid_s;
97*2d543d20SAndroid Build Coastguard Worker       out:
98*2d543d20SAndroid Build Coastguard Worker 	return rc;
99*2d543d20SAndroid Build Coastguard Worker }
100*2d543d20SAndroid Build Coastguard Worker 
sidtab_sid_stats(struct sidtab * s,char * buf,int buflen)101*2d543d20SAndroid Build Coastguard Worker void sidtab_sid_stats(struct sidtab *s, char *buf, int buflen)
102*2d543d20SAndroid Build Coastguard Worker {
103*2d543d20SAndroid Build Coastguard Worker 	int i, chain_len, slots_used, max_chain_len;
104*2d543d20SAndroid Build Coastguard Worker 	struct sidtab_node *cur;
105*2d543d20SAndroid Build Coastguard Worker 
106*2d543d20SAndroid Build Coastguard Worker 	slots_used = 0;
107*2d543d20SAndroid Build Coastguard Worker 	max_chain_len = 0;
108*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SIDTAB_SIZE; i++) {
109*2d543d20SAndroid Build Coastguard Worker 		cur = s->htable[i];
110*2d543d20SAndroid Build Coastguard Worker 		if (cur) {
111*2d543d20SAndroid Build Coastguard Worker 			slots_used++;
112*2d543d20SAndroid Build Coastguard Worker 			chain_len = 0;
113*2d543d20SAndroid Build Coastguard Worker 			while (cur) {
114*2d543d20SAndroid Build Coastguard Worker 				chain_len++;
115*2d543d20SAndroid Build Coastguard Worker 				cur = cur->next;
116*2d543d20SAndroid Build Coastguard Worker 			}
117*2d543d20SAndroid Build Coastguard Worker 
118*2d543d20SAndroid Build Coastguard Worker 			if (chain_len > max_chain_len)
119*2d543d20SAndroid Build Coastguard Worker 				max_chain_len = chain_len;
120*2d543d20SAndroid Build Coastguard Worker 		}
121*2d543d20SAndroid Build Coastguard Worker 	}
122*2d543d20SAndroid Build Coastguard Worker 
123*2d543d20SAndroid Build Coastguard Worker 	snprintf(buf, buflen,
124*2d543d20SAndroid Build Coastguard Worker 		 "%s:  %u SID entries and %d/%d buckets used, longest "
125*2d543d20SAndroid Build Coastguard Worker 		 "chain length %d\n", avc_prefix, s->nel, slots_used,
126*2d543d20SAndroid Build Coastguard Worker 		 SIDTAB_SIZE, max_chain_len);
127*2d543d20SAndroid Build Coastguard Worker }
128*2d543d20SAndroid Build Coastguard Worker 
sidtab_destroy(struct sidtab * s)129*2d543d20SAndroid Build Coastguard Worker void sidtab_destroy(struct sidtab *s)
130*2d543d20SAndroid Build Coastguard Worker {
131*2d543d20SAndroid Build Coastguard Worker 	int i;
132*2d543d20SAndroid Build Coastguard Worker 	struct sidtab_node *cur, *temp;
133*2d543d20SAndroid Build Coastguard Worker 
134*2d543d20SAndroid Build Coastguard Worker 	if (!s)
135*2d543d20SAndroid Build Coastguard Worker 		return;
136*2d543d20SAndroid Build Coastguard Worker 
137*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < SIDTAB_SIZE; i++) {
138*2d543d20SAndroid Build Coastguard Worker 		cur = s->htable[i];
139*2d543d20SAndroid Build Coastguard Worker 		while (cur != NULL) {
140*2d543d20SAndroid Build Coastguard Worker 			temp = cur;
141*2d543d20SAndroid Build Coastguard Worker 			cur = cur->next;
142*2d543d20SAndroid Build Coastguard Worker 			freecon(temp->sid_s.ctx);
143*2d543d20SAndroid Build Coastguard Worker 			avc_free(temp);
144*2d543d20SAndroid Build Coastguard Worker 		}
145*2d543d20SAndroid Build Coastguard Worker 		s->htable[i] = NULL;
146*2d543d20SAndroid Build Coastguard Worker 	}
147*2d543d20SAndroid Build Coastguard Worker 	avc_free(s->htable);
148*2d543d20SAndroid Build Coastguard Worker 	s->htable = NULL;
149*2d543d20SAndroid Build Coastguard Worker }
150