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