1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker * Property Service contexts backend for labeling Android
3*2d543d20SAndroid Build Coastguard Worker * property keys
4*2d543d20SAndroid Build Coastguard Worker */
5*2d543d20SAndroid Build Coastguard Worker
6*2d543d20SAndroid Build Coastguard Worker #include <stdarg.h>
7*2d543d20SAndroid Build Coastguard Worker #include <string.h>
8*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
9*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
10*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
11*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
12*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
13*2d543d20SAndroid Build Coastguard Worker #include "callbacks.h"
14*2d543d20SAndroid Build Coastguard Worker #include "label_internal.h"
15*2d543d20SAndroid Build Coastguard Worker
16*2d543d20SAndroid Build Coastguard Worker /* A property security context specification. */
17*2d543d20SAndroid Build Coastguard Worker typedef struct spec {
18*2d543d20SAndroid Build Coastguard Worker struct selabel_lookup_rec lr; /* holds contexts for lookup result */
19*2d543d20SAndroid Build Coastguard Worker char *property_key; /* property key string */
20*2d543d20SAndroid Build Coastguard Worker } spec_t;
21*2d543d20SAndroid Build Coastguard Worker
22*2d543d20SAndroid Build Coastguard Worker /* Our stored configuration */
23*2d543d20SAndroid Build Coastguard Worker struct saved_data {
24*2d543d20SAndroid Build Coastguard Worker /*
25*2d543d20SAndroid Build Coastguard Worker * The array of specifications is sorted for longest
26*2d543d20SAndroid Build Coastguard Worker * prefix match
27*2d543d20SAndroid Build Coastguard Worker */
28*2d543d20SAndroid Build Coastguard Worker spec_t *spec_arr;
29*2d543d20SAndroid Build Coastguard Worker unsigned int nspec; /* total number of specifications */
30*2d543d20SAndroid Build Coastguard Worker };
31*2d543d20SAndroid Build Coastguard Worker
cmp(const void * A,const void * B)32*2d543d20SAndroid Build Coastguard Worker static int cmp(const void *A, const void *B)
33*2d543d20SAndroid Build Coastguard Worker {
34*2d543d20SAndroid Build Coastguard Worker const struct spec *sp1 = A, *sp2 = B;
35*2d543d20SAndroid Build Coastguard Worker
36*2d543d20SAndroid Build Coastguard Worker if (strncmp(sp1->property_key, "*", 1) == 0)
37*2d543d20SAndroid Build Coastguard Worker return 1;
38*2d543d20SAndroid Build Coastguard Worker if (strncmp(sp2->property_key, "*", 1) == 0)
39*2d543d20SAndroid Build Coastguard Worker return -1;
40*2d543d20SAndroid Build Coastguard Worker
41*2d543d20SAndroid Build Coastguard Worker size_t L1 = strlen(sp1->property_key);
42*2d543d20SAndroid Build Coastguard Worker size_t L2 = strlen(sp2->property_key);
43*2d543d20SAndroid Build Coastguard Worker
44*2d543d20SAndroid Build Coastguard Worker return (L1 < L2) - (L1 > L2);
45*2d543d20SAndroid Build Coastguard Worker }
46*2d543d20SAndroid Build Coastguard Worker
47*2d543d20SAndroid Build Coastguard Worker /*
48*2d543d20SAndroid Build Coastguard Worker * Warn about duplicate specifications. Return error on different specifications.
49*2d543d20SAndroid Build Coastguard Worker * TODO: Remove duplicate specifications. Move duplicate check to after sort
50*2d543d20SAndroid Build Coastguard Worker * to improve performance.
51*2d543d20SAndroid Build Coastguard Worker */
nodups_specs(struct saved_data * data)52*2d543d20SAndroid Build Coastguard Worker static int nodups_specs(struct saved_data *data)
53*2d543d20SAndroid Build Coastguard Worker {
54*2d543d20SAndroid Build Coastguard Worker int rc = 0;
55*2d543d20SAndroid Build Coastguard Worker unsigned int ii, jj;
56*2d543d20SAndroid Build Coastguard Worker struct spec *curr_spec, *spec_arr = data->spec_arr;
57*2d543d20SAndroid Build Coastguard Worker
58*2d543d20SAndroid Build Coastguard Worker for (ii = 0; ii < data->nspec; ii++) {
59*2d543d20SAndroid Build Coastguard Worker curr_spec = &spec_arr[ii];
60*2d543d20SAndroid Build Coastguard Worker for (jj = ii + 1; jj < data->nspec; jj++) {
61*2d543d20SAndroid Build Coastguard Worker if (!strcmp(spec_arr[jj].property_key,
62*2d543d20SAndroid Build Coastguard Worker curr_spec->property_key)) {
63*2d543d20SAndroid Build Coastguard Worker if (strcmp(spec_arr[jj].lr.ctx_raw,
64*2d543d20SAndroid Build Coastguard Worker curr_spec->lr.ctx_raw)) {
65*2d543d20SAndroid Build Coastguard Worker rc = -1;
66*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
67*2d543d20SAndroid Build Coastguard Worker selinux_log
68*2d543d20SAndroid Build Coastguard Worker (SELINUX_ERROR,
69*2d543d20SAndroid Build Coastguard Worker "Multiple different specifications for %s (%s and %s).\n",
70*2d543d20SAndroid Build Coastguard Worker curr_spec->property_key,
71*2d543d20SAndroid Build Coastguard Worker spec_arr[jj].lr.ctx_raw,
72*2d543d20SAndroid Build Coastguard Worker curr_spec->lr.ctx_raw);
73*2d543d20SAndroid Build Coastguard Worker } else {
74*2d543d20SAndroid Build Coastguard Worker selinux_log
75*2d543d20SAndroid Build Coastguard Worker (SELINUX_WARNING,
76*2d543d20SAndroid Build Coastguard Worker "Multiple same specifications for %s.\n",
77*2d543d20SAndroid Build Coastguard Worker curr_spec->property_key);
78*2d543d20SAndroid Build Coastguard Worker }
79*2d543d20SAndroid Build Coastguard Worker }
80*2d543d20SAndroid Build Coastguard Worker }
81*2d543d20SAndroid Build Coastguard Worker }
82*2d543d20SAndroid Build Coastguard Worker return rc;
83*2d543d20SAndroid Build Coastguard Worker }
84*2d543d20SAndroid Build Coastguard Worker
process_line(struct selabel_handle * rec,const char * path,char * line_buf,int pass,unsigned lineno)85*2d543d20SAndroid Build Coastguard Worker static int process_line(struct selabel_handle *rec,
86*2d543d20SAndroid Build Coastguard Worker const char *path, char *line_buf,
87*2d543d20SAndroid Build Coastguard Worker int pass, unsigned lineno)
88*2d543d20SAndroid Build Coastguard Worker {
89*2d543d20SAndroid Build Coastguard Worker int items;
90*2d543d20SAndroid Build Coastguard Worker char *prop = NULL, *context = NULL;
91*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
92*2d543d20SAndroid Build Coastguard Worker spec_t *spec_arr = data->spec_arr;
93*2d543d20SAndroid Build Coastguard Worker unsigned int nspec = data->nspec;
94*2d543d20SAndroid Build Coastguard Worker const char *errbuf = NULL;
95*2d543d20SAndroid Build Coastguard Worker
96*2d543d20SAndroid Build Coastguard Worker items = read_spec_entries(line_buf, &errbuf, 2, &prop, &context);
97*2d543d20SAndroid Build Coastguard Worker if (items < 0) {
98*2d543d20SAndroid Build Coastguard Worker if (errbuf) {
99*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
100*2d543d20SAndroid Build Coastguard Worker "%s: line %u error due to: %s\n", path,
101*2d543d20SAndroid Build Coastguard Worker lineno, errbuf);
102*2d543d20SAndroid Build Coastguard Worker } else {
103*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
104*2d543d20SAndroid Build Coastguard Worker "%s: line %u error due to: %m\n", path,
105*2d543d20SAndroid Build Coastguard Worker lineno);
106*2d543d20SAndroid Build Coastguard Worker }
107*2d543d20SAndroid Build Coastguard Worker return -1;
108*2d543d20SAndroid Build Coastguard Worker }
109*2d543d20SAndroid Build Coastguard Worker
110*2d543d20SAndroid Build Coastguard Worker if (items == 0)
111*2d543d20SAndroid Build Coastguard Worker return items;
112*2d543d20SAndroid Build Coastguard Worker
113*2d543d20SAndroid Build Coastguard Worker if (items != 2) {
114*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
115*2d543d20SAndroid Build Coastguard Worker "%s: line %u is missing fields\n", path,
116*2d543d20SAndroid Build Coastguard Worker lineno);
117*2d543d20SAndroid Build Coastguard Worker free(prop);
118*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
119*2d543d20SAndroid Build Coastguard Worker return -1;
120*2d543d20SAndroid Build Coastguard Worker }
121*2d543d20SAndroid Build Coastguard Worker
122*2d543d20SAndroid Build Coastguard Worker if (pass == 0) {
123*2d543d20SAndroid Build Coastguard Worker free(prop);
124*2d543d20SAndroid Build Coastguard Worker free(context);
125*2d543d20SAndroid Build Coastguard Worker } else if (pass == 1) {
126*2d543d20SAndroid Build Coastguard Worker /* On the second pass, process and store the specification in spec. */
127*2d543d20SAndroid Build Coastguard Worker spec_arr[nspec].property_key = prop;
128*2d543d20SAndroid Build Coastguard Worker spec_arr[nspec].lr.ctx_raw = context;
129*2d543d20SAndroid Build Coastguard Worker
130*2d543d20SAndroid Build Coastguard Worker if (rec->validating) {
131*2d543d20SAndroid Build Coastguard Worker if (selabel_validate(&spec_arr[nspec].lr) < 0) {
132*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_ERROR,
133*2d543d20SAndroid Build Coastguard Worker "%s: line %u has invalid context %s\n",
134*2d543d20SAndroid Build Coastguard Worker path, lineno, spec_arr[nspec].lr.ctx_raw);
135*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
136*2d543d20SAndroid Build Coastguard Worker return -1;
137*2d543d20SAndroid Build Coastguard Worker }
138*2d543d20SAndroid Build Coastguard Worker }
139*2d543d20SAndroid Build Coastguard Worker
140*2d543d20SAndroid Build Coastguard Worker data->nspec = ++nspec;
141*2d543d20SAndroid Build Coastguard Worker }
142*2d543d20SAndroid Build Coastguard Worker
143*2d543d20SAndroid Build Coastguard Worker return 0;
144*2d543d20SAndroid Build Coastguard Worker }
145*2d543d20SAndroid Build Coastguard Worker
process_file(struct selabel_handle * rec,const char * path)146*2d543d20SAndroid Build Coastguard Worker static int process_file(struct selabel_handle *rec, const char *path)
147*2d543d20SAndroid Build Coastguard Worker {
148*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
149*2d543d20SAndroid Build Coastguard Worker char line_buf[BUFSIZ];
150*2d543d20SAndroid Build Coastguard Worker unsigned int lineno, maxnspec, pass;
151*2d543d20SAndroid Build Coastguard Worker struct stat sb;
152*2d543d20SAndroid Build Coastguard Worker FILE *fp;
153*2d543d20SAndroid Build Coastguard Worker int status = -1;
154*2d543d20SAndroid Build Coastguard Worker unsigned int nspec;
155*2d543d20SAndroid Build Coastguard Worker spec_t *spec_arr;
156*2d543d20SAndroid Build Coastguard Worker
157*2d543d20SAndroid Build Coastguard Worker /* Open the specification file. */
158*2d543d20SAndroid Build Coastguard Worker if ((fp = fopen(path, "re")) == NULL)
159*2d543d20SAndroid Build Coastguard Worker return -1;
160*2d543d20SAndroid Build Coastguard Worker
161*2d543d20SAndroid Build Coastguard Worker if (fstat(fileno(fp), &sb) < 0)
162*2d543d20SAndroid Build Coastguard Worker goto finish;
163*2d543d20SAndroid Build Coastguard Worker
164*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
165*2d543d20SAndroid Build Coastguard Worker
166*2d543d20SAndroid Build Coastguard Worker if (!S_ISREG(sb.st_mode))
167*2d543d20SAndroid Build Coastguard Worker goto finish;
168*2d543d20SAndroid Build Coastguard Worker
169*2d543d20SAndroid Build Coastguard Worker /*
170*2d543d20SAndroid Build Coastguard Worker * Two passes per specification file. First is to get the size.
171*2d543d20SAndroid Build Coastguard Worker * After the first pass, the spec array is malloced / realloced to
172*2d543d20SAndroid Build Coastguard Worker * the appropriate size. Second pass is to populate the spec array.
173*2d543d20SAndroid Build Coastguard Worker */
174*2d543d20SAndroid Build Coastguard Worker maxnspec = UINT_MAX / sizeof(spec_t);
175*2d543d20SAndroid Build Coastguard Worker for (pass = 0; pass < 2; pass++) {
176*2d543d20SAndroid Build Coastguard Worker nspec = 0;
177*2d543d20SAndroid Build Coastguard Worker lineno = 0;
178*2d543d20SAndroid Build Coastguard Worker
179*2d543d20SAndroid Build Coastguard Worker while (fgets(line_buf, sizeof(line_buf) - 1, fp) &&
180*2d543d20SAndroid Build Coastguard Worker nspec < maxnspec) {
181*2d543d20SAndroid Build Coastguard Worker if (process_line(rec, path, line_buf, pass, ++lineno))
182*2d543d20SAndroid Build Coastguard Worker goto finish;
183*2d543d20SAndroid Build Coastguard Worker nspec++;
184*2d543d20SAndroid Build Coastguard Worker }
185*2d543d20SAndroid Build Coastguard Worker
186*2d543d20SAndroid Build Coastguard Worker if (pass == 0) {
187*2d543d20SAndroid Build Coastguard Worker if (nspec == 0) {
188*2d543d20SAndroid Build Coastguard Worker status = 0;
189*2d543d20SAndroid Build Coastguard Worker goto finish;
190*2d543d20SAndroid Build Coastguard Worker }
191*2d543d20SAndroid Build Coastguard Worker
192*2d543d20SAndroid Build Coastguard Worker /* grow spec array if required */
193*2d543d20SAndroid Build Coastguard Worker spec_arr = realloc(data->spec_arr,
194*2d543d20SAndroid Build Coastguard Worker (data->nspec + nspec) * sizeof(spec_t));
195*2d543d20SAndroid Build Coastguard Worker if (spec_arr == NULL)
196*2d543d20SAndroid Build Coastguard Worker goto finish;
197*2d543d20SAndroid Build Coastguard Worker
198*2d543d20SAndroid Build Coastguard Worker memset(&spec_arr[data->nspec], 0, nspec * sizeof(spec_t));
199*2d543d20SAndroid Build Coastguard Worker data->spec_arr = spec_arr;
200*2d543d20SAndroid Build Coastguard Worker maxnspec = nspec;
201*2d543d20SAndroid Build Coastguard Worker rewind(fp);
202*2d543d20SAndroid Build Coastguard Worker }
203*2d543d20SAndroid Build Coastguard Worker }
204*2d543d20SAndroid Build Coastguard Worker
205*2d543d20SAndroid Build Coastguard Worker status = digest_add_specfile(rec->digest, fp, NULL, sb.st_size, path);
206*2d543d20SAndroid Build Coastguard Worker
207*2d543d20SAndroid Build Coastguard Worker finish:
208*2d543d20SAndroid Build Coastguard Worker fclose(fp);
209*2d543d20SAndroid Build Coastguard Worker return status;
210*2d543d20SAndroid Build Coastguard Worker }
211*2d543d20SAndroid Build Coastguard Worker
212*2d543d20SAndroid Build Coastguard Worker static void closef(struct selabel_handle *rec);
213*2d543d20SAndroid Build Coastguard Worker
init(struct selabel_handle * rec,const struct selinux_opt * opts,unsigned n)214*2d543d20SAndroid Build Coastguard Worker static int init(struct selabel_handle *rec, const struct selinux_opt *opts,
215*2d543d20SAndroid Build Coastguard Worker unsigned n)
216*2d543d20SAndroid Build Coastguard Worker {
217*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
218*2d543d20SAndroid Build Coastguard Worker char **paths = NULL;
219*2d543d20SAndroid Build Coastguard Worker size_t num_paths = 0;
220*2d543d20SAndroid Build Coastguard Worker int status = -1;
221*2d543d20SAndroid Build Coastguard Worker size_t i;
222*2d543d20SAndroid Build Coastguard Worker
223*2d543d20SAndroid Build Coastguard Worker /* Process arguments */
224*2d543d20SAndroid Build Coastguard Worker i = n;
225*2d543d20SAndroid Build Coastguard Worker while (i--) {
226*2d543d20SAndroid Build Coastguard Worker switch (opts[i].type) {
227*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_PATH:
228*2d543d20SAndroid Build Coastguard Worker num_paths++;
229*2d543d20SAndroid Build Coastguard Worker break;
230*2d543d20SAndroid Build Coastguard Worker }
231*2d543d20SAndroid Build Coastguard Worker }
232*2d543d20SAndroid Build Coastguard Worker
233*2d543d20SAndroid Build Coastguard Worker if (!num_paths)
234*2d543d20SAndroid Build Coastguard Worker return -1;
235*2d543d20SAndroid Build Coastguard Worker
236*2d543d20SAndroid Build Coastguard Worker paths = calloc(num_paths, sizeof(*paths));
237*2d543d20SAndroid Build Coastguard Worker if (!paths)
238*2d543d20SAndroid Build Coastguard Worker return -1;
239*2d543d20SAndroid Build Coastguard Worker
240*2d543d20SAndroid Build Coastguard Worker rec->spec_files = paths;
241*2d543d20SAndroid Build Coastguard Worker rec->spec_files_len = num_paths;
242*2d543d20SAndroid Build Coastguard Worker
243*2d543d20SAndroid Build Coastguard Worker i = n;
244*2d543d20SAndroid Build Coastguard Worker while (i--) {
245*2d543d20SAndroid Build Coastguard Worker switch(opts[i].type) {
246*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_PATH:
247*2d543d20SAndroid Build Coastguard Worker *paths = strdup(opts[i].value);
248*2d543d20SAndroid Build Coastguard Worker if (*paths == NULL)
249*2d543d20SAndroid Build Coastguard Worker goto finish;
250*2d543d20SAndroid Build Coastguard Worker paths++;
251*2d543d20SAndroid Build Coastguard Worker }
252*2d543d20SAndroid Build Coastguard Worker }
253*2d543d20SAndroid Build Coastguard Worker
254*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_paths; i++) {
255*2d543d20SAndroid Build Coastguard Worker status = process_file(rec, rec->spec_files[i]);
256*2d543d20SAndroid Build Coastguard Worker if (status)
257*2d543d20SAndroid Build Coastguard Worker goto finish;
258*2d543d20SAndroid Build Coastguard Worker }
259*2d543d20SAndroid Build Coastguard Worker
260*2d543d20SAndroid Build Coastguard Worker /* warn about duplicates after all files have been processed. */
261*2d543d20SAndroid Build Coastguard Worker status = nodups_specs(data);
262*2d543d20SAndroid Build Coastguard Worker if (status)
263*2d543d20SAndroid Build Coastguard Worker goto finish;
264*2d543d20SAndroid Build Coastguard Worker
265*2d543d20SAndroid Build Coastguard Worker qsort(data->spec_arr, data->nspec, sizeof(struct spec), cmp);
266*2d543d20SAndroid Build Coastguard Worker
267*2d543d20SAndroid Build Coastguard Worker digest_gen_hash(rec->digest);
268*2d543d20SAndroid Build Coastguard Worker
269*2d543d20SAndroid Build Coastguard Worker finish:
270*2d543d20SAndroid Build Coastguard Worker if (status)
271*2d543d20SAndroid Build Coastguard Worker closef(rec);
272*2d543d20SAndroid Build Coastguard Worker
273*2d543d20SAndroid Build Coastguard Worker return status;
274*2d543d20SAndroid Build Coastguard Worker }
275*2d543d20SAndroid Build Coastguard Worker
276*2d543d20SAndroid Build Coastguard Worker /*
277*2d543d20SAndroid Build Coastguard Worker * Backend interface routines
278*2d543d20SAndroid Build Coastguard Worker */
closef(struct selabel_handle * rec)279*2d543d20SAndroid Build Coastguard Worker static void closef(struct selabel_handle *rec)
280*2d543d20SAndroid Build Coastguard Worker {
281*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
282*2d543d20SAndroid Build Coastguard Worker struct spec *spec;
283*2d543d20SAndroid Build Coastguard Worker unsigned int i;
284*2d543d20SAndroid Build Coastguard Worker
285*2d543d20SAndroid Build Coastguard Worker if (!data)
286*2d543d20SAndroid Build Coastguard Worker return;
287*2d543d20SAndroid Build Coastguard Worker
288*2d543d20SAndroid Build Coastguard Worker /* make sure successive ->func_close() calls are harmless */
289*2d543d20SAndroid Build Coastguard Worker rec->data = NULL;
290*2d543d20SAndroid Build Coastguard Worker
291*2d543d20SAndroid Build Coastguard Worker if (data->spec_arr) {
292*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < data->nspec; i++) {
293*2d543d20SAndroid Build Coastguard Worker spec = &data->spec_arr[i];
294*2d543d20SAndroid Build Coastguard Worker free(spec->property_key);
295*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_raw);
296*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_trans);
297*2d543d20SAndroid Build Coastguard Worker }
298*2d543d20SAndroid Build Coastguard Worker free(data->spec_arr);
299*2d543d20SAndroid Build Coastguard Worker }
300*2d543d20SAndroid Build Coastguard Worker
301*2d543d20SAndroid Build Coastguard Worker free(data);
302*2d543d20SAndroid Build Coastguard Worker rec->data = NULL;
303*2d543d20SAndroid Build Coastguard Worker }
304*2d543d20SAndroid Build Coastguard Worker
property_lookup(struct selabel_handle * rec,const char * key,int type)305*2d543d20SAndroid Build Coastguard Worker static struct selabel_lookup_rec *property_lookup(struct selabel_handle *rec,
306*2d543d20SAndroid Build Coastguard Worker const char *key,
307*2d543d20SAndroid Build Coastguard Worker int __attribute__((unused)) type)
308*2d543d20SAndroid Build Coastguard Worker {
309*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
310*2d543d20SAndroid Build Coastguard Worker spec_t *spec_arr = data->spec_arr;
311*2d543d20SAndroid Build Coastguard Worker unsigned int i;
312*2d543d20SAndroid Build Coastguard Worker struct selabel_lookup_rec *ret = NULL;
313*2d543d20SAndroid Build Coastguard Worker
314*2d543d20SAndroid Build Coastguard Worker if (!data->nspec) {
315*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
316*2d543d20SAndroid Build Coastguard Worker goto finish;
317*2d543d20SAndroid Build Coastguard Worker }
318*2d543d20SAndroid Build Coastguard Worker
319*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < data->nspec; i++) {
320*2d543d20SAndroid Build Coastguard Worker if (strncmp(spec_arr[i].property_key, key,
321*2d543d20SAndroid Build Coastguard Worker strlen(spec_arr[i].property_key)) == 0) {
322*2d543d20SAndroid Build Coastguard Worker break;
323*2d543d20SAndroid Build Coastguard Worker }
324*2d543d20SAndroid Build Coastguard Worker if (strncmp(spec_arr[i].property_key, "*", 1) == 0)
325*2d543d20SAndroid Build Coastguard Worker break;
326*2d543d20SAndroid Build Coastguard Worker }
327*2d543d20SAndroid Build Coastguard Worker
328*2d543d20SAndroid Build Coastguard Worker if (i >= data->nspec) {
329*2d543d20SAndroid Build Coastguard Worker /* No matching specification. */
330*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
331*2d543d20SAndroid Build Coastguard Worker goto finish;
332*2d543d20SAndroid Build Coastguard Worker }
333*2d543d20SAndroid Build Coastguard Worker
334*2d543d20SAndroid Build Coastguard Worker ret = &spec_arr[i].lr;
335*2d543d20SAndroid Build Coastguard Worker
336*2d543d20SAndroid Build Coastguard Worker finish:
337*2d543d20SAndroid Build Coastguard Worker return ret;
338*2d543d20SAndroid Build Coastguard Worker }
339*2d543d20SAndroid Build Coastguard Worker
lookup_exact_match(struct selabel_handle * rec,const char * key,int type)340*2d543d20SAndroid Build Coastguard Worker static struct selabel_lookup_rec *lookup_exact_match(struct selabel_handle *rec,
341*2d543d20SAndroid Build Coastguard Worker const char *key, int __attribute__((unused)) type)
342*2d543d20SAndroid Build Coastguard Worker {
343*2d543d20SAndroid Build Coastguard Worker struct saved_data *data = (struct saved_data *)rec->data;
344*2d543d20SAndroid Build Coastguard Worker spec_t *spec_arr = data->spec_arr;
345*2d543d20SAndroid Build Coastguard Worker unsigned int i;
346*2d543d20SAndroid Build Coastguard Worker struct selabel_lookup_rec *ret = NULL;
347*2d543d20SAndroid Build Coastguard Worker
348*2d543d20SAndroid Build Coastguard Worker if (!data->nspec) {
349*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
350*2d543d20SAndroid Build Coastguard Worker goto finish;
351*2d543d20SAndroid Build Coastguard Worker }
352*2d543d20SAndroid Build Coastguard Worker
353*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < data->nspec; i++) {
354*2d543d20SAndroid Build Coastguard Worker if (strcmp(spec_arr[i].property_key, key) == 0)
355*2d543d20SAndroid Build Coastguard Worker break;
356*2d543d20SAndroid Build Coastguard Worker if (strcmp(spec_arr[i].property_key, "*") == 0)
357*2d543d20SAndroid Build Coastguard Worker break;
358*2d543d20SAndroid Build Coastguard Worker }
359*2d543d20SAndroid Build Coastguard Worker
360*2d543d20SAndroid Build Coastguard Worker if (i >= data->nspec) {
361*2d543d20SAndroid Build Coastguard Worker /* No matching specification. */
362*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
363*2d543d20SAndroid Build Coastguard Worker goto finish;
364*2d543d20SAndroid Build Coastguard Worker }
365*2d543d20SAndroid Build Coastguard Worker
366*2d543d20SAndroid Build Coastguard Worker ret = &spec_arr[i].lr;
367*2d543d20SAndroid Build Coastguard Worker
368*2d543d20SAndroid Build Coastguard Worker finish:
369*2d543d20SAndroid Build Coastguard Worker return ret;
370*2d543d20SAndroid Build Coastguard Worker }
371*2d543d20SAndroid Build Coastguard Worker
stats(struct selabel_handle * rec)372*2d543d20SAndroid Build Coastguard Worker static void stats(struct selabel_handle __attribute__((unused)) *rec)
373*2d543d20SAndroid Build Coastguard Worker {
374*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_WARNING, "'stats' functionality not implemented.\n");
375*2d543d20SAndroid Build Coastguard Worker }
376*2d543d20SAndroid Build Coastguard Worker
selabel_property_init(struct selabel_handle * rec,const struct selinux_opt * opts,unsigned nopts)377*2d543d20SAndroid Build Coastguard Worker int selabel_property_init(struct selabel_handle *rec,
378*2d543d20SAndroid Build Coastguard Worker const struct selinux_opt *opts,
379*2d543d20SAndroid Build Coastguard Worker unsigned nopts)
380*2d543d20SAndroid Build Coastguard Worker {
381*2d543d20SAndroid Build Coastguard Worker struct saved_data *data;
382*2d543d20SAndroid Build Coastguard Worker
383*2d543d20SAndroid Build Coastguard Worker data = (struct saved_data *)calloc(1, sizeof(*data));
384*2d543d20SAndroid Build Coastguard Worker if (!data)
385*2d543d20SAndroid Build Coastguard Worker return -1;
386*2d543d20SAndroid Build Coastguard Worker
387*2d543d20SAndroid Build Coastguard Worker rec->data = data;
388*2d543d20SAndroid Build Coastguard Worker rec->func_close = &closef;
389*2d543d20SAndroid Build Coastguard Worker rec->func_stats = &stats;
390*2d543d20SAndroid Build Coastguard Worker rec->func_lookup = &property_lookup;
391*2d543d20SAndroid Build Coastguard Worker
392*2d543d20SAndroid Build Coastguard Worker return init(rec, opts, nopts);
393*2d543d20SAndroid Build Coastguard Worker }
394*2d543d20SAndroid Build Coastguard Worker
selabel_exact_match_init(struct selabel_handle * rec,const struct selinux_opt * opts,unsigned nopts)395*2d543d20SAndroid Build Coastguard Worker int selabel_exact_match_init(struct selabel_handle *rec,
396*2d543d20SAndroid Build Coastguard Worker const struct selinux_opt *opts, unsigned nopts)
397*2d543d20SAndroid Build Coastguard Worker {
398*2d543d20SAndroid Build Coastguard Worker struct saved_data *data;
399*2d543d20SAndroid Build Coastguard Worker
400*2d543d20SAndroid Build Coastguard Worker data = (struct saved_data *)calloc(1, sizeof(*data));
401*2d543d20SAndroid Build Coastguard Worker if (!data)
402*2d543d20SAndroid Build Coastguard Worker return -1;
403*2d543d20SAndroid Build Coastguard Worker
404*2d543d20SAndroid Build Coastguard Worker rec->data = data;
405*2d543d20SAndroid Build Coastguard Worker rec->func_close = &closef;
406*2d543d20SAndroid Build Coastguard Worker rec->func_stats = &stats;
407*2d543d20SAndroid Build Coastguard Worker rec->func_lookup = &lookup_exact_match;
408*2d543d20SAndroid Build Coastguard Worker
409*2d543d20SAndroid Build Coastguard Worker return init(rec, opts, nopts);
410*2d543d20SAndroid Build Coastguard Worker }
411