1*2d543d20SAndroid Build Coastguard Worker /* Authors: Karl MacMillan <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker * Joshua Brindle <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker * Jason Tang <[email protected]>
4*2d543d20SAndroid Build Coastguard Worker * Christopher Ashworth <[email protected]>
5*2d543d20SAndroid Build Coastguard Worker * Chris PeBenito <[email protected]>
6*2d543d20SAndroid Build Coastguard Worker * Caleb Case <[email protected]>
7*2d543d20SAndroid Build Coastguard Worker *
8*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2004-2006,2009 Tresys Technology, LLC
9*2d543d20SAndroid Build Coastguard Worker * Copyright (C) 2005 Red Hat, Inc.
10*2d543d20SAndroid Build Coastguard Worker *
11*2d543d20SAndroid Build Coastguard Worker * This library is free software; you can redistribute it and/or
12*2d543d20SAndroid Build Coastguard Worker * modify it under the terms of the GNU Lesser General Public
13*2d543d20SAndroid Build Coastguard Worker * License as published by the Free Software Foundation; either
14*2d543d20SAndroid Build Coastguard Worker * version 2.1 of the License, or (at your option) any later version.
15*2d543d20SAndroid Build Coastguard Worker *
16*2d543d20SAndroid Build Coastguard Worker * This library is distributed in the hope that it will be useful,
17*2d543d20SAndroid Build Coastguard Worker * but WITHOUT ANY WARRANTY; without even the implied warranty of
18*2d543d20SAndroid Build Coastguard Worker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19*2d543d20SAndroid Build Coastguard Worker * Lesser General Public License for more details.
20*2d543d20SAndroid Build Coastguard Worker *
21*2d543d20SAndroid Build Coastguard Worker * You should have received a copy of the GNU Lesser General Public
22*2d543d20SAndroid Build Coastguard Worker * License along with this library; if not, write to the Free Software
23*2d543d20SAndroid Build Coastguard Worker * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*2d543d20SAndroid Build Coastguard Worker */
25*2d543d20SAndroid Build Coastguard Worker
26*2d543d20SAndroid Build Coastguard Worker /* This file contains semanage routines that manipulate the files on a
27*2d543d20SAndroid Build Coastguard Worker * local module store. Sandbox routines, used by both source and
28*2d543d20SAndroid Build Coastguard Worker * direct connections, are here as well.
29*2d543d20SAndroid Build Coastguard Worker */
30*2d543d20SAndroid Build Coastguard Worker
31*2d543d20SAndroid Build Coastguard Worker struct dbase_policydb;
32*2d543d20SAndroid Build Coastguard Worker typedef struct dbase_policydb dbase_t;
33*2d543d20SAndroid Build Coastguard Worker #define DBASE_DEFINED
34*2d543d20SAndroid Build Coastguard Worker
35*2d543d20SAndroid Build Coastguard Worker #include "semanage_store.h"
36*2d543d20SAndroid Build Coastguard Worker #include "database_policydb.h"
37*2d543d20SAndroid Build Coastguard Worker #include "handle.h"
38*2d543d20SAndroid Build Coastguard Worker
39*2d543d20SAndroid Build Coastguard Worker #include <selinux/restorecon.h>
40*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
41*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb.h>
42*2d543d20SAndroid Build Coastguard Worker #include <sepol/module.h>
43*2d543d20SAndroid Build Coastguard Worker
44*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
45*2d543d20SAndroid Build Coastguard Worker #include <ctype.h>
46*2d543d20SAndroid Build Coastguard Worker #include <dirent.h>
47*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
48*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
49*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
50*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
51*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
52*2d543d20SAndroid Build Coastguard Worker #include <string.h>
53*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
54*2d543d20SAndroid Build Coastguard Worker #include <sys/file.h>
55*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
56*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
57*2d543d20SAndroid Build Coastguard Worker #include <sys/wait.h>
58*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
59*2d543d20SAndroid Build Coastguard Worker #include <libgen.h>
60*2d543d20SAndroid Build Coastguard Worker
61*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
62*2d543d20SAndroid Build Coastguard Worker #include "utilities.h"
63*2d543d20SAndroid Build Coastguard Worker #include "compressed_file.h"
64*2d543d20SAndroid Build Coastguard Worker
65*2d543d20SAndroid Build Coastguard Worker #define SEMANAGE_CONF_FILE "semanage.conf"
66*2d543d20SAndroid Build Coastguard Worker /* relative path names to enum semanage_paths to special files and
67*2d543d20SAndroid Build Coastguard Worker * directories for the module store */
68*2d543d20SAndroid Build Coastguard Worker
69*2d543d20SAndroid Build Coastguard Worker #define TRUE 1
70*2d543d20SAndroid Build Coastguard Worker
71*2d543d20SAndroid Build Coastguard Worker enum semanage_file_defs {
72*2d543d20SAndroid Build Coastguard Worker SEMANAGE_ROOT,
73*2d543d20SAndroid Build Coastguard Worker SEMANAGE_TRANS_LOCK,
74*2d543d20SAndroid Build Coastguard Worker SEMANAGE_READ_LOCK,
75*2d543d20SAndroid Build Coastguard Worker SEMANAGE_NUM_FILES
76*2d543d20SAndroid Build Coastguard Worker };
77*2d543d20SAndroid Build Coastguard Worker
78*2d543d20SAndroid Build Coastguard Worker static char *semanage_paths[SEMANAGE_NUM_STORES][SEMANAGE_STORE_NUM_PATHS];
79*2d543d20SAndroid Build Coastguard Worker static char *semanage_files[SEMANAGE_NUM_FILES] = { NULL };
80*2d543d20SAndroid Build Coastguard Worker static int semanage_paths_initialized = 0;
81*2d543d20SAndroid Build Coastguard Worker
82*2d543d20SAndroid Build Coastguard Worker /* These are paths relative to the bottom of the module store */
83*2d543d20SAndroid Build Coastguard Worker static const char *semanage_relative_files[SEMANAGE_NUM_FILES] = {
84*2d543d20SAndroid Build Coastguard Worker "",
85*2d543d20SAndroid Build Coastguard Worker "/semanage.trans.LOCK",
86*2d543d20SAndroid Build Coastguard Worker "/semanage.read.LOCK"
87*2d543d20SAndroid Build Coastguard Worker };
88*2d543d20SAndroid Build Coastguard Worker
89*2d543d20SAndroid Build Coastguard Worker static const char *semanage_store_paths[SEMANAGE_NUM_STORES] = {
90*2d543d20SAndroid Build Coastguard Worker "/active",
91*2d543d20SAndroid Build Coastguard Worker "/previous",
92*2d543d20SAndroid Build Coastguard Worker "/tmp"
93*2d543d20SAndroid Build Coastguard Worker };
94*2d543d20SAndroid Build Coastguard Worker
95*2d543d20SAndroid Build Coastguard Worker /* relative path names to enum sandbox_paths for special files within
96*2d543d20SAndroid Build Coastguard Worker * a sandbox */
97*2d543d20SAndroid Build Coastguard Worker static const char *semanage_sandbox_paths[SEMANAGE_STORE_NUM_PATHS] = {
98*2d543d20SAndroid Build Coastguard Worker "",
99*2d543d20SAndroid Build Coastguard Worker "/modules",
100*2d543d20SAndroid Build Coastguard Worker "/policy.linked",
101*2d543d20SAndroid Build Coastguard Worker "/homedir_template",
102*2d543d20SAndroid Build Coastguard Worker "/file_contexts.template",
103*2d543d20SAndroid Build Coastguard Worker "/commit_num",
104*2d543d20SAndroid Build Coastguard Worker "/pkeys.local",
105*2d543d20SAndroid Build Coastguard Worker "/ibendports.local",
106*2d543d20SAndroid Build Coastguard Worker "/ports.local",
107*2d543d20SAndroid Build Coastguard Worker "/interfaces.local",
108*2d543d20SAndroid Build Coastguard Worker "/nodes.local",
109*2d543d20SAndroid Build Coastguard Worker "/booleans.local",
110*2d543d20SAndroid Build Coastguard Worker "/seusers.local",
111*2d543d20SAndroid Build Coastguard Worker "/seusers.linked",
112*2d543d20SAndroid Build Coastguard Worker "/users.local",
113*2d543d20SAndroid Build Coastguard Worker "/users_extra.local",
114*2d543d20SAndroid Build Coastguard Worker "/users_extra.linked",
115*2d543d20SAndroid Build Coastguard Worker "/users_extra",
116*2d543d20SAndroid Build Coastguard Worker "/disable_dontaudit",
117*2d543d20SAndroid Build Coastguard Worker "/preserve_tunables",
118*2d543d20SAndroid Build Coastguard Worker "/modules/disabled",
119*2d543d20SAndroid Build Coastguard Worker "/modules_checksum",
120*2d543d20SAndroid Build Coastguard Worker "/policy.kern",
121*2d543d20SAndroid Build Coastguard Worker "/file_contexts.local",
122*2d543d20SAndroid Build Coastguard Worker "/file_contexts.homedirs",
123*2d543d20SAndroid Build Coastguard Worker "/file_contexts",
124*2d543d20SAndroid Build Coastguard Worker "/seusers"
125*2d543d20SAndroid Build Coastguard Worker };
126*2d543d20SAndroid Build Coastguard Worker
127*2d543d20SAndroid Build Coastguard Worker static char const * const semanage_final_prefix[SEMANAGE_FINAL_NUM] = {
128*2d543d20SAndroid Build Coastguard Worker "/final",
129*2d543d20SAndroid Build Coastguard Worker "",
130*2d543d20SAndroid Build Coastguard Worker };
131*2d543d20SAndroid Build Coastguard Worker
132*2d543d20SAndroid Build Coastguard Worker static char *semanage_final[SEMANAGE_FINAL_NUM] = { NULL };
133*2d543d20SAndroid Build Coastguard Worker static char *semanage_final_suffix[SEMANAGE_FINAL_PATH_NUM] = { NULL };
134*2d543d20SAndroid Build Coastguard Worker static char *semanage_final_paths[SEMANAGE_FINAL_NUM][SEMANAGE_FINAL_PATH_NUM] = {{ NULL }};
135*2d543d20SAndroid Build Coastguard Worker
136*2d543d20SAndroid Build Coastguard Worker /* A node used in a linked list of file contexts; used for sorting.
137*2d543d20SAndroid Build Coastguard Worker */
138*2d543d20SAndroid Build Coastguard Worker typedef struct semanage_file_context_node {
139*2d543d20SAndroid Build Coastguard Worker char *path;
140*2d543d20SAndroid Build Coastguard Worker char *file_type;
141*2d543d20SAndroid Build Coastguard Worker char *context;
142*2d543d20SAndroid Build Coastguard Worker int path_len;
143*2d543d20SAndroid Build Coastguard Worker int effective_len;
144*2d543d20SAndroid Build Coastguard Worker int type_len;
145*2d543d20SAndroid Build Coastguard Worker int context_len;
146*2d543d20SAndroid Build Coastguard Worker int meta; /* position of first meta char in path, -1 if none */
147*2d543d20SAndroid Build Coastguard Worker struct semanage_file_context_node *next;
148*2d543d20SAndroid Build Coastguard Worker } semanage_file_context_node_t;
149*2d543d20SAndroid Build Coastguard Worker
150*2d543d20SAndroid Build Coastguard Worker /* A node used in a linked list of buckets that contain
151*2d543d20SAndroid Build Coastguard Worker * semanage_file_context_node lists. Used for sorting.
152*2d543d20SAndroid Build Coastguard Worker */
153*2d543d20SAndroid Build Coastguard Worker typedef struct semanage_file_context_bucket {
154*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *data;
155*2d543d20SAndroid Build Coastguard Worker struct semanage_file_context_bucket *next;
156*2d543d20SAndroid Build Coastguard Worker } semanage_file_context_bucket_t;
157*2d543d20SAndroid Build Coastguard Worker
158*2d543d20SAndroid Build Coastguard Worker /* A node used in a linked list of netfilter rules.
159*2d543d20SAndroid Build Coastguard Worker */
160*2d543d20SAndroid Build Coastguard Worker typedef struct semanage_netfilter_context_node {
161*2d543d20SAndroid Build Coastguard Worker char *rule;
162*2d543d20SAndroid Build Coastguard Worker size_t rule_len;
163*2d543d20SAndroid Build Coastguard Worker struct semanage_netfilter_context_node *next;
164*2d543d20SAndroid Build Coastguard Worker } semanage_netfilter_context_node_t;
165*2d543d20SAndroid Build Coastguard Worker
166*2d543d20SAndroid Build Coastguard Worker /* Initialize the paths to config file, lock files and store root.
167*2d543d20SAndroid Build Coastguard Worker */
semanage_init_paths(const char * root)168*2d543d20SAndroid Build Coastguard Worker static int semanage_init_paths(const char *root)
169*2d543d20SAndroid Build Coastguard Worker {
170*2d543d20SAndroid Build Coastguard Worker size_t len, prefix_len;
171*2d543d20SAndroid Build Coastguard Worker int i;
172*2d543d20SAndroid Build Coastguard Worker
173*2d543d20SAndroid Build Coastguard Worker if (!root)
174*2d543d20SAndroid Build Coastguard Worker return -1;
175*2d543d20SAndroid Build Coastguard Worker
176*2d543d20SAndroid Build Coastguard Worker prefix_len = strlen(root);
177*2d543d20SAndroid Build Coastguard Worker
178*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_NUM_FILES; i++) {
179*2d543d20SAndroid Build Coastguard Worker len = (strlen(semanage_relative_files[i]) + prefix_len);
180*2d543d20SAndroid Build Coastguard Worker semanage_files[i] = calloc(len + 1, sizeof(char));
181*2d543d20SAndroid Build Coastguard Worker if (!semanage_files[i])
182*2d543d20SAndroid Build Coastguard Worker return -1;
183*2d543d20SAndroid Build Coastguard Worker sprintf(semanage_files[i], "%s%s", root,
184*2d543d20SAndroid Build Coastguard Worker semanage_relative_files[i]);
185*2d543d20SAndroid Build Coastguard Worker }
186*2d543d20SAndroid Build Coastguard Worker
187*2d543d20SAndroid Build Coastguard Worker return 0;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker
190*2d543d20SAndroid Build Coastguard Worker /* This initializes the paths inside the stores, this is only necessary
191*2d543d20SAndroid Build Coastguard Worker * when directly accessing the store
192*2d543d20SAndroid Build Coastguard Worker */
semanage_init_store_paths(const char * root)193*2d543d20SAndroid Build Coastguard Worker static int semanage_init_store_paths(const char *root)
194*2d543d20SAndroid Build Coastguard Worker {
195*2d543d20SAndroid Build Coastguard Worker int i, j;
196*2d543d20SAndroid Build Coastguard Worker size_t len;
197*2d543d20SAndroid Build Coastguard Worker size_t prefix_len;
198*2d543d20SAndroid Build Coastguard Worker
199*2d543d20SAndroid Build Coastguard Worker if (!root)
200*2d543d20SAndroid Build Coastguard Worker return -1;
201*2d543d20SAndroid Build Coastguard Worker
202*2d543d20SAndroid Build Coastguard Worker prefix_len = strlen(root);
203*2d543d20SAndroid Build Coastguard Worker
204*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_NUM_STORES; i++) {
205*2d543d20SAndroid Build Coastguard Worker for (j = 0; j < SEMANAGE_STORE_NUM_PATHS; j++) {
206*2d543d20SAndroid Build Coastguard Worker len = prefix_len + strlen(semanage_store_paths[i])
207*2d543d20SAndroid Build Coastguard Worker + strlen(semanage_sandbox_paths[j]);
208*2d543d20SAndroid Build Coastguard Worker semanage_paths[i][j] = calloc(len + 1, sizeof(char));
209*2d543d20SAndroid Build Coastguard Worker if (!semanage_paths[i][j])
210*2d543d20SAndroid Build Coastguard Worker goto cleanup;
211*2d543d20SAndroid Build Coastguard Worker sprintf(semanage_paths[i][j], "%s%s%s", root,
212*2d543d20SAndroid Build Coastguard Worker semanage_store_paths[i],
213*2d543d20SAndroid Build Coastguard Worker semanage_sandbox_paths[j]);
214*2d543d20SAndroid Build Coastguard Worker }
215*2d543d20SAndroid Build Coastguard Worker }
216*2d543d20SAndroid Build Coastguard Worker
217*2d543d20SAndroid Build Coastguard Worker cleanup:
218*2d543d20SAndroid Build Coastguard Worker return 0;
219*2d543d20SAndroid Build Coastguard Worker }
220*2d543d20SAndroid Build Coastguard Worker
semanage_init_final(semanage_handle_t * sh,const char * prefix)221*2d543d20SAndroid Build Coastguard Worker static int semanage_init_final(semanage_handle_t *sh, const char *prefix)
222*2d543d20SAndroid Build Coastguard Worker {
223*2d543d20SAndroid Build Coastguard Worker assert(sh);
224*2d543d20SAndroid Build Coastguard Worker assert(prefix);
225*2d543d20SAndroid Build Coastguard Worker
226*2d543d20SAndroid Build Coastguard Worker int status = 0;
227*2d543d20SAndroid Build Coastguard Worker size_t len;
228*2d543d20SAndroid Build Coastguard Worker const char *store_path = sh->conf->store_path;
229*2d543d20SAndroid Build Coastguard Worker size_t store_len = strlen(store_path);
230*2d543d20SAndroid Build Coastguard Worker
231*2d543d20SAndroid Build Coastguard Worker /* SEMANAGE_FINAL_TMP */
232*2d543d20SAndroid Build Coastguard Worker len = strlen(semanage_root()) +
233*2d543d20SAndroid Build Coastguard Worker strlen(prefix) +
234*2d543d20SAndroid Build Coastguard Worker strlen("/") +
235*2d543d20SAndroid Build Coastguard Worker strlen(semanage_final_prefix[SEMANAGE_FINAL_TMP]) +
236*2d543d20SAndroid Build Coastguard Worker store_len;
237*2d543d20SAndroid Build Coastguard Worker semanage_final[SEMANAGE_FINAL_TMP] = malloc(len + 1);
238*2d543d20SAndroid Build Coastguard Worker if (semanage_final[SEMANAGE_FINAL_TMP] == NULL) {
239*2d543d20SAndroid Build Coastguard Worker status = -1;
240*2d543d20SAndroid Build Coastguard Worker goto cleanup;
241*2d543d20SAndroid Build Coastguard Worker }
242*2d543d20SAndroid Build Coastguard Worker
243*2d543d20SAndroid Build Coastguard Worker sprintf(semanage_final[SEMANAGE_FINAL_TMP],
244*2d543d20SAndroid Build Coastguard Worker "%s%s%s/%s",
245*2d543d20SAndroid Build Coastguard Worker semanage_root(),
246*2d543d20SAndroid Build Coastguard Worker prefix,
247*2d543d20SAndroid Build Coastguard Worker semanage_final_prefix[SEMANAGE_FINAL_TMP],
248*2d543d20SAndroid Build Coastguard Worker store_path);
249*2d543d20SAndroid Build Coastguard Worker
250*2d543d20SAndroid Build Coastguard Worker /* SEMANAGE_FINAL_SELINUX */
251*2d543d20SAndroid Build Coastguard Worker const char *selinux_root = selinux_path();
252*2d543d20SAndroid Build Coastguard Worker len = strlen(semanage_root()) +
253*2d543d20SAndroid Build Coastguard Worker strlen(selinux_root) +
254*2d543d20SAndroid Build Coastguard Worker strlen(semanage_final_prefix[SEMANAGE_FINAL_SELINUX]) +
255*2d543d20SAndroid Build Coastguard Worker store_len;
256*2d543d20SAndroid Build Coastguard Worker semanage_final[SEMANAGE_FINAL_SELINUX] = malloc(len + 1);
257*2d543d20SAndroid Build Coastguard Worker if (semanage_final[SEMANAGE_FINAL_SELINUX] == NULL) {
258*2d543d20SAndroid Build Coastguard Worker status = -1;
259*2d543d20SAndroid Build Coastguard Worker goto cleanup;
260*2d543d20SAndroid Build Coastguard Worker }
261*2d543d20SAndroid Build Coastguard Worker
262*2d543d20SAndroid Build Coastguard Worker sprintf(semanage_final[SEMANAGE_FINAL_SELINUX],
263*2d543d20SAndroid Build Coastguard Worker "%s%s%s%s",
264*2d543d20SAndroid Build Coastguard Worker semanage_root(),
265*2d543d20SAndroid Build Coastguard Worker selinux_root,
266*2d543d20SAndroid Build Coastguard Worker semanage_final_prefix[SEMANAGE_FINAL_SELINUX],
267*2d543d20SAndroid Build Coastguard Worker store_path);
268*2d543d20SAndroid Build Coastguard Worker
269*2d543d20SAndroid Build Coastguard Worker cleanup:
270*2d543d20SAndroid Build Coastguard Worker if (status != 0) {
271*2d543d20SAndroid Build Coastguard Worker int i;
272*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
273*2d543d20SAndroid Build Coastguard Worker free(semanage_final[i]);
274*2d543d20SAndroid Build Coastguard Worker semanage_final[i] = NULL;
275*2d543d20SAndroid Build Coastguard Worker }
276*2d543d20SAndroid Build Coastguard Worker }
277*2d543d20SAndroid Build Coastguard Worker
278*2d543d20SAndroid Build Coastguard Worker return status;
279*2d543d20SAndroid Build Coastguard Worker }
280*2d543d20SAndroid Build Coastguard Worker
semanage_init_final_suffix(semanage_handle_t * sh)281*2d543d20SAndroid Build Coastguard Worker static int semanage_init_final_suffix(semanage_handle_t *sh)
282*2d543d20SAndroid Build Coastguard Worker {
283*2d543d20SAndroid Build Coastguard Worker int ret = 0;
284*2d543d20SAndroid Build Coastguard Worker int status = 0;
285*2d543d20SAndroid Build Coastguard Worker char path[PATH_MAX];
286*2d543d20SAndroid Build Coastguard Worker size_t offset = strlen(selinux_policy_root());
287*2d543d20SAndroid Build Coastguard Worker
288*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] = strdup("");
289*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_FINAL_TOPLEVEL] == NULL) {
290*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for policy top level path.");
291*2d543d20SAndroid Build Coastguard Worker status = -1;
292*2d543d20SAndroid Build Coastguard Worker goto cleanup;
293*2d543d20SAndroid Build Coastguard Worker }
294*2d543d20SAndroid Build Coastguard Worker
295*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC] =
296*2d543d20SAndroid Build Coastguard Worker strdup(selinux_file_context_path() + offset);
297*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_FC] == NULL) {
298*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for file context path.");
299*2d543d20SAndroid Build Coastguard Worker status = -1;
300*2d543d20SAndroid Build Coastguard Worker goto cleanup;
301*2d543d20SAndroid Build Coastguard Worker }
302*2d543d20SAndroid Build Coastguard Worker
303*2d543d20SAndroid Build Coastguard Worker if (asprintf(&semanage_final_suffix[SEMANAGE_FC_BIN], "%s.bin",
304*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC]) < 0) {
305*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for file context path.");
306*2d543d20SAndroid Build Coastguard Worker status = -1;
307*2d543d20SAndroid Build Coastguard Worker goto cleanup;
308*2d543d20SAndroid Build Coastguard Worker }
309*2d543d20SAndroid Build Coastguard Worker
310*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] =
311*2d543d20SAndroid Build Coastguard Worker strdup(selinux_file_context_homedir_path() + offset);
312*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_FC_HOMEDIRS] == NULL) {
313*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for file context home directory path.");
314*2d543d20SAndroid Build Coastguard Worker status = -1;
315*2d543d20SAndroid Build Coastguard Worker goto cleanup;
316*2d543d20SAndroid Build Coastguard Worker }
317*2d543d20SAndroid Build Coastguard Worker
318*2d543d20SAndroid Build Coastguard Worker if (asprintf(&semanage_final_suffix[SEMANAGE_FC_HOMEDIRS_BIN], "%s.bin",
319*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC_HOMEDIRS]) < 0) {
320*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for file context home directory path.");
321*2d543d20SAndroid Build Coastguard Worker status = -1;
322*2d543d20SAndroid Build Coastguard Worker goto cleanup;
323*2d543d20SAndroid Build Coastguard Worker }
324*2d543d20SAndroid Build Coastguard Worker
325*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC_LOCAL] =
326*2d543d20SAndroid Build Coastguard Worker strdup(selinux_file_context_local_path() + offset);
327*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_FC_LOCAL] == NULL) {
328*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for local file context path.");
329*2d543d20SAndroid Build Coastguard Worker status = -1;
330*2d543d20SAndroid Build Coastguard Worker goto cleanup;
331*2d543d20SAndroid Build Coastguard Worker }
332*2d543d20SAndroid Build Coastguard Worker
333*2d543d20SAndroid Build Coastguard Worker if (asprintf(&semanage_final_suffix[SEMANAGE_FC_LOCAL_BIN], "%s.bin",
334*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_FC_LOCAL]) < 0) {
335*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for local file context path.");
336*2d543d20SAndroid Build Coastguard Worker status = -1;
337*2d543d20SAndroid Build Coastguard Worker goto cleanup;
338*2d543d20SAndroid Build Coastguard Worker }
339*2d543d20SAndroid Build Coastguard Worker
340*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_NC] =
341*2d543d20SAndroid Build Coastguard Worker strdup(selinux_netfilter_context_path() + offset);
342*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_NC] == NULL) {
343*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for netfilter context path.");
344*2d543d20SAndroid Build Coastguard Worker status = -1;
345*2d543d20SAndroid Build Coastguard Worker goto cleanup;
346*2d543d20SAndroid Build Coastguard Worker }
347*2d543d20SAndroid Build Coastguard Worker
348*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_SEUSERS] =
349*2d543d20SAndroid Build Coastguard Worker strdup(selinux_usersconf_path() + offset);
350*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_SEUSERS] == NULL) {
351*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for userconf path.");
352*2d543d20SAndroid Build Coastguard Worker status = -1;
353*2d543d20SAndroid Build Coastguard Worker goto cleanup;
354*2d543d20SAndroid Build Coastguard Worker }
355*2d543d20SAndroid Build Coastguard Worker
356*2d543d20SAndroid Build Coastguard Worker ret = snprintf(path,
357*2d543d20SAndroid Build Coastguard Worker sizeof(path),
358*2d543d20SAndroid Build Coastguard Worker "%s.%d",
359*2d543d20SAndroid Build Coastguard Worker selinux_binary_policy_path() + offset,
360*2d543d20SAndroid Build Coastguard Worker sh->conf->policyvers);
361*2d543d20SAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(path)) {
362*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to compose policy binary path.");
363*2d543d20SAndroid Build Coastguard Worker status = -1;
364*2d543d20SAndroid Build Coastguard Worker goto cleanup;
365*2d543d20SAndroid Build Coastguard Worker }
366*2d543d20SAndroid Build Coastguard Worker
367*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[SEMANAGE_KERNEL] = strdup(path);
368*2d543d20SAndroid Build Coastguard Worker if (semanage_final_suffix[SEMANAGE_KERNEL] == NULL) {
369*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for policy binary path.");
370*2d543d20SAndroid Build Coastguard Worker status = -1;
371*2d543d20SAndroid Build Coastguard Worker goto cleanup;
372*2d543d20SAndroid Build Coastguard Worker }
373*2d543d20SAndroid Build Coastguard Worker
374*2d543d20SAndroid Build Coastguard Worker cleanup:
375*2d543d20SAndroid Build Coastguard Worker if (status != 0) {
376*2d543d20SAndroid Build Coastguard Worker int i;
377*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_FINAL_PATH_NUM; i++) {
378*2d543d20SAndroid Build Coastguard Worker free(semanage_final_suffix[i]);
379*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[i] = NULL;
380*2d543d20SAndroid Build Coastguard Worker }
381*2d543d20SAndroid Build Coastguard Worker }
382*2d543d20SAndroid Build Coastguard Worker
383*2d543d20SAndroid Build Coastguard Worker return status;
384*2d543d20SAndroid Build Coastguard Worker }
385*2d543d20SAndroid Build Coastguard Worker
386*2d543d20SAndroid Build Coastguard Worker /* Initialize final paths. */
semanage_init_final_paths(semanage_handle_t * sh)387*2d543d20SAndroid Build Coastguard Worker static int semanage_init_final_paths(semanage_handle_t *sh)
388*2d543d20SAndroid Build Coastguard Worker {
389*2d543d20SAndroid Build Coastguard Worker int status = 0;
390*2d543d20SAndroid Build Coastguard Worker int i, j;
391*2d543d20SAndroid Build Coastguard Worker size_t len;
392*2d543d20SAndroid Build Coastguard Worker
393*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
394*2d543d20SAndroid Build Coastguard Worker for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
395*2d543d20SAndroid Build Coastguard Worker len = strlen(semanage_final[i])
396*2d543d20SAndroid Build Coastguard Worker + strlen(semanage_final_suffix[j]);
397*2d543d20SAndroid Build Coastguard Worker
398*2d543d20SAndroid Build Coastguard Worker semanage_final_paths[i][j] = malloc(len + 1);
399*2d543d20SAndroid Build Coastguard Worker if (semanage_final_paths[i][j] == NULL) {
400*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to allocate space for policy final path.");
401*2d543d20SAndroid Build Coastguard Worker status = -1;
402*2d543d20SAndroid Build Coastguard Worker goto cleanup;
403*2d543d20SAndroid Build Coastguard Worker }
404*2d543d20SAndroid Build Coastguard Worker
405*2d543d20SAndroid Build Coastguard Worker sprintf(semanage_final_paths[i][j],
406*2d543d20SAndroid Build Coastguard Worker "%s%s",
407*2d543d20SAndroid Build Coastguard Worker semanage_final[i],
408*2d543d20SAndroid Build Coastguard Worker semanage_final_suffix[j]);
409*2d543d20SAndroid Build Coastguard Worker }
410*2d543d20SAndroid Build Coastguard Worker }
411*2d543d20SAndroid Build Coastguard Worker
412*2d543d20SAndroid Build Coastguard Worker cleanup:
413*2d543d20SAndroid Build Coastguard Worker if (status != 0) {
414*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < SEMANAGE_FINAL_NUM; i++) {
415*2d543d20SAndroid Build Coastguard Worker for (j = 0; j < SEMANAGE_FINAL_PATH_NUM; j++) {
416*2d543d20SAndroid Build Coastguard Worker free(semanage_final_paths[i][j]);
417*2d543d20SAndroid Build Coastguard Worker semanage_final_paths[i][j] = NULL;
418*2d543d20SAndroid Build Coastguard Worker }
419*2d543d20SAndroid Build Coastguard Worker }
420*2d543d20SAndroid Build Coastguard Worker }
421*2d543d20SAndroid Build Coastguard Worker
422*2d543d20SAndroid Build Coastguard Worker return status;
423*2d543d20SAndroid Build Coastguard Worker }
424*2d543d20SAndroid Build Coastguard Worker
425*2d543d20SAndroid Build Coastguard Worker /* THIS MUST BE THE FIRST FUNCTION CALLED IN THIS LIBRARY. If the
426*2d543d20SAndroid Build Coastguard Worker * library has nnot been initialized yet then call the functions that
427*2d543d20SAndroid Build Coastguard Worker * initialize the path variables. This function does nothing if it
428*2d543d20SAndroid Build Coastguard Worker * was previously called and that call was successful. Return 0 on
429*2d543d20SAndroid Build Coastguard Worker * success, -1 on error.
430*2d543d20SAndroid Build Coastguard Worker *
431*2d543d20SAndroid Build Coastguard Worker * Note that this function is NOT thread-safe.
432*2d543d20SAndroid Build Coastguard Worker */
semanage_check_init(semanage_handle_t * sh,const char * prefix)433*2d543d20SAndroid Build Coastguard Worker int semanage_check_init(semanage_handle_t *sh, const char *prefix)
434*2d543d20SAndroid Build Coastguard Worker {
435*2d543d20SAndroid Build Coastguard Worker int rc;
436*2d543d20SAndroid Build Coastguard Worker if (semanage_paths_initialized == 0) {
437*2d543d20SAndroid Build Coastguard Worker char root[PATH_MAX];
438*2d543d20SAndroid Build Coastguard Worker
439*2d543d20SAndroid Build Coastguard Worker rc = snprintf(root,
440*2d543d20SAndroid Build Coastguard Worker sizeof(root),
441*2d543d20SAndroid Build Coastguard Worker "%s%s/%s",
442*2d543d20SAndroid Build Coastguard Worker semanage_root(),
443*2d543d20SAndroid Build Coastguard Worker prefix,
444*2d543d20SAndroid Build Coastguard Worker sh->conf->store_path);
445*2d543d20SAndroid Build Coastguard Worker if (rc < 0 || rc >= (int)sizeof(root))
446*2d543d20SAndroid Build Coastguard Worker return -1;
447*2d543d20SAndroid Build Coastguard Worker
448*2d543d20SAndroid Build Coastguard Worker rc = semanage_init_paths(root);
449*2d543d20SAndroid Build Coastguard Worker if (rc)
450*2d543d20SAndroid Build Coastguard Worker return rc;
451*2d543d20SAndroid Build Coastguard Worker
452*2d543d20SAndroid Build Coastguard Worker rc = semanage_init_store_paths(root);
453*2d543d20SAndroid Build Coastguard Worker if (rc)
454*2d543d20SAndroid Build Coastguard Worker return rc;
455*2d543d20SAndroid Build Coastguard Worker
456*2d543d20SAndroid Build Coastguard Worker rc = semanage_init_final(sh, prefix);
457*2d543d20SAndroid Build Coastguard Worker if (rc)
458*2d543d20SAndroid Build Coastguard Worker return rc;
459*2d543d20SAndroid Build Coastguard Worker
460*2d543d20SAndroid Build Coastguard Worker rc = semanage_init_final_suffix(sh);
461*2d543d20SAndroid Build Coastguard Worker if (rc)
462*2d543d20SAndroid Build Coastguard Worker return rc;
463*2d543d20SAndroid Build Coastguard Worker
464*2d543d20SAndroid Build Coastguard Worker rc = semanage_init_final_paths(sh);
465*2d543d20SAndroid Build Coastguard Worker if (rc)
466*2d543d20SAndroid Build Coastguard Worker return rc;
467*2d543d20SAndroid Build Coastguard Worker
468*2d543d20SAndroid Build Coastguard Worker semanage_paths_initialized = 1;
469*2d543d20SAndroid Build Coastguard Worker }
470*2d543d20SAndroid Build Coastguard Worker return 0;
471*2d543d20SAndroid Build Coastguard Worker }
472*2d543d20SAndroid Build Coastguard Worker
473*2d543d20SAndroid Build Coastguard Worker /* Given a definition number, return a file name from the paths array */
semanage_fname(enum semanage_sandbox_defs file_enum)474*2d543d20SAndroid Build Coastguard Worker const char *semanage_fname(enum semanage_sandbox_defs file_enum)
475*2d543d20SAndroid Build Coastguard Worker {
476*2d543d20SAndroid Build Coastguard Worker return semanage_sandbox_paths[file_enum];
477*2d543d20SAndroid Build Coastguard Worker }
478*2d543d20SAndroid Build Coastguard Worker
479*2d543d20SAndroid Build Coastguard Worker /* Given a store location (active/previous/tmp) and a definition
480*2d543d20SAndroid Build Coastguard Worker * number, return a fully-qualified path to that file or directory.
481*2d543d20SAndroid Build Coastguard Worker * The caller must not alter the string returned (and hence why this
482*2d543d20SAndroid Build Coastguard Worker * function return type is const).
483*2d543d20SAndroid Build Coastguard Worker *
484*2d543d20SAndroid Build Coastguard Worker * This function shall never return a NULL, assuming that
485*2d543d20SAndroid Build Coastguard Worker * semanage_check_init() was previously called.
486*2d543d20SAndroid Build Coastguard Worker */
semanage_path(enum semanage_store_defs store,enum semanage_sandbox_defs path_name)487*2d543d20SAndroid Build Coastguard Worker const char *semanage_path(enum semanage_store_defs store,
488*2d543d20SAndroid Build Coastguard Worker enum semanage_sandbox_defs path_name)
489*2d543d20SAndroid Build Coastguard Worker {
490*2d543d20SAndroid Build Coastguard Worker assert(semanage_paths[store][path_name]);
491*2d543d20SAndroid Build Coastguard Worker return semanage_paths[store][path_name];
492*2d543d20SAndroid Build Coastguard Worker }
493*2d543d20SAndroid Build Coastguard Worker
494*2d543d20SAndroid Build Coastguard Worker /* Given a store location (tmp or selinux) and a definition
495*2d543d20SAndroid Build Coastguard Worker * number, return a fully-qualified path to that file or directory.
496*2d543d20SAndroid Build Coastguard Worker * The caller must not alter the string returned (and hence why this
497*2d543d20SAndroid Build Coastguard Worker * function return type is const).
498*2d543d20SAndroid Build Coastguard Worker *
499*2d543d20SAndroid Build Coastguard Worker * This function shall never return a NULL, assuming that
500*2d543d20SAndroid Build Coastguard Worker * semanage_check_init() was previously called.
501*2d543d20SAndroid Build Coastguard Worker */
semanage_final_path(enum semanage_final_defs store,enum semanage_final_path_defs path_name)502*2d543d20SAndroid Build Coastguard Worker const char *semanage_final_path(enum semanage_final_defs store,
503*2d543d20SAndroid Build Coastguard Worker enum semanage_final_path_defs path_name)
504*2d543d20SAndroid Build Coastguard Worker {
505*2d543d20SAndroid Build Coastguard Worker assert(semanage_final_paths[store][path_name]);
506*2d543d20SAndroid Build Coastguard Worker return semanage_final_paths[store][path_name];
507*2d543d20SAndroid Build Coastguard Worker }
508*2d543d20SAndroid Build Coastguard Worker
509*2d543d20SAndroid Build Coastguard Worker /* Return a fully-qualified path + filename to the semanage
510*2d543d20SAndroid Build Coastguard Worker * configuration file. If semanage.conf file in the semanage
511*2d543d20SAndroid Build Coastguard Worker * root is cannot be read, use the default semanage.conf as a
512*2d543d20SAndroid Build Coastguard Worker * fallback.
513*2d543d20SAndroid Build Coastguard Worker *
514*2d543d20SAndroid Build Coastguard Worker * The caller is responsible for freeing the returned string.
515*2d543d20SAndroid Build Coastguard Worker */
semanage_conf_path(void)516*2d543d20SAndroid Build Coastguard Worker char *semanage_conf_path(void)
517*2d543d20SAndroid Build Coastguard Worker {
518*2d543d20SAndroid Build Coastguard Worker char *semanage_conf = NULL;
519*2d543d20SAndroid Build Coastguard Worker int len;
520*2d543d20SAndroid Build Coastguard Worker struct stat sb;
521*2d543d20SAndroid Build Coastguard Worker
522*2d543d20SAndroid Build Coastguard Worker len = strlen(semanage_root()) + strlen(selinux_path()) + strlen(SEMANAGE_CONF_FILE);
523*2d543d20SAndroid Build Coastguard Worker semanage_conf = calloc(len + 1, sizeof(char));
524*2d543d20SAndroid Build Coastguard Worker if (!semanage_conf)
525*2d543d20SAndroid Build Coastguard Worker return NULL;
526*2d543d20SAndroid Build Coastguard Worker snprintf(semanage_conf, len + 1, "%s%s%s", semanage_root(), selinux_path(),
527*2d543d20SAndroid Build Coastguard Worker SEMANAGE_CONF_FILE);
528*2d543d20SAndroid Build Coastguard Worker
529*2d543d20SAndroid Build Coastguard Worker if (stat(semanage_conf, &sb) != 0 && errno == ENOENT) {
530*2d543d20SAndroid Build Coastguard Worker snprintf(semanage_conf, len + 1, "%s%s", selinux_path(), SEMANAGE_CONF_FILE);
531*2d543d20SAndroid Build Coastguard Worker }
532*2d543d20SAndroid Build Coastguard Worker
533*2d543d20SAndroid Build Coastguard Worker return semanage_conf;
534*2d543d20SAndroid Build Coastguard Worker }
535*2d543d20SAndroid Build Coastguard Worker
536*2d543d20SAndroid Build Coastguard Worker /**************** functions that create module store ***************/
537*2d543d20SAndroid Build Coastguard Worker
538*2d543d20SAndroid Build Coastguard Worker /* Check that the semanage store exists. If 'create' is non-zero then
539*2d543d20SAndroid Build Coastguard Worker * create the directories. Returns 0 if module store exists (either
540*2d543d20SAndroid Build Coastguard Worker * already or just created), -1 if does not exist or could not be
541*2d543d20SAndroid Build Coastguard Worker * read, or -2 if it could not create the store. */
semanage_create_store(semanage_handle_t * sh,int create)542*2d543d20SAndroid Build Coastguard Worker int semanage_create_store(semanage_handle_t * sh, int create)
543*2d543d20SAndroid Build Coastguard Worker {
544*2d543d20SAndroid Build Coastguard Worker struct stat sb;
545*2d543d20SAndroid Build Coastguard Worker const char *path = semanage_files[SEMANAGE_ROOT];
546*2d543d20SAndroid Build Coastguard Worker int fd;
547*2d543d20SAndroid Build Coastguard Worker mode_t mask;
548*2d543d20SAndroid Build Coastguard Worker
549*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) == -1) {
550*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT && create) {
551*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
552*2d543d20SAndroid Build Coastguard Worker if (mkdir(path, S_IRWXU) == -1) {
553*2d543d20SAndroid Build Coastguard Worker umask(mask);
554*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not create module store at %s.",
555*2d543d20SAndroid Build Coastguard Worker path);
556*2d543d20SAndroid Build Coastguard Worker return -2;
557*2d543d20SAndroid Build Coastguard Worker }
558*2d543d20SAndroid Build Coastguard Worker umask(mask);
559*2d543d20SAndroid Build Coastguard Worker } else {
560*2d543d20SAndroid Build Coastguard Worker if (create)
561*2d543d20SAndroid Build Coastguard Worker ERR(sh,
562*2d543d20SAndroid Build Coastguard Worker "Could not read from module store at %s.",
563*2d543d20SAndroid Build Coastguard Worker path);
564*2d543d20SAndroid Build Coastguard Worker return -1;
565*2d543d20SAndroid Build Coastguard Worker }
566*2d543d20SAndroid Build Coastguard Worker } else {
567*2d543d20SAndroid Build Coastguard Worker if (!S_ISDIR(sb.st_mode)) {
568*2d543d20SAndroid Build Coastguard Worker ERR(sh,
569*2d543d20SAndroid Build Coastguard Worker "Module store at %s is not a directory.",
570*2d543d20SAndroid Build Coastguard Worker path);
571*2d543d20SAndroid Build Coastguard Worker return -1;
572*2d543d20SAndroid Build Coastguard Worker }
573*2d543d20SAndroid Build Coastguard Worker }
574*2d543d20SAndroid Build Coastguard Worker path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
575*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) == -1) {
576*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT && create) {
577*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
578*2d543d20SAndroid Build Coastguard Worker if (mkdir(path, S_IRWXU) == -1) {
579*2d543d20SAndroid Build Coastguard Worker umask(mask);
580*2d543d20SAndroid Build Coastguard Worker ERR(sh,
581*2d543d20SAndroid Build Coastguard Worker "Could not create module store, active subdirectory at %s.",
582*2d543d20SAndroid Build Coastguard Worker path);
583*2d543d20SAndroid Build Coastguard Worker return -2;
584*2d543d20SAndroid Build Coastguard Worker }
585*2d543d20SAndroid Build Coastguard Worker umask(mask);
586*2d543d20SAndroid Build Coastguard Worker } else {
587*2d543d20SAndroid Build Coastguard Worker ERR(sh,
588*2d543d20SAndroid Build Coastguard Worker "Could not read from module store, active subdirectory at %s.",
589*2d543d20SAndroid Build Coastguard Worker path);
590*2d543d20SAndroid Build Coastguard Worker return -1;
591*2d543d20SAndroid Build Coastguard Worker }
592*2d543d20SAndroid Build Coastguard Worker } else {
593*2d543d20SAndroid Build Coastguard Worker if (!S_ISDIR(sb.st_mode)) {
594*2d543d20SAndroid Build Coastguard Worker ERR(sh,
595*2d543d20SAndroid Build Coastguard Worker "Module store active subdirectory at %s is not a directory.",
596*2d543d20SAndroid Build Coastguard Worker path);
597*2d543d20SAndroid Build Coastguard Worker return -1;
598*2d543d20SAndroid Build Coastguard Worker }
599*2d543d20SAndroid Build Coastguard Worker }
600*2d543d20SAndroid Build Coastguard Worker path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
601*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) == -1) {
602*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT && create) {
603*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
604*2d543d20SAndroid Build Coastguard Worker if (mkdir(path, S_IRWXU) == -1) {
605*2d543d20SAndroid Build Coastguard Worker umask(mask);
606*2d543d20SAndroid Build Coastguard Worker ERR(sh,
607*2d543d20SAndroid Build Coastguard Worker "Could not create module store, active modules subdirectory at %s.",
608*2d543d20SAndroid Build Coastguard Worker path);
609*2d543d20SAndroid Build Coastguard Worker return -2;
610*2d543d20SAndroid Build Coastguard Worker }
611*2d543d20SAndroid Build Coastguard Worker umask(mask);
612*2d543d20SAndroid Build Coastguard Worker } else {
613*2d543d20SAndroid Build Coastguard Worker ERR(sh,
614*2d543d20SAndroid Build Coastguard Worker "Could not read from module store, active modules subdirectory at %s.",
615*2d543d20SAndroid Build Coastguard Worker path);
616*2d543d20SAndroid Build Coastguard Worker return -1;
617*2d543d20SAndroid Build Coastguard Worker }
618*2d543d20SAndroid Build Coastguard Worker } else {
619*2d543d20SAndroid Build Coastguard Worker if (!S_ISDIR(sb.st_mode)) {
620*2d543d20SAndroid Build Coastguard Worker ERR(sh,
621*2d543d20SAndroid Build Coastguard Worker "Module store active modules subdirectory at %s is not a directory.",
622*2d543d20SAndroid Build Coastguard Worker path);
623*2d543d20SAndroid Build Coastguard Worker return -1;
624*2d543d20SAndroid Build Coastguard Worker }
625*2d543d20SAndroid Build Coastguard Worker }
626*2d543d20SAndroid Build Coastguard Worker path = semanage_files[SEMANAGE_READ_LOCK];
627*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) == -1) {
628*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT && create) {
629*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
630*2d543d20SAndroid Build Coastguard Worker if ((fd = creat(path, S_IRUSR | S_IWUSR)) == -1) {
631*2d543d20SAndroid Build Coastguard Worker umask(mask);
632*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not create lock file at %s.",
633*2d543d20SAndroid Build Coastguard Worker path);
634*2d543d20SAndroid Build Coastguard Worker return -2;
635*2d543d20SAndroid Build Coastguard Worker }
636*2d543d20SAndroid Build Coastguard Worker umask(mask);
637*2d543d20SAndroid Build Coastguard Worker close(fd);
638*2d543d20SAndroid Build Coastguard Worker } else {
639*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not read lock file at %s.", path);
640*2d543d20SAndroid Build Coastguard Worker return -1;
641*2d543d20SAndroid Build Coastguard Worker }
642*2d543d20SAndroid Build Coastguard Worker } else {
643*2d543d20SAndroid Build Coastguard Worker if (!S_ISREG(sb.st_mode)) {
644*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Object at %s is not a lock file.", path);
645*2d543d20SAndroid Build Coastguard Worker return -1;
646*2d543d20SAndroid Build Coastguard Worker }
647*2d543d20SAndroid Build Coastguard Worker }
648*2d543d20SAndroid Build Coastguard Worker return 0;
649*2d543d20SAndroid Build Coastguard Worker }
650*2d543d20SAndroid Build Coastguard Worker
651*2d543d20SAndroid Build Coastguard Worker /* returns <0 if the active store cannot be read or doesn't exist
652*2d543d20SAndroid Build Coastguard Worker * 0 if the store exists but the lock file cannot be accessed
653*2d543d20SAndroid Build Coastguard Worker * SEMANAGE_CAN_READ if the store can be read and the lock file used
654*2d543d20SAndroid Build Coastguard Worker * SEMANAGE_CAN_WRITE if the modules directory and binary policy dir can be written to
655*2d543d20SAndroid Build Coastguard Worker */
semanage_store_access_check(void)656*2d543d20SAndroid Build Coastguard Worker int semanage_store_access_check(void)
657*2d543d20SAndroid Build Coastguard Worker {
658*2d543d20SAndroid Build Coastguard Worker const char *path;
659*2d543d20SAndroid Build Coastguard Worker int rc = -1;
660*2d543d20SAndroid Build Coastguard Worker
661*2d543d20SAndroid Build Coastguard Worker /* read access on active store */
662*2d543d20SAndroid Build Coastguard Worker path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
663*2d543d20SAndroid Build Coastguard Worker if (access(path, R_OK | X_OK) != 0)
664*2d543d20SAndroid Build Coastguard Worker goto out;
665*2d543d20SAndroid Build Coastguard Worker
666*2d543d20SAndroid Build Coastguard Worker /* we can read the active store meaning it is managed
667*2d543d20SAndroid Build Coastguard Worker * so now we return 0 to indicate no error */
668*2d543d20SAndroid Build Coastguard Worker rc = 0;
669*2d543d20SAndroid Build Coastguard Worker
670*2d543d20SAndroid Build Coastguard Worker /* read access on lock file required for locking
671*2d543d20SAndroid Build Coastguard Worker * write access necessary if the lock file does not exist
672*2d543d20SAndroid Build Coastguard Worker */
673*2d543d20SAndroid Build Coastguard Worker path = semanage_files[SEMANAGE_READ_LOCK];
674*2d543d20SAndroid Build Coastguard Worker if (access(path, R_OK) != 0) {
675*2d543d20SAndroid Build Coastguard Worker if (access(path, F_OK) == 0) {
676*2d543d20SAndroid Build Coastguard Worker goto out;
677*2d543d20SAndroid Build Coastguard Worker }
678*2d543d20SAndroid Build Coastguard Worker
679*2d543d20SAndroid Build Coastguard Worker path = semanage_files[SEMANAGE_ROOT];
680*2d543d20SAndroid Build Coastguard Worker if (access(path, R_OK | W_OK | X_OK) != 0) {
681*2d543d20SAndroid Build Coastguard Worker goto out;
682*2d543d20SAndroid Build Coastguard Worker }
683*2d543d20SAndroid Build Coastguard Worker }
684*2d543d20SAndroid Build Coastguard Worker
685*2d543d20SAndroid Build Coastguard Worker /* everything needed for reading has been checked */
686*2d543d20SAndroid Build Coastguard Worker rc = SEMANAGE_CAN_READ;
687*2d543d20SAndroid Build Coastguard Worker
688*2d543d20SAndroid Build Coastguard Worker /* check the modules directory */
689*2d543d20SAndroid Build Coastguard Worker path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
690*2d543d20SAndroid Build Coastguard Worker if (access(path, R_OK | W_OK | X_OK) != 0)
691*2d543d20SAndroid Build Coastguard Worker goto out;
692*2d543d20SAndroid Build Coastguard Worker
693*2d543d20SAndroid Build Coastguard Worker rc = SEMANAGE_CAN_WRITE;
694*2d543d20SAndroid Build Coastguard Worker
695*2d543d20SAndroid Build Coastguard Worker out:
696*2d543d20SAndroid Build Coastguard Worker return rc;
697*2d543d20SAndroid Build Coastguard Worker }
698*2d543d20SAndroid Build Coastguard Worker
699*2d543d20SAndroid Build Coastguard Worker /********************* other I/O functions *********************/
700*2d543d20SAndroid Build Coastguard Worker
701*2d543d20SAndroid Build Coastguard Worker static int semanage_rename(semanage_handle_t * sh, const char *tmp, const char *dst);
702*2d543d20SAndroid Build Coastguard Worker int semanage_remove_directory(const char *path);
703*2d543d20SAndroid Build Coastguard Worker static int semanage_copy_dir_flags(const char *src, const char *dst, int flag);
704*2d543d20SAndroid Build Coastguard Worker
705*2d543d20SAndroid Build Coastguard Worker /* Callback used by scandir() to select files. */
semanage_filename_select(const struct dirent * d)706*2d543d20SAndroid Build Coastguard Worker static int semanage_filename_select(const struct dirent *d)
707*2d543d20SAndroid Build Coastguard Worker {
708*2d543d20SAndroid Build Coastguard Worker if (d->d_name[0] == '.'
709*2d543d20SAndroid Build Coastguard Worker && (d->d_name[1] == '\0'
710*2d543d20SAndroid Build Coastguard Worker || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
711*2d543d20SAndroid Build Coastguard Worker return 0;
712*2d543d20SAndroid Build Coastguard Worker return 1;
713*2d543d20SAndroid Build Coastguard Worker }
714*2d543d20SAndroid Build Coastguard Worker
715*2d543d20SAndroid Build Coastguard Worker /* Copies a file from src to dst. If dst already exists then
716*2d543d20SAndroid Build Coastguard Worker * overwrite it. Returns 0 on success, -1 on error. */
semanage_copy_file(const char * src,const char * dst,mode_t mode,bool syncrequired)717*2d543d20SAndroid Build Coastguard Worker int semanage_copy_file(const char *src, const char *dst, mode_t mode,
718*2d543d20SAndroid Build Coastguard Worker bool syncrequired)
719*2d543d20SAndroid Build Coastguard Worker {
720*2d543d20SAndroid Build Coastguard Worker int in, out, retval = 0, amount_read, n, errsv = errno;
721*2d543d20SAndroid Build Coastguard Worker char tmp[PATH_MAX];
722*2d543d20SAndroid Build Coastguard Worker char buf[4192];
723*2d543d20SAndroid Build Coastguard Worker mode_t mask;
724*2d543d20SAndroid Build Coastguard Worker
725*2d543d20SAndroid Build Coastguard Worker n = snprintf(tmp, PATH_MAX, "%s.tmp", dst);
726*2d543d20SAndroid Build Coastguard Worker if (n < 0 || n >= PATH_MAX)
727*2d543d20SAndroid Build Coastguard Worker return -1;
728*2d543d20SAndroid Build Coastguard Worker
729*2d543d20SAndroid Build Coastguard Worker if ((in = open(src, O_RDONLY)) == -1) {
730*2d543d20SAndroid Build Coastguard Worker return -1;
731*2d543d20SAndroid Build Coastguard Worker }
732*2d543d20SAndroid Build Coastguard Worker
733*2d543d20SAndroid Build Coastguard Worker if (!mode)
734*2d543d20SAndroid Build Coastguard Worker mode = S_IRUSR | S_IWUSR;
735*2d543d20SAndroid Build Coastguard Worker
736*2d543d20SAndroid Build Coastguard Worker mask = umask(0);
737*2d543d20SAndroid Build Coastguard Worker if ((out = open(tmp, O_WRONLY | O_CREAT | O_TRUNC, mode)) == -1) {
738*2d543d20SAndroid Build Coastguard Worker umask(mask);
739*2d543d20SAndroid Build Coastguard Worker errsv = errno;
740*2d543d20SAndroid Build Coastguard Worker close(in);
741*2d543d20SAndroid Build Coastguard Worker retval = -1;
742*2d543d20SAndroid Build Coastguard Worker goto out;
743*2d543d20SAndroid Build Coastguard Worker }
744*2d543d20SAndroid Build Coastguard Worker umask(mask);
745*2d543d20SAndroid Build Coastguard Worker while (retval == 0 && (amount_read = read(in, buf, sizeof(buf))) > 0) {
746*2d543d20SAndroid Build Coastguard Worker if (write(out, buf, amount_read) != amount_read) {
747*2d543d20SAndroid Build Coastguard Worker if (errno)
748*2d543d20SAndroid Build Coastguard Worker errsv = errno;
749*2d543d20SAndroid Build Coastguard Worker else
750*2d543d20SAndroid Build Coastguard Worker errsv = EIO;
751*2d543d20SAndroid Build Coastguard Worker retval = -1;
752*2d543d20SAndroid Build Coastguard Worker }
753*2d543d20SAndroid Build Coastguard Worker }
754*2d543d20SAndroid Build Coastguard Worker if (amount_read < 0) {
755*2d543d20SAndroid Build Coastguard Worker errsv = errno;
756*2d543d20SAndroid Build Coastguard Worker retval = -1;
757*2d543d20SAndroid Build Coastguard Worker }
758*2d543d20SAndroid Build Coastguard Worker close(in);
759*2d543d20SAndroid Build Coastguard Worker if (syncrequired && fsync(out) < 0) {
760*2d543d20SAndroid Build Coastguard Worker errsv = errno;
761*2d543d20SAndroid Build Coastguard Worker retval = -1;
762*2d543d20SAndroid Build Coastguard Worker }
763*2d543d20SAndroid Build Coastguard Worker if (close(out) < 0) {
764*2d543d20SAndroid Build Coastguard Worker errsv = errno;
765*2d543d20SAndroid Build Coastguard Worker retval = -1;
766*2d543d20SAndroid Build Coastguard Worker }
767*2d543d20SAndroid Build Coastguard Worker
768*2d543d20SAndroid Build Coastguard Worker if (!retval && rename(tmp, dst) == -1)
769*2d543d20SAndroid Build Coastguard Worker return -1;
770*2d543d20SAndroid Build Coastguard Worker
771*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(dst);
772*2d543d20SAndroid Build Coastguard Worker out:
773*2d543d20SAndroid Build Coastguard Worker errno = errsv;
774*2d543d20SAndroid Build Coastguard Worker return retval;
775*2d543d20SAndroid Build Coastguard Worker }
776*2d543d20SAndroid Build Coastguard Worker
semanage_rename(semanage_handle_t * sh,const char * src,const char * dst)777*2d543d20SAndroid Build Coastguard Worker static int semanage_rename(semanage_handle_t * sh, const char *src, const char *dst) {
778*2d543d20SAndroid Build Coastguard Worker int retval;
779*2d543d20SAndroid Build Coastguard Worker
780*2d543d20SAndroid Build Coastguard Worker retval = rename(src, dst);
781*2d543d20SAndroid Build Coastguard Worker if (retval == 0 || errno != EXDEV)
782*2d543d20SAndroid Build Coastguard Worker return retval;
783*2d543d20SAndroid Build Coastguard Worker
784*2d543d20SAndroid Build Coastguard Worker /* we can't use rename() due to filesystem limitation, lets try to copy files manually */
785*2d543d20SAndroid Build Coastguard Worker WARN(sh, "WARNING: rename(%s, %s) failed: %s, fall back to non-atomic semanage_copy_dir_flags()",
786*2d543d20SAndroid Build Coastguard Worker src, dst, strerror(errno));
787*2d543d20SAndroid Build Coastguard Worker if (semanage_copy_dir_flags(src, dst, 1) == -1) {
788*2d543d20SAndroid Build Coastguard Worker return -1;
789*2d543d20SAndroid Build Coastguard Worker }
790*2d543d20SAndroid Build Coastguard Worker return semanage_remove_directory(src);
791*2d543d20SAndroid Build Coastguard Worker }
792*2d543d20SAndroid Build Coastguard Worker
793*2d543d20SAndroid Build Coastguard Worker /* Copies all of the files from src to dst, recursing into
794*2d543d20SAndroid Build Coastguard Worker * subdirectories. Returns 0 on success, -1 on error. */
semanage_copy_dir(const char * src,const char * dst)795*2d543d20SAndroid Build Coastguard Worker static int semanage_copy_dir(const char *src, const char *dst)
796*2d543d20SAndroid Build Coastguard Worker {
797*2d543d20SAndroid Build Coastguard Worker return semanage_copy_dir_flags(src, dst, 1);
798*2d543d20SAndroid Build Coastguard Worker }
799*2d543d20SAndroid Build Coastguard Worker
800*2d543d20SAndroid Build Coastguard Worker /* Copies all of the dirs from src to dst, recursing into
801*2d543d20SAndroid Build Coastguard Worker * subdirectories. If flag == 1, then copy regular files as
802*2d543d20SAndroid Build Coastguard Worker * well. Returns 0 on success, -1 on error. */
semanage_copy_dir_flags(const char * src,const char * dst,int flag)803*2d543d20SAndroid Build Coastguard Worker static int semanage_copy_dir_flags(const char *src, const char *dst, int flag)
804*2d543d20SAndroid Build Coastguard Worker {
805*2d543d20SAndroid Build Coastguard Worker int i, len = 0, retval = -1;
806*2d543d20SAndroid Build Coastguard Worker struct stat sb;
807*2d543d20SAndroid Build Coastguard Worker struct dirent **names = NULL;
808*2d543d20SAndroid Build Coastguard Worker char path[PATH_MAX], path2[PATH_MAX];
809*2d543d20SAndroid Build Coastguard Worker mode_t mask;
810*2d543d20SAndroid Build Coastguard Worker
811*2d543d20SAndroid Build Coastguard Worker if ((len = scandir(src, &names, semanage_filename_select, NULL)) == -1) {
812*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not read the contents of %s: %s\n", src, strerror(errno));
813*2d543d20SAndroid Build Coastguard Worker return -1;
814*2d543d20SAndroid Build Coastguard Worker }
815*2d543d20SAndroid Build Coastguard Worker
816*2d543d20SAndroid Build Coastguard Worker if (stat(dst, &sb) != 0) {
817*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
818*2d543d20SAndroid Build Coastguard Worker if (mkdir(dst, S_IRWXU) != 0) {
819*2d543d20SAndroid Build Coastguard Worker umask(mask);
820*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Could not create %s: %s\n", dst, strerror(errno));
821*2d543d20SAndroid Build Coastguard Worker goto cleanup;
822*2d543d20SAndroid Build Coastguard Worker }
823*2d543d20SAndroid Build Coastguard Worker umask(mask);
824*2d543d20SAndroid Build Coastguard Worker
825*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(dst);
826*2d543d20SAndroid Build Coastguard Worker }
827*2d543d20SAndroid Build Coastguard Worker
828*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < len; i++) {
829*2d543d20SAndroid Build Coastguard Worker snprintf(path, sizeof(path), "%s/%s", src, names[i]->d_name);
830*2d543d20SAndroid Build Coastguard Worker /* stat() to see if this entry is a file or not since
831*2d543d20SAndroid Build Coastguard Worker * d_type isn't set properly on XFS */
832*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb)) {
833*2d543d20SAndroid Build Coastguard Worker goto cleanup;
834*2d543d20SAndroid Build Coastguard Worker }
835*2d543d20SAndroid Build Coastguard Worker snprintf(path2, sizeof(path2), "%s/%s", dst, names[i]->d_name);
836*2d543d20SAndroid Build Coastguard Worker if (S_ISDIR(sb.st_mode)) {
837*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
838*2d543d20SAndroid Build Coastguard Worker if (mkdir(path2, 0700) == -1 ||
839*2d543d20SAndroid Build Coastguard Worker semanage_copy_dir_flags(path, path2, flag) == -1) {
840*2d543d20SAndroid Build Coastguard Worker umask(mask);
841*2d543d20SAndroid Build Coastguard Worker goto cleanup;
842*2d543d20SAndroid Build Coastguard Worker }
843*2d543d20SAndroid Build Coastguard Worker umask(mask);
844*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(path2);
845*2d543d20SAndroid Build Coastguard Worker } else if (S_ISREG(sb.st_mode) && flag == 1) {
846*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
847*2d543d20SAndroid Build Coastguard Worker if (semanage_copy_file(path, path2, sb.st_mode,
848*2d543d20SAndroid Build Coastguard Worker false) < 0) {
849*2d543d20SAndroid Build Coastguard Worker umask(mask);
850*2d543d20SAndroid Build Coastguard Worker goto cleanup;
851*2d543d20SAndroid Build Coastguard Worker }
852*2d543d20SAndroid Build Coastguard Worker umask(mask);
853*2d543d20SAndroid Build Coastguard Worker }
854*2d543d20SAndroid Build Coastguard Worker }
855*2d543d20SAndroid Build Coastguard Worker retval = 0;
856*2d543d20SAndroid Build Coastguard Worker cleanup:
857*2d543d20SAndroid Build Coastguard Worker for (i = 0; names != NULL && i < len; i++) {
858*2d543d20SAndroid Build Coastguard Worker free(names[i]);
859*2d543d20SAndroid Build Coastguard Worker }
860*2d543d20SAndroid Build Coastguard Worker free(names);
861*2d543d20SAndroid Build Coastguard Worker return retval;
862*2d543d20SAndroid Build Coastguard Worker }
863*2d543d20SAndroid Build Coastguard Worker
864*2d543d20SAndroid Build Coastguard Worker /* Recursively removes the contents of a directory along with the
865*2d543d20SAndroid Build Coastguard Worker * directory itself. Returns 0 on success, non-zero on error. */
semanage_remove_directory(const char * path)866*2d543d20SAndroid Build Coastguard Worker int semanage_remove_directory(const char *path)
867*2d543d20SAndroid Build Coastguard Worker {
868*2d543d20SAndroid Build Coastguard Worker struct dirent **namelist = NULL;
869*2d543d20SAndroid Build Coastguard Worker int num_entries, i;
870*2d543d20SAndroid Build Coastguard Worker if ((num_entries = scandir(path, &namelist, semanage_filename_select,
871*2d543d20SAndroid Build Coastguard Worker NULL)) == -1) {
872*2d543d20SAndroid Build Coastguard Worker return -1;
873*2d543d20SAndroid Build Coastguard Worker }
874*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_entries; i++) {
875*2d543d20SAndroid Build Coastguard Worker char s[PATH_MAX];
876*2d543d20SAndroid Build Coastguard Worker struct stat buf;
877*2d543d20SAndroid Build Coastguard Worker snprintf(s, sizeof(s), "%s/%s", path, namelist[i]->d_name);
878*2d543d20SAndroid Build Coastguard Worker if (stat(s, &buf) == -1) {
879*2d543d20SAndroid Build Coastguard Worker return -2;
880*2d543d20SAndroid Build Coastguard Worker }
881*2d543d20SAndroid Build Coastguard Worker if (S_ISDIR(buf.st_mode)) {
882*2d543d20SAndroid Build Coastguard Worker int retval;
883*2d543d20SAndroid Build Coastguard Worker if ((retval = semanage_remove_directory(s)) != 0) {
884*2d543d20SAndroid Build Coastguard Worker return retval;
885*2d543d20SAndroid Build Coastguard Worker }
886*2d543d20SAndroid Build Coastguard Worker } else {
887*2d543d20SAndroid Build Coastguard Worker if (remove(s) == -1) {
888*2d543d20SAndroid Build Coastguard Worker return -3;
889*2d543d20SAndroid Build Coastguard Worker }
890*2d543d20SAndroid Build Coastguard Worker }
891*2d543d20SAndroid Build Coastguard Worker free(namelist[i]);
892*2d543d20SAndroid Build Coastguard Worker }
893*2d543d20SAndroid Build Coastguard Worker free(namelist);
894*2d543d20SAndroid Build Coastguard Worker if (rmdir(path) == -1) {
895*2d543d20SAndroid Build Coastguard Worker return -4;
896*2d543d20SAndroid Build Coastguard Worker }
897*2d543d20SAndroid Build Coastguard Worker return 0;
898*2d543d20SAndroid Build Coastguard Worker }
899*2d543d20SAndroid Build Coastguard Worker
semanage_mkpath(semanage_handle_t * sh,const char * path)900*2d543d20SAndroid Build Coastguard Worker int semanage_mkpath(semanage_handle_t *sh, const char *path)
901*2d543d20SAndroid Build Coastguard Worker {
902*2d543d20SAndroid Build Coastguard Worker char fn[PATH_MAX];
903*2d543d20SAndroid Build Coastguard Worker char *c;
904*2d543d20SAndroid Build Coastguard Worker int rc = 0;
905*2d543d20SAndroid Build Coastguard Worker
906*2d543d20SAndroid Build Coastguard Worker if (strlen(path) >= PATH_MAX) {
907*2d543d20SAndroid Build Coastguard Worker return -1;
908*2d543d20SAndroid Build Coastguard Worker }
909*2d543d20SAndroid Build Coastguard Worker
910*2d543d20SAndroid Build Coastguard Worker for (c = strcpy(fn, path) + 1; *c != '\0'; c++) {
911*2d543d20SAndroid Build Coastguard Worker if (*c != '/') {
912*2d543d20SAndroid Build Coastguard Worker continue;
913*2d543d20SAndroid Build Coastguard Worker }
914*2d543d20SAndroid Build Coastguard Worker
915*2d543d20SAndroid Build Coastguard Worker *c = '\0';
916*2d543d20SAndroid Build Coastguard Worker rc = semanage_mkdir(sh, fn);
917*2d543d20SAndroid Build Coastguard Worker if (rc < 0) {
918*2d543d20SAndroid Build Coastguard Worker goto cleanup;
919*2d543d20SAndroid Build Coastguard Worker }
920*2d543d20SAndroid Build Coastguard Worker *c = '/';
921*2d543d20SAndroid Build Coastguard Worker }
922*2d543d20SAndroid Build Coastguard Worker rc = semanage_mkdir(sh, fn);
923*2d543d20SAndroid Build Coastguard Worker
924*2d543d20SAndroid Build Coastguard Worker cleanup:
925*2d543d20SAndroid Build Coastguard Worker return rc;
926*2d543d20SAndroid Build Coastguard Worker }
927*2d543d20SAndroid Build Coastguard Worker
semanage_mkdir(semanage_handle_t * sh,const char * path)928*2d543d20SAndroid Build Coastguard Worker int semanage_mkdir(semanage_handle_t *sh, const char *path)
929*2d543d20SAndroid Build Coastguard Worker {
930*2d543d20SAndroid Build Coastguard Worker int status = 0;
931*2d543d20SAndroid Build Coastguard Worker struct stat sb;
932*2d543d20SAndroid Build Coastguard Worker mode_t mask;
933*2d543d20SAndroid Build Coastguard Worker
934*2d543d20SAndroid Build Coastguard Worker /* check if directory already exists */
935*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) != 0) {
936*2d543d20SAndroid Build Coastguard Worker /* make the modules directory */
937*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
938*2d543d20SAndroid Build Coastguard Worker if (mkdir(path, S_IRWXU) != 0) {
939*2d543d20SAndroid Build Coastguard Worker umask(mask);
940*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Cannot make directory at %s", path);
941*2d543d20SAndroid Build Coastguard Worker status = -1;
942*2d543d20SAndroid Build Coastguard Worker goto cleanup;
943*2d543d20SAndroid Build Coastguard Worker
944*2d543d20SAndroid Build Coastguard Worker }
945*2d543d20SAndroid Build Coastguard Worker umask(mask);
946*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(path);
947*2d543d20SAndroid Build Coastguard Worker }
948*2d543d20SAndroid Build Coastguard Worker else {
949*2d543d20SAndroid Build Coastguard Worker /* check that it really is a directory */
950*2d543d20SAndroid Build Coastguard Worker if (!S_ISDIR(sb.st_mode)) {
951*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Directory path taken by non-directory file at %s.", path);
952*2d543d20SAndroid Build Coastguard Worker status = -1;
953*2d543d20SAndroid Build Coastguard Worker goto cleanup;
954*2d543d20SAndroid Build Coastguard Worker }
955*2d543d20SAndroid Build Coastguard Worker }
956*2d543d20SAndroid Build Coastguard Worker
957*2d543d20SAndroid Build Coastguard Worker cleanup:
958*2d543d20SAndroid Build Coastguard Worker return status;
959*2d543d20SAndroid Build Coastguard Worker }
960*2d543d20SAndroid Build Coastguard Worker
961*2d543d20SAndroid Build Coastguard Worker /********************* sandbox management routines *********************/
962*2d543d20SAndroid Build Coastguard Worker
963*2d543d20SAndroid Build Coastguard Worker /* Creates a sandbox for a single client. Returns 0 if a
964*2d543d20SAndroid Build Coastguard Worker * sandbox was created, -1 on error.
965*2d543d20SAndroid Build Coastguard Worker */
semanage_make_sandbox(semanage_handle_t * sh)966*2d543d20SAndroid Build Coastguard Worker int semanage_make_sandbox(semanage_handle_t * sh)
967*2d543d20SAndroid Build Coastguard Worker {
968*2d543d20SAndroid Build Coastguard Worker const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL);
969*2d543d20SAndroid Build Coastguard Worker struct stat buf;
970*2d543d20SAndroid Build Coastguard Worker int errsv;
971*2d543d20SAndroid Build Coastguard Worker mode_t mask;
972*2d543d20SAndroid Build Coastguard Worker
973*2d543d20SAndroid Build Coastguard Worker if (stat(sandbox, &buf) == -1) {
974*2d543d20SAndroid Build Coastguard Worker if (errno != ENOENT) {
975*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error scanning directory %s.", sandbox);
976*2d543d20SAndroid Build Coastguard Worker return -1;
977*2d543d20SAndroid Build Coastguard Worker }
978*2d543d20SAndroid Build Coastguard Worker errno = 0;
979*2d543d20SAndroid Build Coastguard Worker } else {
980*2d543d20SAndroid Build Coastguard Worker /* remove the old sandbox */
981*2d543d20SAndroid Build Coastguard Worker if (semanage_remove_directory(sandbox) != 0) {
982*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error removing old sandbox directory %s.",
983*2d543d20SAndroid Build Coastguard Worker sandbox);
984*2d543d20SAndroid Build Coastguard Worker return -1;
985*2d543d20SAndroid Build Coastguard Worker }
986*2d543d20SAndroid Build Coastguard Worker }
987*2d543d20SAndroid Build Coastguard Worker
988*2d543d20SAndroid Build Coastguard Worker mask = umask(0077);
989*2d543d20SAndroid Build Coastguard Worker if (mkdir(sandbox, S_IRWXU) == -1 ||
990*2d543d20SAndroid Build Coastguard Worker semanage_copy_dir(semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL),
991*2d543d20SAndroid Build Coastguard Worker sandbox) == -1) {
992*2d543d20SAndroid Build Coastguard Worker umask(mask);
993*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not copy files to sandbox %s.", sandbox);
994*2d543d20SAndroid Build Coastguard Worker goto cleanup;
995*2d543d20SAndroid Build Coastguard Worker }
996*2d543d20SAndroid Build Coastguard Worker umask(mask);
997*2d543d20SAndroid Build Coastguard Worker return 0;
998*2d543d20SAndroid Build Coastguard Worker
999*2d543d20SAndroid Build Coastguard Worker cleanup:
1000*2d543d20SAndroid Build Coastguard Worker errsv = errno;
1001*2d543d20SAndroid Build Coastguard Worker semanage_remove_directory(sandbox);
1002*2d543d20SAndroid Build Coastguard Worker errno = errsv;
1003*2d543d20SAndroid Build Coastguard Worker return -1;
1004*2d543d20SAndroid Build Coastguard Worker }
1005*2d543d20SAndroid Build Coastguard Worker
1006*2d543d20SAndroid Build Coastguard Worker /* Create final temporary space. Returns -1 on error 0 on success. */
semanage_make_final(semanage_handle_t * sh)1007*2d543d20SAndroid Build Coastguard Worker int semanage_make_final(semanage_handle_t *sh)
1008*2d543d20SAndroid Build Coastguard Worker {
1009*2d543d20SAndroid Build Coastguard Worker int status = 0;
1010*2d543d20SAndroid Build Coastguard Worker int ret = 0;
1011*2d543d20SAndroid Build Coastguard Worker char fn[PATH_MAX];
1012*2d543d20SAndroid Build Coastguard Worker
1013*2d543d20SAndroid Build Coastguard Worker /* Create tmp dir if it does not exist. */
1014*2d543d20SAndroid Build Coastguard Worker ret = snprintf(fn,
1015*2d543d20SAndroid Build Coastguard Worker sizeof(fn),
1016*2d543d20SAndroid Build Coastguard Worker "%s%s%s",
1017*2d543d20SAndroid Build Coastguard Worker semanage_root(),
1018*2d543d20SAndroid Build Coastguard Worker sh->conf->store_root_path,
1019*2d543d20SAndroid Build Coastguard Worker semanage_final_prefix[SEMANAGE_FINAL_TMP]);
1020*2d543d20SAndroid Build Coastguard Worker if (ret < 0 || ret >= (int)sizeof(fn)) {
1021*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to compose the final tmp path.");
1022*2d543d20SAndroid Build Coastguard Worker status = -1;
1023*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1024*2d543d20SAndroid Build Coastguard Worker }
1025*2d543d20SAndroid Build Coastguard Worker
1026*2d543d20SAndroid Build Coastguard Worker ret = semanage_mkdir(sh, fn);
1027*2d543d20SAndroid Build Coastguard Worker if (ret != 0) {
1028*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to create temporary directory for final files at %s", fn);
1029*2d543d20SAndroid Build Coastguard Worker status = -1;
1030*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1031*2d543d20SAndroid Build Coastguard Worker }
1032*2d543d20SAndroid Build Coastguard Worker
1033*2d543d20SAndroid Build Coastguard Worker /* Delete store specific dir if it exists. */
1034*2d543d20SAndroid Build Coastguard Worker ret = semanage_remove_directory(
1035*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP,
1036*2d543d20SAndroid Build Coastguard Worker SEMANAGE_FINAL_TOPLEVEL));
1037*2d543d20SAndroid Build Coastguard Worker if (ret < -1) {
1038*2d543d20SAndroid Build Coastguard Worker status = -1;
1039*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1040*2d543d20SAndroid Build Coastguard Worker }
1041*2d543d20SAndroid Build Coastguard Worker
1042*2d543d20SAndroid Build Coastguard Worker // Build final directory structure
1043*2d543d20SAndroid Build Coastguard Worker int i;
1044*2d543d20SAndroid Build Coastguard Worker for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
1045*2d543d20SAndroid Build Coastguard Worker if (strlen(semanage_final_path(SEMANAGE_FINAL_TMP, i)) >= sizeof(fn)) {
1046*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to compose the final paths.");
1047*2d543d20SAndroid Build Coastguard Worker status = -1;
1048*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1049*2d543d20SAndroid Build Coastguard Worker }
1050*2d543d20SAndroid Build Coastguard Worker strcpy(fn, semanage_final_path(SEMANAGE_FINAL_TMP, i));
1051*2d543d20SAndroid Build Coastguard Worker ret = semanage_mkpath(sh, dirname(fn));
1052*2d543d20SAndroid Build Coastguard Worker if (ret < 0) {
1053*2d543d20SAndroid Build Coastguard Worker status = -1;
1054*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1055*2d543d20SAndroid Build Coastguard Worker }
1056*2d543d20SAndroid Build Coastguard Worker }
1057*2d543d20SAndroid Build Coastguard Worker
1058*2d543d20SAndroid Build Coastguard Worker cleanup:
1059*2d543d20SAndroid Build Coastguard Worker return status;
1060*2d543d20SAndroid Build Coastguard Worker }
1061*2d543d20SAndroid Build Coastguard Worker
1062*2d543d20SAndroid Build Coastguard Worker /* qsort comparison function for semanage_get_active_modules. */
semanage_get_active_modules_cmp(const void * a,const void * b)1063*2d543d20SAndroid Build Coastguard Worker static int semanage_get_active_modules_cmp(const void *a, const void *b)
1064*2d543d20SAndroid Build Coastguard Worker {
1065*2d543d20SAndroid Build Coastguard Worker semanage_module_info_t *aa = (semanage_module_info_t *)a;
1066*2d543d20SAndroid Build Coastguard Worker semanage_module_info_t *bb = (semanage_module_info_t *)b;
1067*2d543d20SAndroid Build Coastguard Worker
1068*2d543d20SAndroid Build Coastguard Worker return strcmp(aa->name, bb->name);
1069*2d543d20SAndroid Build Coastguard Worker }
1070*2d543d20SAndroid Build Coastguard Worker
semanage_get_cil_paths(semanage_handle_t * sh,semanage_module_info_t * modinfos,int num_modinfos,char *** filenames)1071*2d543d20SAndroid Build Coastguard Worker int semanage_get_cil_paths(semanage_handle_t * sh,
1072*2d543d20SAndroid Build Coastguard Worker semanage_module_info_t *modinfos,
1073*2d543d20SAndroid Build Coastguard Worker int num_modinfos,
1074*2d543d20SAndroid Build Coastguard Worker char *** filenames)
1075*2d543d20SAndroid Build Coastguard Worker {
1076*2d543d20SAndroid Build Coastguard Worker char path[PATH_MAX];
1077*2d543d20SAndroid Build Coastguard Worker char **names = NULL;
1078*2d543d20SAndroid Build Coastguard Worker
1079*2d543d20SAndroid Build Coastguard Worker int ret;
1080*2d543d20SAndroid Build Coastguard Worker int status = 0;
1081*2d543d20SAndroid Build Coastguard Worker int i = 0;
1082*2d543d20SAndroid Build Coastguard Worker
1083*2d543d20SAndroid Build Coastguard Worker names = calloc(num_modinfos, sizeof(*names));
1084*2d543d20SAndroid Build Coastguard Worker if (names == NULL) {
1085*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error allocating space for filenames.");
1086*2d543d20SAndroid Build Coastguard Worker return -1;
1087*2d543d20SAndroid Build Coastguard Worker }
1088*2d543d20SAndroid Build Coastguard Worker
1089*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_modinfos; i++) {
1090*2d543d20SAndroid Build Coastguard Worker ret = semanage_module_get_path(
1091*2d543d20SAndroid Build Coastguard Worker sh,
1092*2d543d20SAndroid Build Coastguard Worker &modinfos[i],
1093*2d543d20SAndroid Build Coastguard Worker SEMANAGE_MODULE_PATH_CIL,
1094*2d543d20SAndroid Build Coastguard Worker path,
1095*2d543d20SAndroid Build Coastguard Worker sizeof(path));
1096*2d543d20SAndroid Build Coastguard Worker if (ret != 0) {
1097*2d543d20SAndroid Build Coastguard Worker status = -1;
1098*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1099*2d543d20SAndroid Build Coastguard Worker }
1100*2d543d20SAndroid Build Coastguard Worker
1101*2d543d20SAndroid Build Coastguard Worker names[i] = strdup(path);
1102*2d543d20SAndroid Build Coastguard Worker
1103*2d543d20SAndroid Build Coastguard Worker if (names[i] == NULL) {
1104*2d543d20SAndroid Build Coastguard Worker status = -1;
1105*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1106*2d543d20SAndroid Build Coastguard Worker }
1107*2d543d20SAndroid Build Coastguard Worker }
1108*2d543d20SAndroid Build Coastguard Worker
1109*2d543d20SAndroid Build Coastguard Worker cleanup:
1110*2d543d20SAndroid Build Coastguard Worker if (status != 0) {
1111*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_modinfos; i++) {
1112*2d543d20SAndroid Build Coastguard Worker free(names[i]);
1113*2d543d20SAndroid Build Coastguard Worker }
1114*2d543d20SAndroid Build Coastguard Worker free(names);
1115*2d543d20SAndroid Build Coastguard Worker } else {
1116*2d543d20SAndroid Build Coastguard Worker *filenames = names;
1117*2d543d20SAndroid Build Coastguard Worker }
1118*2d543d20SAndroid Build Coastguard Worker
1119*2d543d20SAndroid Build Coastguard Worker return status;
1120*2d543d20SAndroid Build Coastguard Worker }
1121*2d543d20SAndroid Build Coastguard Worker
1122*2d543d20SAndroid Build Coastguard Worker /* Scans the modules directory for the current semanage handler. This
1123*2d543d20SAndroid Build Coastguard Worker * might be the active directory or sandbox, depending upon if the
1124*2d543d20SAndroid Build Coastguard Worker * handler has a transaction lock. Allocates and fills in *modinfos
1125*2d543d20SAndroid Build Coastguard Worker * with an array of module infos; length of array is stored in
1126*2d543d20SAndroid Build Coastguard Worker * *num_modules. The caller is responsible for free()ing *modinfos and its
1127*2d543d20SAndroid Build Coastguard Worker * individual elements. Upon success returns 0, -1 on error.
1128*2d543d20SAndroid Build Coastguard Worker */
semanage_get_active_modules(semanage_handle_t * sh,semanage_module_info_t ** modinfo,int * num_modules)1129*2d543d20SAndroid Build Coastguard Worker int semanage_get_active_modules(semanage_handle_t * sh,
1130*2d543d20SAndroid Build Coastguard Worker semanage_module_info_t ** modinfo,
1131*2d543d20SAndroid Build Coastguard Worker int *num_modules)
1132*2d543d20SAndroid Build Coastguard Worker {
1133*2d543d20SAndroid Build Coastguard Worker assert(sh);
1134*2d543d20SAndroid Build Coastguard Worker assert(modinfo);
1135*2d543d20SAndroid Build Coastguard Worker assert(num_modules);
1136*2d543d20SAndroid Build Coastguard Worker *modinfo = NULL;
1137*2d543d20SAndroid Build Coastguard Worker *num_modules = 0;
1138*2d543d20SAndroid Build Coastguard Worker
1139*2d543d20SAndroid Build Coastguard Worker int status = 0;
1140*2d543d20SAndroid Build Coastguard Worker int ret = 0;
1141*2d543d20SAndroid Build Coastguard Worker
1142*2d543d20SAndroid Build Coastguard Worker int i = 0;
1143*2d543d20SAndroid Build Coastguard Worker int j = 0;
1144*2d543d20SAndroid Build Coastguard Worker
1145*2d543d20SAndroid Build Coastguard Worker semanage_list_t *list = NULL;
1146*2d543d20SAndroid Build Coastguard Worker semanage_list_t *found = NULL;
1147*2d543d20SAndroid Build Coastguard Worker
1148*2d543d20SAndroid Build Coastguard Worker semanage_module_info_t *all_modinfos = NULL;
1149*2d543d20SAndroid Build Coastguard Worker int all_modinfos_len = 0;
1150*2d543d20SAndroid Build Coastguard Worker
1151*2d543d20SAndroid Build Coastguard Worker void *tmp = NULL;
1152*2d543d20SAndroid Build Coastguard Worker
1153*2d543d20SAndroid Build Coastguard Worker /* get all modules */
1154*2d543d20SAndroid Build Coastguard Worker ret = semanage_module_list_all(sh, &all_modinfos, &all_modinfos_len);
1155*2d543d20SAndroid Build Coastguard Worker if (ret != 0) {
1156*2d543d20SAndroid Build Coastguard Worker status = -1;
1157*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1158*2d543d20SAndroid Build Coastguard Worker }
1159*2d543d20SAndroid Build Coastguard Worker
1160*2d543d20SAndroid Build Coastguard Worker if (all_modinfos_len == 0) {
1161*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1162*2d543d20SAndroid Build Coastguard Worker }
1163*2d543d20SAndroid Build Coastguard Worker
1164*2d543d20SAndroid Build Coastguard Worker /* allocate enough for worst case */
1165*2d543d20SAndroid Build Coastguard Worker (*modinfo) = calloc(all_modinfos_len, sizeof(**modinfo));
1166*2d543d20SAndroid Build Coastguard Worker if ((*modinfo) == NULL) {
1167*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error allocating space for module information.");
1168*2d543d20SAndroid Build Coastguard Worker status = -1;
1169*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1170*2d543d20SAndroid Build Coastguard Worker }
1171*2d543d20SAndroid Build Coastguard Worker
1172*2d543d20SAndroid Build Coastguard Worker /* for each highest priority, enabled module get its path */
1173*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&list);
1174*2d543d20SAndroid Build Coastguard Worker j = 0;
1175*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < all_modinfos_len; i++) {
1176*2d543d20SAndroid Build Coastguard Worker /* check if enabled */
1177*2d543d20SAndroid Build Coastguard Worker if (all_modinfos[i].enabled != 1) continue;
1178*2d543d20SAndroid Build Coastguard Worker
1179*2d543d20SAndroid Build Coastguard Worker /* check if we've seen this before (i.e. highest priority) */
1180*2d543d20SAndroid Build Coastguard Worker found = semanage_list_find(list, all_modinfos[i].name);
1181*2d543d20SAndroid Build Coastguard Worker if (found == NULL) {
1182*2d543d20SAndroid Build Coastguard Worker ret = semanage_list_push(&list, all_modinfos[i].name);
1183*2d543d20SAndroid Build Coastguard Worker if (ret != 0) {
1184*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failed to add module name to list of known names.");
1185*2d543d20SAndroid Build Coastguard Worker status = -1;
1186*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1187*2d543d20SAndroid Build Coastguard Worker }
1188*2d543d20SAndroid Build Coastguard Worker }
1189*2d543d20SAndroid Build Coastguard Worker else continue;
1190*2d543d20SAndroid Build Coastguard Worker
1191*2d543d20SAndroid Build Coastguard Worker if (semanage_module_info_clone(sh, &all_modinfos[i], &(*modinfo)[j]) != 0) {
1192*2d543d20SAndroid Build Coastguard Worker status = -1;
1193*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1194*2d543d20SAndroid Build Coastguard Worker }
1195*2d543d20SAndroid Build Coastguard Worker
1196*2d543d20SAndroid Build Coastguard Worker j += 1;
1197*2d543d20SAndroid Build Coastguard Worker }
1198*2d543d20SAndroid Build Coastguard Worker
1199*2d543d20SAndroid Build Coastguard Worker *num_modules = j;
1200*2d543d20SAndroid Build Coastguard Worker
1201*2d543d20SAndroid Build Coastguard Worker if (j == 0) {
1202*2d543d20SAndroid Build Coastguard Worker free(*modinfo);
1203*2d543d20SAndroid Build Coastguard Worker *modinfo = NULL;
1204*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1205*2d543d20SAndroid Build Coastguard Worker }
1206*2d543d20SAndroid Build Coastguard Worker
1207*2d543d20SAndroid Build Coastguard Worker /* realloc the array to its min size */
1208*2d543d20SAndroid Build Coastguard Worker tmp = realloc(*modinfo, j * sizeof(**modinfo));
1209*2d543d20SAndroid Build Coastguard Worker if (tmp == NULL) {
1210*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error allocating space for filenames.");
1211*2d543d20SAndroid Build Coastguard Worker status = -1;
1212*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1213*2d543d20SAndroid Build Coastguard Worker }
1214*2d543d20SAndroid Build Coastguard Worker *modinfo = tmp;
1215*2d543d20SAndroid Build Coastguard Worker
1216*2d543d20SAndroid Build Coastguard Worker /* sort array on module name */
1217*2d543d20SAndroid Build Coastguard Worker qsort(*modinfo,
1218*2d543d20SAndroid Build Coastguard Worker *num_modules,
1219*2d543d20SAndroid Build Coastguard Worker sizeof(**modinfo),
1220*2d543d20SAndroid Build Coastguard Worker semanage_get_active_modules_cmp);
1221*2d543d20SAndroid Build Coastguard Worker
1222*2d543d20SAndroid Build Coastguard Worker cleanup:
1223*2d543d20SAndroid Build Coastguard Worker semanage_list_destroy(&list);
1224*2d543d20SAndroid Build Coastguard Worker
1225*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < all_modinfos_len; i++) {
1226*2d543d20SAndroid Build Coastguard Worker semanage_module_info_destroy(sh, &all_modinfos[i]);
1227*2d543d20SAndroid Build Coastguard Worker }
1228*2d543d20SAndroid Build Coastguard Worker free(all_modinfos);
1229*2d543d20SAndroid Build Coastguard Worker
1230*2d543d20SAndroid Build Coastguard Worker if (status != 0) {
1231*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < j; i++) {
1232*2d543d20SAndroid Build Coastguard Worker semanage_module_info_destroy(sh, &(*modinfo)[i]);
1233*2d543d20SAndroid Build Coastguard Worker }
1234*2d543d20SAndroid Build Coastguard Worker free(*modinfo);
1235*2d543d20SAndroid Build Coastguard Worker }
1236*2d543d20SAndroid Build Coastguard Worker
1237*2d543d20SAndroid Build Coastguard Worker return status;
1238*2d543d20SAndroid Build Coastguard Worker }
1239*2d543d20SAndroid Build Coastguard Worker
1240*2d543d20SAndroid Build Coastguard Worker /******************* routines that run external programs *******************/
1241*2d543d20SAndroid Build Coastguard Worker
1242*2d543d20SAndroid Build Coastguard Worker /* Appends a single character to a string. Returns a pointer to the
1243*2d543d20SAndroid Build Coastguard Worker * realloc()ated string. If out of memory return NULL; original
1244*2d543d20SAndroid Build Coastguard Worker * string will remain untouched.
1245*2d543d20SAndroid Build Coastguard Worker */
append(char * s,char c)1246*2d543d20SAndroid Build Coastguard Worker static char *append(char *s, char c)
1247*2d543d20SAndroid Build Coastguard Worker {
1248*2d543d20SAndroid Build Coastguard Worker size_t len = (s == NULL ? 0 : strlen(s));
1249*2d543d20SAndroid Build Coastguard Worker char *new_s = realloc(s, len + 2);
1250*2d543d20SAndroid Build Coastguard Worker if (new_s == NULL) {
1251*2d543d20SAndroid Build Coastguard Worker return NULL;
1252*2d543d20SAndroid Build Coastguard Worker }
1253*2d543d20SAndroid Build Coastguard Worker s = new_s;
1254*2d543d20SAndroid Build Coastguard Worker s[len] = c;
1255*2d543d20SAndroid Build Coastguard Worker s[len + 1] = '\0';
1256*2d543d20SAndroid Build Coastguard Worker return s;
1257*2d543d20SAndroid Build Coastguard Worker }
1258*2d543d20SAndroid Build Coastguard Worker
1259*2d543d20SAndroid Build Coastguard Worker /* Append string 't' to string 's', realloc()ating 's' as needed. 't'
1260*2d543d20SAndroid Build Coastguard Worker * may be safely free()d afterwards. Returns a pointer to the
1261*2d543d20SAndroid Build Coastguard Worker * realloc()ated 's'. If out of memory return NULL; original strings
1262*2d543d20SAndroid Build Coastguard Worker * will remain untouched.
1263*2d543d20SAndroid Build Coastguard Worker */
append_str(char * s,const char * t)1264*2d543d20SAndroid Build Coastguard Worker static char *append_str(char *s, const char *t)
1265*2d543d20SAndroid Build Coastguard Worker {
1266*2d543d20SAndroid Build Coastguard Worker size_t s_len = (s == NULL ? 0 : strlen(s));
1267*2d543d20SAndroid Build Coastguard Worker size_t t_len;
1268*2d543d20SAndroid Build Coastguard Worker char *new_s;
1269*2d543d20SAndroid Build Coastguard Worker
1270*2d543d20SAndroid Build Coastguard Worker if (t == NULL) {
1271*2d543d20SAndroid Build Coastguard Worker return s;
1272*2d543d20SAndroid Build Coastguard Worker }
1273*2d543d20SAndroid Build Coastguard Worker t_len = strlen(t);
1274*2d543d20SAndroid Build Coastguard Worker new_s = realloc(s, s_len + t_len + 1);
1275*2d543d20SAndroid Build Coastguard Worker if (new_s == NULL) {
1276*2d543d20SAndroid Build Coastguard Worker return NULL;
1277*2d543d20SAndroid Build Coastguard Worker }
1278*2d543d20SAndroid Build Coastguard Worker s = new_s;
1279*2d543d20SAndroid Build Coastguard Worker memcpy(s + s_len, t, t_len);
1280*2d543d20SAndroid Build Coastguard Worker s[s_len + t_len] = '\0';
1281*2d543d20SAndroid Build Coastguard Worker return s;
1282*2d543d20SAndroid Build Coastguard Worker }
1283*2d543d20SAndroid Build Coastguard Worker
1284*2d543d20SAndroid Build Coastguard Worker /*
1285*2d543d20SAndroid Build Coastguard Worker * Append an argument string to an argument vector. Replaces the
1286*2d543d20SAndroid Build Coastguard Worker * argument pointer passed in. Returns -1 on error. Increments
1287*2d543d20SAndroid Build Coastguard Worker * 'num_args' on success.
1288*2d543d20SAndroid Build Coastguard Worker */
append_arg(char *** argv,int * num_args,const char * arg)1289*2d543d20SAndroid Build Coastguard Worker static int append_arg(char ***argv, int *num_args, const char *arg)
1290*2d543d20SAndroid Build Coastguard Worker {
1291*2d543d20SAndroid Build Coastguard Worker char **a;
1292*2d543d20SAndroid Build Coastguard Worker
1293*2d543d20SAndroid Build Coastguard Worker a = realloc(*argv, sizeof(**argv) * (*num_args + 1));
1294*2d543d20SAndroid Build Coastguard Worker if (a == NULL)
1295*2d543d20SAndroid Build Coastguard Worker return -1;
1296*2d543d20SAndroid Build Coastguard Worker
1297*2d543d20SAndroid Build Coastguard Worker *argv = a;
1298*2d543d20SAndroid Build Coastguard Worker a[*num_args] = NULL;
1299*2d543d20SAndroid Build Coastguard Worker
1300*2d543d20SAndroid Build Coastguard Worker if (arg) {
1301*2d543d20SAndroid Build Coastguard Worker a[*num_args] = strdup(arg);
1302*2d543d20SAndroid Build Coastguard Worker if (!a[*num_args])
1303*2d543d20SAndroid Build Coastguard Worker return -1;
1304*2d543d20SAndroid Build Coastguard Worker }
1305*2d543d20SAndroid Build Coastguard Worker (*num_args)++;
1306*2d543d20SAndroid Build Coastguard Worker return 0;
1307*2d543d20SAndroid Build Coastguard Worker }
1308*2d543d20SAndroid Build Coastguard Worker
1309*2d543d20SAndroid Build Coastguard Worker /* free()s all strings within a null-terminated argument vector, as
1310*2d543d20SAndroid Build Coastguard Worker * well as the pointer itself. */
free_argv(char ** argv)1311*2d543d20SAndroid Build Coastguard Worker static void free_argv(char **argv)
1312*2d543d20SAndroid Build Coastguard Worker {
1313*2d543d20SAndroid Build Coastguard Worker int i;
1314*2d543d20SAndroid Build Coastguard Worker for (i = 0; argv != NULL && argv[i] != NULL; i++) {
1315*2d543d20SAndroid Build Coastguard Worker free(argv[i]);
1316*2d543d20SAndroid Build Coastguard Worker }
1317*2d543d20SAndroid Build Coastguard Worker free(argv);
1318*2d543d20SAndroid Build Coastguard Worker }
1319*2d543d20SAndroid Build Coastguard Worker
1320*2d543d20SAndroid Build Coastguard Worker /* Take an argument string and split and place into an argument
1321*2d543d20SAndroid Build Coastguard Worker * vector. Respect normal quoting, double-quoting, and backslash
1322*2d543d20SAndroid Build Coastguard Worker * conventions. Perform substitutions on $@ and $< symbols. Returns
1323*2d543d20SAndroid Build Coastguard Worker * a NULL-terminated argument vector; caller is responsible for
1324*2d543d20SAndroid Build Coastguard Worker * free()ing the vector and its elements. */
split_args(const char * arg0,char * arg_string,const char * new_name,const char * old_name)1325*2d543d20SAndroid Build Coastguard Worker static char **split_args(const char *arg0, char *arg_string,
1326*2d543d20SAndroid Build Coastguard Worker const char *new_name, const char *old_name)
1327*2d543d20SAndroid Build Coastguard Worker {
1328*2d543d20SAndroid Build Coastguard Worker char **argv = NULL, *s, *arg = NULL, *targ;
1329*2d543d20SAndroid Build Coastguard Worker int num_args = 0, in_quote = 0, in_dquote = 0, rc;
1330*2d543d20SAndroid Build Coastguard Worker
1331*2d543d20SAndroid Build Coastguard Worker rc = append_arg(&argv, &num_args, arg0);
1332*2d543d20SAndroid Build Coastguard Worker if (rc)
1333*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1334*2d543d20SAndroid Build Coastguard Worker s = arg_string;
1335*2d543d20SAndroid Build Coastguard Worker /* parse the argument string one character at a time,
1336*2d543d20SAndroid Build Coastguard Worker * respecting quotes and other special characters */
1337*2d543d20SAndroid Build Coastguard Worker while (s != NULL && *s != '\0') {
1338*2d543d20SAndroid Build Coastguard Worker switch (*s) {
1339*2d543d20SAndroid Build Coastguard Worker case '\\':{
1340*2d543d20SAndroid Build Coastguard Worker if (*(s + 1) == '\0') {
1341*2d543d20SAndroid Build Coastguard Worker targ = append(arg, '\\');
1342*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1343*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1344*2d543d20SAndroid Build Coastguard Worker arg = targ;
1345*2d543d20SAndroid Build Coastguard Worker } else {
1346*2d543d20SAndroid Build Coastguard Worker targ = append(arg, *(s + 1));
1347*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1348*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1349*2d543d20SAndroid Build Coastguard Worker arg = targ;
1350*2d543d20SAndroid Build Coastguard Worker s++;
1351*2d543d20SAndroid Build Coastguard Worker }
1352*2d543d20SAndroid Build Coastguard Worker break;
1353*2d543d20SAndroid Build Coastguard Worker }
1354*2d543d20SAndroid Build Coastguard Worker case '\'':{
1355*2d543d20SAndroid Build Coastguard Worker if (in_dquote) {
1356*2d543d20SAndroid Build Coastguard Worker targ = append(arg, *s);
1357*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1358*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1359*2d543d20SAndroid Build Coastguard Worker arg = targ;
1360*2d543d20SAndroid Build Coastguard Worker } else if (in_quote) {
1361*2d543d20SAndroid Build Coastguard Worker in_quote = 0;
1362*2d543d20SAndroid Build Coastguard Worker } else {
1363*2d543d20SAndroid Build Coastguard Worker in_quote = 1;
1364*2d543d20SAndroid Build Coastguard Worker targ = append(arg, '\0');
1365*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1366*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1367*2d543d20SAndroid Build Coastguard Worker arg = targ;
1368*2d543d20SAndroid Build Coastguard Worker }
1369*2d543d20SAndroid Build Coastguard Worker break;
1370*2d543d20SAndroid Build Coastguard Worker }
1371*2d543d20SAndroid Build Coastguard Worker case '\"':{
1372*2d543d20SAndroid Build Coastguard Worker if (in_quote) {
1373*2d543d20SAndroid Build Coastguard Worker targ = append(arg, *s);
1374*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1375*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1376*2d543d20SAndroid Build Coastguard Worker arg = targ;
1377*2d543d20SAndroid Build Coastguard Worker } else if (in_dquote) {
1378*2d543d20SAndroid Build Coastguard Worker in_dquote = 0;
1379*2d543d20SAndroid Build Coastguard Worker } else {
1380*2d543d20SAndroid Build Coastguard Worker in_dquote = 1;
1381*2d543d20SAndroid Build Coastguard Worker targ = append(arg, '\0');
1382*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1383*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1384*2d543d20SAndroid Build Coastguard Worker arg = targ;
1385*2d543d20SAndroid Build Coastguard Worker }
1386*2d543d20SAndroid Build Coastguard Worker break;
1387*2d543d20SAndroid Build Coastguard Worker }
1388*2d543d20SAndroid Build Coastguard Worker case '$':{
1389*2d543d20SAndroid Build Coastguard Worker switch (*(s + 1)) {
1390*2d543d20SAndroid Build Coastguard Worker case '@':{
1391*2d543d20SAndroid Build Coastguard Worker targ = append_str(arg, new_name);
1392*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1393*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1394*2d543d20SAndroid Build Coastguard Worker arg = targ;
1395*2d543d20SAndroid Build Coastguard Worker s++;
1396*2d543d20SAndroid Build Coastguard Worker break;
1397*2d543d20SAndroid Build Coastguard Worker }
1398*2d543d20SAndroid Build Coastguard Worker case '<':{
1399*2d543d20SAndroid Build Coastguard Worker targ = append_str(arg, old_name);
1400*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1401*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1402*2d543d20SAndroid Build Coastguard Worker arg = targ;
1403*2d543d20SAndroid Build Coastguard Worker s++;
1404*2d543d20SAndroid Build Coastguard Worker break;
1405*2d543d20SAndroid Build Coastguard Worker }
1406*2d543d20SAndroid Build Coastguard Worker default:{
1407*2d543d20SAndroid Build Coastguard Worker targ = append(arg, *s);
1408*2d543d20SAndroid Build Coastguard Worker if (targ == NULL)
1409*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1410*2d543d20SAndroid Build Coastguard Worker arg = targ;
1411*2d543d20SAndroid Build Coastguard Worker }
1412*2d543d20SAndroid Build Coastguard Worker }
1413*2d543d20SAndroid Build Coastguard Worker break;
1414*2d543d20SAndroid Build Coastguard Worker }
1415*2d543d20SAndroid Build Coastguard Worker default:{
1416*2d543d20SAndroid Build Coastguard Worker if (isspace(*s) && !in_quote && !in_dquote) {
1417*2d543d20SAndroid Build Coastguard Worker if (arg != NULL) {
1418*2d543d20SAndroid Build Coastguard Worker rc = append_arg(&argv, &num_args, arg);
1419*2d543d20SAndroid Build Coastguard Worker if (rc)
1420*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1421*2d543d20SAndroid Build Coastguard Worker free(arg);
1422*2d543d20SAndroid Build Coastguard Worker arg = NULL;
1423*2d543d20SAndroid Build Coastguard Worker }
1424*2d543d20SAndroid Build Coastguard Worker } else {
1425*2d543d20SAndroid Build Coastguard Worker if ((targ = append(arg, *s)) == NULL) {
1426*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1427*2d543d20SAndroid Build Coastguard Worker } else {
1428*2d543d20SAndroid Build Coastguard Worker arg = targ;
1429*2d543d20SAndroid Build Coastguard Worker }
1430*2d543d20SAndroid Build Coastguard Worker }
1431*2d543d20SAndroid Build Coastguard Worker }
1432*2d543d20SAndroid Build Coastguard Worker }
1433*2d543d20SAndroid Build Coastguard Worker s++;
1434*2d543d20SAndroid Build Coastguard Worker }
1435*2d543d20SAndroid Build Coastguard Worker if (arg != NULL) {
1436*2d543d20SAndroid Build Coastguard Worker rc = append_arg(&argv, &num_args, arg);
1437*2d543d20SAndroid Build Coastguard Worker if (rc)
1438*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1439*2d543d20SAndroid Build Coastguard Worker free(arg);
1440*2d543d20SAndroid Build Coastguard Worker arg = NULL;
1441*2d543d20SAndroid Build Coastguard Worker }
1442*2d543d20SAndroid Build Coastguard Worker /* explicitly add a NULL at the end */
1443*2d543d20SAndroid Build Coastguard Worker rc = append_arg(&argv, &num_args, NULL);
1444*2d543d20SAndroid Build Coastguard Worker if (rc)
1445*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1446*2d543d20SAndroid Build Coastguard Worker return argv;
1447*2d543d20SAndroid Build Coastguard Worker cleanup:
1448*2d543d20SAndroid Build Coastguard Worker free_argv(argv);
1449*2d543d20SAndroid Build Coastguard Worker free(arg);
1450*2d543d20SAndroid Build Coastguard Worker return NULL;
1451*2d543d20SAndroid Build Coastguard Worker }
1452*2d543d20SAndroid Build Coastguard Worker
1453*2d543d20SAndroid Build Coastguard Worker /* Take the arguments given in v->args and expand any $ macros within.
1454*2d543d20SAndroid Build Coastguard Worker * Split the arguments into different strings (argv). Next fork and
1455*2d543d20SAndroid Build Coastguard Worker * execute the process. BE SURE THAT ALL FILE DESCRIPTORS ARE SET TO
1456*2d543d20SAndroid Build Coastguard Worker * CLOSE-ON-EXEC. Take the return value of the child process and
1457*2d543d20SAndroid Build Coastguard Worker * return it, -1 on error.
1458*2d543d20SAndroid Build Coastguard Worker */
semanage_exec_prog(semanage_handle_t * sh,external_prog_t * e,const char * new_name,const char * old_name)1459*2d543d20SAndroid Build Coastguard Worker static int semanage_exec_prog(semanage_handle_t * sh,
1460*2d543d20SAndroid Build Coastguard Worker external_prog_t * e, const char *new_name,
1461*2d543d20SAndroid Build Coastguard Worker const char *old_name)
1462*2d543d20SAndroid Build Coastguard Worker {
1463*2d543d20SAndroid Build Coastguard Worker char **argv;
1464*2d543d20SAndroid Build Coastguard Worker pid_t forkval;
1465*2d543d20SAndroid Build Coastguard Worker int status = 0;
1466*2d543d20SAndroid Build Coastguard Worker
1467*2d543d20SAndroid Build Coastguard Worker argv = split_args(e->path, e->args, new_name, old_name);
1468*2d543d20SAndroid Build Coastguard Worker if (argv == NULL) {
1469*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Out of memory!");
1470*2d543d20SAndroid Build Coastguard Worker return -1;
1471*2d543d20SAndroid Build Coastguard Worker }
1472*2d543d20SAndroid Build Coastguard Worker
1473*2d543d20SAndroid Build Coastguard Worker /* no need to use pthread_atfork() -- child will not be using
1474*2d543d20SAndroid Build Coastguard Worker * any mutexes. */
1475*2d543d20SAndroid Build Coastguard Worker forkval = vfork();
1476*2d543d20SAndroid Build Coastguard Worker if (forkval == 0) {
1477*2d543d20SAndroid Build Coastguard Worker /* child process. file descriptors will be closed
1478*2d543d20SAndroid Build Coastguard Worker * because they were set as close-on-exec. */
1479*2d543d20SAndroid Build Coastguard Worker execve(e->path, argv, NULL);
1480*2d543d20SAndroid Build Coastguard Worker _exit(EXIT_FAILURE); /* if execve() failed */
1481*2d543d20SAndroid Build Coastguard Worker }
1482*2d543d20SAndroid Build Coastguard Worker
1483*2d543d20SAndroid Build Coastguard Worker free_argv(argv);
1484*2d543d20SAndroid Build Coastguard Worker
1485*2d543d20SAndroid Build Coastguard Worker if (forkval == -1) {
1486*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while forking process.");
1487*2d543d20SAndroid Build Coastguard Worker return -1;
1488*2d543d20SAndroid Build Coastguard Worker }
1489*2d543d20SAndroid Build Coastguard Worker
1490*2d543d20SAndroid Build Coastguard Worker /* parent process. wait for child to finish */
1491*2d543d20SAndroid Build Coastguard Worker if (waitpid(forkval, &status, 0) == -1 || !WIFEXITED(status)) {
1492*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Child process %s did not exit cleanly.",
1493*2d543d20SAndroid Build Coastguard Worker e->path);
1494*2d543d20SAndroid Build Coastguard Worker return -1;
1495*2d543d20SAndroid Build Coastguard Worker }
1496*2d543d20SAndroid Build Coastguard Worker return WEXITSTATUS(status);
1497*2d543d20SAndroid Build Coastguard Worker }
1498*2d543d20SAndroid Build Coastguard Worker
1499*2d543d20SAndroid Build Coastguard Worker /* reloads the policy pointed to by the handle, used locally by install
1500*2d543d20SAndroid Build Coastguard Worker * and exported for user reload requests */
semanage_reload_policy(semanage_handle_t * sh)1501*2d543d20SAndroid Build Coastguard Worker int semanage_reload_policy(semanage_handle_t * sh)
1502*2d543d20SAndroid Build Coastguard Worker {
1503*2d543d20SAndroid Build Coastguard Worker int r = 0;
1504*2d543d20SAndroid Build Coastguard Worker
1505*2d543d20SAndroid Build Coastguard Worker if (!sh)
1506*2d543d20SAndroid Build Coastguard Worker return -1;
1507*2d543d20SAndroid Build Coastguard Worker
1508*2d543d20SAndroid Build Coastguard Worker if ((r = semanage_exec_prog(sh, sh->conf->load_policy, "", "")) != 0) {
1509*2d543d20SAndroid Build Coastguard Worker ERR(sh, "load_policy returned error code %d.", r);
1510*2d543d20SAndroid Build Coastguard Worker }
1511*2d543d20SAndroid Build Coastguard Worker return r;
1512*2d543d20SAndroid Build Coastguard Worker }
1513*2d543d20SAndroid Build Coastguard Worker
1514*2d543d20SAndroid Build Coastguard Worker
1515*2d543d20SAndroid Build Coastguard Worker /* This expands the file_context.tmpl file to file_context and homedirs.template */
semanage_split_fc(semanage_handle_t * sh)1516*2d543d20SAndroid Build Coastguard Worker int semanage_split_fc(semanage_handle_t * sh)
1517*2d543d20SAndroid Build Coastguard Worker {
1518*2d543d20SAndroid Build Coastguard Worker FILE *file_con = NULL;
1519*2d543d20SAndroid Build Coastguard Worker int fc = -1, hd = -1, retval = -1;
1520*2d543d20SAndroid Build Coastguard Worker char buf[PATH_MAX] = { 0 };
1521*2d543d20SAndroid Build Coastguard Worker
1522*2d543d20SAndroid Build Coastguard Worker /* I use fopen here instead of open so that I can use fgets which only reads a single line */
1523*2d543d20SAndroid Build Coastguard Worker file_con = fopen(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL), "r");
1524*2d543d20SAndroid Build Coastguard Worker if (!file_con) {
1525*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open %s for reading.",
1526*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
1527*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1528*2d543d20SAndroid Build Coastguard Worker }
1529*2d543d20SAndroid Build Coastguard Worker
1530*2d543d20SAndroid Build Coastguard Worker fc = open(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
1531*2d543d20SAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
1532*2d543d20SAndroid Build Coastguard Worker if (fc < 0) {
1533*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open %s for writing.",
1534*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
1535*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1536*2d543d20SAndroid Build Coastguard Worker }
1537*2d543d20SAndroid Build Coastguard Worker hd = open(semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL),
1538*2d543d20SAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
1539*2d543d20SAndroid Build Coastguard Worker if (hd < 0) {
1540*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open %s for writing.",
1541*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_HOMEDIR_TMPL));
1542*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1543*2d543d20SAndroid Build Coastguard Worker }
1544*2d543d20SAndroid Build Coastguard Worker
1545*2d543d20SAndroid Build Coastguard Worker while (fgets_unlocked(buf, PATH_MAX, file_con)) {
1546*2d543d20SAndroid Build Coastguard Worker if (!strncmp(buf, "HOME_DIR", 8) ||
1547*2d543d20SAndroid Build Coastguard Worker !strncmp(buf, "HOME_ROOT", 9) || strstr(buf, "ROLE") ||
1548*2d543d20SAndroid Build Coastguard Worker strstr(buf, "USER")) {
1549*2d543d20SAndroid Build Coastguard Worker /* This contains one of the template variables, write it to homedir.template */
1550*2d543d20SAndroid Build Coastguard Worker if (write(hd, buf, strlen(buf)) < 0) {
1551*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Write to %s failed.",
1552*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP,
1553*2d543d20SAndroid Build Coastguard Worker SEMANAGE_HOMEDIR_TMPL));
1554*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1555*2d543d20SAndroid Build Coastguard Worker }
1556*2d543d20SAndroid Build Coastguard Worker } else {
1557*2d543d20SAndroid Build Coastguard Worker if (write(fc, buf, strlen(buf)) < 0) {
1558*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Write to %s failed.",
1559*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC));
1560*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1561*2d543d20SAndroid Build Coastguard Worker }
1562*2d543d20SAndroid Build Coastguard Worker }
1563*2d543d20SAndroid Build Coastguard Worker }
1564*2d543d20SAndroid Build Coastguard Worker
1565*2d543d20SAndroid Build Coastguard Worker retval = 0;
1566*2d543d20SAndroid Build Coastguard Worker cleanup:
1567*2d543d20SAndroid Build Coastguard Worker if (file_con)
1568*2d543d20SAndroid Build Coastguard Worker fclose(file_con);
1569*2d543d20SAndroid Build Coastguard Worker if (fc >= 0)
1570*2d543d20SAndroid Build Coastguard Worker close(fc);
1571*2d543d20SAndroid Build Coastguard Worker if (hd >= 0)
1572*2d543d20SAndroid Build Coastguard Worker close(hd);
1573*2d543d20SAndroid Build Coastguard Worker
1574*2d543d20SAndroid Build Coastguard Worker return retval;
1575*2d543d20SAndroid Build Coastguard Worker
1576*2d543d20SAndroid Build Coastguard Worker }
1577*2d543d20SAndroid Build Coastguard Worker
sefcontext_compile(semanage_handle_t * sh,const char * path)1578*2d543d20SAndroid Build Coastguard Worker static int sefcontext_compile(semanage_handle_t * sh, const char *path) {
1579*2d543d20SAndroid Build Coastguard Worker
1580*2d543d20SAndroid Build Coastguard Worker int r;
1581*2d543d20SAndroid Build Coastguard Worker struct stat sb;
1582*2d543d20SAndroid Build Coastguard Worker
1583*2d543d20SAndroid Build Coastguard Worker if (stat(path, &sb) < 0) {
1584*2d543d20SAndroid Build Coastguard Worker if (errno != ENOENT) {
1585*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1586*2d543d20SAndroid Build Coastguard Worker return -1;
1587*2d543d20SAndroid Build Coastguard Worker }
1588*2d543d20SAndroid Build Coastguard Worker
1589*2d543d20SAndroid Build Coastguard Worker return 0;
1590*2d543d20SAndroid Build Coastguard Worker }
1591*2d543d20SAndroid Build Coastguard Worker
1592*2d543d20SAndroid Build Coastguard Worker if ((r = semanage_exec_prog(sh, sh->conf->sefcontext_compile, path, "")) != 0) {
1593*2d543d20SAndroid Build Coastguard Worker ERR(sh, "sefcontext_compile returned error code %d. Compiling %s", r, path);
1594*2d543d20SAndroid Build Coastguard Worker return -1;
1595*2d543d20SAndroid Build Coastguard Worker }
1596*2d543d20SAndroid Build Coastguard Worker
1597*2d543d20SAndroid Build Coastguard Worker return 0;
1598*2d543d20SAndroid Build Coastguard Worker }
1599*2d543d20SAndroid Build Coastguard Worker
semanage_validate_and_compile_fcontexts(semanage_handle_t * sh)1600*2d543d20SAndroid Build Coastguard Worker static int semanage_validate_and_compile_fcontexts(semanage_handle_t * sh)
1601*2d543d20SAndroid Build Coastguard Worker {
1602*2d543d20SAndroid Build Coastguard Worker int status = -1;
1603*2d543d20SAndroid Build Coastguard Worker
1604*2d543d20SAndroid Build Coastguard Worker if (sh->do_check_contexts) {
1605*2d543d20SAndroid Build Coastguard Worker int ret;
1606*2d543d20SAndroid Build Coastguard Worker ret = semanage_exec_prog(
1607*2d543d20SAndroid Build Coastguard Worker sh,
1608*2d543d20SAndroid Build Coastguard Worker sh->conf->setfiles,
1609*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP,
1610*2d543d20SAndroid Build Coastguard Worker SEMANAGE_KERNEL),
1611*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP,
1612*2d543d20SAndroid Build Coastguard Worker SEMANAGE_FC));
1613*2d543d20SAndroid Build Coastguard Worker if (ret != 0) {
1614*2d543d20SAndroid Build Coastguard Worker ERR(sh, "setfiles returned error code %d.", ret);
1615*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1616*2d543d20SAndroid Build Coastguard Worker }
1617*2d543d20SAndroid Build Coastguard Worker }
1618*2d543d20SAndroid Build Coastguard Worker
1619*2d543d20SAndroid Build Coastguard Worker if (sefcontext_compile(sh,
1620*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC)) != 0) {
1621*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1622*2d543d20SAndroid Build Coastguard Worker }
1623*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_BIN));
1624*2d543d20SAndroid Build Coastguard Worker
1625*2d543d20SAndroid Build Coastguard Worker if (sefcontext_compile(sh,
1626*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL)) != 0) {
1627*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1628*2d543d20SAndroid Build Coastguard Worker }
1629*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL_BIN));
1630*2d543d20SAndroid Build Coastguard Worker
1631*2d543d20SAndroid Build Coastguard Worker if (sefcontext_compile(sh,
1632*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS)) != 0) {
1633*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1634*2d543d20SAndroid Build Coastguard Worker }
1635*2d543d20SAndroid Build Coastguard Worker semanage_setfiles(semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_HOMEDIRS_BIN));
1636*2d543d20SAndroid Build Coastguard Worker
1637*2d543d20SAndroid Build Coastguard Worker status = 0;
1638*2d543d20SAndroid Build Coastguard Worker cleanup:
1639*2d543d20SAndroid Build Coastguard Worker return status;
1640*2d543d20SAndroid Build Coastguard Worker }
1641*2d543d20SAndroid Build Coastguard Worker
1642*2d543d20SAndroid Build Coastguard Worker /* Load the contexts of the final tmp into the final selinux directory.
1643*2d543d20SAndroid Build Coastguard Worker * Return 0 on success, -3 on error.
1644*2d543d20SAndroid Build Coastguard Worker */
semanage_install_final_tmp(semanage_handle_t * sh)1645*2d543d20SAndroid Build Coastguard Worker static int semanage_install_final_tmp(semanage_handle_t * sh)
1646*2d543d20SAndroid Build Coastguard Worker {
1647*2d543d20SAndroid Build Coastguard Worker int status = -3;
1648*2d543d20SAndroid Build Coastguard Worker int ret = 0;
1649*2d543d20SAndroid Build Coastguard Worker int i = 0;
1650*2d543d20SAndroid Build Coastguard Worker const char *src = NULL;
1651*2d543d20SAndroid Build Coastguard Worker const char *dst = NULL;
1652*2d543d20SAndroid Build Coastguard Worker struct stat sb;
1653*2d543d20SAndroid Build Coastguard Worker char fn[PATH_MAX];
1654*2d543d20SAndroid Build Coastguard Worker
1655*2d543d20SAndroid Build Coastguard Worker /* For each of the final files install it if it exists.
1656*2d543d20SAndroid Build Coastguard Worker * i = 1 to avoid copying the top level directory.
1657*2d543d20SAndroid Build Coastguard Worker */
1658*2d543d20SAndroid Build Coastguard Worker for (i = 1; i < SEMANAGE_FINAL_PATH_NUM; i++) {
1659*2d543d20SAndroid Build Coastguard Worker src = semanage_final_path(SEMANAGE_FINAL_TMP, i);
1660*2d543d20SAndroid Build Coastguard Worker dst = semanage_final_path(SEMANAGE_FINAL_SELINUX, i);
1661*2d543d20SAndroid Build Coastguard Worker
1662*2d543d20SAndroid Build Coastguard Worker /* skip file if src doesn't exist */
1663*2d543d20SAndroid Build Coastguard Worker if (stat(src, &sb) != 0) continue;
1664*2d543d20SAndroid Build Coastguard Worker
1665*2d543d20SAndroid Build Coastguard Worker /* skip genhomedircon if configured */
1666*2d543d20SAndroid Build Coastguard Worker if (sh->conf->disable_genhomedircon &&
1667*2d543d20SAndroid Build Coastguard Worker i == SEMANAGE_FC_HOMEDIRS) continue;
1668*2d543d20SAndroid Build Coastguard Worker
1669*2d543d20SAndroid Build Coastguard Worker if (strlen(dst) >= sizeof(fn)) {
1670*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Unable to compose the final paths.");
1671*2d543d20SAndroid Build Coastguard Worker status = -1;
1672*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1673*2d543d20SAndroid Build Coastguard Worker }
1674*2d543d20SAndroid Build Coastguard Worker strcpy(fn, dst);
1675*2d543d20SAndroid Build Coastguard Worker ret = semanage_mkpath(sh, dirname(fn));
1676*2d543d20SAndroid Build Coastguard Worker if (ret < 0) {
1677*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1678*2d543d20SAndroid Build Coastguard Worker }
1679*2d543d20SAndroid Build Coastguard Worker
1680*2d543d20SAndroid Build Coastguard Worker ret = semanage_copy_file(src, dst, sh->conf->file_mode,
1681*2d543d20SAndroid Build Coastguard Worker true);
1682*2d543d20SAndroid Build Coastguard Worker if (ret < 0) {
1683*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not copy %s to %s.", src, dst);
1684*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1685*2d543d20SAndroid Build Coastguard Worker }
1686*2d543d20SAndroid Build Coastguard Worker }
1687*2d543d20SAndroid Build Coastguard Worker
1688*2d543d20SAndroid Build Coastguard Worker if (!sh->do_reload)
1689*2d543d20SAndroid Build Coastguard Worker goto skip_reload;
1690*2d543d20SAndroid Build Coastguard Worker
1691*2d543d20SAndroid Build Coastguard Worker /* This stats what libselinux says the active store is (according to config)
1692*2d543d20SAndroid Build Coastguard Worker * and what we are installing to, to decide if they are the same store. If
1693*2d543d20SAndroid Build Coastguard Worker * they are not then we do not reload policy.
1694*2d543d20SAndroid Build Coastguard Worker */
1695*2d543d20SAndroid Build Coastguard Worker const char *really_active_store = selinux_policy_root();
1696*2d543d20SAndroid Build Coastguard Worker struct stat astore;
1697*2d543d20SAndroid Build Coastguard Worker struct stat istore;
1698*2d543d20SAndroid Build Coastguard Worker const char *storepath = semanage_final_path(SEMANAGE_FINAL_SELINUX,
1699*2d543d20SAndroid Build Coastguard Worker SEMANAGE_FINAL_TOPLEVEL);
1700*2d543d20SAndroid Build Coastguard Worker
1701*2d543d20SAndroid Build Coastguard Worker if (stat(really_active_store, &astore) == 0) {
1702*2d543d20SAndroid Build Coastguard Worker if (stat(storepath, &istore)) {
1703*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not stat store path %s.", storepath);
1704*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1705*2d543d20SAndroid Build Coastguard Worker }
1706*2d543d20SAndroid Build Coastguard Worker
1707*2d543d20SAndroid Build Coastguard Worker if (!(astore.st_ino == istore.st_ino &&
1708*2d543d20SAndroid Build Coastguard Worker astore.st_dev == istore.st_dev)) {
1709*2d543d20SAndroid Build Coastguard Worker /* They are not the same store */
1710*2d543d20SAndroid Build Coastguard Worker goto skip_reload;
1711*2d543d20SAndroid Build Coastguard Worker }
1712*2d543d20SAndroid Build Coastguard Worker } else if (errno == ENOENT &&
1713*2d543d20SAndroid Build Coastguard Worker strcmp(really_active_store, storepath) != 0) {
1714*2d543d20SAndroid Build Coastguard Worker errno = 0;
1715*2d543d20SAndroid Build Coastguard Worker goto skip_reload;
1716*2d543d20SAndroid Build Coastguard Worker }
1717*2d543d20SAndroid Build Coastguard Worker
1718*2d543d20SAndroid Build Coastguard Worker if (semanage_reload_policy(sh)) {
1719*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1720*2d543d20SAndroid Build Coastguard Worker }
1721*2d543d20SAndroid Build Coastguard Worker
1722*2d543d20SAndroid Build Coastguard Worker skip_reload:
1723*2d543d20SAndroid Build Coastguard Worker status = 0;
1724*2d543d20SAndroid Build Coastguard Worker cleanup:
1725*2d543d20SAndroid Build Coastguard Worker return status;
1726*2d543d20SAndroid Build Coastguard Worker }
1727*2d543d20SAndroid Build Coastguard Worker
1728*2d543d20SAndroid Build Coastguard Worker /* Prepare the sandbox to be installed by making a backup of the
1729*2d543d20SAndroid Build Coastguard Worker * current active directory. Then copy the sandbox to the active
1730*2d543d20SAndroid Build Coastguard Worker * directory. Return the new commit number on success, negative
1731*2d543d20SAndroid Build Coastguard Worker * values on error. */
semanage_commit_sandbox(semanage_handle_t * sh)1732*2d543d20SAndroid Build Coastguard Worker static int semanage_commit_sandbox(semanage_handle_t * sh)
1733*2d543d20SAndroid Build Coastguard Worker {
1734*2d543d20SAndroid Build Coastguard Worker int commit_number, fd, retval;
1735*2d543d20SAndroid Build Coastguard Worker char write_buf[32];
1736*2d543d20SAndroid Build Coastguard Worker const char *commit_filename =
1737*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE);
1738*2d543d20SAndroid Build Coastguard Worker ssize_t amount_written;
1739*2d543d20SAndroid Build Coastguard Worker const char *active = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_TOPLEVEL);
1740*2d543d20SAndroid Build Coastguard Worker const char *backup =
1741*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_PREVIOUS, SEMANAGE_TOPLEVEL);
1742*2d543d20SAndroid Build Coastguard Worker const char *sandbox = semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL);
1743*2d543d20SAndroid Build Coastguard Worker struct stat buf;
1744*2d543d20SAndroid Build Coastguard Worker
1745*2d543d20SAndroid Build Coastguard Worker /* update the commit number */
1746*2d543d20SAndroid Build Coastguard Worker if ((commit_number = semanage_direct_get_serial(sh)) < 0) {
1747*2d543d20SAndroid Build Coastguard Worker return -1;
1748*2d543d20SAndroid Build Coastguard Worker }
1749*2d543d20SAndroid Build Coastguard Worker commit_number++;
1750*2d543d20SAndroid Build Coastguard Worker memset(write_buf, 0, sizeof(write_buf));
1751*2d543d20SAndroid Build Coastguard Worker snprintf(write_buf, sizeof(write_buf), "%d", commit_number);
1752*2d543d20SAndroid Build Coastguard Worker if ((fd =
1753*2d543d20SAndroid Build Coastguard Worker open(commit_filename, O_WRONLY | O_CREAT | O_TRUNC,
1754*2d543d20SAndroid Build Coastguard Worker S_IRUSR | S_IWUSR)) == -1) {
1755*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open commit number file %s for writing.",
1756*2d543d20SAndroid Build Coastguard Worker commit_filename);
1757*2d543d20SAndroid Build Coastguard Worker return -1;
1758*2d543d20SAndroid Build Coastguard Worker }
1759*2d543d20SAndroid Build Coastguard Worker amount_written = write(fd, write_buf, sizeof(write_buf));
1760*2d543d20SAndroid Build Coastguard Worker if (amount_written == -1) {
1761*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while writing commit number to %s.",
1762*2d543d20SAndroid Build Coastguard Worker commit_filename);
1763*2d543d20SAndroid Build Coastguard Worker close(fd);
1764*2d543d20SAndroid Build Coastguard Worker return -1;
1765*2d543d20SAndroid Build Coastguard Worker }
1766*2d543d20SAndroid Build Coastguard Worker close(fd);
1767*2d543d20SAndroid Build Coastguard Worker
1768*2d543d20SAndroid Build Coastguard Worker /* sync changes in sandbox to filesystem */
1769*2d543d20SAndroid Build Coastguard Worker fd = open(sandbox, O_DIRECTORY);
1770*2d543d20SAndroid Build Coastguard Worker if (fd == -1) {
1771*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while opening %s for syncfs(): %d", sandbox, errno);
1772*2d543d20SAndroid Build Coastguard Worker return -1;
1773*2d543d20SAndroid Build Coastguard Worker }
1774*2d543d20SAndroid Build Coastguard Worker if (syncfs(fd) == -1) {
1775*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while syncing %s to filesystem: %d", sandbox, errno);
1776*2d543d20SAndroid Build Coastguard Worker close(fd);
1777*2d543d20SAndroid Build Coastguard Worker return -1;
1778*2d543d20SAndroid Build Coastguard Worker }
1779*2d543d20SAndroid Build Coastguard Worker close(fd);
1780*2d543d20SAndroid Build Coastguard Worker
1781*2d543d20SAndroid Build Coastguard Worker retval = commit_number;
1782*2d543d20SAndroid Build Coastguard Worker
1783*2d543d20SAndroid Build Coastguard Worker if (semanage_get_active_lock(sh) < 0) {
1784*2d543d20SAndroid Build Coastguard Worker return -1;
1785*2d543d20SAndroid Build Coastguard Worker }
1786*2d543d20SAndroid Build Coastguard Worker /* make the backup of the current active directory */
1787*2d543d20SAndroid Build Coastguard Worker if (stat(backup, &buf) == 0) {
1788*2d543d20SAndroid Build Coastguard Worker if (S_ISDIR(buf.st_mode) &&
1789*2d543d20SAndroid Build Coastguard Worker semanage_remove_directory(backup) != 0) {
1790*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not remove previous backup %s.", backup);
1791*2d543d20SAndroid Build Coastguard Worker retval = -1;
1792*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1793*2d543d20SAndroid Build Coastguard Worker }
1794*2d543d20SAndroid Build Coastguard Worker } else if (errno != ENOENT) {
1795*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not stat directory %s.", backup);
1796*2d543d20SAndroid Build Coastguard Worker retval = -1;
1797*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1798*2d543d20SAndroid Build Coastguard Worker }
1799*2d543d20SAndroid Build Coastguard Worker
1800*2d543d20SAndroid Build Coastguard Worker if (semanage_rename(sh, active, backup) == -1) {
1801*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while renaming %s to %s.", active, backup);
1802*2d543d20SAndroid Build Coastguard Worker retval = -1;
1803*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1804*2d543d20SAndroid Build Coastguard Worker }
1805*2d543d20SAndroid Build Coastguard Worker
1806*2d543d20SAndroid Build Coastguard Worker /* clean up some files from the sandbox before install */
1807*2d543d20SAndroid Build Coastguard Worker /* remove homedir_template from sandbox */
1808*2d543d20SAndroid Build Coastguard Worker
1809*2d543d20SAndroid Build Coastguard Worker if (semanage_rename(sh, sandbox, active) == -1) {
1810*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while renaming %s to %s.", sandbox, active);
1811*2d543d20SAndroid Build Coastguard Worker /* note that if an error occurs during the next
1812*2d543d20SAndroid Build Coastguard Worker * function then the store will be left in an
1813*2d543d20SAndroid Build Coastguard Worker * inconsistent state */
1814*2d543d20SAndroid Build Coastguard Worker if (semanage_rename(sh, backup, active) < 0)
1815*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while renaming %s back to %s.", backup,
1816*2d543d20SAndroid Build Coastguard Worker active);
1817*2d543d20SAndroid Build Coastguard Worker retval = -1;
1818*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1819*2d543d20SAndroid Build Coastguard Worker }
1820*2d543d20SAndroid Build Coastguard Worker if (semanage_install_final_tmp(sh) != 0) {
1821*2d543d20SAndroid Build Coastguard Worker /* note that if an error occurs during the next three
1822*2d543d20SAndroid Build Coastguard Worker * function then the store will be left in an
1823*2d543d20SAndroid Build Coastguard Worker * inconsistent state */
1824*2d543d20SAndroid Build Coastguard Worker int errsv = errno;
1825*2d543d20SAndroid Build Coastguard Worker if (semanage_rename(sh, active, sandbox) < 0)
1826*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while renaming %s back to %s.", active,
1827*2d543d20SAndroid Build Coastguard Worker sandbox);
1828*2d543d20SAndroid Build Coastguard Worker else if (semanage_rename(sh, backup, active) < 0)
1829*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while renaming %s back to %s.", backup,
1830*2d543d20SAndroid Build Coastguard Worker active);
1831*2d543d20SAndroid Build Coastguard Worker else
1832*2d543d20SAndroid Build Coastguard Worker semanage_install_final_tmp(sh);
1833*2d543d20SAndroid Build Coastguard Worker errno = errsv;
1834*2d543d20SAndroid Build Coastguard Worker retval = -1;
1835*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1836*2d543d20SAndroid Build Coastguard Worker }
1837*2d543d20SAndroid Build Coastguard Worker
1838*2d543d20SAndroid Build Coastguard Worker if (!sh->conf->save_previous) {
1839*2d543d20SAndroid Build Coastguard Worker int errsv = errno;
1840*2d543d20SAndroid Build Coastguard Worker if (semanage_remove_directory(backup) != 0) {
1841*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not delete previous directory %s.", backup);
1842*2d543d20SAndroid Build Coastguard Worker retval = -1;
1843*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1844*2d543d20SAndroid Build Coastguard Worker }
1845*2d543d20SAndroid Build Coastguard Worker errno = errsv;
1846*2d543d20SAndroid Build Coastguard Worker }
1847*2d543d20SAndroid Build Coastguard Worker
1848*2d543d20SAndroid Build Coastguard Worker cleanup:
1849*2d543d20SAndroid Build Coastguard Worker semanage_release_active_lock(sh);
1850*2d543d20SAndroid Build Coastguard Worker return retval;
1851*2d543d20SAndroid Build Coastguard Worker }
1852*2d543d20SAndroid Build Coastguard Worker
1853*2d543d20SAndroid Build Coastguard Worker /* Takes the kernel policy in a sandbox, move it to the active
1854*2d543d20SAndroid Build Coastguard Worker * directory, copy it to the binary policy path, then load it. Upon
1855*2d543d20SAndroid Build Coastguard Worker * error move the active directory back to the sandbox. This function
1856*2d543d20SAndroid Build Coastguard Worker * should be placed within a mutex lock to ensure that it runs
1857*2d543d20SAndroid Build Coastguard Worker * atomically. Returns commit number on success, -1 on error.
1858*2d543d20SAndroid Build Coastguard Worker */
semanage_install_sandbox(semanage_handle_t * sh)1859*2d543d20SAndroid Build Coastguard Worker int semanage_install_sandbox(semanage_handle_t * sh)
1860*2d543d20SAndroid Build Coastguard Worker {
1861*2d543d20SAndroid Build Coastguard Worker int retval = -1, commit_num = -1;
1862*2d543d20SAndroid Build Coastguard Worker
1863*2d543d20SAndroid Build Coastguard Worker if (sh->conf->load_policy == NULL) {
1864*2d543d20SAndroid Build Coastguard Worker ERR(sh,
1865*2d543d20SAndroid Build Coastguard Worker "No load_policy program specified in configuration file.");
1866*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1867*2d543d20SAndroid Build Coastguard Worker }
1868*2d543d20SAndroid Build Coastguard Worker if (sh->conf->setfiles == NULL) {
1869*2d543d20SAndroid Build Coastguard Worker ERR(sh, "No setfiles program specified in configuration file.");
1870*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1871*2d543d20SAndroid Build Coastguard Worker }
1872*2d543d20SAndroid Build Coastguard Worker
1873*2d543d20SAndroid Build Coastguard Worker if (sh->conf->sefcontext_compile == NULL) {
1874*2d543d20SAndroid Build Coastguard Worker ERR(sh, "No sefcontext_compile program specified in configuration file.");
1875*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1876*2d543d20SAndroid Build Coastguard Worker }
1877*2d543d20SAndroid Build Coastguard Worker
1878*2d543d20SAndroid Build Coastguard Worker if (semanage_validate_and_compile_fcontexts(sh) < 0)
1879*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1880*2d543d20SAndroid Build Coastguard Worker
1881*2d543d20SAndroid Build Coastguard Worker if ((commit_num = semanage_commit_sandbox(sh)) < 0) {
1882*2d543d20SAndroid Build Coastguard Worker retval = commit_num;
1883*2d543d20SAndroid Build Coastguard Worker goto cleanup;
1884*2d543d20SAndroid Build Coastguard Worker }
1885*2d543d20SAndroid Build Coastguard Worker
1886*2d543d20SAndroid Build Coastguard Worker retval = commit_num;
1887*2d543d20SAndroid Build Coastguard Worker
1888*2d543d20SAndroid Build Coastguard Worker cleanup:
1889*2d543d20SAndroid Build Coastguard Worker return retval;
1890*2d543d20SAndroid Build Coastguard Worker
1891*2d543d20SAndroid Build Coastguard Worker }
1892*2d543d20SAndroid Build Coastguard Worker
1893*2d543d20SAndroid Build Coastguard Worker /********************* functions that manipulate lock *********************/
1894*2d543d20SAndroid Build Coastguard Worker
semanage_get_lock(semanage_handle_t * sh,const char * lock_name,const char * lock_file)1895*2d543d20SAndroid Build Coastguard Worker static int semanage_get_lock(semanage_handle_t * sh,
1896*2d543d20SAndroid Build Coastguard Worker const char *lock_name, const char *lock_file)
1897*2d543d20SAndroid Build Coastguard Worker {
1898*2d543d20SAndroid Build Coastguard Worker int fd;
1899*2d543d20SAndroid Build Coastguard Worker struct timeval origtime, curtime;
1900*2d543d20SAndroid Build Coastguard Worker int got_lock = 0;
1901*2d543d20SAndroid Build Coastguard Worker
1902*2d543d20SAndroid Build Coastguard Worker if ((fd = open(lock_file, O_RDONLY)) == -1) {
1903*2d543d20SAndroid Build Coastguard Worker if ((fd =
1904*2d543d20SAndroid Build Coastguard Worker open(lock_file, O_RDWR | O_CREAT | O_TRUNC,
1905*2d543d20SAndroid Build Coastguard Worker S_IRUSR | S_IWUSR)) == -1) {
1906*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open direct %s at %s.", lock_name,
1907*2d543d20SAndroid Build Coastguard Worker lock_file);
1908*2d543d20SAndroid Build Coastguard Worker return -1;
1909*2d543d20SAndroid Build Coastguard Worker }
1910*2d543d20SAndroid Build Coastguard Worker }
1911*2d543d20SAndroid Build Coastguard Worker if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0) {
1912*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not set close-on-exec for %s at %s.", lock_name,
1913*2d543d20SAndroid Build Coastguard Worker lock_file);
1914*2d543d20SAndroid Build Coastguard Worker close(fd);
1915*2d543d20SAndroid Build Coastguard Worker return -1;
1916*2d543d20SAndroid Build Coastguard Worker }
1917*2d543d20SAndroid Build Coastguard Worker
1918*2d543d20SAndroid Build Coastguard Worker if (sh->timeout == 0) {
1919*2d543d20SAndroid Build Coastguard Worker /* return immediately */
1920*2d543d20SAndroid Build Coastguard Worker origtime.tv_sec = 0;
1921*2d543d20SAndroid Build Coastguard Worker } else {
1922*2d543d20SAndroid Build Coastguard Worker origtime.tv_sec = sh->timeout;
1923*2d543d20SAndroid Build Coastguard Worker }
1924*2d543d20SAndroid Build Coastguard Worker origtime.tv_usec = 0;
1925*2d543d20SAndroid Build Coastguard Worker do {
1926*2d543d20SAndroid Build Coastguard Worker curtime.tv_sec = 1;
1927*2d543d20SAndroid Build Coastguard Worker curtime.tv_usec = 0;
1928*2d543d20SAndroid Build Coastguard Worker if (flock(fd, LOCK_EX | LOCK_NB) == 0) {
1929*2d543d20SAndroid Build Coastguard Worker got_lock = 1;
1930*2d543d20SAndroid Build Coastguard Worker break;
1931*2d543d20SAndroid Build Coastguard Worker } else if (errno != EAGAIN) {
1932*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error obtaining direct %s at %s.", lock_name,
1933*2d543d20SAndroid Build Coastguard Worker lock_file);
1934*2d543d20SAndroid Build Coastguard Worker close(fd);
1935*2d543d20SAndroid Build Coastguard Worker return -1;
1936*2d543d20SAndroid Build Coastguard Worker }
1937*2d543d20SAndroid Build Coastguard Worker if (origtime.tv_sec > 0 || sh->timeout == -1) {
1938*2d543d20SAndroid Build Coastguard Worker if (select(0, NULL, NULL, NULL, &curtime) == -1) {
1939*2d543d20SAndroid Build Coastguard Worker if (errno == EINTR) {
1940*2d543d20SAndroid Build Coastguard Worker continue;
1941*2d543d20SAndroid Build Coastguard Worker }
1942*2d543d20SAndroid Build Coastguard Worker ERR(sh,
1943*2d543d20SAndroid Build Coastguard Worker "Error while waiting to get direct %s at %s.",
1944*2d543d20SAndroid Build Coastguard Worker lock_name, lock_file);
1945*2d543d20SAndroid Build Coastguard Worker close(fd);
1946*2d543d20SAndroid Build Coastguard Worker return -1;
1947*2d543d20SAndroid Build Coastguard Worker }
1948*2d543d20SAndroid Build Coastguard Worker origtime.tv_sec--;
1949*2d543d20SAndroid Build Coastguard Worker }
1950*2d543d20SAndroid Build Coastguard Worker } while (origtime.tv_sec > 0 || sh->timeout == -1);
1951*2d543d20SAndroid Build Coastguard Worker if (!got_lock) {
1952*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not get direct %s at %s.", lock_name, lock_file);
1953*2d543d20SAndroid Build Coastguard Worker close(fd);
1954*2d543d20SAndroid Build Coastguard Worker return -1;
1955*2d543d20SAndroid Build Coastguard Worker }
1956*2d543d20SAndroid Build Coastguard Worker return fd;
1957*2d543d20SAndroid Build Coastguard Worker }
1958*2d543d20SAndroid Build Coastguard Worker
1959*2d543d20SAndroid Build Coastguard Worker /* Locking for the module store for transactions. This is very basic
1960*2d543d20SAndroid Build Coastguard Worker * locking of the module store and doesn't do anything if the module
1961*2d543d20SAndroid Build Coastguard Worker * store is being manipulated with a program not using this library
1962*2d543d20SAndroid Build Coastguard Worker * (but the policy should prevent that). Returns 0 on success, -1 if
1963*2d543d20SAndroid Build Coastguard Worker * it could not obtain a lock.
1964*2d543d20SAndroid Build Coastguard Worker */
semanage_get_trans_lock(semanage_handle_t * sh)1965*2d543d20SAndroid Build Coastguard Worker int semanage_get_trans_lock(semanage_handle_t * sh)
1966*2d543d20SAndroid Build Coastguard Worker {
1967*2d543d20SAndroid Build Coastguard Worker const char *lock_file = semanage_files[SEMANAGE_TRANS_LOCK];
1968*2d543d20SAndroid Build Coastguard Worker
1969*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.translock_file_fd >= 0)
1970*2d543d20SAndroid Build Coastguard Worker return 0;
1971*2d543d20SAndroid Build Coastguard Worker
1972*2d543d20SAndroid Build Coastguard Worker sh->u.direct.translock_file_fd =
1973*2d543d20SAndroid Build Coastguard Worker semanage_get_lock(sh, "transaction lock", lock_file);
1974*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.translock_file_fd >= 0) {
1975*2d543d20SAndroid Build Coastguard Worker return 0;
1976*2d543d20SAndroid Build Coastguard Worker } else {
1977*2d543d20SAndroid Build Coastguard Worker return -1;
1978*2d543d20SAndroid Build Coastguard Worker }
1979*2d543d20SAndroid Build Coastguard Worker }
1980*2d543d20SAndroid Build Coastguard Worker
1981*2d543d20SAndroid Build Coastguard Worker /* Locking for the module store for active store reading; this also includes
1982*2d543d20SAndroid Build Coastguard Worker * the file containing the commit number. This is very basic locking
1983*2d543d20SAndroid Build Coastguard Worker * of the module store and doesn't do anything if the module store is
1984*2d543d20SAndroid Build Coastguard Worker * being manipulated with a program not using this library (but the
1985*2d543d20SAndroid Build Coastguard Worker * policy should prevent that). Returns 0 on success, -1 if it could
1986*2d543d20SAndroid Build Coastguard Worker * not obtain a lock.
1987*2d543d20SAndroid Build Coastguard Worker */
semanage_get_active_lock(semanage_handle_t * sh)1988*2d543d20SAndroid Build Coastguard Worker int semanage_get_active_lock(semanage_handle_t * sh)
1989*2d543d20SAndroid Build Coastguard Worker {
1990*2d543d20SAndroid Build Coastguard Worker const char *lock_file = semanage_files[SEMANAGE_READ_LOCK];
1991*2d543d20SAndroid Build Coastguard Worker
1992*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.activelock_file_fd >= 0)
1993*2d543d20SAndroid Build Coastguard Worker return 0;
1994*2d543d20SAndroid Build Coastguard Worker
1995*2d543d20SAndroid Build Coastguard Worker sh->u.direct.activelock_file_fd =
1996*2d543d20SAndroid Build Coastguard Worker semanage_get_lock(sh, "read lock", lock_file);
1997*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.activelock_file_fd >= 0) {
1998*2d543d20SAndroid Build Coastguard Worker return 0;
1999*2d543d20SAndroid Build Coastguard Worker } else {
2000*2d543d20SAndroid Build Coastguard Worker return -1;
2001*2d543d20SAndroid Build Coastguard Worker }
2002*2d543d20SAndroid Build Coastguard Worker }
2003*2d543d20SAndroid Build Coastguard Worker
2004*2d543d20SAndroid Build Coastguard Worker /* Releases the transaction lock. Does nothing if there was not one already
2005*2d543d20SAndroid Build Coastguard Worker * there. */
semanage_release_trans_lock(semanage_handle_t * sh)2006*2d543d20SAndroid Build Coastguard Worker void semanage_release_trans_lock(semanage_handle_t * sh)
2007*2d543d20SAndroid Build Coastguard Worker {
2008*2d543d20SAndroid Build Coastguard Worker int errsv = errno;
2009*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.translock_file_fd >= 0) {
2010*2d543d20SAndroid Build Coastguard Worker flock(sh->u.direct.translock_file_fd, LOCK_UN);
2011*2d543d20SAndroid Build Coastguard Worker close(sh->u.direct.translock_file_fd);
2012*2d543d20SAndroid Build Coastguard Worker sh->u.direct.translock_file_fd = -1;
2013*2d543d20SAndroid Build Coastguard Worker }
2014*2d543d20SAndroid Build Coastguard Worker errno = errsv;
2015*2d543d20SAndroid Build Coastguard Worker }
2016*2d543d20SAndroid Build Coastguard Worker
2017*2d543d20SAndroid Build Coastguard Worker /* Releases the read lock. Does nothing if there was not one already
2018*2d543d20SAndroid Build Coastguard Worker * there. */
semanage_release_active_lock(semanage_handle_t * sh)2019*2d543d20SAndroid Build Coastguard Worker void semanage_release_active_lock(semanage_handle_t * sh)
2020*2d543d20SAndroid Build Coastguard Worker {
2021*2d543d20SAndroid Build Coastguard Worker int errsv = errno;
2022*2d543d20SAndroid Build Coastguard Worker if (sh->u.direct.activelock_file_fd >= 0) {
2023*2d543d20SAndroid Build Coastguard Worker flock(sh->u.direct.activelock_file_fd, LOCK_UN);
2024*2d543d20SAndroid Build Coastguard Worker close(sh->u.direct.activelock_file_fd);
2025*2d543d20SAndroid Build Coastguard Worker sh->u.direct.activelock_file_fd = -1;
2026*2d543d20SAndroid Build Coastguard Worker }
2027*2d543d20SAndroid Build Coastguard Worker errno = errsv;
2028*2d543d20SAndroid Build Coastguard Worker }
2029*2d543d20SAndroid Build Coastguard Worker
2030*2d543d20SAndroid Build Coastguard Worker /* Read the current commit number from the commit number file which
2031*2d543d20SAndroid Build Coastguard Worker * the handle is pointing, resetting the file pointer afterwards.
2032*2d543d20SAndroid Build Coastguard Worker * Return it (a non-negative number), or -1 on error. */
semanage_direct_get_serial(semanage_handle_t * sh)2033*2d543d20SAndroid Build Coastguard Worker int semanage_direct_get_serial(semanage_handle_t * sh)
2034*2d543d20SAndroid Build Coastguard Worker {
2035*2d543d20SAndroid Build Coastguard Worker char buf[32];
2036*2d543d20SAndroid Build Coastguard Worker int fd, commit_number;
2037*2d543d20SAndroid Build Coastguard Worker ssize_t amount_read;
2038*2d543d20SAndroid Build Coastguard Worker const char *commit_filename;
2039*2d543d20SAndroid Build Coastguard Worker memset(buf, 0, sizeof(buf));
2040*2d543d20SAndroid Build Coastguard Worker
2041*2d543d20SAndroid Build Coastguard Worker if (sh->is_in_transaction) {
2042*2d543d20SAndroid Build Coastguard Worker commit_filename =
2043*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_COMMIT_NUM_FILE);
2044*2d543d20SAndroid Build Coastguard Worker } else {
2045*2d543d20SAndroid Build Coastguard Worker commit_filename =
2046*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_ACTIVE, SEMANAGE_COMMIT_NUM_FILE);
2047*2d543d20SAndroid Build Coastguard Worker }
2048*2d543d20SAndroid Build Coastguard Worker
2049*2d543d20SAndroid Build Coastguard Worker if ((fd = open(commit_filename, O_RDONLY)) == -1) {
2050*2d543d20SAndroid Build Coastguard Worker if (errno == ENOENT) {
2051*2d543d20SAndroid Build Coastguard Worker /* the commit number file does not exist yet,
2052*2d543d20SAndroid Build Coastguard Worker * so assume that the number is 0 */
2053*2d543d20SAndroid Build Coastguard Worker errno = 0;
2054*2d543d20SAndroid Build Coastguard Worker return 0;
2055*2d543d20SAndroid Build Coastguard Worker } else {
2056*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open commit number file %s.",
2057*2d543d20SAndroid Build Coastguard Worker commit_filename);
2058*2d543d20SAndroid Build Coastguard Worker return -1;
2059*2d543d20SAndroid Build Coastguard Worker }
2060*2d543d20SAndroid Build Coastguard Worker }
2061*2d543d20SAndroid Build Coastguard Worker
2062*2d543d20SAndroid Build Coastguard Worker amount_read = read(fd, buf, sizeof(buf));
2063*2d543d20SAndroid Build Coastguard Worker if (amount_read == -1) {
2064*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while reading commit number from %s.",
2065*2d543d20SAndroid Build Coastguard Worker commit_filename);
2066*2d543d20SAndroid Build Coastguard Worker commit_number = -1;
2067*2d543d20SAndroid Build Coastguard Worker } else if (sscanf(buf, "%d", &commit_number) != 1) {
2068*2d543d20SAndroid Build Coastguard Worker /* if nothing was read, assume that the commit number is 0 */
2069*2d543d20SAndroid Build Coastguard Worker commit_number = 0;
2070*2d543d20SAndroid Build Coastguard Worker } else if (commit_number < 0) {
2071*2d543d20SAndroid Build Coastguard Worker /* read file ought never have negative values */
2072*2d543d20SAndroid Build Coastguard Worker ERR(sh,
2073*2d543d20SAndroid Build Coastguard Worker "Commit number file %s is corrupted; it should only contain a non-negative integer.",
2074*2d543d20SAndroid Build Coastguard Worker commit_filename);
2075*2d543d20SAndroid Build Coastguard Worker commit_number = -1;
2076*2d543d20SAndroid Build Coastguard Worker }
2077*2d543d20SAndroid Build Coastguard Worker
2078*2d543d20SAndroid Build Coastguard Worker close(fd);
2079*2d543d20SAndroid Build Coastguard Worker return commit_number;
2080*2d543d20SAndroid Build Coastguard Worker }
2081*2d543d20SAndroid Build Coastguard Worker
2082*2d543d20SAndroid Build Coastguard Worker /* HIGHER LEVEL COMMIT FUNCTIONS */
2083*2d543d20SAndroid Build Coastguard Worker
semanage_load_files(semanage_handle_t * sh,cil_db_t * cildb,char ** filenames,int numfiles)2084*2d543d20SAndroid Build Coastguard Worker int semanage_load_files(semanage_handle_t * sh, cil_db_t *cildb, char **filenames, int numfiles)
2085*2d543d20SAndroid Build Coastguard Worker {
2086*2d543d20SAndroid Build Coastguard Worker int i, retval = 0;
2087*2d543d20SAndroid Build Coastguard Worker char *filename;
2088*2d543d20SAndroid Build Coastguard Worker struct file_contents contents = {};
2089*2d543d20SAndroid Build Coastguard Worker
2090*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < numfiles; i++) {
2091*2d543d20SAndroid Build Coastguard Worker filename = filenames[i];
2092*2d543d20SAndroid Build Coastguard Worker
2093*2d543d20SAndroid Build Coastguard Worker retval = map_compressed_file(sh, filename, &contents);
2094*2d543d20SAndroid Build Coastguard Worker if (retval < 0)
2095*2d543d20SAndroid Build Coastguard Worker return -1;
2096*2d543d20SAndroid Build Coastguard Worker
2097*2d543d20SAndroid Build Coastguard Worker retval = cil_add_file(cildb, filename, contents.data, contents.len);
2098*2d543d20SAndroid Build Coastguard Worker unmap_compressed_file(&contents);
2099*2d543d20SAndroid Build Coastguard Worker
2100*2d543d20SAndroid Build Coastguard Worker if (retval != SEPOL_OK) {
2101*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while reading from file %s.", filename);
2102*2d543d20SAndroid Build Coastguard Worker return -1;
2103*2d543d20SAndroid Build Coastguard Worker }
2104*2d543d20SAndroid Build Coastguard Worker }
2105*2d543d20SAndroid Build Coastguard Worker
2106*2d543d20SAndroid Build Coastguard Worker return 0;
2107*2d543d20SAndroid Build Coastguard Worker }
2108*2d543d20SAndroid Build Coastguard Worker
2109*2d543d20SAndroid Build Coastguard Worker /*
2110*2d543d20SAndroid Build Coastguard Worker * Expands the policy contained within *base
2111*2d543d20SAndroid Build Coastguard Worker */
2112*2d543d20SAndroid Build Coastguard Worker
2113*2d543d20SAndroid Build Coastguard Worker /**
2114*2d543d20SAndroid Build Coastguard Worker * Read the policy from the sandbox (linked or kernel)
2115*2d543d20SAndroid Build Coastguard Worker */
semanage_read_policydb(semanage_handle_t * sh,sepol_policydb_t * in,enum semanage_sandbox_defs file)2116*2d543d20SAndroid Build Coastguard Worker int semanage_read_policydb(semanage_handle_t * sh, sepol_policydb_t * in,
2117*2d543d20SAndroid Build Coastguard Worker enum semanage_sandbox_defs file)
2118*2d543d20SAndroid Build Coastguard Worker {
2119*2d543d20SAndroid Build Coastguard Worker
2120*2d543d20SAndroid Build Coastguard Worker int retval = STATUS_ERR;
2121*2d543d20SAndroid Build Coastguard Worker const char *kernel_filename = NULL;
2122*2d543d20SAndroid Build Coastguard Worker struct sepol_policy_file *pf = NULL;
2123*2d543d20SAndroid Build Coastguard Worker FILE *infile = NULL;
2124*2d543d20SAndroid Build Coastguard Worker
2125*2d543d20SAndroid Build Coastguard Worker if ((kernel_filename =
2126*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_ACTIVE, file)) == NULL) {
2127*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2128*2d543d20SAndroid Build Coastguard Worker }
2129*2d543d20SAndroid Build Coastguard Worker if ((infile = fopen(kernel_filename, "r")) == NULL) {
2130*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open kernel policy %s for reading.",
2131*2d543d20SAndroid Build Coastguard Worker kernel_filename);
2132*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2133*2d543d20SAndroid Build Coastguard Worker }
2134*2d543d20SAndroid Build Coastguard Worker __fsetlocking(infile, FSETLOCKING_BYCALLER);
2135*2d543d20SAndroid Build Coastguard Worker if (sepol_policy_file_create(&pf)) {
2136*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Out of memory!");
2137*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2138*2d543d20SAndroid Build Coastguard Worker }
2139*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_fp(pf, infile);
2140*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_handle(pf, sh->sepolh);
2141*2d543d20SAndroid Build Coastguard Worker if (sepol_policydb_read(in, pf) == -1) {
2142*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while reading kernel policy from %s.",
2143*2d543d20SAndroid Build Coastguard Worker kernel_filename);
2144*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2145*2d543d20SAndroid Build Coastguard Worker }
2146*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
2147*2d543d20SAndroid Build Coastguard Worker
2148*2d543d20SAndroid Build Coastguard Worker cleanup:
2149*2d543d20SAndroid Build Coastguard Worker if (infile != NULL) {
2150*2d543d20SAndroid Build Coastguard Worker fclose(infile);
2151*2d543d20SAndroid Build Coastguard Worker }
2152*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_free(pf);
2153*2d543d20SAndroid Build Coastguard Worker return retval;
2154*2d543d20SAndroid Build Coastguard Worker }
2155*2d543d20SAndroid Build Coastguard Worker /**
2156*2d543d20SAndroid Build Coastguard Worker * Writes the policy to the sandbox (linked or kernel)
2157*2d543d20SAndroid Build Coastguard Worker */
semanage_write_policydb(semanage_handle_t * sh,sepol_policydb_t * out,enum semanage_sandbox_defs file)2158*2d543d20SAndroid Build Coastguard Worker int semanage_write_policydb(semanage_handle_t * sh, sepol_policydb_t * out,
2159*2d543d20SAndroid Build Coastguard Worker enum semanage_sandbox_defs file)
2160*2d543d20SAndroid Build Coastguard Worker {
2161*2d543d20SAndroid Build Coastguard Worker
2162*2d543d20SAndroid Build Coastguard Worker int retval = STATUS_ERR;
2163*2d543d20SAndroid Build Coastguard Worker const char *kernel_filename = NULL;
2164*2d543d20SAndroid Build Coastguard Worker struct sepol_policy_file *pf = NULL;
2165*2d543d20SAndroid Build Coastguard Worker FILE *outfile = NULL;
2166*2d543d20SAndroid Build Coastguard Worker mode_t mask = umask(0077);
2167*2d543d20SAndroid Build Coastguard Worker
2168*2d543d20SAndroid Build Coastguard Worker if ((kernel_filename =
2169*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, file)) == NULL) {
2170*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2171*2d543d20SAndroid Build Coastguard Worker }
2172*2d543d20SAndroid Build Coastguard Worker if ((outfile = fopen(kernel_filename, "wb")) == NULL) {
2173*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Could not open kernel policy %s for writing.",
2174*2d543d20SAndroid Build Coastguard Worker kernel_filename);
2175*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2176*2d543d20SAndroid Build Coastguard Worker }
2177*2d543d20SAndroid Build Coastguard Worker __fsetlocking(outfile, FSETLOCKING_BYCALLER);
2178*2d543d20SAndroid Build Coastguard Worker if (sepol_policy_file_create(&pf)) {
2179*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Out of memory!");
2180*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2181*2d543d20SAndroid Build Coastguard Worker }
2182*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_fp(pf, outfile);
2183*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_set_handle(pf, sh->sepolh);
2184*2d543d20SAndroid Build Coastguard Worker if (sepol_policydb_write(out, pf) == -1) {
2185*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Error while writing kernel policy to %s.",
2186*2d543d20SAndroid Build Coastguard Worker kernel_filename);
2187*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2188*2d543d20SAndroid Build Coastguard Worker }
2189*2d543d20SAndroid Build Coastguard Worker retval = STATUS_SUCCESS;
2190*2d543d20SAndroid Build Coastguard Worker
2191*2d543d20SAndroid Build Coastguard Worker cleanup:
2192*2d543d20SAndroid Build Coastguard Worker if (outfile != NULL) {
2193*2d543d20SAndroid Build Coastguard Worker fclose(outfile);
2194*2d543d20SAndroid Build Coastguard Worker }
2195*2d543d20SAndroid Build Coastguard Worker umask(mask);
2196*2d543d20SAndroid Build Coastguard Worker sepol_policy_file_free(pf);
2197*2d543d20SAndroid Build Coastguard Worker return retval;
2198*2d543d20SAndroid Build Coastguard Worker }
2199*2d543d20SAndroid Build Coastguard Worker
2200*2d543d20SAndroid Build Coastguard Worker /* Execute the module verification programs for each source module.
2201*2d543d20SAndroid Build Coastguard Worker * Returns 0 if every verifier returned success, -1 on error.
2202*2d543d20SAndroid Build Coastguard Worker */
semanage_verify_modules(semanage_handle_t * sh,char ** module_filenames,int num_modules)2203*2d543d20SAndroid Build Coastguard Worker int semanage_verify_modules(semanage_handle_t * sh,
2204*2d543d20SAndroid Build Coastguard Worker char **module_filenames, int num_modules)
2205*2d543d20SAndroid Build Coastguard Worker {
2206*2d543d20SAndroid Build Coastguard Worker int i, retval;
2207*2d543d20SAndroid Build Coastguard Worker semanage_conf_t *conf = sh->conf;
2208*2d543d20SAndroid Build Coastguard Worker if (conf->mod_prog == NULL) {
2209*2d543d20SAndroid Build Coastguard Worker return 0;
2210*2d543d20SAndroid Build Coastguard Worker }
2211*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < num_modules; i++) {
2212*2d543d20SAndroid Build Coastguard Worker char *module = module_filenames[i];
2213*2d543d20SAndroid Build Coastguard Worker external_prog_t *e;
2214*2d543d20SAndroid Build Coastguard Worker for (e = conf->mod_prog; e != NULL; e = e->next) {
2215*2d543d20SAndroid Build Coastguard Worker if ((retval =
2216*2d543d20SAndroid Build Coastguard Worker semanage_exec_prog(sh, e, module, "$<")) != 0) {
2217*2d543d20SAndroid Build Coastguard Worker return -1;
2218*2d543d20SAndroid Build Coastguard Worker }
2219*2d543d20SAndroid Build Coastguard Worker }
2220*2d543d20SAndroid Build Coastguard Worker }
2221*2d543d20SAndroid Build Coastguard Worker return 0;
2222*2d543d20SAndroid Build Coastguard Worker }
2223*2d543d20SAndroid Build Coastguard Worker
2224*2d543d20SAndroid Build Coastguard Worker /* Execute the linker verification programs for the linked (but not
2225*2d543d20SAndroid Build Coastguard Worker * expanded) base. Returns 0 if every verifier returned success, -1
2226*2d543d20SAndroid Build Coastguard Worker * on error.
2227*2d543d20SAndroid Build Coastguard Worker */
semanage_verify_linked(semanage_handle_t * sh)2228*2d543d20SAndroid Build Coastguard Worker int semanage_verify_linked(semanage_handle_t * sh)
2229*2d543d20SAndroid Build Coastguard Worker {
2230*2d543d20SAndroid Build Coastguard Worker external_prog_t *e;
2231*2d543d20SAndroid Build Coastguard Worker semanage_conf_t *conf = sh->conf;
2232*2d543d20SAndroid Build Coastguard Worker const char *linked_filename =
2233*2d543d20SAndroid Build Coastguard Worker semanage_path(SEMANAGE_TMP, SEMANAGE_LINKED);
2234*2d543d20SAndroid Build Coastguard Worker int retval = -1;
2235*2d543d20SAndroid Build Coastguard Worker if (conf->linked_prog == NULL) {
2236*2d543d20SAndroid Build Coastguard Worker return 0;
2237*2d543d20SAndroid Build Coastguard Worker }
2238*2d543d20SAndroid Build Coastguard Worker for (e = conf->linked_prog; e != NULL; e = e->next) {
2239*2d543d20SAndroid Build Coastguard Worker if (semanage_exec_prog(sh, e, linked_filename, "$<") != 0) {
2240*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2241*2d543d20SAndroid Build Coastguard Worker }
2242*2d543d20SAndroid Build Coastguard Worker }
2243*2d543d20SAndroid Build Coastguard Worker retval = 0;
2244*2d543d20SAndroid Build Coastguard Worker cleanup:
2245*2d543d20SAndroid Build Coastguard Worker return retval;
2246*2d543d20SAndroid Build Coastguard Worker }
2247*2d543d20SAndroid Build Coastguard Worker
2248*2d543d20SAndroid Build Coastguard Worker /* Execute each of the kernel verification programs. Returns 0 if
2249*2d543d20SAndroid Build Coastguard Worker * every verifier returned success, -1 on error.
2250*2d543d20SAndroid Build Coastguard Worker */
semanage_verify_kernel(semanage_handle_t * sh)2251*2d543d20SAndroid Build Coastguard Worker int semanage_verify_kernel(semanage_handle_t * sh)
2252*2d543d20SAndroid Build Coastguard Worker {
2253*2d543d20SAndroid Build Coastguard Worker int retval = -1;
2254*2d543d20SAndroid Build Coastguard Worker const char *kernel_filename =
2255*2d543d20SAndroid Build Coastguard Worker semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL);
2256*2d543d20SAndroid Build Coastguard Worker semanage_conf_t *conf = sh->conf;
2257*2d543d20SAndroid Build Coastguard Worker external_prog_t *e;
2258*2d543d20SAndroid Build Coastguard Worker if (conf->kernel_prog == NULL) {
2259*2d543d20SAndroid Build Coastguard Worker return 0;
2260*2d543d20SAndroid Build Coastguard Worker }
2261*2d543d20SAndroid Build Coastguard Worker for (e = conf->kernel_prog; e != NULL; e = e->next) {
2262*2d543d20SAndroid Build Coastguard Worker if (semanage_exec_prog(sh, e, kernel_filename, "$<") != 0) {
2263*2d543d20SAndroid Build Coastguard Worker goto cleanup;
2264*2d543d20SAndroid Build Coastguard Worker }
2265*2d543d20SAndroid Build Coastguard Worker }
2266*2d543d20SAndroid Build Coastguard Worker retval = 0;
2267*2d543d20SAndroid Build Coastguard Worker cleanup:
2268*2d543d20SAndroid Build Coastguard Worker return retval;
2269*2d543d20SAndroid Build Coastguard Worker }
2270*2d543d20SAndroid Build Coastguard Worker
2271*2d543d20SAndroid Build Coastguard Worker /********************* functions that sort file contexts *********************/
2272*2d543d20SAndroid Build Coastguard Worker
2273*2d543d20SAndroid Build Coastguard Worker /* Free the given node. */
semanage_fc_node_destroy(semanage_file_context_node_t * x)2274*2d543d20SAndroid Build Coastguard Worker static void semanage_fc_node_destroy(semanage_file_context_node_t * x)
2275*2d543d20SAndroid Build Coastguard Worker {
2276*2d543d20SAndroid Build Coastguard Worker free(x->path);
2277*2d543d20SAndroid Build Coastguard Worker free(x->file_type);
2278*2d543d20SAndroid Build Coastguard Worker free(x->context);
2279*2d543d20SAndroid Build Coastguard Worker free(x);
2280*2d543d20SAndroid Build Coastguard Worker }
2281*2d543d20SAndroid Build Coastguard Worker
2282*2d543d20SAndroid Build Coastguard Worker /* Free the linked list of nodes starting at the given node. */
semanage_fc_node_list_destroy(semanage_file_context_node_t * x)2283*2d543d20SAndroid Build Coastguard Worker static void semanage_fc_node_list_destroy(semanage_file_context_node_t * x)
2284*2d543d20SAndroid Build Coastguard Worker {
2285*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *temp;
2286*2d543d20SAndroid Build Coastguard Worker
2287*2d543d20SAndroid Build Coastguard Worker while (x) {
2288*2d543d20SAndroid Build Coastguard Worker temp = x;
2289*2d543d20SAndroid Build Coastguard Worker x = x->next;
2290*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2291*2d543d20SAndroid Build Coastguard Worker }
2292*2d543d20SAndroid Build Coastguard Worker }
2293*2d543d20SAndroid Build Coastguard Worker
2294*2d543d20SAndroid Build Coastguard Worker /* Free the linked list of buckets (and their node lists)
2295*2d543d20SAndroid Build Coastguard Worker * starting at the given bucket. */
semanage_fc_bucket_list_destroy(semanage_file_context_bucket_t * x)2296*2d543d20SAndroid Build Coastguard Worker static void semanage_fc_bucket_list_destroy(semanage_file_context_bucket_t * x)
2297*2d543d20SAndroid Build Coastguard Worker {
2298*2d543d20SAndroid Build Coastguard Worker semanage_file_context_bucket_t *temp;
2299*2d543d20SAndroid Build Coastguard Worker
2300*2d543d20SAndroid Build Coastguard Worker while (x) {
2301*2d543d20SAndroid Build Coastguard Worker temp = x;
2302*2d543d20SAndroid Build Coastguard Worker x = x->next;
2303*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(temp->data);
2304*2d543d20SAndroid Build Coastguard Worker free(temp);
2305*2d543d20SAndroid Build Coastguard Worker }
2306*2d543d20SAndroid Build Coastguard Worker }
2307*2d543d20SAndroid Build Coastguard Worker
2308*2d543d20SAndroid Build Coastguard Worker /* Compares two file contexts' regular expressions and returns:
2309*2d543d20SAndroid Build Coastguard Worker * -1 if a is less specific than b
2310*2d543d20SAndroid Build Coastguard Worker * 0 if a and be are equally specific
2311*2d543d20SAndroid Build Coastguard Worker * 1 if a is more specific than b
2312*2d543d20SAndroid Build Coastguard Worker * The comparison is based on the following heuristics,
2313*2d543d20SAndroid Build Coastguard Worker * in order from most important to least important, given a and b:
2314*2d543d20SAndroid Build Coastguard Worker * If a is a regular expression and b is not,
2315*2d543d20SAndroid Build Coastguard Worker * -> a is less specific than b.
2316*2d543d20SAndroid Build Coastguard Worker * If a's stem length is shorter than b's stem length,
2317*2d543d20SAndroid Build Coastguard Worker * -> a is less specific than b.
2318*2d543d20SAndroid Build Coastguard Worker * If a's string length is shorter than b's string length,
2319*2d543d20SAndroid Build Coastguard Worker * -> a is less specific than b.
2320*2d543d20SAndroid Build Coastguard Worker * If a does not have a specified type and b does not,
2321*2d543d20SAndroid Build Coastguard Worker * -> a is less specific than b.
2322*2d543d20SAndroid Build Coastguard Worker * FIXME: These heuristics are imperfect, but good enough for
2323*2d543d20SAndroid Build Coastguard Worker * now. A proper comparison would determine which (if either)
2324*2d543d20SAndroid Build Coastguard Worker * regular expression is a subset of the other.
2325*2d543d20SAndroid Build Coastguard Worker */
semanage_fc_compare(semanage_file_context_node_t * a,semanage_file_context_node_t * b)2326*2d543d20SAndroid Build Coastguard Worker static int semanage_fc_compare(semanage_file_context_node_t * a,
2327*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t * b)
2328*2d543d20SAndroid Build Coastguard Worker {
2329*2d543d20SAndroid Build Coastguard Worker int a_has_meta = (a->meta >= 0);
2330*2d543d20SAndroid Build Coastguard Worker int b_has_meta = (b->meta >= 0);
2331*2d543d20SAndroid Build Coastguard Worker
2332*2d543d20SAndroid Build Coastguard Worker /* Check to see if either a or b are regexes
2333*2d543d20SAndroid Build Coastguard Worker * and the other isn't. */
2334*2d543d20SAndroid Build Coastguard Worker if (a_has_meta && !b_has_meta)
2335*2d543d20SAndroid Build Coastguard Worker return -1;
2336*2d543d20SAndroid Build Coastguard Worker if (b_has_meta && !a_has_meta)
2337*2d543d20SAndroid Build Coastguard Worker return 1;
2338*2d543d20SAndroid Build Coastguard Worker
2339*2d543d20SAndroid Build Coastguard Worker /* Check to see if either a or b have a shorter stem
2340*2d543d20SAndroid Build Coastguard Worker * length than the other. */
2341*2d543d20SAndroid Build Coastguard Worker if (a->meta < b->meta)
2342*2d543d20SAndroid Build Coastguard Worker return -1;
2343*2d543d20SAndroid Build Coastguard Worker if (b->meta < a->meta)
2344*2d543d20SAndroid Build Coastguard Worker return 1;
2345*2d543d20SAndroid Build Coastguard Worker
2346*2d543d20SAndroid Build Coastguard Worker /* Check to see if either a or b have a shorter string
2347*2d543d20SAndroid Build Coastguard Worker * length than the other. */
2348*2d543d20SAndroid Build Coastguard Worker if (a->effective_len < b->effective_len)
2349*2d543d20SAndroid Build Coastguard Worker return -1;
2350*2d543d20SAndroid Build Coastguard Worker if (b->effective_len < a->effective_len)
2351*2d543d20SAndroid Build Coastguard Worker return 1;
2352*2d543d20SAndroid Build Coastguard Worker
2353*2d543d20SAndroid Build Coastguard Worker /* Check to see if either a or b has a specified type
2354*2d543d20SAndroid Build Coastguard Worker * and the other doesn't. */
2355*2d543d20SAndroid Build Coastguard Worker if (!a->file_type && b->file_type)
2356*2d543d20SAndroid Build Coastguard Worker return -1;
2357*2d543d20SAndroid Build Coastguard Worker if (!b->file_type && a->file_type)
2358*2d543d20SAndroid Build Coastguard Worker return 1;
2359*2d543d20SAndroid Build Coastguard Worker
2360*2d543d20SAndroid Build Coastguard Worker /* If none of the above conditions were satisfied,
2361*2d543d20SAndroid Build Coastguard Worker * then a and b are equally specific. */
2362*2d543d20SAndroid Build Coastguard Worker return 0;
2363*2d543d20SAndroid Build Coastguard Worker }
2364*2d543d20SAndroid Build Coastguard Worker
2365*2d543d20SAndroid Build Coastguard Worker /* Merges two sorted file context linked lists into a single sorted one.
2366*2d543d20SAndroid Build Coastguard Worker * The left list is assumed to represent nodes that came first in the original ordering.
2367*2d543d20SAndroid Build Coastguard Worker * The final sorted list is returned.
2368*2d543d20SAndroid Build Coastguard Worker */
2369*2d543d20SAndroid Build Coastguard Worker static semanage_file_context_node_t
semanage_fc_merge(semanage_file_context_node_t * left,semanage_file_context_node_t * right)2370*2d543d20SAndroid Build Coastguard Worker * semanage_fc_merge(semanage_file_context_node_t * left,
2371*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t * right)
2372*2d543d20SAndroid Build Coastguard Worker {
2373*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *head;
2374*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *current;
2375*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *tail;
2376*2d543d20SAndroid Build Coastguard Worker
2377*2d543d20SAndroid Build Coastguard Worker if (!left)
2378*2d543d20SAndroid Build Coastguard Worker return right;
2379*2d543d20SAndroid Build Coastguard Worker
2380*2d543d20SAndroid Build Coastguard Worker if (!right)
2381*2d543d20SAndroid Build Coastguard Worker return left;
2382*2d543d20SAndroid Build Coastguard Worker
2383*2d543d20SAndroid Build Coastguard Worker if (semanage_fc_compare(left, right) == 1) {
2384*2d543d20SAndroid Build Coastguard Worker head = tail = right;
2385*2d543d20SAndroid Build Coastguard Worker right = right->next;
2386*2d543d20SAndroid Build Coastguard Worker } else {
2387*2d543d20SAndroid Build Coastguard Worker head = tail = left;
2388*2d543d20SAndroid Build Coastguard Worker left = left->next;
2389*2d543d20SAndroid Build Coastguard Worker }
2390*2d543d20SAndroid Build Coastguard Worker
2391*2d543d20SAndroid Build Coastguard Worker while (left && right) {
2392*2d543d20SAndroid Build Coastguard Worker /* if left was more specific than right,
2393*2d543d20SAndroid Build Coastguard Worker * insert right before left. Otherwise leave order alone. */
2394*2d543d20SAndroid Build Coastguard Worker if (semanage_fc_compare(left, right) == 1) {
2395*2d543d20SAndroid Build Coastguard Worker current = right;
2396*2d543d20SAndroid Build Coastguard Worker right = right->next;
2397*2d543d20SAndroid Build Coastguard Worker } else {
2398*2d543d20SAndroid Build Coastguard Worker current = left;
2399*2d543d20SAndroid Build Coastguard Worker left = left->next;
2400*2d543d20SAndroid Build Coastguard Worker }
2401*2d543d20SAndroid Build Coastguard Worker
2402*2d543d20SAndroid Build Coastguard Worker tail = tail->next = current;
2403*2d543d20SAndroid Build Coastguard Worker }
2404*2d543d20SAndroid Build Coastguard Worker
2405*2d543d20SAndroid Build Coastguard Worker tail->next = (left != NULL) ? left : right;
2406*2d543d20SAndroid Build Coastguard Worker
2407*2d543d20SAndroid Build Coastguard Worker return head;
2408*2d543d20SAndroid Build Coastguard Worker }
2409*2d543d20SAndroid Build Coastguard Worker
2410*2d543d20SAndroid Build Coastguard Worker /* Sorts file contexts from least specific to most specific.
2411*2d543d20SAndroid Build Coastguard Worker * A bucket linked list is passed in. Upon completion,
2412*2d543d20SAndroid Build Coastguard Worker * there is only one bucket (pointed to by "main") that
2413*2d543d20SAndroid Build Coastguard Worker * contains a linked list of all the file contexts in sorted order.
2414*2d543d20SAndroid Build Coastguard Worker * Explanation of the algorithm:
2415*2d543d20SAndroid Build Coastguard Worker * This is a stable implementation of an iterative merge sort.
2416*2d543d20SAndroid Build Coastguard Worker * Each bucket initially has a linked list of file contexts
2417*2d543d20SAndroid Build Coastguard Worker * that are 1 node long.
2418*2d543d20SAndroid Build Coastguard Worker * Each pass, buckets (and the nodes they contain) are merged
2419*2d543d20SAndroid Build Coastguard Worker * two at time.
2420*2d543d20SAndroid Build Coastguard Worker * Buckets are merged until there is only one bucket left,
2421*2d543d20SAndroid Build Coastguard Worker * containing the list of file contexts, sorted.
2422*2d543d20SAndroid Build Coastguard Worker */
semanage_fc_merge_sort(semanage_file_context_bucket_t * main)2423*2d543d20SAndroid Build Coastguard Worker static void semanage_fc_merge_sort(semanage_file_context_bucket_t * main)
2424*2d543d20SAndroid Build Coastguard Worker {
2425*2d543d20SAndroid Build Coastguard Worker semanage_file_context_bucket_t *current;
2426*2d543d20SAndroid Build Coastguard Worker semanage_file_context_bucket_t *temp;
2427*2d543d20SAndroid Build Coastguard Worker
2428*2d543d20SAndroid Build Coastguard Worker /* Loop until "main" is the only bucket left.
2429*2d543d20SAndroid Build Coastguard Worker * When we stop "main" contains the sorted list. */
2430*2d543d20SAndroid Build Coastguard Worker while (main->next) {
2431*2d543d20SAndroid Build Coastguard Worker current = main;
2432*2d543d20SAndroid Build Coastguard Worker
2433*2d543d20SAndroid Build Coastguard Worker /* Merge buckets two-by-two.
2434*2d543d20SAndroid Build Coastguard Worker * If there is an odd number of buckets, the last
2435*2d543d20SAndroid Build Coastguard Worker * bucket will be left alone, which corresponds
2436*2d543d20SAndroid Build Coastguard Worker * to the operation of merging it with an empty bucket. */
2437*2d543d20SAndroid Build Coastguard Worker while (current) {
2438*2d543d20SAndroid Build Coastguard Worker if (current->next) {
2439*2d543d20SAndroid Build Coastguard Worker current->data =
2440*2d543d20SAndroid Build Coastguard Worker semanage_fc_merge(current->data,
2441*2d543d20SAndroid Build Coastguard Worker current->next->data);
2442*2d543d20SAndroid Build Coastguard Worker temp = current->next;
2443*2d543d20SAndroid Build Coastguard Worker current->next = current->next->next;
2444*2d543d20SAndroid Build Coastguard Worker
2445*2d543d20SAndroid Build Coastguard Worker /* Free the (now empty) second bucket.
2446*2d543d20SAndroid Build Coastguard Worker * (This does not touch the node list
2447*2d543d20SAndroid Build Coastguard Worker * in the bucket because it has been
2448*2d543d20SAndroid Build Coastguard Worker * shifted over to the first bucket. */
2449*2d543d20SAndroid Build Coastguard Worker free(temp);
2450*2d543d20SAndroid Build Coastguard Worker }
2451*2d543d20SAndroid Build Coastguard Worker current = current->next;
2452*2d543d20SAndroid Build Coastguard Worker }
2453*2d543d20SAndroid Build Coastguard Worker }
2454*2d543d20SAndroid Build Coastguard Worker }
2455*2d543d20SAndroid Build Coastguard Worker
2456*2d543d20SAndroid Build Coastguard Worker /* Compute the location of the first regular expression
2457*2d543d20SAndroid Build Coastguard Worker * meta character in the path of the given node, if it exists.
2458*2d543d20SAndroid Build Coastguard Worker * On return:
2459*2d543d20SAndroid Build Coastguard Worker * fc_node->meta = position of meta character, if it exists
2460*2d543d20SAndroid Build Coastguard Worker * (-1 corresponds to no character)
2461*2d543d20SAndroid Build Coastguard Worker */
semanage_fc_find_meta(semanage_file_context_node_t * fc_node)2462*2d543d20SAndroid Build Coastguard Worker static void semanage_fc_find_meta(semanage_file_context_node_t * fc_node)
2463*2d543d20SAndroid Build Coastguard Worker {
2464*2d543d20SAndroid Build Coastguard Worker int c = 0;
2465*2d543d20SAndroid Build Coastguard Worker int escape_chars = 0;
2466*2d543d20SAndroid Build Coastguard Worker
2467*2d543d20SAndroid Build Coastguard Worker fc_node->meta = -1;
2468*2d543d20SAndroid Build Coastguard Worker
2469*2d543d20SAndroid Build Coastguard Worker /* Note: this while loop has been adapted from
2470*2d543d20SAndroid Build Coastguard Worker * spec_hasMetaChars in matchpathcon.c from
2471*2d543d20SAndroid Build Coastguard Worker * libselinux-1.22. */
2472*2d543d20SAndroid Build Coastguard Worker while (fc_node->path[c] != '\0') {
2473*2d543d20SAndroid Build Coastguard Worker switch (fc_node->path[c]) {
2474*2d543d20SAndroid Build Coastguard Worker case '.':
2475*2d543d20SAndroid Build Coastguard Worker case '^':
2476*2d543d20SAndroid Build Coastguard Worker case '$':
2477*2d543d20SAndroid Build Coastguard Worker case '?':
2478*2d543d20SAndroid Build Coastguard Worker case '*':
2479*2d543d20SAndroid Build Coastguard Worker case '+':
2480*2d543d20SAndroid Build Coastguard Worker case '|':
2481*2d543d20SAndroid Build Coastguard Worker case '[':
2482*2d543d20SAndroid Build Coastguard Worker case '(':
2483*2d543d20SAndroid Build Coastguard Worker case '{':
2484*2d543d20SAndroid Build Coastguard Worker fc_node->meta = c - escape_chars;
2485*2d543d20SAndroid Build Coastguard Worker return;
2486*2d543d20SAndroid Build Coastguard Worker case '\\':
2487*2d543d20SAndroid Build Coastguard Worker /* If an escape character is found,
2488*2d543d20SAndroid Build Coastguard Worker * skip the next character. */
2489*2d543d20SAndroid Build Coastguard Worker c++;
2490*2d543d20SAndroid Build Coastguard Worker escape_chars++;
2491*2d543d20SAndroid Build Coastguard Worker break;
2492*2d543d20SAndroid Build Coastguard Worker }
2493*2d543d20SAndroid Build Coastguard Worker
2494*2d543d20SAndroid Build Coastguard Worker c++;
2495*2d543d20SAndroid Build Coastguard Worker }
2496*2d543d20SAndroid Build Coastguard Worker }
2497*2d543d20SAndroid Build Coastguard Worker
2498*2d543d20SAndroid Build Coastguard Worker /* Replicates strchr, but limits search to buf_len characters. */
semanage_strnchr(const char * buf,size_t buf_len,char c)2499*2d543d20SAndroid Build Coastguard Worker static char *semanage_strnchr(const char *buf, size_t buf_len, char c)
2500*2d543d20SAndroid Build Coastguard Worker {
2501*2d543d20SAndroid Build Coastguard Worker size_t idx = 0;
2502*2d543d20SAndroid Build Coastguard Worker
2503*2d543d20SAndroid Build Coastguard Worker if (buf == NULL)
2504*2d543d20SAndroid Build Coastguard Worker return NULL;
2505*2d543d20SAndroid Build Coastguard Worker if (buf_len <= 0)
2506*2d543d20SAndroid Build Coastguard Worker return NULL;
2507*2d543d20SAndroid Build Coastguard Worker
2508*2d543d20SAndroid Build Coastguard Worker while (idx < buf_len) {
2509*2d543d20SAndroid Build Coastguard Worker if (buf[idx] == c)
2510*2d543d20SAndroid Build Coastguard Worker return (char *)buf + idx;
2511*2d543d20SAndroid Build Coastguard Worker idx++;
2512*2d543d20SAndroid Build Coastguard Worker }
2513*2d543d20SAndroid Build Coastguard Worker
2514*2d543d20SAndroid Build Coastguard Worker return NULL;
2515*2d543d20SAndroid Build Coastguard Worker }
2516*2d543d20SAndroid Build Coastguard Worker
2517*2d543d20SAndroid Build Coastguard Worker /* Returns a pointer to the end of line character in the given buffer.
2518*2d543d20SAndroid Build Coastguard Worker * Used in the context of a file context char buffer that we will be
2519*2d543d20SAndroid Build Coastguard Worker * parsing and sorting.
2520*2d543d20SAndroid Build Coastguard Worker */
semanage_get_line_end(const char * buf,size_t buf_len)2521*2d543d20SAndroid Build Coastguard Worker static char *semanage_get_line_end(const char *buf, size_t buf_len)
2522*2d543d20SAndroid Build Coastguard Worker {
2523*2d543d20SAndroid Build Coastguard Worker char *line_end = NULL;
2524*2d543d20SAndroid Build Coastguard Worker
2525*2d543d20SAndroid Build Coastguard Worker if (buf == NULL)
2526*2d543d20SAndroid Build Coastguard Worker return NULL;
2527*2d543d20SAndroid Build Coastguard Worker if (buf_len <= 0)
2528*2d543d20SAndroid Build Coastguard Worker return NULL;
2529*2d543d20SAndroid Build Coastguard Worker
2530*2d543d20SAndroid Build Coastguard Worker line_end = semanage_strnchr(buf, buf_len, '\n');
2531*2d543d20SAndroid Build Coastguard Worker if (!line_end)
2532*2d543d20SAndroid Build Coastguard Worker line_end = semanage_strnchr(buf, buf_len, '\r');
2533*2d543d20SAndroid Build Coastguard Worker if (!line_end)
2534*2d543d20SAndroid Build Coastguard Worker line_end = semanage_strnchr(buf, buf_len, EOF);
2535*2d543d20SAndroid Build Coastguard Worker
2536*2d543d20SAndroid Build Coastguard Worker return line_end;
2537*2d543d20SAndroid Build Coastguard Worker }
2538*2d543d20SAndroid Build Coastguard Worker
2539*2d543d20SAndroid Build Coastguard Worker /* Entry function for sorting a set of file context lines.
2540*2d543d20SAndroid Build Coastguard Worker * Returns 0 on success, -1 on failure.
2541*2d543d20SAndroid Build Coastguard Worker * Allocates a buffer pointed to by sorted_buf that contains the sorted lines.
2542*2d543d20SAndroid Build Coastguard Worker * sorted_buf_len is set to the size of this buffer.
2543*2d543d20SAndroid Build Coastguard Worker * This buffer is guaranteed to have a final \0 character.
2544*2d543d20SAndroid Build Coastguard Worker * This buffer must be released by the caller.
2545*2d543d20SAndroid Build Coastguard Worker */
semanage_fc_sort(semanage_handle_t * sh,const char * buf,size_t buf_len,char ** sorted_buf,size_t * sorted_buf_len)2546*2d543d20SAndroid Build Coastguard Worker int semanage_fc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len,
2547*2d543d20SAndroid Build Coastguard Worker char **sorted_buf, size_t * sorted_buf_len)
2548*2d543d20SAndroid Build Coastguard Worker {
2549*2d543d20SAndroid Build Coastguard Worker size_t start, finish, regex_len, type_len, context_len;
2550*2d543d20SAndroid Build Coastguard Worker size_t line_len, buf_remainder, i;
2551*2d543d20SAndroid Build Coastguard Worker ssize_t sanity_check;
2552*2d543d20SAndroid Build Coastguard Worker const char *line_buf, *line_end;
2553*2d543d20SAndroid Build Coastguard Worker char *sorted_buf_pos;
2554*2d543d20SAndroid Build Coastguard Worker int escape_chars, just_saw_escape;
2555*2d543d20SAndroid Build Coastguard Worker
2556*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *temp;
2557*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *head;
2558*2d543d20SAndroid Build Coastguard Worker semanage_file_context_node_t *current;
2559*2d543d20SAndroid Build Coastguard Worker semanage_file_context_bucket_t *main;
2560*2d543d20SAndroid Build Coastguard Worker semanage_file_context_bucket_t *bcurrent;
2561*2d543d20SAndroid Build Coastguard Worker
2562*2d543d20SAndroid Build Coastguard Worker i = 0;
2563*2d543d20SAndroid Build Coastguard Worker
2564*2d543d20SAndroid Build Coastguard Worker if (sh == NULL) {
2565*2d543d20SAndroid Build Coastguard Worker return -1;
2566*2d543d20SAndroid Build Coastguard Worker }
2567*2d543d20SAndroid Build Coastguard Worker if (buf == NULL) {
2568*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Received NULL buffer.");
2569*2d543d20SAndroid Build Coastguard Worker return -1;
2570*2d543d20SAndroid Build Coastguard Worker }
2571*2d543d20SAndroid Build Coastguard Worker if (buf_len <= 0) {
2572*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Received buffer of length 0.");
2573*2d543d20SAndroid Build Coastguard Worker return -1;
2574*2d543d20SAndroid Build Coastguard Worker }
2575*2d543d20SAndroid Build Coastguard Worker
2576*2d543d20SAndroid Build Coastguard Worker /* Initialize the head of the linked list
2577*2d543d20SAndroid Build Coastguard Worker * that will contain a node for each file context line. */
2578*2d543d20SAndroid Build Coastguard Worker head = current =
2579*2d543d20SAndroid Build Coastguard Worker (semanage_file_context_node_t *) calloc(1,
2580*2d543d20SAndroid Build Coastguard Worker sizeof
2581*2d543d20SAndroid Build Coastguard Worker (semanage_file_context_node_t));
2582*2d543d20SAndroid Build Coastguard Worker if (!head) {
2583*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2584*2d543d20SAndroid Build Coastguard Worker return -1;
2585*2d543d20SAndroid Build Coastguard Worker }
2586*2d543d20SAndroid Build Coastguard Worker
2587*2d543d20SAndroid Build Coastguard Worker /* Parse the char buffer into a semanage_file_context_node_t linked list. */
2588*2d543d20SAndroid Build Coastguard Worker line_buf = buf;
2589*2d543d20SAndroid Build Coastguard Worker buf_remainder = buf_len;
2590*2d543d20SAndroid Build Coastguard Worker while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) {
2591*2d543d20SAndroid Build Coastguard Worker line_len = line_end - line_buf + 1;
2592*2d543d20SAndroid Build Coastguard Worker sanity_check = buf_remainder - line_len;
2593*2d543d20SAndroid Build Coastguard Worker buf_remainder = buf_remainder - line_len;
2594*2d543d20SAndroid Build Coastguard Worker
2595*2d543d20SAndroid Build Coastguard Worker if (sanity_check < 0) {
2596*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure parsing file context buffer.");
2597*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2598*2d543d20SAndroid Build Coastguard Worker return -1;
2599*2d543d20SAndroid Build Coastguard Worker }
2600*2d543d20SAndroid Build Coastguard Worker
2601*2d543d20SAndroid Build Coastguard Worker if (line_len == 0 || line_len == 1) {
2602*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2603*2d543d20SAndroid Build Coastguard Worker continue;
2604*2d543d20SAndroid Build Coastguard Worker }
2605*2d543d20SAndroid Build Coastguard Worker
2606*2d543d20SAndroid Build Coastguard Worker /* Skip the whitespace at the front of the line. */
2607*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < line_len; i++) {
2608*2d543d20SAndroid Build Coastguard Worker if (!isspace(line_buf[i]))
2609*2d543d20SAndroid Build Coastguard Worker break;
2610*2d543d20SAndroid Build Coastguard Worker }
2611*2d543d20SAndroid Build Coastguard Worker
2612*2d543d20SAndroid Build Coastguard Worker /* Check for a blank line. */
2613*2d543d20SAndroid Build Coastguard Worker if (i >= line_len) {
2614*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2615*2d543d20SAndroid Build Coastguard Worker continue;
2616*2d543d20SAndroid Build Coastguard Worker }
2617*2d543d20SAndroid Build Coastguard Worker
2618*2d543d20SAndroid Build Coastguard Worker /* Check if the line is a comment. */
2619*2d543d20SAndroid Build Coastguard Worker if (line_buf[i] == '#') {
2620*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2621*2d543d20SAndroid Build Coastguard Worker continue;
2622*2d543d20SAndroid Build Coastguard Worker }
2623*2d543d20SAndroid Build Coastguard Worker
2624*2d543d20SAndroid Build Coastguard Worker /* Allocate a new node. */
2625*2d543d20SAndroid Build Coastguard Worker temp =
2626*2d543d20SAndroid Build Coastguard Worker (semanage_file_context_node_t *) calloc(1,
2627*2d543d20SAndroid Build Coastguard Worker sizeof
2628*2d543d20SAndroid Build Coastguard Worker (semanage_file_context_node_t));
2629*2d543d20SAndroid Build Coastguard Worker if (!temp) {
2630*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2631*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2632*2d543d20SAndroid Build Coastguard Worker return -1;
2633*2d543d20SAndroid Build Coastguard Worker }
2634*2d543d20SAndroid Build Coastguard Worker temp->next = NULL;
2635*2d543d20SAndroid Build Coastguard Worker
2636*2d543d20SAndroid Build Coastguard Worker /* Extract the regular expression from the line. */
2637*2d543d20SAndroid Build Coastguard Worker escape_chars = 0;
2638*2d543d20SAndroid Build Coastguard Worker just_saw_escape = 0;
2639*2d543d20SAndroid Build Coastguard Worker start = i;
2640*2d543d20SAndroid Build Coastguard Worker while (i < line_len && (!isspace(line_buf[i]))) {
2641*2d543d20SAndroid Build Coastguard Worker if (line_buf[i] == '\\') {
2642*2d543d20SAndroid Build Coastguard Worker if (!just_saw_escape) {
2643*2d543d20SAndroid Build Coastguard Worker escape_chars++;
2644*2d543d20SAndroid Build Coastguard Worker just_saw_escape = 1;
2645*2d543d20SAndroid Build Coastguard Worker } else {
2646*2d543d20SAndroid Build Coastguard Worker /* We're looking at an escaped
2647*2d543d20SAndroid Build Coastguard Worker escape. Reset our flag. */
2648*2d543d20SAndroid Build Coastguard Worker just_saw_escape = 0;
2649*2d543d20SAndroid Build Coastguard Worker }
2650*2d543d20SAndroid Build Coastguard Worker } else {
2651*2d543d20SAndroid Build Coastguard Worker just_saw_escape = 0;
2652*2d543d20SAndroid Build Coastguard Worker }
2653*2d543d20SAndroid Build Coastguard Worker i++;
2654*2d543d20SAndroid Build Coastguard Worker }
2655*2d543d20SAndroid Build Coastguard Worker finish = i;
2656*2d543d20SAndroid Build Coastguard Worker regex_len = finish - start;
2657*2d543d20SAndroid Build Coastguard Worker
2658*2d543d20SAndroid Build Coastguard Worker if (regex_len == 0) {
2659*2d543d20SAndroid Build Coastguard Worker ERR(sh,
2660*2d543d20SAndroid Build Coastguard Worker "WARNING: semanage_fc_sort: Regex of length 0.");
2661*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2662*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2663*2d543d20SAndroid Build Coastguard Worker continue;
2664*2d543d20SAndroid Build Coastguard Worker }
2665*2d543d20SAndroid Build Coastguard Worker
2666*2d543d20SAndroid Build Coastguard Worker temp->path = (char *)strndup(&line_buf[start], regex_len);
2667*2d543d20SAndroid Build Coastguard Worker if (!temp->path) {
2668*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2669*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2670*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2671*2d543d20SAndroid Build Coastguard Worker return -1;
2672*2d543d20SAndroid Build Coastguard Worker }
2673*2d543d20SAndroid Build Coastguard Worker
2674*2d543d20SAndroid Build Coastguard Worker /* Skip the whitespace after the regular expression. */
2675*2d543d20SAndroid Build Coastguard Worker for (; i < line_len; i++) {
2676*2d543d20SAndroid Build Coastguard Worker if (!isspace(line_buf[i]))
2677*2d543d20SAndroid Build Coastguard Worker break;
2678*2d543d20SAndroid Build Coastguard Worker }
2679*2d543d20SAndroid Build Coastguard Worker if (i == line_len) {
2680*2d543d20SAndroid Build Coastguard Worker ERR(sh,
2681*2d543d20SAndroid Build Coastguard Worker "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
2682*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2683*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2684*2d543d20SAndroid Build Coastguard Worker continue;
2685*2d543d20SAndroid Build Coastguard Worker }
2686*2d543d20SAndroid Build Coastguard Worker
2687*2d543d20SAndroid Build Coastguard Worker /* Extract the inode type from the line (if it exists). */
2688*2d543d20SAndroid Build Coastguard Worker if (line_buf[i] == '-') {
2689*2d543d20SAndroid Build Coastguard Worker type_len = 2; /* defined as '--', '-d', '-f', etc. */
2690*2d543d20SAndroid Build Coastguard Worker
2691*2d543d20SAndroid Build Coastguard Worker if (i + type_len >= line_len) {
2692*2d543d20SAndroid Build Coastguard Worker ERR(sh,
2693*2d543d20SAndroid Build Coastguard Worker "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
2694*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2695*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2696*2d543d20SAndroid Build Coastguard Worker continue;
2697*2d543d20SAndroid Build Coastguard Worker }
2698*2d543d20SAndroid Build Coastguard Worker
2699*2d543d20SAndroid Build Coastguard Worker /* Record the inode type. */
2700*2d543d20SAndroid Build Coastguard Worker temp->file_type =
2701*2d543d20SAndroid Build Coastguard Worker (char *)strndup(&line_buf[i], type_len);
2702*2d543d20SAndroid Build Coastguard Worker if (!temp->file_type) {
2703*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2704*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2705*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2706*2d543d20SAndroid Build Coastguard Worker return -1;
2707*2d543d20SAndroid Build Coastguard Worker }
2708*2d543d20SAndroid Build Coastguard Worker
2709*2d543d20SAndroid Build Coastguard Worker i += type_len;
2710*2d543d20SAndroid Build Coastguard Worker
2711*2d543d20SAndroid Build Coastguard Worker /* Skip the whitespace after the type. */
2712*2d543d20SAndroid Build Coastguard Worker for (; i < line_len; i++) {
2713*2d543d20SAndroid Build Coastguard Worker if (!isspace(line_buf[i]))
2714*2d543d20SAndroid Build Coastguard Worker break;
2715*2d543d20SAndroid Build Coastguard Worker }
2716*2d543d20SAndroid Build Coastguard Worker if (i == line_len) {
2717*2d543d20SAndroid Build Coastguard Worker ERR(sh,
2718*2d543d20SAndroid Build Coastguard Worker "WARNING: semanage_fc_sort: Incomplete context. %s", temp->path);
2719*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2720*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2721*2d543d20SAndroid Build Coastguard Worker continue;
2722*2d543d20SAndroid Build Coastguard Worker }
2723*2d543d20SAndroid Build Coastguard Worker } else {
2724*2d543d20SAndroid Build Coastguard Worker type_len = 0; /* inode type did not exist in the file context */
2725*2d543d20SAndroid Build Coastguard Worker }
2726*2d543d20SAndroid Build Coastguard Worker
2727*2d543d20SAndroid Build Coastguard Worker /* Extract the context from the line. */
2728*2d543d20SAndroid Build Coastguard Worker start = i;
2729*2d543d20SAndroid Build Coastguard Worker while (i < line_len && (!isspace(line_buf[i])))
2730*2d543d20SAndroid Build Coastguard Worker i++;
2731*2d543d20SAndroid Build Coastguard Worker finish = i;
2732*2d543d20SAndroid Build Coastguard Worker context_len = finish - start;
2733*2d543d20SAndroid Build Coastguard Worker
2734*2d543d20SAndroid Build Coastguard Worker temp->context = (char *)strndup(&line_buf[start], context_len);
2735*2d543d20SAndroid Build Coastguard Worker if (!temp->context) {
2736*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2737*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(temp);
2738*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2739*2d543d20SAndroid Build Coastguard Worker return -1;
2740*2d543d20SAndroid Build Coastguard Worker }
2741*2d543d20SAndroid Build Coastguard Worker
2742*2d543d20SAndroid Build Coastguard Worker /* Initialize the data about the file context. */
2743*2d543d20SAndroid Build Coastguard Worker temp->path_len = regex_len;
2744*2d543d20SAndroid Build Coastguard Worker temp->effective_len = regex_len - escape_chars;
2745*2d543d20SAndroid Build Coastguard Worker temp->type_len = type_len;
2746*2d543d20SAndroid Build Coastguard Worker temp->context_len = context_len;
2747*2d543d20SAndroid Build Coastguard Worker semanage_fc_find_meta(temp);
2748*2d543d20SAndroid Build Coastguard Worker
2749*2d543d20SAndroid Build Coastguard Worker /* Add this node to the end of the linked list. */
2750*2d543d20SAndroid Build Coastguard Worker current->next = temp;
2751*2d543d20SAndroid Build Coastguard Worker current = current->next;
2752*2d543d20SAndroid Build Coastguard Worker
2753*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2754*2d543d20SAndroid Build Coastguard Worker }
2755*2d543d20SAndroid Build Coastguard Worker
2756*2d543d20SAndroid Build Coastguard Worker /* Create the bucket linked list from the node linked list. */
2757*2d543d20SAndroid Build Coastguard Worker current = head->next;
2758*2d543d20SAndroid Build Coastguard Worker bcurrent = main = (semanage_file_context_bucket_t *)
2759*2d543d20SAndroid Build Coastguard Worker calloc(1, sizeof(semanage_file_context_bucket_t));
2760*2d543d20SAndroid Build Coastguard Worker if (!main) {
2761*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2762*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_list_destroy(head);
2763*2d543d20SAndroid Build Coastguard Worker return -1;
2764*2d543d20SAndroid Build Coastguard Worker }
2765*2d543d20SAndroid Build Coastguard Worker
2766*2d543d20SAndroid Build Coastguard Worker /* Free the head node, as it is no longer used. */
2767*2d543d20SAndroid Build Coastguard Worker semanage_fc_node_destroy(head);
2768*2d543d20SAndroid Build Coastguard Worker head = NULL;
2769*2d543d20SAndroid Build Coastguard Worker
2770*2d543d20SAndroid Build Coastguard Worker /* Place each node into a bucket. */
2771*2d543d20SAndroid Build Coastguard Worker while (current) {
2772*2d543d20SAndroid Build Coastguard Worker bcurrent->data = current;
2773*2d543d20SAndroid Build Coastguard Worker current = current->next;
2774*2d543d20SAndroid Build Coastguard Worker
2775*2d543d20SAndroid Build Coastguard Worker /* Detach the node in the bucket from the old list. */
2776*2d543d20SAndroid Build Coastguard Worker bcurrent->data->next = NULL;
2777*2d543d20SAndroid Build Coastguard Worker
2778*2d543d20SAndroid Build Coastguard Worker /* If we need another bucket, add one to the end. */
2779*2d543d20SAndroid Build Coastguard Worker if (current) {
2780*2d543d20SAndroid Build Coastguard Worker bcurrent->next = (semanage_file_context_bucket_t *)
2781*2d543d20SAndroid Build Coastguard Worker calloc(1, sizeof(semanage_file_context_bucket_t));
2782*2d543d20SAndroid Build Coastguard Worker if (!(bcurrent->next)) {
2783*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2784*2d543d20SAndroid Build Coastguard Worker semanage_fc_bucket_list_destroy(main);
2785*2d543d20SAndroid Build Coastguard Worker return -1;
2786*2d543d20SAndroid Build Coastguard Worker }
2787*2d543d20SAndroid Build Coastguard Worker
2788*2d543d20SAndroid Build Coastguard Worker bcurrent = bcurrent->next;
2789*2d543d20SAndroid Build Coastguard Worker }
2790*2d543d20SAndroid Build Coastguard Worker }
2791*2d543d20SAndroid Build Coastguard Worker
2792*2d543d20SAndroid Build Coastguard Worker /* Sort the bucket list. */
2793*2d543d20SAndroid Build Coastguard Worker semanage_fc_merge_sort(main);
2794*2d543d20SAndroid Build Coastguard Worker
2795*2d543d20SAndroid Build Coastguard Worker /* First, calculate how much space we'll need for
2796*2d543d20SAndroid Build Coastguard Worker * the newly sorted block of data. (We don't just
2797*2d543d20SAndroid Build Coastguard Worker * use buf_len for this because we have extracted
2798*2d543d20SAndroid Build Coastguard Worker * comments and whitespace.) */
2799*2d543d20SAndroid Build Coastguard Worker i = 0;
2800*2d543d20SAndroid Build Coastguard Worker current = main->data;
2801*2d543d20SAndroid Build Coastguard Worker while (current) {
2802*2d543d20SAndroid Build Coastguard Worker i += current->path_len + 1; /* +1 for a tab */
2803*2d543d20SAndroid Build Coastguard Worker if (current->file_type) {
2804*2d543d20SAndroid Build Coastguard Worker i += current->type_len + 1; /* +1 for a tab */
2805*2d543d20SAndroid Build Coastguard Worker }
2806*2d543d20SAndroid Build Coastguard Worker i += current->context_len + 1; /* +1 for a newline */
2807*2d543d20SAndroid Build Coastguard Worker current = current->next;
2808*2d543d20SAndroid Build Coastguard Worker }
2809*2d543d20SAndroid Build Coastguard Worker i = i + 1; /* +1 for trailing \0 */
2810*2d543d20SAndroid Build Coastguard Worker
2811*2d543d20SAndroid Build Coastguard Worker /* Allocate the buffer for the sorted list. */
2812*2d543d20SAndroid Build Coastguard Worker *sorted_buf = calloc(i, sizeof(char));
2813*2d543d20SAndroid Build Coastguard Worker if (!*sorted_buf) {
2814*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2815*2d543d20SAndroid Build Coastguard Worker semanage_fc_bucket_list_destroy(main);
2816*2d543d20SAndroid Build Coastguard Worker return -1;
2817*2d543d20SAndroid Build Coastguard Worker }
2818*2d543d20SAndroid Build Coastguard Worker *sorted_buf_len = i;
2819*2d543d20SAndroid Build Coastguard Worker
2820*2d543d20SAndroid Build Coastguard Worker /* Output the sorted semanage_file_context linked list to the char buffer. */
2821*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = *sorted_buf;
2822*2d543d20SAndroid Build Coastguard Worker current = main->data;
2823*2d543d20SAndroid Build Coastguard Worker while (current) {
2824*2d543d20SAndroid Build Coastguard Worker /* Output the path. */
2825*2d543d20SAndroid Build Coastguard Worker i = current->path_len + 1; /* +1 for tab */
2826*2d543d20SAndroid Build Coastguard Worker snprintf(sorted_buf_pos, i + 1, "%s\t", current->path);
2827*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = sorted_buf_pos + i;
2828*2d543d20SAndroid Build Coastguard Worker
2829*2d543d20SAndroid Build Coastguard Worker /* Output the type, if there is one. */
2830*2d543d20SAndroid Build Coastguard Worker if (current->file_type) {
2831*2d543d20SAndroid Build Coastguard Worker i = strlen(current->file_type) + 1; /* +1 for tab */
2832*2d543d20SAndroid Build Coastguard Worker snprintf(sorted_buf_pos, i + 1, "%s\t",
2833*2d543d20SAndroid Build Coastguard Worker current->file_type);
2834*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = sorted_buf_pos + i;
2835*2d543d20SAndroid Build Coastguard Worker }
2836*2d543d20SAndroid Build Coastguard Worker
2837*2d543d20SAndroid Build Coastguard Worker /* Output the context. */
2838*2d543d20SAndroid Build Coastguard Worker i = strlen(current->context) + 1; /* +1 for newline */
2839*2d543d20SAndroid Build Coastguard Worker snprintf(sorted_buf_pos, i + 1, "%s\n", current->context);
2840*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = sorted_buf_pos + i;
2841*2d543d20SAndroid Build Coastguard Worker
2842*2d543d20SAndroid Build Coastguard Worker current = current->next;
2843*2d543d20SAndroid Build Coastguard Worker }
2844*2d543d20SAndroid Build Coastguard Worker
2845*2d543d20SAndroid Build Coastguard Worker /* Clean up. */
2846*2d543d20SAndroid Build Coastguard Worker semanage_fc_bucket_list_destroy(main);
2847*2d543d20SAndroid Build Coastguard Worker
2848*2d543d20SAndroid Build Coastguard Worker /* Sanity check. */
2849*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos++;
2850*2d543d20SAndroid Build Coastguard Worker if ((sorted_buf_pos - *sorted_buf) != (ssize_t) * sorted_buf_len) {
2851*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure writing sorted buffer.");
2852*2d543d20SAndroid Build Coastguard Worker free(*sorted_buf);
2853*2d543d20SAndroid Build Coastguard Worker *sorted_buf = NULL;
2854*2d543d20SAndroid Build Coastguard Worker return -1;
2855*2d543d20SAndroid Build Coastguard Worker }
2856*2d543d20SAndroid Build Coastguard Worker
2857*2d543d20SAndroid Build Coastguard Worker return 0;
2858*2d543d20SAndroid Build Coastguard Worker }
2859*2d543d20SAndroid Build Coastguard Worker
2860*2d543d20SAndroid Build Coastguard Worker /********************* functions that sort netfilter contexts *********************/
2861*2d543d20SAndroid Build Coastguard Worker #define NC_SORT_NAMES { "pre", "base", "module", "local", "post" }
2862*2d543d20SAndroid Build Coastguard Worker #define NC_SORT_NAMES_LEN { 3, 4, 6, 5, 4 }
2863*2d543d20SAndroid Build Coastguard Worker #define NC_SORT_NEL 5
semanage_nc_destroy_ruletab(semanage_netfilter_context_node_t * ruletab[NC_SORT_NEL][2])2864*2d543d20SAndroid Build Coastguard Worker static void semanage_nc_destroy_ruletab(semanage_netfilter_context_node_t *
2865*2d543d20SAndroid Build Coastguard Worker ruletab[NC_SORT_NEL][2])
2866*2d543d20SAndroid Build Coastguard Worker {
2867*2d543d20SAndroid Build Coastguard Worker semanage_netfilter_context_node_t *curr, *next;
2868*2d543d20SAndroid Build Coastguard Worker int i;
2869*2d543d20SAndroid Build Coastguard Worker
2870*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < NC_SORT_NEL; i++) {
2871*2d543d20SAndroid Build Coastguard Worker for (curr = ruletab[i][0]; curr != NULL; curr = next) {
2872*2d543d20SAndroid Build Coastguard Worker next = curr->next;
2873*2d543d20SAndroid Build Coastguard Worker free(curr->rule);
2874*2d543d20SAndroid Build Coastguard Worker free(curr);
2875*2d543d20SAndroid Build Coastguard Worker }
2876*2d543d20SAndroid Build Coastguard Worker }
2877*2d543d20SAndroid Build Coastguard Worker }
2878*2d543d20SAndroid Build Coastguard Worker
2879*2d543d20SAndroid Build Coastguard Worker /* Entry function for sorting a set of netfilter context lines.
2880*2d543d20SAndroid Build Coastguard Worker * Returns 0 on success, -1 on failure.
2881*2d543d20SAndroid Build Coastguard Worker * Allocates a buffer pointed to by sorted_buf that contains the sorted lines.
2882*2d543d20SAndroid Build Coastguard Worker * sorted_buf_len is set to the size of this buffer.
2883*2d543d20SAndroid Build Coastguard Worker * This buffer is guaranteed to have a final \0 character.
2884*2d543d20SAndroid Build Coastguard Worker * This buffer must be released by the caller.
2885*2d543d20SAndroid Build Coastguard Worker */
semanage_nc_sort(semanage_handle_t * sh,const char * buf,size_t buf_len,char ** sorted_buf,size_t * sorted_buf_len)2886*2d543d20SAndroid Build Coastguard Worker int semanage_nc_sort(semanage_handle_t * sh, const char *buf, size_t buf_len,
2887*2d543d20SAndroid Build Coastguard Worker char **sorted_buf, size_t * sorted_buf_len)
2888*2d543d20SAndroid Build Coastguard Worker {
2889*2d543d20SAndroid Build Coastguard Worker
2890*2d543d20SAndroid Build Coastguard Worker /* parsing bits */
2891*2d543d20SAndroid Build Coastguard Worker const char *priority_names[] = NC_SORT_NAMES;
2892*2d543d20SAndroid Build Coastguard Worker const int priority_names_len[] = NC_SORT_NAMES_LEN;
2893*2d543d20SAndroid Build Coastguard Worker size_t line_len, buf_remainder, i, offset;
2894*2d543d20SAndroid Build Coastguard Worker const char *line_buf, *line_end;
2895*2d543d20SAndroid Build Coastguard Worker
2896*2d543d20SAndroid Build Coastguard Worker /* ruletab bits */
2897*2d543d20SAndroid Build Coastguard Worker /* keep track of the head (index 0) and tail (index 1) with this array */
2898*2d543d20SAndroid Build Coastguard Worker semanage_netfilter_context_node_t *ruletab[NC_SORT_NEL][2];
2899*2d543d20SAndroid Build Coastguard Worker semanage_netfilter_context_node_t *curr, *node;
2900*2d543d20SAndroid Build Coastguard Worker int priority;
2901*2d543d20SAndroid Build Coastguard Worker
2902*2d543d20SAndroid Build Coastguard Worker /* sorted buffer bits */
2903*2d543d20SAndroid Build Coastguard Worker char *sorted_buf_pos;
2904*2d543d20SAndroid Build Coastguard Worker size_t count;
2905*2d543d20SAndroid Build Coastguard Worker
2906*2d543d20SAndroid Build Coastguard Worker /* initialize ruletab */
2907*2d543d20SAndroid Build Coastguard Worker memset(ruletab, 0,
2908*2d543d20SAndroid Build Coastguard Worker NC_SORT_NEL * 2 * sizeof(semanage_netfilter_context_node_t *));
2909*2d543d20SAndroid Build Coastguard Worker
2910*2d543d20SAndroid Build Coastguard Worker /* while lines to be read */
2911*2d543d20SAndroid Build Coastguard Worker line_buf = buf;
2912*2d543d20SAndroid Build Coastguard Worker buf_remainder = buf_len;
2913*2d543d20SAndroid Build Coastguard Worker while ((line_end = semanage_get_line_end(line_buf, buf_remainder))) {
2914*2d543d20SAndroid Build Coastguard Worker line_len = line_end - line_buf + 1;
2915*2d543d20SAndroid Build Coastguard Worker buf_remainder = buf_remainder - line_len;
2916*2d543d20SAndroid Build Coastguard Worker
2917*2d543d20SAndroid Build Coastguard Worker if (line_len == 0 || line_len == 1) {
2918*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2919*2d543d20SAndroid Build Coastguard Worker continue;
2920*2d543d20SAndroid Build Coastguard Worker }
2921*2d543d20SAndroid Build Coastguard Worker
2922*2d543d20SAndroid Build Coastguard Worker /* Skip the whitespace at the front of the line. */
2923*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < line_len; i++) {
2924*2d543d20SAndroid Build Coastguard Worker if (!isspace(line_buf[i]))
2925*2d543d20SAndroid Build Coastguard Worker break;
2926*2d543d20SAndroid Build Coastguard Worker }
2927*2d543d20SAndroid Build Coastguard Worker
2928*2d543d20SAndroid Build Coastguard Worker /* Check for a blank line. */
2929*2d543d20SAndroid Build Coastguard Worker if (i >= line_len) {
2930*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2931*2d543d20SAndroid Build Coastguard Worker continue;
2932*2d543d20SAndroid Build Coastguard Worker }
2933*2d543d20SAndroid Build Coastguard Worker
2934*2d543d20SAndroid Build Coastguard Worker /* Check if the line is a comment. */
2935*2d543d20SAndroid Build Coastguard Worker if (line_buf[i] == '#') {
2936*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2937*2d543d20SAndroid Build Coastguard Worker continue;
2938*2d543d20SAndroid Build Coastguard Worker }
2939*2d543d20SAndroid Build Coastguard Worker
2940*2d543d20SAndroid Build Coastguard Worker /* extract priority */
2941*2d543d20SAndroid Build Coastguard Worker priority = -1;
2942*2d543d20SAndroid Build Coastguard Worker offset = 0;
2943*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < NC_SORT_NEL; i++) {
2944*2d543d20SAndroid Build Coastguard Worker if (strncmp
2945*2d543d20SAndroid Build Coastguard Worker (line_buf, priority_names[i],
2946*2d543d20SAndroid Build Coastguard Worker priority_names_len[i]) == 0) {
2947*2d543d20SAndroid Build Coastguard Worker priority = i;
2948*2d543d20SAndroid Build Coastguard Worker offset = priority_names_len[i];
2949*2d543d20SAndroid Build Coastguard Worker break;
2950*2d543d20SAndroid Build Coastguard Worker }
2951*2d543d20SAndroid Build Coastguard Worker }
2952*2d543d20SAndroid Build Coastguard Worker
2953*2d543d20SAndroid Build Coastguard Worker if (priority < 0) {
2954*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Netfilter context line missing priority.");
2955*2d543d20SAndroid Build Coastguard Worker semanage_nc_destroy_ruletab(ruletab);
2956*2d543d20SAndroid Build Coastguard Worker return -1;
2957*2d543d20SAndroid Build Coastguard Worker }
2958*2d543d20SAndroid Build Coastguard Worker
2959*2d543d20SAndroid Build Coastguard Worker /* skip over whitespace */
2960*2d543d20SAndroid Build Coastguard Worker for (; offset < line_len && isspace(line_buf[offset]);
2961*2d543d20SAndroid Build Coastguard Worker offset++) ;
2962*2d543d20SAndroid Build Coastguard Worker
2963*2d543d20SAndroid Build Coastguard Worker /* load rule into node */
2964*2d543d20SAndroid Build Coastguard Worker node = (semanage_netfilter_context_node_t *)
2965*2d543d20SAndroid Build Coastguard Worker malloc(sizeof(semanage_netfilter_context_node_t));
2966*2d543d20SAndroid Build Coastguard Worker if (!node) {
2967*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2968*2d543d20SAndroid Build Coastguard Worker semanage_nc_destroy_ruletab(ruletab);
2969*2d543d20SAndroid Build Coastguard Worker return -1;
2970*2d543d20SAndroid Build Coastguard Worker }
2971*2d543d20SAndroid Build Coastguard Worker
2972*2d543d20SAndroid Build Coastguard Worker node->rule =
2973*2d543d20SAndroid Build Coastguard Worker (char *)strndup(line_buf + offset, line_len - offset);
2974*2d543d20SAndroid Build Coastguard Worker node->rule_len = line_len - offset;
2975*2d543d20SAndroid Build Coastguard Worker node->next = NULL;
2976*2d543d20SAndroid Build Coastguard Worker
2977*2d543d20SAndroid Build Coastguard Worker if (!node->rule) {
2978*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
2979*2d543d20SAndroid Build Coastguard Worker free(node);
2980*2d543d20SAndroid Build Coastguard Worker semanage_nc_destroy_ruletab(ruletab);
2981*2d543d20SAndroid Build Coastguard Worker return -1;
2982*2d543d20SAndroid Build Coastguard Worker }
2983*2d543d20SAndroid Build Coastguard Worker
2984*2d543d20SAndroid Build Coastguard Worker /* add node to rule table */
2985*2d543d20SAndroid Build Coastguard Worker if (ruletab[priority][0] && ruletab[priority][1]) {
2986*2d543d20SAndroid Build Coastguard Worker /* add to end of list, update tail pointer */
2987*2d543d20SAndroid Build Coastguard Worker ruletab[priority][1]->next = node;
2988*2d543d20SAndroid Build Coastguard Worker ruletab[priority][1] = node;
2989*2d543d20SAndroid Build Coastguard Worker } else {
2990*2d543d20SAndroid Build Coastguard Worker /* this list is empty, make head and tail point to the node */
2991*2d543d20SAndroid Build Coastguard Worker ruletab[priority][0] = ruletab[priority][1] = node;
2992*2d543d20SAndroid Build Coastguard Worker }
2993*2d543d20SAndroid Build Coastguard Worker
2994*2d543d20SAndroid Build Coastguard Worker line_buf = line_end + 1;
2995*2d543d20SAndroid Build Coastguard Worker }
2996*2d543d20SAndroid Build Coastguard Worker
2997*2d543d20SAndroid Build Coastguard Worker /* First, calculate how much space we'll need for
2998*2d543d20SAndroid Build Coastguard Worker * the newly sorted block of data. (We don't just
2999*2d543d20SAndroid Build Coastguard Worker * use buf_len for this because we have extracted
3000*2d543d20SAndroid Build Coastguard Worker * comments and whitespace.) Start at 1 for trailing \0 */
3001*2d543d20SAndroid Build Coastguard Worker count = 1;
3002*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < NC_SORT_NEL; i++)
3003*2d543d20SAndroid Build Coastguard Worker for (curr = ruletab[i][0]; curr != NULL; curr = curr->next)
3004*2d543d20SAndroid Build Coastguard Worker count += curr->rule_len;
3005*2d543d20SAndroid Build Coastguard Worker
3006*2d543d20SAndroid Build Coastguard Worker /* Allocate the buffer for the sorted list. */
3007*2d543d20SAndroid Build Coastguard Worker *sorted_buf = calloc(count, sizeof(char));
3008*2d543d20SAndroid Build Coastguard Worker if (!*sorted_buf) {
3009*2d543d20SAndroid Build Coastguard Worker ERR(sh, "Failure allocating memory.");
3010*2d543d20SAndroid Build Coastguard Worker semanage_nc_destroy_ruletab(ruletab);
3011*2d543d20SAndroid Build Coastguard Worker return -1;
3012*2d543d20SAndroid Build Coastguard Worker }
3013*2d543d20SAndroid Build Coastguard Worker *sorted_buf_len = count;
3014*2d543d20SAndroid Build Coastguard Worker
3015*2d543d20SAndroid Build Coastguard Worker /* write out rule buffer */
3016*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = *sorted_buf;
3017*2d543d20SAndroid Build Coastguard Worker for (i = 0; i < NC_SORT_NEL; i++) {
3018*2d543d20SAndroid Build Coastguard Worker for (curr = ruletab[i][0]; curr != NULL; curr = curr->next) {
3019*2d543d20SAndroid Build Coastguard Worker /* put rule into buffer */
3020*2d543d20SAndroid Build Coastguard Worker snprintf(sorted_buf_pos, curr->rule_len + 1, "%s\n", curr->rule); /* +1 for newline */
3021*2d543d20SAndroid Build Coastguard Worker sorted_buf_pos = sorted_buf_pos + curr->rule_len;
3022*2d543d20SAndroid Build Coastguard Worker }
3023*2d543d20SAndroid Build Coastguard Worker }
3024*2d543d20SAndroid Build Coastguard Worker
3025*2d543d20SAndroid Build Coastguard Worker /* free ruletab */
3026*2d543d20SAndroid Build Coastguard Worker semanage_nc_destroy_ruletab(ruletab);
3027*2d543d20SAndroid Build Coastguard Worker
3028*2d543d20SAndroid Build Coastguard Worker return 0;
3029*2d543d20SAndroid Build Coastguard Worker }
3030*2d543d20SAndroid Build Coastguard Worker
3031*2d543d20SAndroid Build Coastguard Worker /* Make sure the file context and ownership of files in the policy
3032*2d543d20SAndroid Build Coastguard Worker * store does not change */
semanage_setfiles(const char * path)3033*2d543d20SAndroid Build Coastguard Worker void semanage_setfiles(const char *path){
3034*2d543d20SAndroid Build Coastguard Worker struct stat sb;
3035*2d543d20SAndroid Build Coastguard Worker int fd;
3036*2d543d20SAndroid Build Coastguard Worker /* Fix the user and role portions of the context, ignore errors
3037*2d543d20SAndroid Build Coastguard Worker * since this is not a critical operation */
3038*2d543d20SAndroid Build Coastguard Worker selinux_restorecon(path, SELINUX_RESTORECON_SET_SPECFILE_CTX | SELINUX_RESTORECON_IGNORE_NOENTRY);
3039*2d543d20SAndroid Build Coastguard Worker
3040*2d543d20SAndroid Build Coastguard Worker /* Make sure "path" is owned by root */
3041*2d543d20SAndroid Build Coastguard Worker if ((geteuid() != 0 || getegid() != 0) &&
3042*2d543d20SAndroid Build Coastguard Worker ((fd = open(path, O_RDONLY)) != -1)){
3043*2d543d20SAndroid Build Coastguard Worker /* Skip files with the SUID or SGID bit set -- abuse protection */
3044*2d543d20SAndroid Build Coastguard Worker if ((fstat(fd, &sb) != -1) &&
3045*2d543d20SAndroid Build Coastguard Worker !(S_ISREG(sb.st_mode) &&
3046*2d543d20SAndroid Build Coastguard Worker (sb.st_mode & (S_ISUID | S_ISGID))) &&
3047*2d543d20SAndroid Build Coastguard Worker (fchown(fd, 0, 0) == -1))
3048*2d543d20SAndroid Build Coastguard Worker fprintf(stderr, "Warning! Could not set ownership of %s to root\n", path);
3049*2d543d20SAndroid Build Coastguard Worker
3050*2d543d20SAndroid Build Coastguard Worker close(fd);
3051*2d543d20SAndroid Build Coastguard Worker }
3052*2d543d20SAndroid Build Coastguard Worker }
3053