xref: /aosp_15_r20/external/selinux/mcstrans/src/mls_level.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
2*2d543d20SAndroid Build Coastguard Worker #include "mls_level.h"
3*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/ebitmap.h>
4*2d543d20SAndroid Build Coastguard Worker 
mls_level_from_string(char * mls_context)5*2d543d20SAndroid Build Coastguard Worker mls_level_t *mls_level_from_string(char *mls_context)
6*2d543d20SAndroid Build Coastguard Worker {
7*2d543d20SAndroid Build Coastguard Worker 	char delim;
8*2d543d20SAndroid Build Coastguard Worker 	char *scontextp, *p, *lptr;
9*2d543d20SAndroid Build Coastguard Worker 	mls_level_t *l;
10*2d543d20SAndroid Build Coastguard Worker 
11*2d543d20SAndroid Build Coastguard Worker 	if (!mls_context) {
12*2d543d20SAndroid Build Coastguard Worker 		return NULL;
13*2d543d20SAndroid Build Coastguard Worker 	}
14*2d543d20SAndroid Build Coastguard Worker 
15*2d543d20SAndroid Build Coastguard Worker 	l = (mls_level_t *) calloc(1, sizeof(mls_level_t));
16*2d543d20SAndroid Build Coastguard Worker 	if (!l)
17*2d543d20SAndroid Build Coastguard Worker 		return NULL;
18*2d543d20SAndroid Build Coastguard Worker 
19*2d543d20SAndroid Build Coastguard Worker 	/* Extract low sensitivity. */
20*2d543d20SAndroid Build Coastguard Worker 	scontextp = p = mls_context;
21*2d543d20SAndroid Build Coastguard Worker 	while (*p && *p != ':' && *p != '-')
22*2d543d20SAndroid Build Coastguard Worker 		p++;
23*2d543d20SAndroid Build Coastguard Worker 
24*2d543d20SAndroid Build Coastguard Worker 	delim = *p;
25*2d543d20SAndroid Build Coastguard Worker 	if (delim != 0)
26*2d543d20SAndroid Build Coastguard Worker 		*p++ = 0;
27*2d543d20SAndroid Build Coastguard Worker 
28*2d543d20SAndroid Build Coastguard Worker 	if (*scontextp != 's')
29*2d543d20SAndroid Build Coastguard Worker 		goto err;
30*2d543d20SAndroid Build Coastguard Worker 	l->sens = atoi(scontextp + 1);
31*2d543d20SAndroid Build Coastguard Worker 
32*2d543d20SAndroid Build Coastguard Worker 	if (delim == ':') {
33*2d543d20SAndroid Build Coastguard Worker 		/* Extract category set. */
34*2d543d20SAndroid Build Coastguard Worker 		while (1) {
35*2d543d20SAndroid Build Coastguard Worker 			scontextp = p;
36*2d543d20SAndroid Build Coastguard Worker 			while (*p && *p != ',' && *p != '-')
37*2d543d20SAndroid Build Coastguard Worker 				p++;
38*2d543d20SAndroid Build Coastguard Worker 			delim = *p;
39*2d543d20SAndroid Build Coastguard Worker 			if (delim != 0)
40*2d543d20SAndroid Build Coastguard Worker 				*p++ = 0;
41*2d543d20SAndroid Build Coastguard Worker 
42*2d543d20SAndroid Build Coastguard Worker 			/* Separate into level if exists */
43*2d543d20SAndroid Build Coastguard Worker 			if ((lptr = strchr(scontextp, '.')) != NULL) {
44*2d543d20SAndroid Build Coastguard Worker 				/* Remove '.' */
45*2d543d20SAndroid Build Coastguard Worker 				*lptr++ = 0;
46*2d543d20SAndroid Build Coastguard Worker 			}
47*2d543d20SAndroid Build Coastguard Worker 
48*2d543d20SAndroid Build Coastguard Worker 			if (*scontextp != 'c')
49*2d543d20SAndroid Build Coastguard Worker 				goto err;
50*2d543d20SAndroid Build Coastguard Worker 			int bit = atoi(scontextp + 1);
51*2d543d20SAndroid Build Coastguard Worker 			if (ebitmap_set_bit(&l->cat, bit, 1))
52*2d543d20SAndroid Build Coastguard Worker 				goto err;
53*2d543d20SAndroid Build Coastguard Worker 
54*2d543d20SAndroid Build Coastguard Worker 			/* If level, set all categories in level */
55*2d543d20SAndroid Build Coastguard Worker 			if (lptr) {
56*2d543d20SAndroid Build Coastguard Worker 				if (*lptr != 'c')
57*2d543d20SAndroid Build Coastguard Worker 					goto err;
58*2d543d20SAndroid Build Coastguard Worker 				int ubit = atoi(lptr + 1);
59*2d543d20SAndroid Build Coastguard Worker 				int i;
60*2d543d20SAndroid Build Coastguard Worker 				for (i = bit + 1; i <= ubit; i++) {
61*2d543d20SAndroid Build Coastguard Worker 					if (ebitmap_set_bit
62*2d543d20SAndroid Build Coastguard Worker 					    (&l->cat, i, 1))
63*2d543d20SAndroid Build Coastguard Worker 						goto err;
64*2d543d20SAndroid Build Coastguard Worker 				}
65*2d543d20SAndroid Build Coastguard Worker 			}
66*2d543d20SAndroid Build Coastguard Worker 
67*2d543d20SAndroid Build Coastguard Worker 			if (delim != ',')
68*2d543d20SAndroid Build Coastguard Worker 				break;
69*2d543d20SAndroid Build Coastguard Worker 		}
70*2d543d20SAndroid Build Coastguard Worker 	}
71*2d543d20SAndroid Build Coastguard Worker 
72*2d543d20SAndroid Build Coastguard Worker 	return l;
73*2d543d20SAndroid Build Coastguard Worker 
74*2d543d20SAndroid Build Coastguard Worker       err:
75*2d543d20SAndroid Build Coastguard Worker 	free(l);
76*2d543d20SAndroid Build Coastguard Worker 	return NULL;
77*2d543d20SAndroid Build Coastguard Worker }
78*2d543d20SAndroid Build Coastguard Worker 
79*2d543d20SAndroid Build Coastguard Worker /*
80*2d543d20SAndroid Build Coastguard Worker  * Return the length in bytes for the MLS fields of the
81*2d543d20SAndroid Build Coastguard Worker  * security context string representation of `context'.
82*2d543d20SAndroid Build Coastguard Worker  */
mls_compute_string_len(mls_level_t * l)83*2d543d20SAndroid Build Coastguard Worker unsigned int mls_compute_string_len(mls_level_t *l)
84*2d543d20SAndroid Build Coastguard Worker {
85*2d543d20SAndroid Build Coastguard Worker 	unsigned int len = 0;
86*2d543d20SAndroid Build Coastguard Worker 	char temp[16];
87*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, level = 0;
88*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *cnode;
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker 	if (!l)
91*2d543d20SAndroid Build Coastguard Worker 		return 0;
92*2d543d20SAndroid Build Coastguard Worker 
93*2d543d20SAndroid Build Coastguard Worker 	len += snprintf(temp, sizeof(temp), "s%d", l->sens);
94*2d543d20SAndroid Build Coastguard Worker 
95*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_bit(&l->cat, cnode, i) {
96*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_node_get_bit(cnode, i)) {
97*2d543d20SAndroid Build Coastguard Worker 			if (level) {
98*2d543d20SAndroid Build Coastguard Worker 				level++;
99*2d543d20SAndroid Build Coastguard Worker 				continue;
100*2d543d20SAndroid Build Coastguard Worker 			}
101*2d543d20SAndroid Build Coastguard Worker 
102*2d543d20SAndroid Build Coastguard Worker 			len++; /* : or ,` */
103*2d543d20SAndroid Build Coastguard Worker 
104*2d543d20SAndroid Build Coastguard Worker 			len += snprintf(temp, sizeof(temp), "c%d", i);
105*2d543d20SAndroid Build Coastguard Worker 			level++;
106*2d543d20SAndroid Build Coastguard Worker 		} else {
107*2d543d20SAndroid Build Coastguard Worker 			if (level > 1)
108*2d543d20SAndroid Build Coastguard Worker 				len += snprintf(temp, sizeof(temp), ".c%d", i-1);
109*2d543d20SAndroid Build Coastguard Worker 			level = 0;
110*2d543d20SAndroid Build Coastguard Worker 		}
111*2d543d20SAndroid Build Coastguard Worker 	}
112*2d543d20SAndroid Build Coastguard Worker 
113*2d543d20SAndroid Build Coastguard Worker 	/* Handle case where last category is the end of level */
114*2d543d20SAndroid Build Coastguard Worker 	if (level > 1)
115*2d543d20SAndroid Build Coastguard Worker 		len += snprintf(temp, sizeof(temp), ".c%d", i-1);
116*2d543d20SAndroid Build Coastguard Worker 	return len;
117*2d543d20SAndroid Build Coastguard Worker }
118*2d543d20SAndroid Build Coastguard Worker 
mls_level_to_string(mls_level_t * l)119*2d543d20SAndroid Build Coastguard Worker char *mls_level_to_string(mls_level_t *l)
120*2d543d20SAndroid Build Coastguard Worker {
121*2d543d20SAndroid Build Coastguard Worker 	unsigned int wrote_sep, len = mls_compute_string_len(l);
122*2d543d20SAndroid Build Coastguard Worker 	unsigned int i, level = 0;
123*2d543d20SAndroid Build Coastguard Worker 	ebitmap_node_t *cnode;
124*2d543d20SAndroid Build Coastguard Worker 	wrote_sep = 0;
125*2d543d20SAndroid Build Coastguard Worker 
126*2d543d20SAndroid Build Coastguard Worker 	if (len == 0)
127*2d543d20SAndroid Build Coastguard Worker 		return NULL;
128*2d543d20SAndroid Build Coastguard Worker 	char *result = (char *)malloc(len + 1);
129*2d543d20SAndroid Build Coastguard Worker 	if (!result)
130*2d543d20SAndroid Build Coastguard Worker 		return NULL;
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 	char *p = result;
133*2d543d20SAndroid Build Coastguard Worker 
134*2d543d20SAndroid Build Coastguard Worker 	p += sprintf(p, "s%d", l->sens);
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker 	/* categories */
137*2d543d20SAndroid Build Coastguard Worker 	ebitmap_for_each_bit(&l->cat, cnode, i) {
138*2d543d20SAndroid Build Coastguard Worker 		if (ebitmap_node_get_bit(cnode, i)) {
139*2d543d20SAndroid Build Coastguard Worker 			if (level) {
140*2d543d20SAndroid Build Coastguard Worker 				level++;
141*2d543d20SAndroid Build Coastguard Worker 				continue;
142*2d543d20SAndroid Build Coastguard Worker 			}
143*2d543d20SAndroid Build Coastguard Worker 
144*2d543d20SAndroid Build Coastguard Worker 			if (!wrote_sep) {
145*2d543d20SAndroid Build Coastguard Worker 				*p++ = ':';
146*2d543d20SAndroid Build Coastguard Worker 				wrote_sep = 1;
147*2d543d20SAndroid Build Coastguard Worker 			} else
148*2d543d20SAndroid Build Coastguard Worker 				*p++ = ',';
149*2d543d20SAndroid Build Coastguard Worker 			p += sprintf(p, "c%d", i);
150*2d543d20SAndroid Build Coastguard Worker 			level++;
151*2d543d20SAndroid Build Coastguard Worker 		} else {
152*2d543d20SAndroid Build Coastguard Worker 			if (level > 1) {
153*2d543d20SAndroid Build Coastguard Worker 				if (level > 2)
154*2d543d20SAndroid Build Coastguard Worker 					*p++ = '.';
155*2d543d20SAndroid Build Coastguard Worker 				else
156*2d543d20SAndroid Build Coastguard Worker 					*p++ = ',';
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker 				p += sprintf(p, "c%d", i-1);
159*2d543d20SAndroid Build Coastguard Worker 			}
160*2d543d20SAndroid Build Coastguard Worker 			level = 0;
161*2d543d20SAndroid Build Coastguard Worker 		}
162*2d543d20SAndroid Build Coastguard Worker 	}
163*2d543d20SAndroid Build Coastguard Worker 	/* Handle case where last category is the end of level */
164*2d543d20SAndroid Build Coastguard Worker 	if (level > 1) {
165*2d543d20SAndroid Build Coastguard Worker 		if (level > 2)
166*2d543d20SAndroid Build Coastguard Worker 			*p++ = '.';
167*2d543d20SAndroid Build Coastguard Worker 		else
168*2d543d20SAndroid Build Coastguard Worker 			*p++ = ',';
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 		p += sprintf(p, "c%d", i-1);
171*2d543d20SAndroid Build Coastguard Worker 	}
172*2d543d20SAndroid Build Coastguard Worker 
173*2d543d20SAndroid Build Coastguard Worker 	*(result + len) = 0;
174*2d543d20SAndroid Build Coastguard Worker 	return result;
175*2d543d20SAndroid Build Coastguard Worker }
176