1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker * Media contexts backend for DB objects
3*2d543d20SAndroid Build Coastguard Worker *
4*2d543d20SAndroid Build Coastguard Worker * Author: KaiGai Kohei <[email protected]>
5*2d543d20SAndroid Build Coastguard Worker */
6*2d543d20SAndroid Build Coastguard Worker
7*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
8*2d543d20SAndroid Build Coastguard Worker #include <string.h>
9*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
10*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
11*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
12*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
13*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
14*2d543d20SAndroid Build Coastguard Worker #include <fnmatch.h>
15*2d543d20SAndroid Build Coastguard Worker #include "callbacks.h"
16*2d543d20SAndroid Build Coastguard Worker #include "label_internal.h"
17*2d543d20SAndroid Build Coastguard Worker
18*2d543d20SAndroid Build Coastguard Worker /*
19*2d543d20SAndroid Build Coastguard Worker * Regular database object's security context interface
20*2d543d20SAndroid Build Coastguard Worker *
21*2d543d20SAndroid Build Coastguard Worker * It provides applications a regular security context for the given
22*2d543d20SAndroid Build Coastguard Worker * database objects. The pair of object's name and a security context
23*2d543d20SAndroid Build Coastguard Worker * are described in the specfile. In the default, it shall be stored
24*2d543d20SAndroid Build Coastguard Worker * in the /etc/selinux/$POLICYTYPE/contexts/sepgsql_contexts .
25*2d543d20SAndroid Build Coastguard Worker * (It assumes SE-PostgreSQL in the default. For other RDBMS, use the
26*2d543d20SAndroid Build Coastguard Worker * SELABEL_OPT_PATH option to specify different specfile.)
27*2d543d20SAndroid Build Coastguard Worker *
28*2d543d20SAndroid Build Coastguard Worker * Each line has the following format:
29*2d543d20SAndroid Build Coastguard Worker * <object class> <object name/identifier> <security context>
30*2d543d20SAndroid Build Coastguard Worker *
31*2d543d20SAndroid Build Coastguard Worker * For example:
32*2d543d20SAndroid Build Coastguard Worker * ----------------------------------------
33*2d543d20SAndroid Build Coastguard Worker * #
34*2d543d20SAndroid Build Coastguard Worker * # It is an example specfile for database objects
35*2d543d20SAndroid Build Coastguard Worker * #
36*2d543d20SAndroid Build Coastguard Worker * db_database template1 system_u:object_r:sepgsql_db_t:s0
37*2d543d20SAndroid Build Coastguard Worker *
38*2d543d20SAndroid Build Coastguard Worker * db_schema *.pg_catalog system_u:object_r:sepgsql_sys_schema_t:s0
39*2d543d20SAndroid Build Coastguard Worker *
40*2d543d20SAndroid Build Coastguard Worker * db_table *.pg_catalog.* system_u:object_r:sepgsql_sysobj_t:s0
41*2d543d20SAndroid Build Coastguard Worker * db_column *.pg_catalog.*.* system_u:object_r:sepgsql_sysobj_t:s0
42*2d543d20SAndroid Build Coastguard Worker * ----------------------------------------
43*2d543d20SAndroid Build Coastguard Worker *
44*2d543d20SAndroid Build Coastguard Worker * All the characters after the '#' are dealt as comments.
45*2d543d20SAndroid Build Coastguard Worker *
46*2d543d20SAndroid Build Coastguard Worker * The first token is object class. SELABEL_DB_* declared in label.h are
47*2d543d20SAndroid Build Coastguard Worker * corresponding to a certain database object.
48*2d543d20SAndroid Build Coastguard Worker *
49*2d543d20SAndroid Build Coastguard Worker * The object name/identifier is compared to the given key.
50*2d543d20SAndroid Build Coastguard Worker * A database object can have its own namespace hierarchy.
51*2d543d20SAndroid Build Coastguard Worker * In the case of SE-PgSQL, database is the top level object, and schema
52*2d543d20SAndroid Build Coastguard Worker * is deployed just under a database. A schema can contains various kind
53*2d543d20SAndroid Build Coastguard Worker * of objects, such as tables, procedures and so on.
54*2d543d20SAndroid Build Coastguard Worker * Thus, when we lookup an expected security context for a table of
55*2d543d20SAndroid Build Coastguard Worker * "pg_class", it is necessary to assume selabel_lookup() is called with
56*2d543d20SAndroid Build Coastguard Worker * "postgres.pg_catalog.pg_class", not just a "pg_class".
57*2d543d20SAndroid Build Coastguard Worker *
58*2d543d20SAndroid Build Coastguard Worker * Wildcards ('*' or '?') are available on the patterns, so if you want
59*2d543d20SAndroid Build Coastguard Worker * to match a table within any schema, you should set '*' on the upper
60*2d543d20SAndroid Build Coastguard Worker * namespaces of the table.
61*2d543d20SAndroid Build Coastguard Worker *
62*2d543d20SAndroid Build Coastguard Worker * The structure of namespace depends on RDBMS.
63*2d543d20SAndroid Build Coastguard Worker * For example, Trusted-RUBIX has an idea of "catalog" which performs
64*2d543d20SAndroid Build Coastguard Worker * as a namespace between a database and individual schemas. In this
65*2d543d20SAndroid Build Coastguard Worker * case, a table has upper three layers.
66*2d543d20SAndroid Build Coastguard Worker */
67*2d543d20SAndroid Build Coastguard Worker
68*2d543d20SAndroid Build Coastguard Worker /*
69*2d543d20SAndroid Build Coastguard Worker * spec_t : It holds a pair of a key and an expected security context
70*2d543d20SAndroid Build Coastguard Worker */
71*2d543d20SAndroid Build Coastguard Worker typedef struct spec {
72*2d543d20SAndroid Build Coastguard Worker struct selabel_lookup_rec lr;
73*2d543d20SAndroid Build Coastguard Worker char *key;
74*2d543d20SAndroid Build Coastguard Worker int type;
75*2d543d20SAndroid Build Coastguard Worker int matches;
76*2d543d20SAndroid Build Coastguard Worker } spec_t;
77*2d543d20SAndroid Build Coastguard Worker
78*2d543d20SAndroid Build Coastguard Worker /*
79*2d543d20SAndroid Build Coastguard Worker * catalog_t : An array of spec_t
80*2d543d20SAndroid Build Coastguard Worker */
81*2d543d20SAndroid Build Coastguard Worker typedef struct catalog {
82*2d543d20SAndroid Build Coastguard Worker unsigned int nspec; /* number of specs in use */
83*2d543d20SAndroid Build Coastguard Worker unsigned int limit; /* physical limitation of specs[] */
84*2d543d20SAndroid Build Coastguard Worker spec_t specs[0];
85*2d543d20SAndroid Build Coastguard Worker } catalog_t;
86*2d543d20SAndroid Build Coastguard Worker
87*2d543d20SAndroid Build Coastguard Worker /*
88*2d543d20SAndroid Build Coastguard Worker * Helper function to parse a line read from the specfile
89*2d543d20SAndroid Build Coastguard Worker */
90*2d543d20SAndroid Build Coastguard Worker static int
process_line(const char * path,char * line_buf,unsigned int line_num,catalog_t * catalog)91*2d543d20SAndroid Build Coastguard Worker process_line(const char *path, char *line_buf, unsigned int line_num,
92*2d543d20SAndroid Build Coastguard Worker catalog_t *catalog)
93*2d543d20SAndroid Build Coastguard Worker {
94*2d543d20SAndroid Build Coastguard Worker spec_t *spec = &catalog->specs[catalog->nspec];
95*2d543d20SAndroid Build Coastguard Worker char *type, *key, *context, *temp;
96*2d543d20SAndroid Build Coastguard Worker int items;
97*2d543d20SAndroid Build Coastguard Worker
98*2d543d20SAndroid Build Coastguard Worker /* Cut off comments */
99*2d543d20SAndroid Build Coastguard Worker temp = strchr(line_buf, '#');
100*2d543d20SAndroid Build Coastguard Worker if (temp)
101*2d543d20SAndroid Build Coastguard Worker *temp = '\0';
102*2d543d20SAndroid Build Coastguard Worker
103*2d543d20SAndroid Build Coastguard Worker /*
104*2d543d20SAndroid Build Coastguard Worker * Every entry must have the following format
105*2d543d20SAndroid Build Coastguard Worker * <object class> <object name> <security context>
106*2d543d20SAndroid Build Coastguard Worker */
107*2d543d20SAndroid Build Coastguard Worker type = key = context = temp = NULL;
108*2d543d20SAndroid Build Coastguard Worker items = sscanf(line_buf, "%ms %ms %ms %ms",
109*2d543d20SAndroid Build Coastguard Worker &type, &key, &context, &temp);
110*2d543d20SAndroid Build Coastguard Worker if (items != 3) {
111*2d543d20SAndroid Build Coastguard Worker if (items > 0)
112*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_WARNING,
113*2d543d20SAndroid Build Coastguard Worker "%s: line %u has invalid format, skipped",
114*2d543d20SAndroid Build Coastguard Worker path, line_num);
115*2d543d20SAndroid Build Coastguard Worker goto skip;
116*2d543d20SAndroid Build Coastguard Worker }
117*2d543d20SAndroid Build Coastguard Worker
118*2d543d20SAndroid Build Coastguard Worker /*
119*2d543d20SAndroid Build Coastguard Worker * Set up individual spec entry
120*2d543d20SAndroid Build Coastguard Worker */
121*2d543d20SAndroid Build Coastguard Worker memset(spec, 0, sizeof(spec_t));
122*2d543d20SAndroid Build Coastguard Worker
123*2d543d20SAndroid Build Coastguard Worker if (!strcmp(type, "db_database"))
124*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_DATABASE;
125*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_schema"))
126*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_SCHEMA;
127*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_table"))
128*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_TABLE;
129*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_column"))
130*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_COLUMN;
131*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_sequence"))
132*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_SEQUENCE;
133*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_view"))
134*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_VIEW;
135*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_procedure"))
136*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_PROCEDURE;
137*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_blob"))
138*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_BLOB;
139*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_tuple"))
140*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_TUPLE;
141*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_language"))
142*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_LANGUAGE;
143*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_exception"))
144*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_EXCEPTION;
145*2d543d20SAndroid Build Coastguard Worker else if (!strcmp(type, "db_datatype"))
146*2d543d20SAndroid Build Coastguard Worker spec->type = SELABEL_DB_DATATYPE;
147*2d543d20SAndroid Build Coastguard Worker else {
148*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_WARNING,
149*2d543d20SAndroid Build Coastguard Worker "%s: line %u has invalid object type %s\n",
150*2d543d20SAndroid Build Coastguard Worker path, line_num, type);
151*2d543d20SAndroid Build Coastguard Worker goto skip;
152*2d543d20SAndroid Build Coastguard Worker }
153*2d543d20SAndroid Build Coastguard Worker
154*2d543d20SAndroid Build Coastguard Worker free(type);
155*2d543d20SAndroid Build Coastguard Worker spec->key = key;
156*2d543d20SAndroid Build Coastguard Worker spec->lr.ctx_raw = context;
157*2d543d20SAndroid Build Coastguard Worker
158*2d543d20SAndroid Build Coastguard Worker catalog->nspec++;
159*2d543d20SAndroid Build Coastguard Worker
160*2d543d20SAndroid Build Coastguard Worker return 0;
161*2d543d20SAndroid Build Coastguard Worker
162*2d543d20SAndroid Build Coastguard Worker skip:
163*2d543d20SAndroid Build Coastguard Worker free(type);
164*2d543d20SAndroid Build Coastguard Worker free(key);
165*2d543d20SAndroid Build Coastguard Worker free(context);
166*2d543d20SAndroid Build Coastguard Worker free(temp);
167*2d543d20SAndroid Build Coastguard Worker
168*2d543d20SAndroid Build Coastguard Worker return 0;
169*2d543d20SAndroid Build Coastguard Worker }
170*2d543d20SAndroid Build Coastguard Worker
171*2d543d20SAndroid Build Coastguard Worker /*
172*2d543d20SAndroid Build Coastguard Worker * selabel_close() handler
173*2d543d20SAndroid Build Coastguard Worker */
174*2d543d20SAndroid Build Coastguard Worker static void
db_close(struct selabel_handle * rec)175*2d543d20SAndroid Build Coastguard Worker db_close(struct selabel_handle *rec)
176*2d543d20SAndroid Build Coastguard Worker {
177*2d543d20SAndroid Build Coastguard Worker catalog_t *catalog = (catalog_t *)rec->data;
178*2d543d20SAndroid Build Coastguard Worker spec_t *spec;
179*2d543d20SAndroid Build Coastguard Worker unsigned int i;
180*2d543d20SAndroid Build Coastguard Worker
181*2d543d20SAndroid Build Coastguard Worker if (!catalog)
182*2d543d20SAndroid Build Coastguard Worker return;
183*2d543d20SAndroid Build Coastguard Worker
184*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < catalog->nspec; i++) {
185*2d543d20SAndroid Build Coastguard Worker spec = &catalog->specs[i];
186*2d543d20SAndroid Build Coastguard Worker free(spec->key);
187*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_raw);
188*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_trans);
189*2d543d20SAndroid Build Coastguard Worker }
190*2d543d20SAndroid Build Coastguard Worker free(catalog);
191*2d543d20SAndroid Build Coastguard Worker }
192*2d543d20SAndroid Build Coastguard Worker
193*2d543d20SAndroid Build Coastguard Worker /*
194*2d543d20SAndroid Build Coastguard Worker * selabel_lookup() handler
195*2d543d20SAndroid Build Coastguard Worker */
196*2d543d20SAndroid Build Coastguard Worker static struct selabel_lookup_rec *
db_lookup(struct selabel_handle * rec,const char * key,int type)197*2d543d20SAndroid Build Coastguard Worker db_lookup(struct selabel_handle *rec, const char *key, int type)
198*2d543d20SAndroid Build Coastguard Worker {
199*2d543d20SAndroid Build Coastguard Worker catalog_t *catalog = (catalog_t *)rec->data;
200*2d543d20SAndroid Build Coastguard Worker spec_t *spec;
201*2d543d20SAndroid Build Coastguard Worker unsigned int i;
202*2d543d20SAndroid Build Coastguard Worker
203*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < catalog->nspec; i++) {
204*2d543d20SAndroid Build Coastguard Worker spec = &catalog->specs[i];
205*2d543d20SAndroid Build Coastguard Worker
206*2d543d20SAndroid Build Coastguard Worker if (spec->type != type)
207*2d543d20SAndroid Build Coastguard Worker continue;
208*2d543d20SAndroid Build Coastguard Worker if (!fnmatch(spec->key, key, 0)) {
209*2d543d20SAndroid Build Coastguard Worker spec->matches++;
210*2d543d20SAndroid Build Coastguard Worker
211*2d543d20SAndroid Build Coastguard Worker return &spec->lr;
212*2d543d20SAndroid Build Coastguard Worker }
213*2d543d20SAndroid Build Coastguard Worker }
214*2d543d20SAndroid Build Coastguard Worker
215*2d543d20SAndroid Build Coastguard Worker /* No found */
216*2d543d20SAndroid Build Coastguard Worker errno = ENOENT;
217*2d543d20SAndroid Build Coastguard Worker return NULL;
218*2d543d20SAndroid Build Coastguard Worker }
219*2d543d20SAndroid Build Coastguard Worker
220*2d543d20SAndroid Build Coastguard Worker /*
221*2d543d20SAndroid Build Coastguard Worker * selabel_stats() handler
222*2d543d20SAndroid Build Coastguard Worker */
223*2d543d20SAndroid Build Coastguard Worker static void
db_stats(struct selabel_handle * rec)224*2d543d20SAndroid Build Coastguard Worker db_stats(struct selabel_handle *rec)
225*2d543d20SAndroid Build Coastguard Worker {
226*2d543d20SAndroid Build Coastguard Worker catalog_t *catalog = (catalog_t *)rec->data;
227*2d543d20SAndroid Build Coastguard Worker unsigned int i, total = 0;
228*2d543d20SAndroid Build Coastguard Worker
229*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < catalog->nspec; i++)
230*2d543d20SAndroid Build Coastguard Worker total += catalog->specs[i].matches;
231*2d543d20SAndroid Build Coastguard Worker
232*2d543d20SAndroid Build Coastguard Worker selinux_log(SELINUX_INFO, "%u entries, %u matches made\n",
233*2d543d20SAndroid Build Coastguard Worker catalog->nspec, total);
234*2d543d20SAndroid Build Coastguard Worker }
235*2d543d20SAndroid Build Coastguard Worker
236*2d543d20SAndroid Build Coastguard Worker /*
237*2d543d20SAndroid Build Coastguard Worker * selabel_open() handler
238*2d543d20SAndroid Build Coastguard Worker */
239*2d543d20SAndroid Build Coastguard Worker static catalog_t *
db_init(const struct selinux_opt * opts,unsigned nopts,struct selabel_handle * rec)240*2d543d20SAndroid Build Coastguard Worker db_init(const struct selinux_opt *opts, unsigned nopts,
241*2d543d20SAndroid Build Coastguard Worker struct selabel_handle *rec)
242*2d543d20SAndroid Build Coastguard Worker {
243*2d543d20SAndroid Build Coastguard Worker catalog_t *catalog;
244*2d543d20SAndroid Build Coastguard Worker FILE *filp;
245*2d543d20SAndroid Build Coastguard Worker const char *path = NULL;
246*2d543d20SAndroid Build Coastguard Worker char *line_buf = NULL;
247*2d543d20SAndroid Build Coastguard Worker size_t line_len = 0;
248*2d543d20SAndroid Build Coastguard Worker unsigned int line_num = 0;
249*2d543d20SAndroid Build Coastguard Worker unsigned int i;
250*2d543d20SAndroid Build Coastguard Worker struct stat sb;
251*2d543d20SAndroid Build Coastguard Worker
252*2d543d20SAndroid Build Coastguard Worker /*
253*2d543d20SAndroid Build Coastguard Worker * Initialize catalog data structure
254*2d543d20SAndroid Build Coastguard Worker */
255*2d543d20SAndroid Build Coastguard Worker catalog = malloc(sizeof(catalog_t) + 32 * sizeof(spec_t));
256*2d543d20SAndroid Build Coastguard Worker if (!catalog)
257*2d543d20SAndroid Build Coastguard Worker return NULL;
258*2d543d20SAndroid Build Coastguard Worker catalog->limit = 32;
259*2d543d20SAndroid Build Coastguard Worker catalog->nspec = 0;
260*2d543d20SAndroid Build Coastguard Worker
261*2d543d20SAndroid Build Coastguard Worker /*
262*2d543d20SAndroid Build Coastguard Worker * Process arguments
263*2d543d20SAndroid Build Coastguard Worker *
264*2d543d20SAndroid Build Coastguard Worker * SELABEL_OPT_PATH:
265*2d543d20SAndroid Build Coastguard Worker * It allows to specify an alternative specification file instead of
266*2d543d20SAndroid Build Coastguard Worker * the default one. If RDBMS is not SE-PostgreSQL, it may need to
267*2d543d20SAndroid Build Coastguard Worker * specify an explicit specfile for database objects.
268*2d543d20SAndroid Build Coastguard Worker */
269*2d543d20SAndroid Build Coastguard Worker while (nopts) {
270*2d543d20SAndroid Build Coastguard Worker nopts--;
271*2d543d20SAndroid Build Coastguard Worker switch (opts[nopts].type) {
272*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_PATH:
273*2d543d20SAndroid Build Coastguard Worker path = opts[nopts].value;
274*2d543d20SAndroid Build Coastguard Worker break;
275*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_UNUSED:
276*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_VALIDATE:
277*2d543d20SAndroid Build Coastguard Worker case SELABEL_OPT_DIGEST:
278*2d543d20SAndroid Build Coastguard Worker break;
279*2d543d20SAndroid Build Coastguard Worker default:
280*2d543d20SAndroid Build Coastguard Worker free(catalog);
281*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
282*2d543d20SAndroid Build Coastguard Worker return NULL;
283*2d543d20SAndroid Build Coastguard Worker }
284*2d543d20SAndroid Build Coastguard Worker }
285*2d543d20SAndroid Build Coastguard Worker
286*2d543d20SAndroid Build Coastguard Worker /*
287*2d543d20SAndroid Build Coastguard Worker * Open the specification file
288*2d543d20SAndroid Build Coastguard Worker */
289*2d543d20SAndroid Build Coastguard Worker if (!path)
290*2d543d20SAndroid Build Coastguard Worker path = selinux_sepgsql_context_path();
291*2d543d20SAndroid Build Coastguard Worker
292*2d543d20SAndroid Build Coastguard Worker if ((filp = fopen(path, "re")) == NULL) {
293*2d543d20SAndroid Build Coastguard Worker free(catalog);
294*2d543d20SAndroid Build Coastguard Worker return NULL;
295*2d543d20SAndroid Build Coastguard Worker }
296*2d543d20SAndroid Build Coastguard Worker if (fstat(fileno(filp), &sb) < 0) {
297*2d543d20SAndroid Build Coastguard Worker free(catalog);
298*2d543d20SAndroid Build Coastguard Worker fclose(filp);
299*2d543d20SAndroid Build Coastguard Worker return NULL;
300*2d543d20SAndroid Build Coastguard Worker }
301*2d543d20SAndroid Build Coastguard Worker if (!S_ISREG(sb.st_mode)) {
302*2d543d20SAndroid Build Coastguard Worker free(catalog);
303*2d543d20SAndroid Build Coastguard Worker fclose(filp);
304*2d543d20SAndroid Build Coastguard Worker errno = EINVAL;
305*2d543d20SAndroid Build Coastguard Worker return NULL;
306*2d543d20SAndroid Build Coastguard Worker }
307*2d543d20SAndroid Build Coastguard Worker rec->spec_file = strdup(path);
308*2d543d20SAndroid Build Coastguard Worker if (!rec->spec_file) {
309*2d543d20SAndroid Build Coastguard Worker free(catalog);
310*2d543d20SAndroid Build Coastguard Worker fclose(filp);
311*2d543d20SAndroid Build Coastguard Worker return NULL;
312*2d543d20SAndroid Build Coastguard Worker }
313*2d543d20SAndroid Build Coastguard Worker
314*2d543d20SAndroid Build Coastguard Worker /*
315*2d543d20SAndroid Build Coastguard Worker * Parse for each lines
316*2d543d20SAndroid Build Coastguard Worker */
317*2d543d20SAndroid Build Coastguard Worker while (getline(&line_buf, &line_len, filp) > 0) {
318*2d543d20SAndroid Build Coastguard Worker /*
319*2d543d20SAndroid Build Coastguard Worker * Expand catalog array, if necessary
320*2d543d20SAndroid Build Coastguard Worker */
321*2d543d20SAndroid Build Coastguard Worker if (catalog->limit == catalog->nspec) {
322*2d543d20SAndroid Build Coastguard Worker size_t length;
323*2d543d20SAndroid Build Coastguard Worker unsigned int new_limit = 2 * catalog->limit;
324*2d543d20SAndroid Build Coastguard Worker catalog_t *new_catalog;
325*2d543d20SAndroid Build Coastguard Worker
326*2d543d20SAndroid Build Coastguard Worker length = sizeof(catalog_t)
327*2d543d20SAndroid Build Coastguard Worker + new_limit * sizeof(spec_t);
328*2d543d20SAndroid Build Coastguard Worker new_catalog = realloc(catalog, length);
329*2d543d20SAndroid Build Coastguard Worker if (!new_catalog)
330*2d543d20SAndroid Build Coastguard Worker goto out_error;
331*2d543d20SAndroid Build Coastguard Worker
332*2d543d20SAndroid Build Coastguard Worker catalog = new_catalog;
333*2d543d20SAndroid Build Coastguard Worker catalog->limit = new_limit;
334*2d543d20SAndroid Build Coastguard Worker }
335*2d543d20SAndroid Build Coastguard Worker
336*2d543d20SAndroid Build Coastguard Worker /*
337*2d543d20SAndroid Build Coastguard Worker * Parse a line
338*2d543d20SAndroid Build Coastguard Worker */
339*2d543d20SAndroid Build Coastguard Worker if (process_line(path, line_buf, ++line_num, catalog) < 0)
340*2d543d20SAndroid Build Coastguard Worker goto out_error;
341*2d543d20SAndroid Build Coastguard Worker }
342*2d543d20SAndroid Build Coastguard Worker
343*2d543d20SAndroid Build Coastguard Worker if (digest_add_specfile(rec->digest, filp, NULL, sb.st_size, path) < 0)
344*2d543d20SAndroid Build Coastguard Worker goto out_error;
345*2d543d20SAndroid Build Coastguard Worker
346*2d543d20SAndroid Build Coastguard Worker digest_gen_hash(rec->digest);
347*2d543d20SAndroid Build Coastguard Worker
348*2d543d20SAndroid Build Coastguard Worker free(line_buf);
349*2d543d20SAndroid Build Coastguard Worker fclose(filp);
350*2d543d20SAndroid Build Coastguard Worker
351*2d543d20SAndroid Build Coastguard Worker return catalog;
352*2d543d20SAndroid Build Coastguard Worker
353*2d543d20SAndroid Build Coastguard Worker out_error:
354*2d543d20SAndroid Build Coastguard Worker free(line_buf);
355*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < catalog->nspec; i++) {
356*2d543d20SAndroid Build Coastguard Worker spec_t *spec = &catalog->specs[i];
357*2d543d20SAndroid Build Coastguard Worker
358*2d543d20SAndroid Build Coastguard Worker free(spec->key);
359*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_raw);
360*2d543d20SAndroid Build Coastguard Worker free(spec->lr.ctx_trans);
361*2d543d20SAndroid Build Coastguard Worker }
362*2d543d20SAndroid Build Coastguard Worker free(catalog);
363*2d543d20SAndroid Build Coastguard Worker fclose(filp);
364*2d543d20SAndroid Build Coastguard Worker
365*2d543d20SAndroid Build Coastguard Worker return NULL;
366*2d543d20SAndroid Build Coastguard Worker }
367*2d543d20SAndroid Build Coastguard Worker
368*2d543d20SAndroid Build Coastguard Worker /*
369*2d543d20SAndroid Build Coastguard Worker * Initialize selabel_handle and load the entries of specfile
370*2d543d20SAndroid Build Coastguard Worker */
selabel_db_init(struct selabel_handle * rec,const struct selinux_opt * opts,unsigned nopts)371*2d543d20SAndroid Build Coastguard Worker int selabel_db_init(struct selabel_handle *rec,
372*2d543d20SAndroid Build Coastguard Worker const struct selinux_opt *opts, unsigned nopts)
373*2d543d20SAndroid Build Coastguard Worker {
374*2d543d20SAndroid Build Coastguard Worker rec->func_close = &db_close;
375*2d543d20SAndroid Build Coastguard Worker rec->func_lookup = &db_lookup;
376*2d543d20SAndroid Build Coastguard Worker rec->func_stats = &db_stats;
377*2d543d20SAndroid Build Coastguard Worker rec->data = db_init(opts, nopts, rec);
378*2d543d20SAndroid Build Coastguard Worker
379*2d543d20SAndroid Build Coastguard Worker return !rec->data ? -1 : 0;
380*2d543d20SAndroid Build Coastguard Worker }
381