xref: /aosp_15_r20/external/selinux/libsepol/src/interfaces.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
2*2d543d20SAndroid Build Coastguard Worker 
3*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
4*2d543d20SAndroid Build Coastguard Worker #include "context.h"
5*2d543d20SAndroid Build Coastguard Worker #include "handle.h"
6*2d543d20SAndroid Build Coastguard Worker 
7*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
8*2d543d20SAndroid Build Coastguard Worker #include <sepol/interfaces.h>
9*2d543d20SAndroid Build Coastguard Worker #include "iface_internal.h"
10*2d543d20SAndroid Build Coastguard Worker 
11*2d543d20SAndroid Build Coastguard Worker /* Create a low level structure from record */
iface_from_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t ** iface,const sepol_iface_t * record)12*2d543d20SAndroid Build Coastguard Worker static int iface_from_record(sepol_handle_t * handle,
13*2d543d20SAndroid Build Coastguard Worker 			     const policydb_t * policydb,
14*2d543d20SAndroid Build Coastguard Worker 			     ocontext_t ** iface, const sepol_iface_t * record)
15*2d543d20SAndroid Build Coastguard Worker {
16*2d543d20SAndroid Build Coastguard Worker 
17*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *tmp_iface = NULL;
18*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *tmp_con = NULL;
19*2d543d20SAndroid Build Coastguard Worker 
20*2d543d20SAndroid Build Coastguard Worker 	tmp_iface = (ocontext_t *) calloc(1, sizeof(ocontext_t));
21*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_iface)
22*2d543d20SAndroid Build Coastguard Worker 		goto omem;
23*2d543d20SAndroid Build Coastguard Worker 
24*2d543d20SAndroid Build Coastguard Worker 	/* Name */
25*2d543d20SAndroid Build Coastguard Worker 	tmp_iface->u.name = strdup(sepol_iface_get_name(record));
26*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_iface->u.name)
27*2d543d20SAndroid Build Coastguard Worker 		goto omem;
28*2d543d20SAndroid Build Coastguard Worker 
29*2d543d20SAndroid Build Coastguard Worker 	/* Interface Context */
30*2d543d20SAndroid Build Coastguard Worker 	if (context_from_record(handle, policydb,
31*2d543d20SAndroid Build Coastguard Worker 				&tmp_con, sepol_iface_get_ifcon(record)) < 0)
32*2d543d20SAndroid Build Coastguard Worker 		goto err;
33*2d543d20SAndroid Build Coastguard Worker 	context_cpy(&tmp_iface->context[0], tmp_con);
34*2d543d20SAndroid Build Coastguard Worker 	context_destroy(tmp_con);
35*2d543d20SAndroid Build Coastguard Worker 	free(tmp_con);
36*2d543d20SAndroid Build Coastguard Worker 	tmp_con = NULL;
37*2d543d20SAndroid Build Coastguard Worker 
38*2d543d20SAndroid Build Coastguard Worker 	/* Message Context */
39*2d543d20SAndroid Build Coastguard Worker 	if (context_from_record(handle, policydb,
40*2d543d20SAndroid Build Coastguard Worker 				&tmp_con, sepol_iface_get_msgcon(record)) < 0)
41*2d543d20SAndroid Build Coastguard Worker 		goto err;
42*2d543d20SAndroid Build Coastguard Worker 	context_cpy(&tmp_iface->context[1], tmp_con);
43*2d543d20SAndroid Build Coastguard Worker 	context_destroy(tmp_con);
44*2d543d20SAndroid Build Coastguard Worker 	free(tmp_con);
45*2d543d20SAndroid Build Coastguard Worker 	tmp_con = NULL;
46*2d543d20SAndroid Build Coastguard Worker 
47*2d543d20SAndroid Build Coastguard Worker 	*iface = tmp_iface;
48*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
49*2d543d20SAndroid Build Coastguard Worker 
50*2d543d20SAndroid Build Coastguard Worker       omem:
51*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "out of memory");
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker       err:
54*2d543d20SAndroid Build Coastguard Worker 	if (tmp_iface != NULL) {
55*2d543d20SAndroid Build Coastguard Worker 		free(tmp_iface->u.name);
56*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&tmp_iface->context[0]);
57*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&tmp_iface->context[1]);
58*2d543d20SAndroid Build Coastguard Worker 		free(tmp_iface);
59*2d543d20SAndroid Build Coastguard Worker 	}
60*2d543d20SAndroid Build Coastguard Worker 	context_destroy(tmp_con);
61*2d543d20SAndroid Build Coastguard Worker 	free(tmp_con);
62*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "error creating interface structure");
63*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
64*2d543d20SAndroid Build Coastguard Worker }
65*2d543d20SAndroid Build Coastguard Worker 
iface_to_record(sepol_handle_t * handle,const policydb_t * policydb,ocontext_t * iface,sepol_iface_t ** record)66*2d543d20SAndroid Build Coastguard Worker static int iface_to_record(sepol_handle_t * handle,
67*2d543d20SAndroid Build Coastguard Worker 			   const policydb_t * policydb,
68*2d543d20SAndroid Build Coastguard Worker 			   ocontext_t * iface, sepol_iface_t ** record)
69*2d543d20SAndroid Build Coastguard Worker {
70*2d543d20SAndroid Build Coastguard Worker 
71*2d543d20SAndroid Build Coastguard Worker 	char *name = iface->u.name;
72*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *ifcon = &iface->context[0];
73*2d543d20SAndroid Build Coastguard Worker 	context_struct_t *msgcon = &iface->context[1];
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker 	sepol_context_t *tmp_con = NULL;
76*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_t *tmp_record = NULL;
77*2d543d20SAndroid Build Coastguard Worker 
78*2d543d20SAndroid Build Coastguard Worker 	if (sepol_iface_create(handle, &tmp_record) < 0)
79*2d543d20SAndroid Build Coastguard Worker 		goto err;
80*2d543d20SAndroid Build Coastguard Worker 
81*2d543d20SAndroid Build Coastguard Worker 	if (sepol_iface_set_name(handle, tmp_record, name) < 0)
82*2d543d20SAndroid Build Coastguard Worker 		goto err;
83*2d543d20SAndroid Build Coastguard Worker 
84*2d543d20SAndroid Build Coastguard Worker 	if (context_to_record(handle, policydb, ifcon, &tmp_con) < 0)
85*2d543d20SAndroid Build Coastguard Worker 		goto err;
86*2d543d20SAndroid Build Coastguard Worker 	if (sepol_iface_set_ifcon(handle, tmp_record, tmp_con) < 0)
87*2d543d20SAndroid Build Coastguard Worker 		goto err;
88*2d543d20SAndroid Build Coastguard Worker 	sepol_context_free(tmp_con);
89*2d543d20SAndroid Build Coastguard Worker 	tmp_con = NULL;
90*2d543d20SAndroid Build Coastguard Worker 
91*2d543d20SAndroid Build Coastguard Worker 	if (context_to_record(handle, policydb, msgcon, &tmp_con) < 0)
92*2d543d20SAndroid Build Coastguard Worker 		goto err;
93*2d543d20SAndroid Build Coastguard Worker 	if (sepol_iface_set_msgcon(handle, tmp_record, tmp_con) < 0)
94*2d543d20SAndroid Build Coastguard Worker 		goto err;
95*2d543d20SAndroid Build Coastguard Worker 	sepol_context_free(tmp_con);
96*2d543d20SAndroid Build Coastguard Worker 	tmp_con = NULL;
97*2d543d20SAndroid Build Coastguard Worker 
98*2d543d20SAndroid Build Coastguard Worker 	*record = tmp_record;
99*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
100*2d543d20SAndroid Build Coastguard Worker 
101*2d543d20SAndroid Build Coastguard Worker       err:
102*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not convert interface %s to record", name);
103*2d543d20SAndroid Build Coastguard Worker 	sepol_context_free(tmp_con);
104*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_free(tmp_record);
105*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
106*2d543d20SAndroid Build Coastguard Worker }
107*2d543d20SAndroid Build Coastguard Worker 
108*2d543d20SAndroid Build Coastguard Worker /* Check if an interface exists */
sepol_iface_exists(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_iface_key_t * key,int * response)109*2d543d20SAndroid Build Coastguard Worker int sepol_iface_exists(sepol_handle_t * handle __attribute__ ((unused)),
110*2d543d20SAndroid Build Coastguard Worker 		       const sepol_policydb_t * p,
111*2d543d20SAndroid Build Coastguard Worker 		       const sepol_iface_key_t * key, int *response)
112*2d543d20SAndroid Build Coastguard Worker {
113*2d543d20SAndroid Build Coastguard Worker 
114*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
115*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
116*2d543d20SAndroid Build Coastguard Worker 
117*2d543d20SAndroid Build Coastguard Worker 	const char *name;
118*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_key_unpack(key, &name);
119*2d543d20SAndroid Build Coastguard Worker 
120*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NETIF];
121*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
122*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(name, c->u.name)) {
123*2d543d20SAndroid Build Coastguard Worker 			*response = 1;
124*2d543d20SAndroid Build Coastguard Worker 			return STATUS_SUCCESS;
125*2d543d20SAndroid Build Coastguard Worker 		}
126*2d543d20SAndroid Build Coastguard Worker 	}
127*2d543d20SAndroid Build Coastguard Worker 	*response = 0;
128*2d543d20SAndroid Build Coastguard Worker 
129*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
130*2d543d20SAndroid Build Coastguard Worker }
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker /* Query an interface */
sepol_iface_query(sepol_handle_t * handle,const sepol_policydb_t * p,const sepol_iface_key_t * key,sepol_iface_t ** response)133*2d543d20SAndroid Build Coastguard Worker int sepol_iface_query(sepol_handle_t * handle,
134*2d543d20SAndroid Build Coastguard Worker 		      const sepol_policydb_t * p,
135*2d543d20SAndroid Build Coastguard Worker 		      const sepol_iface_key_t * key, sepol_iface_t ** response)
136*2d543d20SAndroid Build Coastguard Worker {
137*2d543d20SAndroid Build Coastguard Worker 
138*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
139*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
140*2d543d20SAndroid Build Coastguard Worker 
141*2d543d20SAndroid Build Coastguard Worker 	const char *name;
142*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_key_unpack(key, &name);
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NETIF];
145*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
146*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(name, c->u.name)) {
147*2d543d20SAndroid Build Coastguard Worker 
148*2d543d20SAndroid Build Coastguard Worker 			if (iface_to_record(handle, policydb, c, response) < 0)
149*2d543d20SAndroid Build Coastguard Worker 				goto err;
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 			return STATUS_SUCCESS;
152*2d543d20SAndroid Build Coastguard Worker 		}
153*2d543d20SAndroid Build Coastguard Worker 	}
154*2d543d20SAndroid Build Coastguard Worker 
155*2d543d20SAndroid Build Coastguard Worker 	*response = NULL;
156*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker       err:
159*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not query interface %s", name);
160*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
161*2d543d20SAndroid Build Coastguard Worker }
162*2d543d20SAndroid Build Coastguard Worker 
163*2d543d20SAndroid Build Coastguard Worker /* Load an interface into policy */
sepol_iface_modify(sepol_handle_t * handle,sepol_policydb_t * p,const sepol_iface_key_t * key,const sepol_iface_t * data)164*2d543d20SAndroid Build Coastguard Worker int sepol_iface_modify(sepol_handle_t * handle,
165*2d543d20SAndroid Build Coastguard Worker 		       sepol_policydb_t * p,
166*2d543d20SAndroid Build Coastguard Worker 		       const sepol_iface_key_t * key,
167*2d543d20SAndroid Build Coastguard Worker 		       const sepol_iface_t * data)
168*2d543d20SAndroid Build Coastguard Worker {
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 	policydb_t *policydb = &p->p;
171*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *head, *prev, *c, *iface = NULL;
172*2d543d20SAndroid Build Coastguard Worker 
173*2d543d20SAndroid Build Coastguard Worker 	const char *name;
174*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_key_unpack(key, &name);
175*2d543d20SAndroid Build Coastguard Worker 
176*2d543d20SAndroid Build Coastguard Worker 	if (iface_from_record(handle, policydb, &iface, data) < 0)
177*2d543d20SAndroid Build Coastguard Worker 		goto err;
178*2d543d20SAndroid Build Coastguard Worker 
179*2d543d20SAndroid Build Coastguard Worker 	prev = NULL;
180*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NETIF];
181*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
182*2d543d20SAndroid Build Coastguard Worker 		if (!strcmp(name, c->u.name)) {
183*2d543d20SAndroid Build Coastguard Worker 
184*2d543d20SAndroid Build Coastguard Worker 			/* Replace */
185*2d543d20SAndroid Build Coastguard Worker 			iface->next = c->next;
186*2d543d20SAndroid Build Coastguard Worker 			if (prev == NULL)
187*2d543d20SAndroid Build Coastguard Worker 				policydb->ocontexts[OCON_NETIF] = iface;
188*2d543d20SAndroid Build Coastguard Worker 			else
189*2d543d20SAndroid Build Coastguard Worker 				prev->next = iface;
190*2d543d20SAndroid Build Coastguard Worker 			free(c->u.name);
191*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&c->context[0]);
192*2d543d20SAndroid Build Coastguard Worker 			context_destroy(&c->context[1]);
193*2d543d20SAndroid Build Coastguard Worker 			free(c);
194*2d543d20SAndroid Build Coastguard Worker 
195*2d543d20SAndroid Build Coastguard Worker 			return STATUS_SUCCESS;
196*2d543d20SAndroid Build Coastguard Worker 		}
197*2d543d20SAndroid Build Coastguard Worker 		prev = c;
198*2d543d20SAndroid Build Coastguard Worker 	}
199*2d543d20SAndroid Build Coastguard Worker 
200*2d543d20SAndroid Build Coastguard Worker 	/* Attach to context list */
201*2d543d20SAndroid Build Coastguard Worker 	iface->next = policydb->ocontexts[OCON_NETIF];
202*2d543d20SAndroid Build Coastguard Worker 	policydb->ocontexts[OCON_NETIF] = iface;
203*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
204*2d543d20SAndroid Build Coastguard Worker 
205*2d543d20SAndroid Build Coastguard Worker       err:
206*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "error while loading interface %s", name);
207*2d543d20SAndroid Build Coastguard Worker 
208*2d543d20SAndroid Build Coastguard Worker 	if (iface != NULL) {
209*2d543d20SAndroid Build Coastguard Worker 		free(iface->u.name);
210*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&iface->context[0]);
211*2d543d20SAndroid Build Coastguard Worker 		context_destroy(&iface->context[1]);
212*2d543d20SAndroid Build Coastguard Worker 		free(iface);
213*2d543d20SAndroid Build Coastguard Worker 	}
214*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
215*2d543d20SAndroid Build Coastguard Worker }
216*2d543d20SAndroid Build Coastguard Worker 
217*2d543d20SAndroid Build Coastguard Worker /* Return the number of interfaces */
sepol_iface_count(sepol_handle_t * handle,const sepol_policydb_t * p,unsigned int * response)218*2d543d20SAndroid Build Coastguard Worker extern int sepol_iface_count(sepol_handle_t * handle __attribute__ ((unused)),
219*2d543d20SAndroid Build Coastguard Worker 			     const sepol_policydb_t * p, unsigned int *response)
220*2d543d20SAndroid Build Coastguard Worker {
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker 	unsigned int count = 0;
223*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
224*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
225*2d543d20SAndroid Build Coastguard Worker 
226*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NETIF];
227*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c != NULL; c = c->next)
228*2d543d20SAndroid Build Coastguard Worker 		count++;
229*2d543d20SAndroid Build Coastguard Worker 
230*2d543d20SAndroid Build Coastguard Worker 	*response = count;
231*2d543d20SAndroid Build Coastguard Worker 
232*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
233*2d543d20SAndroid Build Coastguard Worker }
234*2d543d20SAndroid Build Coastguard Worker 
sepol_iface_iterate(sepol_handle_t * handle,const sepol_policydb_t * p,int (* fn)(const sepol_iface_t * iface,void * fn_arg),void * arg)235*2d543d20SAndroid Build Coastguard Worker int sepol_iface_iterate(sepol_handle_t * handle,
236*2d543d20SAndroid Build Coastguard Worker 			const sepol_policydb_t * p,
237*2d543d20SAndroid Build Coastguard Worker 			int (*fn) (const sepol_iface_t * iface,
238*2d543d20SAndroid Build Coastguard Worker 				   void *fn_arg), void *arg)
239*2d543d20SAndroid Build Coastguard Worker {
240*2d543d20SAndroid Build Coastguard Worker 
241*2d543d20SAndroid Build Coastguard Worker 	const policydb_t *policydb = &p->p;
242*2d543d20SAndroid Build Coastguard Worker 	ocontext_t *c, *head;
243*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_t *iface = NULL;
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker 	head = policydb->ocontexts[OCON_NETIF];
246*2d543d20SAndroid Build Coastguard Worker 	for (c = head; c; c = c->next) {
247*2d543d20SAndroid Build Coastguard Worker 		int status;
248*2d543d20SAndroid Build Coastguard Worker 
249*2d543d20SAndroid Build Coastguard Worker 		if (iface_to_record(handle, policydb, c, &iface) < 0)
250*2d543d20SAndroid Build Coastguard Worker 			goto err;
251*2d543d20SAndroid Build Coastguard Worker 
252*2d543d20SAndroid Build Coastguard Worker 		/* Invoke handler */
253*2d543d20SAndroid Build Coastguard Worker 		status = fn(iface, arg);
254*2d543d20SAndroid Build Coastguard Worker 		if (status < 0)
255*2d543d20SAndroid Build Coastguard Worker 			goto err;
256*2d543d20SAndroid Build Coastguard Worker 
257*2d543d20SAndroid Build Coastguard Worker 		sepol_iface_free(iface);
258*2d543d20SAndroid Build Coastguard Worker 		iface = NULL;
259*2d543d20SAndroid Build Coastguard Worker 
260*2d543d20SAndroid Build Coastguard Worker 		/* Handler requested exit */
261*2d543d20SAndroid Build Coastguard Worker 		if (status > 0)
262*2d543d20SAndroid Build Coastguard Worker 			break;
263*2d543d20SAndroid Build Coastguard Worker 	}
264*2d543d20SAndroid Build Coastguard Worker 
265*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
266*2d543d20SAndroid Build Coastguard Worker 
267*2d543d20SAndroid Build Coastguard Worker       err:
268*2d543d20SAndroid Build Coastguard Worker 	ERR(handle, "could not iterate over interfaces");
269*2d543d20SAndroid Build Coastguard Worker 	sepol_iface_free(iface);
270*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
271*2d543d20SAndroid Build Coastguard Worker }
272