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