xref: /aosp_15_r20/external/selinux/libselinux/src/label_support.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * This file contains helper functions for labeling support.
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Author : Richard Haines <[email protected]>
5*2d543d20SAndroid Build Coastguard Worker  */
6*2d543d20SAndroid Build Coastguard Worker 
7*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
8*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
9*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
10*2d543d20SAndroid Build Coastguard Worker #include <string.h>
11*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
12*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
13*2d543d20SAndroid Build Coastguard Worker #include "label_internal.h"
14*2d543d20SAndroid Build Coastguard Worker 
15*2d543d20SAndroid Build Coastguard Worker /*
16*2d543d20SAndroid Build Coastguard Worker  * Read an entry from a spec file (e.g. file_contexts)
17*2d543d20SAndroid Build Coastguard Worker  * entry - Buffer to allocate for the entry.
18*2d543d20SAndroid Build Coastguard Worker  * ptr - current location of the line to be processed.
19*2d543d20SAndroid Build Coastguard Worker  * returns  - 0 on success and *entry is set to be a null
20*2d543d20SAndroid Build Coastguard Worker  *            terminated value. On Error it returns -1 and
21*2d543d20SAndroid Build Coastguard Worker  *            errno will be set.
22*2d543d20SAndroid Build Coastguard Worker  *
23*2d543d20SAndroid Build Coastguard Worker  */
read_spec_entry(char ** entry,char ** ptr,int * len,const char ** errbuf)24*2d543d20SAndroid Build Coastguard Worker static inline int read_spec_entry(char **entry, char **ptr, int *len, const char **errbuf)
25*2d543d20SAndroid Build Coastguard Worker {
26*2d543d20SAndroid Build Coastguard Worker 	*entry = NULL;
27*2d543d20SAndroid Build Coastguard Worker 	char *tmp_buf = NULL;
28*2d543d20SAndroid Build Coastguard Worker 
29*2d543d20SAndroid Build Coastguard Worker 	while (isspace((unsigned char)**ptr) && **ptr != '\0')
30*2d543d20SAndroid Build Coastguard Worker 		(*ptr)++;
31*2d543d20SAndroid Build Coastguard Worker 
32*2d543d20SAndroid Build Coastguard Worker 	tmp_buf = *ptr;
33*2d543d20SAndroid Build Coastguard Worker 	*len = 0;
34*2d543d20SAndroid Build Coastguard Worker 
35*2d543d20SAndroid Build Coastguard Worker 	while (!isspace((unsigned char)**ptr) && **ptr != '\0') {
36*2d543d20SAndroid Build Coastguard Worker 		if (!isascii((unsigned char)**ptr)) {
37*2d543d20SAndroid Build Coastguard Worker 			errno = EINVAL;
38*2d543d20SAndroid Build Coastguard Worker 			*errbuf = "Non-ASCII characters found";
39*2d543d20SAndroid Build Coastguard Worker 			return -1;
40*2d543d20SAndroid Build Coastguard Worker 		}
41*2d543d20SAndroid Build Coastguard Worker 		(*ptr)++;
42*2d543d20SAndroid Build Coastguard Worker 		(*len)++;
43*2d543d20SAndroid Build Coastguard Worker 	}
44*2d543d20SAndroid Build Coastguard Worker 
45*2d543d20SAndroid Build Coastguard Worker 	if (*len) {
46*2d543d20SAndroid Build Coastguard Worker 		*entry = strndup(tmp_buf, *len);
47*2d543d20SAndroid Build Coastguard Worker 		if (!*entry)
48*2d543d20SAndroid Build Coastguard Worker 			return -1;
49*2d543d20SAndroid Build Coastguard Worker 	}
50*2d543d20SAndroid Build Coastguard Worker 
51*2d543d20SAndroid Build Coastguard Worker 	return 0;
52*2d543d20SAndroid Build Coastguard Worker }
53*2d543d20SAndroid Build Coastguard Worker 
54*2d543d20SAndroid Build Coastguard Worker /*
55*2d543d20SAndroid Build Coastguard Worker  * line_buf - Buffer containing the spec entries .
56*2d543d20SAndroid Build Coastguard Worker  * errbuf   - Double pointer used for passing back specific error messages.
57*2d543d20SAndroid Build Coastguard Worker  * num_args - The number of spec parameter entries to process.
58*2d543d20SAndroid Build Coastguard Worker  * ...      - A 'char **spec_entry' for each parameter.
59*2d543d20SAndroid Build Coastguard Worker  * returns  - The number of items processed. On error, it returns -1 with errno
60*2d543d20SAndroid Build Coastguard Worker  *            set and may set errbuf to a specific error message.
61*2d543d20SAndroid Build Coastguard Worker  *
62*2d543d20SAndroid Build Coastguard Worker  * This function calls read_spec_entry() to do the actual string processing.
63*2d543d20SAndroid Build Coastguard Worker  * As such, can return anything from that function as well.
64*2d543d20SAndroid Build Coastguard Worker  */
read_spec_entries(char * line_buf,const char ** errbuf,int num_args,...)65*2d543d20SAndroid Build Coastguard Worker int  read_spec_entries(char *line_buf, const char **errbuf, int num_args, ...)
66*2d543d20SAndroid Build Coastguard Worker {
67*2d543d20SAndroid Build Coastguard Worker 	char **spec_entry, *buf_p;
68*2d543d20SAndroid Build Coastguard Worker 	int len, rc, items, entry_len = 0;
69*2d543d20SAndroid Build Coastguard Worker 	va_list ap;
70*2d543d20SAndroid Build Coastguard Worker 
71*2d543d20SAndroid Build Coastguard Worker 	*errbuf = NULL;
72*2d543d20SAndroid Build Coastguard Worker 
73*2d543d20SAndroid Build Coastguard Worker 	len = strlen(line_buf);
74*2d543d20SAndroid Build Coastguard Worker 	if (line_buf[len - 1] == '\n')
75*2d543d20SAndroid Build Coastguard Worker 		line_buf[len - 1] = '\0';
76*2d543d20SAndroid Build Coastguard Worker 	else
77*2d543d20SAndroid Build Coastguard Worker 		/* Handle case if line not \n terminated by bumping
78*2d543d20SAndroid Build Coastguard Worker 		 * the len for the check below (as the line is NUL
79*2d543d20SAndroid Build Coastguard Worker 		 * terminated by getline(3)) */
80*2d543d20SAndroid Build Coastguard Worker 		len++;
81*2d543d20SAndroid Build Coastguard Worker 
82*2d543d20SAndroid Build Coastguard Worker 	buf_p = line_buf;
83*2d543d20SAndroid Build Coastguard Worker 	while (isspace((unsigned char)*buf_p))
84*2d543d20SAndroid Build Coastguard Worker 		buf_p++;
85*2d543d20SAndroid Build Coastguard Worker 
86*2d543d20SAndroid Build Coastguard Worker 	/* Skip comment lines and empty lines. */
87*2d543d20SAndroid Build Coastguard Worker 	if (*buf_p == '#' || *buf_p == '\0')
88*2d543d20SAndroid Build Coastguard Worker 		return 0;
89*2d543d20SAndroid Build Coastguard Worker 
90*2d543d20SAndroid Build Coastguard Worker 	/* Process the spec file entries */
91*2d543d20SAndroid Build Coastguard Worker 	va_start(ap, num_args);
92*2d543d20SAndroid Build Coastguard Worker 
93*2d543d20SAndroid Build Coastguard Worker 	items = 0;
94*2d543d20SAndroid Build Coastguard Worker 	while (items < num_args) {
95*2d543d20SAndroid Build Coastguard Worker 		spec_entry = va_arg(ap, char **);
96*2d543d20SAndroid Build Coastguard Worker 
97*2d543d20SAndroid Build Coastguard Worker 		if (len - 1 == buf_p - line_buf) {
98*2d543d20SAndroid Build Coastguard Worker 			va_end(ap);
99*2d543d20SAndroid Build Coastguard Worker 			return items;
100*2d543d20SAndroid Build Coastguard Worker 		}
101*2d543d20SAndroid Build Coastguard Worker 
102*2d543d20SAndroid Build Coastguard Worker 		rc = read_spec_entry(spec_entry, &buf_p, &entry_len, errbuf);
103*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
104*2d543d20SAndroid Build Coastguard Worker 			va_end(ap);
105*2d543d20SAndroid Build Coastguard Worker 			return rc;
106*2d543d20SAndroid Build Coastguard Worker 		}
107*2d543d20SAndroid Build Coastguard Worker 		if (entry_len)
108*2d543d20SAndroid Build Coastguard Worker 			items++;
109*2d543d20SAndroid Build Coastguard Worker 	}
110*2d543d20SAndroid Build Coastguard Worker 	va_end(ap);
111*2d543d20SAndroid Build Coastguard Worker 	return items;
112*2d543d20SAndroid Build Coastguard Worker }
113*2d543d20SAndroid Build Coastguard Worker 
114*2d543d20SAndroid Build Coastguard Worker /* Once all the specfiles are in the hash_buf, generate the hash. */
digest_gen_hash(struct selabel_digest * digest)115*2d543d20SAndroid Build Coastguard Worker void  digest_gen_hash(struct selabel_digest *digest)
116*2d543d20SAndroid Build Coastguard Worker {
117*2d543d20SAndroid Build Coastguard Worker 	Sha1Context context;
118*2d543d20SAndroid Build Coastguard Worker 	size_t remaining_size;
119*2d543d20SAndroid Build Coastguard Worker 	const unsigned char *ptr;
120*2d543d20SAndroid Build Coastguard Worker 
121*2d543d20SAndroid Build Coastguard Worker 	/* If SELABEL_OPT_DIGEST not set then just return */
122*2d543d20SAndroid Build Coastguard Worker 	if (!digest)
123*2d543d20SAndroid Build Coastguard Worker 		return;
124*2d543d20SAndroid Build Coastguard Worker 
125*2d543d20SAndroid Build Coastguard Worker 	Sha1Initialise(&context);
126*2d543d20SAndroid Build Coastguard Worker 
127*2d543d20SAndroid Build Coastguard Worker 	/* Process in blocks of UINT32_MAX bytes */
128*2d543d20SAndroid Build Coastguard Worker 	remaining_size = digest->hashbuf_size;
129*2d543d20SAndroid Build Coastguard Worker 	ptr = digest->hashbuf;
130*2d543d20SAndroid Build Coastguard Worker 	while (remaining_size > UINT32_MAX) {
131*2d543d20SAndroid Build Coastguard Worker 		Sha1Update(&context, ptr, UINT32_MAX);
132*2d543d20SAndroid Build Coastguard Worker 		remaining_size -= UINT32_MAX;
133*2d543d20SAndroid Build Coastguard Worker 		ptr += UINT32_MAX;
134*2d543d20SAndroid Build Coastguard Worker 	}
135*2d543d20SAndroid Build Coastguard Worker 	Sha1Update(&context, ptr, remaining_size);
136*2d543d20SAndroid Build Coastguard Worker 
137*2d543d20SAndroid Build Coastguard Worker 	Sha1Finalise(&context, (SHA1_HASH *)digest->digest);
138*2d543d20SAndroid Build Coastguard Worker 	free(digest->hashbuf);
139*2d543d20SAndroid Build Coastguard Worker 	digest->hashbuf = NULL;
140*2d543d20SAndroid Build Coastguard Worker }
141*2d543d20SAndroid Build Coastguard Worker 
142*2d543d20SAndroid Build Coastguard Worker /**
143*2d543d20SAndroid Build Coastguard Worker  * digest_add_specfile - Add a specfile to the hashbuf and if gen_hash true
144*2d543d20SAndroid Build Coastguard Worker  *			 then generate the hash.
145*2d543d20SAndroid Build Coastguard Worker  * @digest: pointer to the selabel_digest struct
146*2d543d20SAndroid Build Coastguard Worker  * @fp: file pointer for fread(3) or NULL if not.
147*2d543d20SAndroid Build Coastguard Worker  * @from_addr: pointer at start of buffer for memcpy or NULL if not (used for
148*2d543d20SAndroid Build Coastguard Worker  *	       mmap(3) files).
149*2d543d20SAndroid Build Coastguard Worker  * @buf_len: length of buffer to copy.
150*2d543d20SAndroid Build Coastguard Worker  * @path: pointer to the specfile.
151*2d543d20SAndroid Build Coastguard Worker  *
152*2d543d20SAndroid Build Coastguard Worker  * Return %0 on success, -%1 with @errno set on failure.
153*2d543d20SAndroid Build Coastguard Worker  */
digest_add_specfile(struct selabel_digest * digest,FILE * fp,const char * from_addr,size_t buf_len,const char * path)154*2d543d20SAndroid Build Coastguard Worker int  digest_add_specfile(struct selabel_digest *digest, FILE *fp,
155*2d543d20SAndroid Build Coastguard Worker 				    const char *from_addr, size_t buf_len,
156*2d543d20SAndroid Build Coastguard Worker 				    const char *path)
157*2d543d20SAndroid Build Coastguard Worker {
158*2d543d20SAndroid Build Coastguard Worker 	unsigned char *tmp_buf;
159*2d543d20SAndroid Build Coastguard Worker 
160*2d543d20SAndroid Build Coastguard Worker 	/* If SELABEL_OPT_DIGEST not set then just return */
161*2d543d20SAndroid Build Coastguard Worker 	if (!digest)
162*2d543d20SAndroid Build Coastguard Worker 		return 0;
163*2d543d20SAndroid Build Coastguard Worker 
164*2d543d20SAndroid Build Coastguard Worker 	if (digest->hashbuf_size + buf_len < digest->hashbuf_size) {
165*2d543d20SAndroid Build Coastguard Worker 		errno = EOVERFLOW;
166*2d543d20SAndroid Build Coastguard Worker 		return -1;
167*2d543d20SAndroid Build Coastguard Worker 	}
168*2d543d20SAndroid Build Coastguard Worker 	digest->hashbuf_size += buf_len;
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 	tmp_buf = realloc(digest->hashbuf, digest->hashbuf_size);
171*2d543d20SAndroid Build Coastguard Worker 	if (!tmp_buf)
172*2d543d20SAndroid Build Coastguard Worker 		return -1;
173*2d543d20SAndroid Build Coastguard Worker 
174*2d543d20SAndroid Build Coastguard Worker 	digest->hashbuf = tmp_buf;
175*2d543d20SAndroid Build Coastguard Worker 
176*2d543d20SAndroid Build Coastguard Worker 	if (fp) {
177*2d543d20SAndroid Build Coastguard Worker 		if (fseek(fp, 0L, SEEK_SET) == -1)
178*2d543d20SAndroid Build Coastguard Worker 			return -1;
179*2d543d20SAndroid Build Coastguard Worker 
180*2d543d20SAndroid Build Coastguard Worker 		if (fread(digest->hashbuf + (digest->hashbuf_size - buf_len),
181*2d543d20SAndroid Build Coastguard Worker 					    1, buf_len, fp) != buf_len)
182*2d543d20SAndroid Build Coastguard Worker 			return -1;
183*2d543d20SAndroid Build Coastguard Worker 
184*2d543d20SAndroid Build Coastguard Worker 	} else if (from_addr) {
185*2d543d20SAndroid Build Coastguard Worker 		tmp_buf = memcpy(digest->hashbuf +
186*2d543d20SAndroid Build Coastguard Worker 				    (digest->hashbuf_size - buf_len),
187*2d543d20SAndroid Build Coastguard Worker 				    from_addr, buf_len);
188*2d543d20SAndroid Build Coastguard Worker 		if (!tmp_buf)
189*2d543d20SAndroid Build Coastguard Worker 			return -1;
190*2d543d20SAndroid Build Coastguard Worker 	}
191*2d543d20SAndroid Build Coastguard Worker 	/* Now add path to list */
192*2d543d20SAndroid Build Coastguard Worker 	digest->specfile_list[digest->specfile_cnt] = strdup(path);
193*2d543d20SAndroid Build Coastguard Worker 	if (!digest->specfile_list[digest->specfile_cnt])
194*2d543d20SAndroid Build Coastguard Worker 		return -1;
195*2d543d20SAndroid Build Coastguard Worker 
196*2d543d20SAndroid Build Coastguard Worker 	digest->specfile_cnt++;
197*2d543d20SAndroid Build Coastguard Worker 	if (digest->specfile_cnt > DIGEST_FILES_MAX) {
198*2d543d20SAndroid Build Coastguard Worker 		errno = EOVERFLOW;
199*2d543d20SAndroid Build Coastguard Worker 		return -1;
200*2d543d20SAndroid Build Coastguard Worker 	}
201*2d543d20SAndroid Build Coastguard Worker 
202*2d543d20SAndroid Build Coastguard Worker 	return 0;
203*2d543d20SAndroid Build Coastguard Worker }
204