xref: /aosp_15_r20/external/selinux/libsemanage/src/direct_api.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /* Author: Jason Tang	  <[email protected]>
2*2d543d20SAndroid Build Coastguard Worker  *         Christopher Ashworth <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2004-2006 Tresys Technology, LLC
5*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2005 Red Hat, Inc.
6*2d543d20SAndroid Build Coastguard Worker  *
7*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
8*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
9*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
10*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
11*2d543d20SAndroid Build Coastguard Worker  *
12*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
13*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
16*2d543d20SAndroid Build Coastguard Worker  *
17*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
18*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
19*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
20*2d543d20SAndroid Build Coastguard Worker  */
21*2d543d20SAndroid Build Coastguard Worker 
22*2d543d20SAndroid Build Coastguard Worker #include <sepol/module.h>
23*2d543d20SAndroid Build Coastguard Worker #include <sepol/handle.h>
24*2d543d20SAndroid Build Coastguard Worker #include <sepol/cil/cil.h>
25*2d543d20SAndroid Build Coastguard Worker #include <selinux/selinux.h>
26*2d543d20SAndroid Build Coastguard Worker 
27*2d543d20SAndroid Build Coastguard Worker #include <assert.h>
28*2d543d20SAndroid Build Coastguard Worker #include <fcntl.h>
29*2d543d20SAndroid Build Coastguard Worker #include <stdio.h>
30*2d543d20SAndroid Build Coastguard Worker #include <stdio_ext.h>
31*2d543d20SAndroid Build Coastguard Worker #include <stdlib.h>
32*2d543d20SAndroid Build Coastguard Worker #include <string.h>
33*2d543d20SAndroid Build Coastguard Worker #include <unistd.h>
34*2d543d20SAndroid Build Coastguard Worker #include <sys/stat.h>
35*2d543d20SAndroid Build Coastguard Worker #include <sys/types.h>
36*2d543d20SAndroid Build Coastguard Worker #include <sys/mman.h>
37*2d543d20SAndroid Build Coastguard Worker #include <sys/wait.h>
38*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
39*2d543d20SAndroid Build Coastguard Worker #include <errno.h>
40*2d543d20SAndroid Build Coastguard Worker #include <dirent.h>
41*2d543d20SAndroid Build Coastguard Worker 
42*2d543d20SAndroid Build Coastguard Worker #include "user_internal.h"
43*2d543d20SAndroid Build Coastguard Worker #include "seuser_internal.h"
44*2d543d20SAndroid Build Coastguard Worker #include "port_internal.h"
45*2d543d20SAndroid Build Coastguard Worker #include "ibpkey_internal.h"
46*2d543d20SAndroid Build Coastguard Worker #include "ibendport_internal.h"
47*2d543d20SAndroid Build Coastguard Worker #include "iface_internal.h"
48*2d543d20SAndroid Build Coastguard Worker #include "boolean_internal.h"
49*2d543d20SAndroid Build Coastguard Worker #include "fcontext_internal.h"
50*2d543d20SAndroid Build Coastguard Worker #include "node_internal.h"
51*2d543d20SAndroid Build Coastguard Worker #include "genhomedircon.h"
52*2d543d20SAndroid Build Coastguard Worker 
53*2d543d20SAndroid Build Coastguard Worker #include "debug.h"
54*2d543d20SAndroid Build Coastguard Worker #include "handle.h"
55*2d543d20SAndroid Build Coastguard Worker #include "compressed_file.h"
56*2d543d20SAndroid Build Coastguard Worker #include "modules.h"
57*2d543d20SAndroid Build Coastguard Worker #include "direct_api.h"
58*2d543d20SAndroid Build Coastguard Worker #include "semanage_store.h"
59*2d543d20SAndroid Build Coastguard Worker #include "database_policydb.h"
60*2d543d20SAndroid Build Coastguard Worker #include "policy.h"
61*2d543d20SAndroid Build Coastguard Worker #include "sha256.h"
62*2d543d20SAndroid Build Coastguard Worker 
63*2d543d20SAndroid Build Coastguard Worker #define PIPE_READ 0
64*2d543d20SAndroid Build Coastguard Worker #define PIPE_WRITE 1
65*2d543d20SAndroid Build Coastguard Worker #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
66*2d543d20SAndroid Build Coastguard Worker 
67*2d543d20SAndroid Build Coastguard Worker static void semanage_direct_destroy(semanage_handle_t * sh);
68*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_disconnect(semanage_handle_t * sh);
69*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_begintrans(semanage_handle_t * sh);
70*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_commit(semanage_handle_t * sh);
71*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install(semanage_handle_t * sh, char *data,
72*2d543d20SAndroid Build Coastguard Worker 				   size_t data_len, const char *module_name, const char *lang_ext);
73*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install_file(semanage_handle_t * sh, const char *module_name);
74*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_extract(semanage_handle_t * sh,
75*2d543d20SAndroid Build Coastguard Worker 					   semanage_module_key_t *modkey,
76*2d543d20SAndroid Build Coastguard Worker 					   int extract_cil,
77*2d543d20SAndroid Build Coastguard Worker 					   void **mapped_data,
78*2d543d20SAndroid Build Coastguard Worker 					   size_t *data_len,
79*2d543d20SAndroid Build Coastguard Worker 					   semanage_module_info_t **modinfo);
80*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_remove(semanage_handle_t * sh, char *module_name);
81*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_list(semanage_handle_t * sh,
82*2d543d20SAndroid Build Coastguard Worker 				semanage_module_info_t ** modinfo,
83*2d543d20SAndroid Build Coastguard Worker 				int *num_modules);
84*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_get_enabled(semanage_handle_t *sh,
85*2d543d20SAndroid Build Coastguard Worker 				       const semanage_module_key_t *modkey,
86*2d543d20SAndroid Build Coastguard Worker 				       int *enabled);
87*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_set_enabled(semanage_handle_t *sh,
88*2d543d20SAndroid Build Coastguard Worker 				       const semanage_module_key_t *modkey,
89*2d543d20SAndroid Build Coastguard Worker 				       int enabled);
90*2d543d20SAndroid Build Coastguard Worker 
91*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_get_module_info(semanage_handle_t *sh,
92*2d543d20SAndroid Build Coastguard Worker 					   const semanage_module_key_t *modkey,
93*2d543d20SAndroid Build Coastguard Worker 					   semanage_module_info_t **modinfo);
94*2d543d20SAndroid Build Coastguard Worker 
95*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_list_all(semanage_handle_t *sh,
96*2d543d20SAndroid Build Coastguard Worker 				    semanage_module_info_t **modinfo,
97*2d543d20SAndroid Build Coastguard Worker 				    int *num_modules);
98*2d543d20SAndroid Build Coastguard Worker 
99*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install_info(semanage_handle_t *sh,
100*2d543d20SAndroid Build Coastguard Worker 					const semanage_module_info_t *modinfo,
101*2d543d20SAndroid Build Coastguard Worker 					char *data,
102*2d543d20SAndroid Build Coastguard Worker 					size_t data_len);
103*2d543d20SAndroid Build Coastguard Worker 
104*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_remove_key(semanage_handle_t *sh,
105*2d543d20SAndroid Build Coastguard Worker 				      const semanage_module_key_t *modkey);
106*2d543d20SAndroid Build Coastguard Worker 
107*2d543d20SAndroid Build Coastguard Worker static struct semanage_policy_table direct_funcs = {
108*2d543d20SAndroid Build Coastguard Worker 	.get_serial = semanage_direct_get_serial,
109*2d543d20SAndroid Build Coastguard Worker 	.destroy = semanage_direct_destroy,
110*2d543d20SAndroid Build Coastguard Worker 	.disconnect = semanage_direct_disconnect,
111*2d543d20SAndroid Build Coastguard Worker 	.begin_trans = semanage_direct_begintrans,
112*2d543d20SAndroid Build Coastguard Worker 	.commit = semanage_direct_commit,
113*2d543d20SAndroid Build Coastguard Worker 	.install = semanage_direct_install,
114*2d543d20SAndroid Build Coastguard Worker 	.extract = semanage_direct_extract,
115*2d543d20SAndroid Build Coastguard Worker 	.install_file = semanage_direct_install_file,
116*2d543d20SAndroid Build Coastguard Worker 	.remove = semanage_direct_remove,
117*2d543d20SAndroid Build Coastguard Worker 	.list = semanage_direct_list,
118*2d543d20SAndroid Build Coastguard Worker 	.get_enabled = semanage_direct_get_enabled,
119*2d543d20SAndroid Build Coastguard Worker 	.set_enabled = semanage_direct_set_enabled,
120*2d543d20SAndroid Build Coastguard Worker 	.get_module_info = semanage_direct_get_module_info,
121*2d543d20SAndroid Build Coastguard Worker 	.list_all = semanage_direct_list_all,
122*2d543d20SAndroid Build Coastguard Worker 	.install_info = semanage_direct_install_info,
123*2d543d20SAndroid Build Coastguard Worker 	.remove_key = semanage_direct_remove_key,
124*2d543d20SAndroid Build Coastguard Worker };
125*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_is_managed(semanage_handle_t * sh)126*2d543d20SAndroid Build Coastguard Worker int semanage_direct_is_managed(semanage_handle_t * sh)
127*2d543d20SAndroid Build Coastguard Worker {
128*2d543d20SAndroid Build Coastguard Worker 	if (semanage_check_init(sh, sh->conf->store_root_path))
129*2d543d20SAndroid Build Coastguard Worker 		goto err;
130*2d543d20SAndroid Build Coastguard Worker 
131*2d543d20SAndroid Build Coastguard Worker 	if (semanage_access_check(sh) < 0)
132*2d543d20SAndroid Build Coastguard Worker 		return 0;
133*2d543d20SAndroid Build Coastguard Worker 
134*2d543d20SAndroid Build Coastguard Worker 	return 1;
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker       err:
137*2d543d20SAndroid Build Coastguard Worker 	ERR(sh, "could not check whether policy is managed");
138*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
139*2d543d20SAndroid Build Coastguard Worker }
140*2d543d20SAndroid Build Coastguard Worker 
141*2d543d20SAndroid Build Coastguard Worker /* Check that the module store exists, creating it if necessary.
142*2d543d20SAndroid Build Coastguard Worker  */
semanage_direct_connect(semanage_handle_t * sh)143*2d543d20SAndroid Build Coastguard Worker int semanage_direct_connect(semanage_handle_t * sh)
144*2d543d20SAndroid Build Coastguard Worker {
145*2d543d20SAndroid Build Coastguard Worker 	const char *path;
146*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
147*2d543d20SAndroid Build Coastguard Worker 
148*2d543d20SAndroid Build Coastguard Worker 	if (semanage_check_init(sh, sh->conf->store_root_path))
149*2d543d20SAndroid Build Coastguard Worker 		goto err;
150*2d543d20SAndroid Build Coastguard Worker 
151*2d543d20SAndroid Build Coastguard Worker 	if (sh->create_store)
152*2d543d20SAndroid Build Coastguard Worker 		if (semanage_create_store(sh, 1))
153*2d543d20SAndroid Build Coastguard Worker 			goto err;
154*2d543d20SAndroid Build Coastguard Worker 
155*2d543d20SAndroid Build Coastguard Worker 	sh->u.direct.translock_file_fd = -1;
156*2d543d20SAndroid Build Coastguard Worker 	sh->u.direct.activelock_file_fd = -1;
157*2d543d20SAndroid Build Coastguard Worker 
158*2d543d20SAndroid Build Coastguard Worker 	/* set up function pointers */
159*2d543d20SAndroid Build Coastguard Worker 	sh->funcs = &direct_funcs;
160*2d543d20SAndroid Build Coastguard Worker 
161*2d543d20SAndroid Build Coastguard Worker 	/* Object databases: local modifications */
162*2d543d20SAndroid Build Coastguard Worker 	if (user_base_file_dbase_init(sh,
163*2d543d20SAndroid Build Coastguard Worker 				      semanage_path(SEMANAGE_ACTIVE,
164*2d543d20SAndroid Build Coastguard Worker 						    SEMANAGE_USERS_BASE_LOCAL),
165*2d543d20SAndroid Build Coastguard Worker 				      semanage_path(SEMANAGE_TMP,
166*2d543d20SAndroid Build Coastguard Worker 						    SEMANAGE_USERS_BASE_LOCAL),
167*2d543d20SAndroid Build Coastguard Worker 				      semanage_user_base_dbase_local(sh)) < 0)
168*2d543d20SAndroid Build Coastguard Worker 		goto err;
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 	if (user_extra_file_dbase_init(sh,
171*2d543d20SAndroid Build Coastguard Worker 				       semanage_path(SEMANAGE_ACTIVE,
172*2d543d20SAndroid Build Coastguard Worker 						     SEMANAGE_USERS_EXTRA_LOCAL),
173*2d543d20SAndroid Build Coastguard Worker 				       semanage_path(SEMANAGE_TMP,
174*2d543d20SAndroid Build Coastguard Worker 						     SEMANAGE_USERS_EXTRA_LOCAL),
175*2d543d20SAndroid Build Coastguard Worker 				       semanage_user_extra_dbase_local(sh)) < 0)
176*2d543d20SAndroid Build Coastguard Worker 		goto err;
177*2d543d20SAndroid Build Coastguard Worker 
178*2d543d20SAndroid Build Coastguard Worker 	if (user_join_dbase_init(sh,
179*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_base_dbase_local(sh),
180*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_extra_dbase_local(sh),
181*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_dbase_local(sh)) < 0)
182*2d543d20SAndroid Build Coastguard Worker 		goto err;
183*2d543d20SAndroid Build Coastguard Worker 
184*2d543d20SAndroid Build Coastguard Worker 	if (port_file_dbase_init(sh,
185*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_ACTIVE,
186*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_PORTS_LOCAL),
187*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_TMP,
188*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_PORTS_LOCAL),
189*2d543d20SAndroid Build Coastguard Worker 				 semanage_port_dbase_local(sh)) < 0)
190*2d543d20SAndroid Build Coastguard Worker 		goto err;
191*2d543d20SAndroid Build Coastguard Worker 
192*2d543d20SAndroid Build Coastguard Worker 	if (iface_file_dbase_init(sh,
193*2d543d20SAndroid Build Coastguard Worker 				  semanage_path(SEMANAGE_ACTIVE,
194*2d543d20SAndroid Build Coastguard Worker 						SEMANAGE_INTERFACES_LOCAL),
195*2d543d20SAndroid Build Coastguard Worker 				  semanage_path(SEMANAGE_TMP,
196*2d543d20SAndroid Build Coastguard Worker 						SEMANAGE_INTERFACES_LOCAL),
197*2d543d20SAndroid Build Coastguard Worker 				  semanage_iface_dbase_local(sh)) < 0)
198*2d543d20SAndroid Build Coastguard Worker 		goto err;
199*2d543d20SAndroid Build Coastguard Worker 
200*2d543d20SAndroid Build Coastguard Worker 	if (bool_file_dbase_init(sh,
201*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_ACTIVE,
202*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_BOOLEANS_LOCAL),
203*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_TMP,
204*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_BOOLEANS_LOCAL),
205*2d543d20SAndroid Build Coastguard Worker 				 semanage_bool_dbase_local(sh)) < 0)
206*2d543d20SAndroid Build Coastguard Worker 		goto err;
207*2d543d20SAndroid Build Coastguard Worker 
208*2d543d20SAndroid Build Coastguard Worker 	if (fcontext_file_dbase_init(sh,
209*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC_LOCAL),
210*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
211*2d543d20SAndroid Build Coastguard Worker 				     semanage_fcontext_dbase_local(sh)) < 0)
212*2d543d20SAndroid Build Coastguard Worker 		goto err;
213*2d543d20SAndroid Build Coastguard Worker 
214*2d543d20SAndroid Build Coastguard Worker 	if (fcontext_file_dbase_init(sh,
215*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC_HOMEDIRS),
216*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS),
217*2d543d20SAndroid Build Coastguard Worker 				     semanage_fcontext_dbase_homedirs(sh)) < 0)
218*2d543d20SAndroid Build Coastguard Worker 		goto err;
219*2d543d20SAndroid Build Coastguard Worker 
220*2d543d20SAndroid Build Coastguard Worker 	if (seuser_file_dbase_init(sh,
221*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_ACTIVE,
222*2d543d20SAndroid Build Coastguard Worker 						 SEMANAGE_SEUSERS_LOCAL),
223*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_TMP,
224*2d543d20SAndroid Build Coastguard Worker 						 SEMANAGE_SEUSERS_LOCAL),
225*2d543d20SAndroid Build Coastguard Worker 				   semanage_seuser_dbase_local(sh)) < 0)
226*2d543d20SAndroid Build Coastguard Worker 		goto err;
227*2d543d20SAndroid Build Coastguard Worker 
228*2d543d20SAndroid Build Coastguard Worker 	if (node_file_dbase_init(sh,
229*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_ACTIVE,
230*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_NODES_LOCAL),
231*2d543d20SAndroid Build Coastguard Worker 				 semanage_path(SEMANAGE_TMP,
232*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_NODES_LOCAL),
233*2d543d20SAndroid Build Coastguard Worker 				 semanage_node_dbase_local(sh)) < 0)
234*2d543d20SAndroid Build Coastguard Worker 		goto err;
235*2d543d20SAndroid Build Coastguard Worker 
236*2d543d20SAndroid Build Coastguard Worker 	if (ibpkey_file_dbase_init(sh,
237*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_ACTIVE,
238*2d543d20SAndroid Build Coastguard Worker 					         SEMANAGE_IBPKEYS_LOCAL),
239*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_TMP,
240*2d543d20SAndroid Build Coastguard Worker 					         SEMANAGE_IBPKEYS_LOCAL),
241*2d543d20SAndroid Build Coastguard Worker 				   semanage_ibpkey_dbase_local(sh)) < 0)
242*2d543d20SAndroid Build Coastguard Worker 		goto err;
243*2d543d20SAndroid Build Coastguard Worker 
244*2d543d20SAndroid Build Coastguard Worker 	if (ibendport_file_dbase_init(sh,
245*2d543d20SAndroid Build Coastguard Worker 				      semanage_path(SEMANAGE_ACTIVE,
246*2d543d20SAndroid Build Coastguard Worker 						    SEMANAGE_IBENDPORTS_LOCAL),
247*2d543d20SAndroid Build Coastguard Worker 				      semanage_path(SEMANAGE_TMP,
248*2d543d20SAndroid Build Coastguard Worker 						    SEMANAGE_IBENDPORTS_LOCAL),
249*2d543d20SAndroid Build Coastguard Worker 				      semanage_ibendport_dbase_local(sh)) < 0)
250*2d543d20SAndroid Build Coastguard Worker 		goto err;
251*2d543d20SAndroid Build Coastguard Worker 
252*2d543d20SAndroid Build Coastguard Worker 	/* Object databases: local modifications + policy */
253*2d543d20SAndroid Build Coastguard Worker 	if (user_base_policydb_dbase_init(sh,
254*2d543d20SAndroid Build Coastguard Worker 					  semanage_user_base_dbase_policy(sh)) <
255*2d543d20SAndroid Build Coastguard Worker 	    0)
256*2d543d20SAndroid Build Coastguard Worker 		goto err;
257*2d543d20SAndroid Build Coastguard Worker 
258*2d543d20SAndroid Build Coastguard Worker 	if (user_extra_file_dbase_init(sh,
259*2d543d20SAndroid Build Coastguard Worker 				       semanage_path(SEMANAGE_ACTIVE,
260*2d543d20SAndroid Build Coastguard Worker 						     SEMANAGE_USERS_EXTRA),
261*2d543d20SAndroid Build Coastguard Worker 				       semanage_path(SEMANAGE_TMP,
262*2d543d20SAndroid Build Coastguard Worker 						     SEMANAGE_USERS_EXTRA),
263*2d543d20SAndroid Build Coastguard Worker 				       semanage_user_extra_dbase_policy(sh)) <
264*2d543d20SAndroid Build Coastguard Worker 	    0)
265*2d543d20SAndroid Build Coastguard Worker 		goto err;
266*2d543d20SAndroid Build Coastguard Worker 
267*2d543d20SAndroid Build Coastguard Worker 	if (user_join_dbase_init(sh,
268*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_base_dbase_policy(sh),
269*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_extra_dbase_policy(sh),
270*2d543d20SAndroid Build Coastguard Worker 				 semanage_user_dbase_policy(sh)) < 0)
271*2d543d20SAndroid Build Coastguard Worker 		goto err;
272*2d543d20SAndroid Build Coastguard Worker 
273*2d543d20SAndroid Build Coastguard Worker 	if (port_policydb_dbase_init(sh, semanage_port_dbase_policy(sh)) < 0)
274*2d543d20SAndroid Build Coastguard Worker 		goto err;
275*2d543d20SAndroid Build Coastguard Worker 
276*2d543d20SAndroid Build Coastguard Worker 	if (ibpkey_policydb_dbase_init(sh, semanage_ibpkey_dbase_policy(sh)) < 0)
277*2d543d20SAndroid Build Coastguard Worker 		goto err;
278*2d543d20SAndroid Build Coastguard Worker 
279*2d543d20SAndroid Build Coastguard Worker 	if (ibendport_policydb_dbase_init(sh, semanage_ibendport_dbase_policy(sh)) < 0)
280*2d543d20SAndroid Build Coastguard Worker 		goto err;
281*2d543d20SAndroid Build Coastguard Worker 
282*2d543d20SAndroid Build Coastguard Worker 	if (iface_policydb_dbase_init(sh, semanage_iface_dbase_policy(sh)) < 0)
283*2d543d20SAndroid Build Coastguard Worker 		goto err;
284*2d543d20SAndroid Build Coastguard Worker 
285*2d543d20SAndroid Build Coastguard Worker 	if (bool_policydb_dbase_init(sh, semanage_bool_dbase_policy(sh)) < 0)
286*2d543d20SAndroid Build Coastguard Worker 		goto err;
287*2d543d20SAndroid Build Coastguard Worker 
288*2d543d20SAndroid Build Coastguard Worker 	if (fcontext_file_dbase_init(sh,
289*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_FC),
290*2d543d20SAndroid Build Coastguard Worker 				     semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
291*2d543d20SAndroid Build Coastguard Worker 				     semanage_fcontext_dbase_policy(sh)) < 0)
292*2d543d20SAndroid Build Coastguard Worker 		goto err;
293*2d543d20SAndroid Build Coastguard Worker 
294*2d543d20SAndroid Build Coastguard Worker 	if (seuser_file_dbase_init(sh,
295*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_ACTIVE, SEMANAGE_STORE_SEUSERS),
296*2d543d20SAndroid Build Coastguard Worker 				   semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS),
297*2d543d20SAndroid Build Coastguard Worker 				   semanage_seuser_dbase_policy(sh)) < 0)
298*2d543d20SAndroid Build Coastguard Worker 		goto err;
299*2d543d20SAndroid Build Coastguard Worker 
300*2d543d20SAndroid Build Coastguard Worker 	if (node_policydb_dbase_init(sh, semanage_node_dbase_policy(sh)) < 0)
301*2d543d20SAndroid Build Coastguard Worker 		goto err;
302*2d543d20SAndroid Build Coastguard Worker 
303*2d543d20SAndroid Build Coastguard Worker 	/* Active kernel policy */
304*2d543d20SAndroid Build Coastguard Worker 	if (bool_activedb_dbase_init(sh, semanage_bool_dbase_active(sh)) < 0)
305*2d543d20SAndroid Build Coastguard Worker 		goto err;
306*2d543d20SAndroid Build Coastguard Worker 
307*2d543d20SAndroid Build Coastguard Worker 	/* set the disable dontaudit value */
308*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_DISABLE_DONTAUDIT);
309*2d543d20SAndroid Build Coastguard Worker 
310*2d543d20SAndroid Build Coastguard Worker 	if (stat(path, &sb) == 0)
311*2d543d20SAndroid Build Coastguard Worker 		sepol_set_disable_dontaudit(sh->sepolh, 1);
312*2d543d20SAndroid Build Coastguard Worker 	else if (errno == ENOENT) {
313*2d543d20SAndroid Build Coastguard Worker 		/* The file does not exist */
314*2d543d20SAndroid Build Coastguard Worker 		sepol_set_disable_dontaudit(sh->sepolh, 0);
315*2d543d20SAndroid Build Coastguard Worker 	} else {
316*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
317*2d543d20SAndroid Build Coastguard Worker 		goto err;
318*2d543d20SAndroid Build Coastguard Worker 	}
319*2d543d20SAndroid Build Coastguard Worker 
320*2d543d20SAndroid Build Coastguard Worker 	return STATUS_SUCCESS;
321*2d543d20SAndroid Build Coastguard Worker 
322*2d543d20SAndroid Build Coastguard Worker       err:
323*2d543d20SAndroid Build Coastguard Worker 	ERR(sh, "could not establish direct connection");
324*2d543d20SAndroid Build Coastguard Worker 	return STATUS_ERR;
325*2d543d20SAndroid Build Coastguard Worker }
326*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_destroy(semanage_handle_t * sh)327*2d543d20SAndroid Build Coastguard Worker static void semanage_direct_destroy(semanage_handle_t * sh
328*2d543d20SAndroid Build Coastguard Worker 					__attribute__ ((unused)))
329*2d543d20SAndroid Build Coastguard Worker {
330*2d543d20SAndroid Build Coastguard Worker 	/* do nothing */
331*2d543d20SAndroid Build Coastguard Worker }
332*2d543d20SAndroid Build Coastguard Worker 
semanage_remove_tmps(semanage_handle_t * sh)333*2d543d20SAndroid Build Coastguard Worker static int semanage_remove_tmps(semanage_handle_t *sh)
334*2d543d20SAndroid Build Coastguard Worker {
335*2d543d20SAndroid Build Coastguard Worker 	if (sh->commit_err)
336*2d543d20SAndroid Build Coastguard Worker 		return 0;
337*2d543d20SAndroid Build Coastguard Worker 
338*2d543d20SAndroid Build Coastguard Worker 	/* destroy sandbox if it exists */
339*2d543d20SAndroid Build Coastguard Worker 	if (semanage_remove_directory
340*2d543d20SAndroid Build Coastguard Worker 	    (semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL)) < 0) {
341*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
342*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Could not cleanly remove sandbox %s.",
343*2d543d20SAndroid Build Coastguard Worker 			    semanage_path(SEMANAGE_TMP, SEMANAGE_TOPLEVEL));
344*2d543d20SAndroid Build Coastguard Worker 			return -1;
345*2d543d20SAndroid Build Coastguard Worker 		}
346*2d543d20SAndroid Build Coastguard Worker 	}
347*2d543d20SAndroid Build Coastguard Worker 
348*2d543d20SAndroid Build Coastguard Worker 	/* destroy tmp policy if it exists */
349*2d543d20SAndroid Build Coastguard Worker 	if (semanage_remove_directory
350*2d543d20SAndroid Build Coastguard Worker 	    (semanage_final_path(SEMANAGE_FINAL_TMP,
351*2d543d20SAndroid Build Coastguard Worker 				 SEMANAGE_FINAL_TOPLEVEL)) < 0) {
352*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
353*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Could not cleanly remove tmp %s.",
354*2d543d20SAndroid Build Coastguard Worker 			    semanage_final_path(SEMANAGE_FINAL_TMP,
355*2d543d20SAndroid Build Coastguard Worker 						SEMANAGE_FINAL_TOPLEVEL));
356*2d543d20SAndroid Build Coastguard Worker 			return -1;
357*2d543d20SAndroid Build Coastguard Worker 		}
358*2d543d20SAndroid Build Coastguard Worker 	}
359*2d543d20SAndroid Build Coastguard Worker 
360*2d543d20SAndroid Build Coastguard Worker 	return 0;
361*2d543d20SAndroid Build Coastguard Worker }
362*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_disconnect(semanage_handle_t * sh)363*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_disconnect(semanage_handle_t *sh)
364*2d543d20SAndroid Build Coastguard Worker {
365*2d543d20SAndroid Build Coastguard Worker 	int retval = 0;
366*2d543d20SAndroid Build Coastguard Worker 
367*2d543d20SAndroid Build Coastguard Worker 	/* destroy transaction and remove tmp files if no commit error */
368*2d543d20SAndroid Build Coastguard Worker 	if (sh->is_in_transaction) {
369*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_remove_tmps(sh);
370*2d543d20SAndroid Build Coastguard Worker 		semanage_release_trans_lock(sh);
371*2d543d20SAndroid Build Coastguard Worker 	}
372*2d543d20SAndroid Build Coastguard Worker 
373*2d543d20SAndroid Build Coastguard Worker 	/* Release object databases: local modifications */
374*2d543d20SAndroid Build Coastguard Worker 	user_base_file_dbase_release(semanage_user_base_dbase_local(sh));
375*2d543d20SAndroid Build Coastguard Worker 	user_extra_file_dbase_release(semanage_user_extra_dbase_local(sh));
376*2d543d20SAndroid Build Coastguard Worker 	user_join_dbase_release(semanage_user_dbase_local(sh));
377*2d543d20SAndroid Build Coastguard Worker 	port_file_dbase_release(semanage_port_dbase_local(sh));
378*2d543d20SAndroid Build Coastguard Worker 	ibpkey_file_dbase_release(semanage_ibpkey_dbase_local(sh));
379*2d543d20SAndroid Build Coastguard Worker 	ibendport_file_dbase_release(semanage_ibendport_dbase_local(sh));
380*2d543d20SAndroid Build Coastguard Worker 	iface_file_dbase_release(semanage_iface_dbase_local(sh));
381*2d543d20SAndroid Build Coastguard Worker 	bool_file_dbase_release(semanage_bool_dbase_local(sh));
382*2d543d20SAndroid Build Coastguard Worker 	fcontext_file_dbase_release(semanage_fcontext_dbase_local(sh));
383*2d543d20SAndroid Build Coastguard Worker 	fcontext_file_dbase_release(semanage_fcontext_dbase_homedirs(sh));
384*2d543d20SAndroid Build Coastguard Worker 	seuser_file_dbase_release(semanage_seuser_dbase_local(sh));
385*2d543d20SAndroid Build Coastguard Worker 	node_file_dbase_release(semanage_node_dbase_local(sh));
386*2d543d20SAndroid Build Coastguard Worker 
387*2d543d20SAndroid Build Coastguard Worker 	/* Release object databases: local modifications + policy */
388*2d543d20SAndroid Build Coastguard Worker 	user_base_policydb_dbase_release(semanage_user_base_dbase_policy(sh));
389*2d543d20SAndroid Build Coastguard Worker 	user_extra_file_dbase_release(semanage_user_extra_dbase_policy(sh));
390*2d543d20SAndroid Build Coastguard Worker 	user_join_dbase_release(semanage_user_dbase_policy(sh));
391*2d543d20SAndroid Build Coastguard Worker 	port_policydb_dbase_release(semanage_port_dbase_policy(sh));
392*2d543d20SAndroid Build Coastguard Worker 	ibpkey_policydb_dbase_release(semanage_ibpkey_dbase_policy(sh));
393*2d543d20SAndroid Build Coastguard Worker 	ibendport_policydb_dbase_release(semanage_ibendport_dbase_policy(sh));
394*2d543d20SAndroid Build Coastguard Worker 	iface_policydb_dbase_release(semanage_iface_dbase_policy(sh));
395*2d543d20SAndroid Build Coastguard Worker 	bool_policydb_dbase_release(semanage_bool_dbase_policy(sh));
396*2d543d20SAndroid Build Coastguard Worker 	fcontext_file_dbase_release(semanage_fcontext_dbase_policy(sh));
397*2d543d20SAndroid Build Coastguard Worker 	seuser_file_dbase_release(semanage_seuser_dbase_policy(sh));
398*2d543d20SAndroid Build Coastguard Worker 	node_policydb_dbase_release(semanage_node_dbase_policy(sh));
399*2d543d20SAndroid Build Coastguard Worker 
400*2d543d20SAndroid Build Coastguard Worker 	/* Release object databases: active kernel policy */
401*2d543d20SAndroid Build Coastguard Worker 	bool_activedb_dbase_release(semanage_bool_dbase_active(sh));
402*2d543d20SAndroid Build Coastguard Worker 
403*2d543d20SAndroid Build Coastguard Worker 	return retval;
404*2d543d20SAndroid Build Coastguard Worker }
405*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_begintrans(semanage_handle_t * sh)406*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_begintrans(semanage_handle_t * sh)
407*2d543d20SAndroid Build Coastguard Worker {
408*2d543d20SAndroid Build Coastguard Worker 	if (semanage_get_trans_lock(sh) < 0) {
409*2d543d20SAndroid Build Coastguard Worker 		return -1;
410*2d543d20SAndroid Build Coastguard Worker 	}
411*2d543d20SAndroid Build Coastguard Worker 	if ((semanage_make_sandbox(sh)) < 0) {
412*2d543d20SAndroid Build Coastguard Worker 		return -1;
413*2d543d20SAndroid Build Coastguard Worker 	}
414*2d543d20SAndroid Build Coastguard Worker 	if ((semanage_make_final(sh)) < 0) {
415*2d543d20SAndroid Build Coastguard Worker 		return -1;
416*2d543d20SAndroid Build Coastguard Worker 	}
417*2d543d20SAndroid Build Coastguard Worker 	return 0;
418*2d543d20SAndroid Build Coastguard Worker }
419*2d543d20SAndroid Build Coastguard Worker 
420*2d543d20SAndroid Build Coastguard Worker /********************* utility functions *********************/
421*2d543d20SAndroid Build Coastguard Worker 
422*2d543d20SAndroid Build Coastguard Worker /* Takes a module stored in 'module_data' and parses its headers.
423*2d543d20SAndroid Build Coastguard Worker  * Sets reference variables 'module_name' to module's name, and
424*2d543d20SAndroid Build Coastguard Worker  * 'version' to module's version.  The caller is responsible for
425*2d543d20SAndroid Build Coastguard Worker  * free()ing 'module_name', and 'version'; they will be
426*2d543d20SAndroid Build Coastguard Worker  * set to NULL upon entering this function.  Returns 0 on success, -1
427*2d543d20SAndroid Build Coastguard Worker  * if out of memory.
428*2d543d20SAndroid Build Coastguard Worker  */
parse_module_headers(semanage_handle_t * sh,char * module_data,size_t data_len,char ** module_name,char ** version)429*2d543d20SAndroid Build Coastguard Worker static int parse_module_headers(semanage_handle_t * sh, char *module_data,
430*2d543d20SAndroid Build Coastguard Worker                                size_t data_len, char **module_name,
431*2d543d20SAndroid Build Coastguard Worker                                char **version)
432*2d543d20SAndroid Build Coastguard Worker {
433*2d543d20SAndroid Build Coastguard Worker        struct sepol_policy_file *pf;
434*2d543d20SAndroid Build Coastguard Worker        int file_type;
435*2d543d20SAndroid Build Coastguard Worker        *module_name = *version = NULL;
436*2d543d20SAndroid Build Coastguard Worker 
437*2d543d20SAndroid Build Coastguard Worker        if (sepol_policy_file_create(&pf)) {
438*2d543d20SAndroid Build Coastguard Worker                ERR(sh, "Out of memory!");
439*2d543d20SAndroid Build Coastguard Worker                return -1;
440*2d543d20SAndroid Build Coastguard Worker        }
441*2d543d20SAndroid Build Coastguard Worker        sepol_policy_file_set_mem(pf, module_data, data_len);
442*2d543d20SAndroid Build Coastguard Worker        sepol_policy_file_set_handle(pf, sh->sepolh);
443*2d543d20SAndroid Build Coastguard Worker        if (module_data != NULL && data_len > 0)
444*2d543d20SAndroid Build Coastguard Worker            sepol_module_package_info(pf, &file_type, module_name,
445*2d543d20SAndroid Build Coastguard Worker                                      version);
446*2d543d20SAndroid Build Coastguard Worker        sepol_policy_file_free(pf);
447*2d543d20SAndroid Build Coastguard Worker 
448*2d543d20SAndroid Build Coastguard Worker        return 0;
449*2d543d20SAndroid Build Coastguard Worker }
450*2d543d20SAndroid Build Coastguard Worker 
451*2d543d20SAndroid Build Coastguard Worker /* Writes a block of data to a file.  Returns 0 on success, -1 on
452*2d543d20SAndroid Build Coastguard Worker  * error. */
write_file(semanage_handle_t * sh,const char * filename,const char * data,size_t num_bytes)453*2d543d20SAndroid Build Coastguard Worker static int write_file(semanage_handle_t * sh,
454*2d543d20SAndroid Build Coastguard Worker 		      const char *filename, const char *data, size_t num_bytes)
455*2d543d20SAndroid Build Coastguard Worker {
456*2d543d20SAndroid Build Coastguard Worker 	int out;
457*2d543d20SAndroid Build Coastguard Worker 
458*2d543d20SAndroid Build Coastguard Worker 	if ((out =
459*2d543d20SAndroid Build Coastguard Worker 	     open(filename, O_WRONLY | O_CREAT | O_TRUNC,
460*2d543d20SAndroid Build Coastguard Worker 		  S_IRUSR | S_IWUSR)) == -1) {
461*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Could not open %s for writing.", filename);
462*2d543d20SAndroid Build Coastguard Worker 		return -1;
463*2d543d20SAndroid Build Coastguard Worker 	}
464*2d543d20SAndroid Build Coastguard Worker 	if (write(out, data, num_bytes) == -1) {
465*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Error while writing to %s.", filename);
466*2d543d20SAndroid Build Coastguard Worker 		close(out);
467*2d543d20SAndroid Build Coastguard Worker 		return -1;
468*2d543d20SAndroid Build Coastguard Worker 	}
469*2d543d20SAndroid Build Coastguard Worker 	close(out);
470*2d543d20SAndroid Build Coastguard Worker 	return 0;
471*2d543d20SAndroid Build Coastguard Worker }
472*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_update_user_extra(semanage_handle_t * sh,cil_db_t * cildb)473*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_update_user_extra(semanage_handle_t * sh, cil_db_t *cildb)
474*2d543d20SAndroid Build Coastguard Worker {
475*2d543d20SAndroid Build Coastguard Worker 	const char *ofilename = NULL;
476*2d543d20SAndroid Build Coastguard Worker 	int retval = -1;
477*2d543d20SAndroid Build Coastguard Worker 	char *data = NULL;
478*2d543d20SAndroid Build Coastguard Worker 	size_t size = 0;
479*2d543d20SAndroid Build Coastguard Worker 
480*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh);
481*2d543d20SAndroid Build Coastguard Worker 
482*2d543d20SAndroid Build Coastguard Worker 	retval = cil_userprefixes_to_string(cildb, &data, &size);
483*2d543d20SAndroid Build Coastguard Worker 	if (retval != SEPOL_OK) {
484*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
485*2d543d20SAndroid Build Coastguard Worker 	}
486*2d543d20SAndroid Build Coastguard Worker 
487*2d543d20SAndroid Build Coastguard Worker 	if (size > 0) {
488*2d543d20SAndroid Build Coastguard Worker 		/*
489*2d543d20SAndroid Build Coastguard Worker 		 * Write the users_extra entries from CIL modules.
490*2d543d20SAndroid Build Coastguard Worker 		 * This file is used as our baseline when we do not require
491*2d543d20SAndroid Build Coastguard Worker 		 * re-linking.
492*2d543d20SAndroid Build Coastguard Worker 		 */
493*2d543d20SAndroid Build Coastguard Worker 		ofilename = semanage_path(SEMANAGE_TMP,
494*2d543d20SAndroid Build Coastguard Worker 					  SEMANAGE_USERS_EXTRA_LINKED);
495*2d543d20SAndroid Build Coastguard Worker 		if (ofilename == NULL) {
496*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
497*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
498*2d543d20SAndroid Build Coastguard Worker 		}
499*2d543d20SAndroid Build Coastguard Worker 		retval = write_file(sh, ofilename, data, size);
500*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
501*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
502*2d543d20SAndroid Build Coastguard Worker 
503*2d543d20SAndroid Build Coastguard Worker 		/*
504*2d543d20SAndroid Build Coastguard Worker 		 * Write the users_extra file; users_extra.local
505*2d543d20SAndroid Build Coastguard Worker 		 * will be merged into this file.
506*2d543d20SAndroid Build Coastguard Worker 		 */
507*2d543d20SAndroid Build Coastguard Worker 		ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA);
508*2d543d20SAndroid Build Coastguard Worker 		if (ofilename == NULL) {
509*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
510*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
511*2d543d20SAndroid Build Coastguard Worker 		}
512*2d543d20SAndroid Build Coastguard Worker 		retval = write_file(sh, ofilename, data, size);
513*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
514*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
515*2d543d20SAndroid Build Coastguard Worker 
516*2d543d20SAndroid Build Coastguard Worker 		pusers_extra->dtable->drop_cache(pusers_extra->dbase);
517*2d543d20SAndroid Build Coastguard Worker 
518*2d543d20SAndroid Build Coastguard Worker 	} else {
519*2d543d20SAndroid Build Coastguard Worker 		retval =  pusers_extra->dtable->clear(sh, pusers_extra->dbase);
520*2d543d20SAndroid Build Coastguard Worker 	}
521*2d543d20SAndroid Build Coastguard Worker 
522*2d543d20SAndroid Build Coastguard Worker cleanup:
523*2d543d20SAndroid Build Coastguard Worker 	free(data);
524*2d543d20SAndroid Build Coastguard Worker 
525*2d543d20SAndroid Build Coastguard Worker 	return retval;
526*2d543d20SAndroid Build Coastguard Worker }
527*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_update_seuser(semanage_handle_t * sh,cil_db_t * cildb)528*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_update_seuser(semanage_handle_t * sh, cil_db_t *cildb)
529*2d543d20SAndroid Build Coastguard Worker {
530*2d543d20SAndroid Build Coastguard Worker 	const char *ofilename = NULL;
531*2d543d20SAndroid Build Coastguard Worker 	int retval = -1;
532*2d543d20SAndroid Build Coastguard Worker 	char *data = NULL;
533*2d543d20SAndroid Build Coastguard Worker 	size_t size = 0;
534*2d543d20SAndroid Build Coastguard Worker 
535*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh);
536*2d543d20SAndroid Build Coastguard Worker 
537*2d543d20SAndroid Build Coastguard Worker 	retval = cil_selinuxusers_to_string(cildb, &data, &size);
538*2d543d20SAndroid Build Coastguard Worker 	if (retval != SEPOL_OK) {
539*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
540*2d543d20SAndroid Build Coastguard Worker 	}
541*2d543d20SAndroid Build Coastguard Worker 
542*2d543d20SAndroid Build Coastguard Worker 	if (size > 0) {
543*2d543d20SAndroid Build Coastguard Worker 		/*
544*2d543d20SAndroid Build Coastguard Worker 		 * Write the seusers entries from CIL modules.
545*2d543d20SAndroid Build Coastguard Worker 		 * This file is used as our baseline when we do not require
546*2d543d20SAndroid Build Coastguard Worker 		 * re-linking.
547*2d543d20SAndroid Build Coastguard Worker 		 */
548*2d543d20SAndroid Build Coastguard Worker 		ofilename = semanage_path(SEMANAGE_TMP,
549*2d543d20SAndroid Build Coastguard Worker 					  SEMANAGE_SEUSERS_LINKED);
550*2d543d20SAndroid Build Coastguard Worker 		if (ofilename == NULL) {
551*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
552*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
553*2d543d20SAndroid Build Coastguard Worker 		}
554*2d543d20SAndroid Build Coastguard Worker 		retval = write_file(sh, ofilename, data, size);
555*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
556*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
557*2d543d20SAndroid Build Coastguard Worker 
558*2d543d20SAndroid Build Coastguard Worker 		/*
559*2d543d20SAndroid Build Coastguard Worker 		 * Write the seusers file; seusers.local will be merged into
560*2d543d20SAndroid Build Coastguard Worker 		 * this file.
561*2d543d20SAndroid Build Coastguard Worker 		 */
562*2d543d20SAndroid Build Coastguard Worker 		ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS);
563*2d543d20SAndroid Build Coastguard Worker 		if (ofilename == NULL) {
564*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
565*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
566*2d543d20SAndroid Build Coastguard Worker 		}
567*2d543d20SAndroid Build Coastguard Worker 		retval = write_file(sh, ofilename, data, size);
568*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
569*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
570*2d543d20SAndroid Build Coastguard Worker 
571*2d543d20SAndroid Build Coastguard Worker 		pseusers->dtable->drop_cache(pseusers->dbase);
572*2d543d20SAndroid Build Coastguard Worker 	} else {
573*2d543d20SAndroid Build Coastguard Worker 		retval = pseusers->dtable->clear(sh, pseusers->dbase);
574*2d543d20SAndroid Build Coastguard Worker 	}
575*2d543d20SAndroid Build Coastguard Worker 
576*2d543d20SAndroid Build Coastguard Worker cleanup:
577*2d543d20SAndroid Build Coastguard Worker 	free(data);
578*2d543d20SAndroid Build Coastguard Worker 
579*2d543d20SAndroid Build Coastguard Worker 	return retval;
580*2d543d20SAndroid Build Coastguard Worker }
581*2d543d20SAndroid Build Coastguard Worker 
read_from_pipe_to_data(semanage_handle_t * sh,size_t initial_len,int fd,char ** out_data_read,size_t * out_read_len)582*2d543d20SAndroid Build Coastguard Worker static int read_from_pipe_to_data(semanage_handle_t *sh, size_t initial_len, int fd, char **out_data_read, size_t *out_read_len)
583*2d543d20SAndroid Build Coastguard Worker {
584*2d543d20SAndroid Build Coastguard Worker 	size_t max_len = initial_len;
585*2d543d20SAndroid Build Coastguard Worker 	ssize_t read_len = 0;
586*2d543d20SAndroid Build Coastguard Worker 	size_t data_read_len = 0;
587*2d543d20SAndroid Build Coastguard Worker 	char *data_read = NULL;
588*2d543d20SAndroid Build Coastguard Worker 
589*2d543d20SAndroid Build Coastguard Worker 	if (max_len <= 0) {
590*2d543d20SAndroid Build Coastguard Worker 		max_len = 1;
591*2d543d20SAndroid Build Coastguard Worker 	}
592*2d543d20SAndroid Build Coastguard Worker 	data_read = malloc(max_len * sizeof(*data_read));
593*2d543d20SAndroid Build Coastguard Worker 	if (data_read == NULL) {
594*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Failed to malloc, out of memory.\n");
595*2d543d20SAndroid Build Coastguard Worker 		return -1;
596*2d543d20SAndroid Build Coastguard Worker 	}
597*2d543d20SAndroid Build Coastguard Worker 
598*2d543d20SAndroid Build Coastguard Worker 	while ((read_len = read(fd, data_read + data_read_len, max_len - data_read_len)) > 0) {
599*2d543d20SAndroid Build Coastguard Worker 		data_read_len += read_len;
600*2d543d20SAndroid Build Coastguard Worker 		if (data_read_len == max_len) {
601*2d543d20SAndroid Build Coastguard Worker 			max_len *= 2;
602*2d543d20SAndroid Build Coastguard Worker 			data_read = realloc(data_read, max_len);
603*2d543d20SAndroid Build Coastguard Worker 			if (data_read == NULL) {
604*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Failed to realloc, out of memory.\n");
605*2d543d20SAndroid Build Coastguard Worker 				return -1;
606*2d543d20SAndroid Build Coastguard Worker 			}
607*2d543d20SAndroid Build Coastguard Worker 		}
608*2d543d20SAndroid Build Coastguard Worker 	}
609*2d543d20SAndroid Build Coastguard Worker 
610*2d543d20SAndroid Build Coastguard Worker 	*out_read_len = data_read_len;
611*2d543d20SAndroid Build Coastguard Worker 	*out_data_read = data_read;
612*2d543d20SAndroid Build Coastguard Worker 
613*2d543d20SAndroid Build Coastguard Worker 	return 0;
614*2d543d20SAndroid Build Coastguard Worker }
615*2d543d20SAndroid Build Coastguard Worker 
semanage_pipe_data(semanage_handle_t * sh,char * path,char * in_data,size_t in_data_len,char ** out_data,size_t * out_data_len,char ** err_data,size_t * err_data_len)616*2d543d20SAndroid Build Coastguard Worker static int semanage_pipe_data(semanage_handle_t *sh, char *path, char *in_data, size_t in_data_len, char **out_data, size_t *out_data_len, char **err_data, size_t *err_data_len)
617*2d543d20SAndroid Build Coastguard Worker {
618*2d543d20SAndroid Build Coastguard Worker 	int input_fd[2] = {-1, -1};
619*2d543d20SAndroid Build Coastguard Worker 	int output_fd[2] = {-1, -1};
620*2d543d20SAndroid Build Coastguard Worker 	int err_fd[2] = {-1, -1};
621*2d543d20SAndroid Build Coastguard Worker 	pid_t pid;
622*2d543d20SAndroid Build Coastguard Worker 	char *data_read = NULL;
623*2d543d20SAndroid Build Coastguard Worker 	char *err_data_read = NULL;
624*2d543d20SAndroid Build Coastguard Worker 	int retval;
625*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
626*2d543d20SAndroid Build Coastguard Worker 	size_t initial_len;
627*2d543d20SAndroid Build Coastguard Worker 	size_t data_read_len = 0;
628*2d543d20SAndroid Build Coastguard Worker 	size_t err_data_read_len = 0;
629*2d543d20SAndroid Build Coastguard Worker 	struct sigaction old_signal;
630*2d543d20SAndroid Build Coastguard Worker 	struct sigaction new_signal;
631*2d543d20SAndroid Build Coastguard Worker 	new_signal.sa_handler = SIG_IGN;
632*2d543d20SAndroid Build Coastguard Worker 	sigemptyset(&new_signal.sa_mask);
633*2d543d20SAndroid Build Coastguard Worker 	new_signal.sa_flags = 0;
634*2d543d20SAndroid Build Coastguard Worker 	/* This is needed in case the read end of input_fd is closed causing a SIGPIPE signal to be sent.
635*2d543d20SAndroid Build Coastguard Worker 	 * If SIGPIPE is not caught, the signal will cause semanage to terminate immediately. The sigaction below
636*2d543d20SAndroid Build Coastguard Worker 	 * creates a new_signal that ignores SIGPIPE allowing the write to exit cleanly.
637*2d543d20SAndroid Build Coastguard Worker 	 *
638*2d543d20SAndroid Build Coastguard Worker 	 * Another sigaction is called in cleanup to restore the original behavior when a SIGPIPE is received.
639*2d543d20SAndroid Build Coastguard Worker 	 */
640*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGPIPE, &new_signal, &old_signal);
641*2d543d20SAndroid Build Coastguard Worker 
642*2d543d20SAndroid Build Coastguard Worker 	retval = pipe(input_fd);
643*2d543d20SAndroid Build Coastguard Worker 	if (retval == -1) {
644*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to create pipe for input pipe: %s\n", strerror(errno));
645*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
646*2d543d20SAndroid Build Coastguard Worker 	}
647*2d543d20SAndroid Build Coastguard Worker 	retval = pipe(output_fd);
648*2d543d20SAndroid Build Coastguard Worker 	if (retval == -1) {
649*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to create pipe for output pipe: %s\n", strerror(errno));
650*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
651*2d543d20SAndroid Build Coastguard Worker 	}
652*2d543d20SAndroid Build Coastguard Worker 	retval = pipe(err_fd);
653*2d543d20SAndroid Build Coastguard Worker 	if (retval == -1) {
654*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to create pipe for error pipe: %s\n", strerror(errno));
655*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
656*2d543d20SAndroid Build Coastguard Worker 	}
657*2d543d20SAndroid Build Coastguard Worker 
658*2d543d20SAndroid Build Coastguard Worker 	pid = fork();
659*2d543d20SAndroid Build Coastguard Worker 	if (pid == -1) {
660*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to fork from parent: %s.", strerror(errno));
661*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
662*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
663*2d543d20SAndroid Build Coastguard Worker 	} else if (pid == 0) {
664*2d543d20SAndroid Build Coastguard Worker 		retval = dup2(input_fd[PIPE_READ], STDIN_FILENO);
665*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
666*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to dup2 input pipe: %s\n", strerror(errno));
667*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
668*2d543d20SAndroid Build Coastguard Worker 		}
669*2d543d20SAndroid Build Coastguard Worker 		retval = dup2(output_fd[PIPE_WRITE], STDOUT_FILENO);
670*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
671*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to dup2 output pipe: %s\n", strerror(errno));
672*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
673*2d543d20SAndroid Build Coastguard Worker 		}
674*2d543d20SAndroid Build Coastguard Worker 		retval = dup2(err_fd[PIPE_WRITE], STDERR_FILENO);
675*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
676*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to dup2 error pipe: %s\n", strerror(errno));
677*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
678*2d543d20SAndroid Build Coastguard Worker 		}
679*2d543d20SAndroid Build Coastguard Worker 
680*2d543d20SAndroid Build Coastguard Worker 		retval = close(input_fd[PIPE_WRITE]);
681*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
682*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close input pipe: %s\n", strerror(errno));
683*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
684*2d543d20SAndroid Build Coastguard Worker 		}
685*2d543d20SAndroid Build Coastguard Worker 		retval = close(output_fd[PIPE_READ]);
686*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
687*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close output pipe: %s\n", strerror(errno));
688*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
689*2d543d20SAndroid Build Coastguard Worker 		}
690*2d543d20SAndroid Build Coastguard Worker 		retval = close(err_fd[PIPE_READ]);
691*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
692*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close error pipe: %s\n", strerror(errno));
693*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
694*2d543d20SAndroid Build Coastguard Worker 		}
695*2d543d20SAndroid Build Coastguard Worker 		retval = execl(path, path, NULL);
696*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
697*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to execute %s : %s\n", path, strerror(errno));
698*2d543d20SAndroid Build Coastguard Worker 			_exit(EXIT_FAILURE);
699*2d543d20SAndroid Build Coastguard Worker 		}
700*2d543d20SAndroid Build Coastguard Worker 	} else {
701*2d543d20SAndroid Build Coastguard Worker 		retval = close(input_fd[PIPE_READ]);
702*2d543d20SAndroid Build Coastguard Worker 		input_fd[PIPE_READ] = -1;
703*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
704*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close read end of input pipe: %s\n", strerror(errno));
705*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
706*2d543d20SAndroid Build Coastguard Worker 		}
707*2d543d20SAndroid Build Coastguard Worker 
708*2d543d20SAndroid Build Coastguard Worker 		retval = close(output_fd[PIPE_WRITE]);
709*2d543d20SAndroid Build Coastguard Worker 		output_fd[PIPE_WRITE] = -1;
710*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
711*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close write end of output pipe: %s\n", strerror(errno));
712*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
713*2d543d20SAndroid Build Coastguard Worker 		}
714*2d543d20SAndroid Build Coastguard Worker 
715*2d543d20SAndroid Build Coastguard Worker 		retval = close(err_fd[PIPE_WRITE]);
716*2d543d20SAndroid Build Coastguard Worker 		err_fd[PIPE_WRITE] = -1;
717*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
718*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close write end of error pipe: %s\n", strerror(errno));
719*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
720*2d543d20SAndroid Build Coastguard Worker 		}
721*2d543d20SAndroid Build Coastguard Worker 
722*2d543d20SAndroid Build Coastguard Worker 		retval = write(input_fd[PIPE_WRITE], in_data, in_data_len);
723*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
724*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Failed to write data to input pipe: %s\n", strerror(errno));
725*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
726*2d543d20SAndroid Build Coastguard Worker 		}
727*2d543d20SAndroid Build Coastguard Worker 		retval = close(input_fd[PIPE_WRITE]);
728*2d543d20SAndroid Build Coastguard Worker 		input_fd[PIPE_WRITE] = -1;
729*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
730*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close write end of input pipe: %s\n", strerror(errno));
731*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
732*2d543d20SAndroid Build Coastguard Worker 		}
733*2d543d20SAndroid Build Coastguard Worker 
734*2d543d20SAndroid Build Coastguard Worker 		initial_len = 1 << 17;
735*2d543d20SAndroid Build Coastguard Worker 		retval = read_from_pipe_to_data(sh, initial_len, output_fd[PIPE_READ], &data_read, &data_read_len);
736*2d543d20SAndroid Build Coastguard Worker 		if (retval != 0) {
737*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
738*2d543d20SAndroid Build Coastguard Worker 		}
739*2d543d20SAndroid Build Coastguard Worker 		retval = close(output_fd[PIPE_READ]);
740*2d543d20SAndroid Build Coastguard Worker 		output_fd[PIPE_READ] = -1;
741*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
742*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close read end of output pipe: %s\n", strerror(errno));
743*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
744*2d543d20SAndroid Build Coastguard Worker 		}
745*2d543d20SAndroid Build Coastguard Worker 
746*2d543d20SAndroid Build Coastguard Worker 		initial_len = 1 << 9;
747*2d543d20SAndroid Build Coastguard Worker 		retval = read_from_pipe_to_data(sh, initial_len, err_fd[PIPE_READ], &err_data_read, &err_data_read_len);
748*2d543d20SAndroid Build Coastguard Worker 		if (retval != 0) {
749*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
750*2d543d20SAndroid Build Coastguard Worker 		}
751*2d543d20SAndroid Build Coastguard Worker 		retval = close(err_fd[PIPE_READ]);
752*2d543d20SAndroid Build Coastguard Worker 		err_fd[PIPE_READ] = -1;
753*2d543d20SAndroid Build Coastguard Worker 		if (retval == -1) {
754*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to close read end of error pipe: %s\n", strerror(errno));
755*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
756*2d543d20SAndroid Build Coastguard Worker 		}
757*2d543d20SAndroid Build Coastguard Worker 
758*2d543d20SAndroid Build Coastguard Worker 		if (waitpid(pid, &status, 0) == -1 || !WIFEXITED(status)) {
759*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Child process %s did not exit cleanly.", path);
760*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
761*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
762*2d543d20SAndroid Build Coastguard Worker 		}
763*2d543d20SAndroid Build Coastguard Worker 		if (WEXITSTATUS(status) != 0) {
764*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Child process %s failed with code: %d.", path, WEXITSTATUS(status));
765*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
766*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
767*2d543d20SAndroid Build Coastguard Worker 		}
768*2d543d20SAndroid Build Coastguard Worker 	}
769*2d543d20SAndroid Build Coastguard Worker 
770*2d543d20SAndroid Build Coastguard Worker 	retval = 0;
771*2d543d20SAndroid Build Coastguard Worker 
772*2d543d20SAndroid Build Coastguard Worker cleanup:
773*2d543d20SAndroid Build Coastguard Worker 	sigaction(SIGPIPE, &old_signal, NULL);
774*2d543d20SAndroid Build Coastguard Worker 
775*2d543d20SAndroid Build Coastguard Worker 	if (data_read != NULL) {
776*2d543d20SAndroid Build Coastguard Worker 		*out_data = data_read;
777*2d543d20SAndroid Build Coastguard Worker 		*out_data_len = data_read_len;
778*2d543d20SAndroid Build Coastguard Worker 	}
779*2d543d20SAndroid Build Coastguard Worker 
780*2d543d20SAndroid Build Coastguard Worker 	if (err_data_read != NULL) {
781*2d543d20SAndroid Build Coastguard Worker 		*err_data = err_data_read;
782*2d543d20SAndroid Build Coastguard Worker 		*err_data_len = err_data_read_len;
783*2d543d20SAndroid Build Coastguard Worker 	}
784*2d543d20SAndroid Build Coastguard Worker 
785*2d543d20SAndroid Build Coastguard Worker 	if (output_fd[PIPE_READ] != -1) {
786*2d543d20SAndroid Build Coastguard Worker 		close(output_fd[PIPE_READ]);
787*2d543d20SAndroid Build Coastguard Worker 	}
788*2d543d20SAndroid Build Coastguard Worker 	if (output_fd[PIPE_WRITE] != -1) {
789*2d543d20SAndroid Build Coastguard Worker 		close(output_fd[PIPE_WRITE]);
790*2d543d20SAndroid Build Coastguard Worker 	}
791*2d543d20SAndroid Build Coastguard Worker 	if (err_fd[PIPE_READ] != -1) {
792*2d543d20SAndroid Build Coastguard Worker 		close(err_fd[PIPE_READ]);
793*2d543d20SAndroid Build Coastguard Worker 	}
794*2d543d20SAndroid Build Coastguard Worker 	if (err_fd[PIPE_WRITE] != -1) {
795*2d543d20SAndroid Build Coastguard Worker 		close(err_fd[PIPE_WRITE]);
796*2d543d20SAndroid Build Coastguard Worker 	}
797*2d543d20SAndroid Build Coastguard Worker 	if (input_fd[PIPE_READ] != -1) {
798*2d543d20SAndroid Build Coastguard Worker 		close(input_fd[PIPE_READ]);
799*2d543d20SAndroid Build Coastguard Worker 	}
800*2d543d20SAndroid Build Coastguard Worker 	if (input_fd[PIPE_WRITE] != -1) {
801*2d543d20SAndroid Build Coastguard Worker 		close(input_fd[PIPE_WRITE]);
802*2d543d20SAndroid Build Coastguard Worker 	}
803*2d543d20SAndroid Build Coastguard Worker 
804*2d543d20SAndroid Build Coastguard Worker 	return retval;
805*2d543d20SAndroid Build Coastguard Worker }
806*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_write_langext(semanage_handle_t * sh,const char * lang_ext,const semanage_module_info_t * modinfo)807*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_write_langext(semanage_handle_t *sh,
808*2d543d20SAndroid Build Coastguard Worker 				const char *lang_ext,
809*2d543d20SAndroid Build Coastguard Worker 				const semanage_module_info_t *modinfo)
810*2d543d20SAndroid Build Coastguard Worker {
811*2d543d20SAndroid Build Coastguard Worker 	int ret = -1;
812*2d543d20SAndroid Build Coastguard Worker 	char fn[PATH_MAX];
813*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
814*2d543d20SAndroid Build Coastguard Worker 
815*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
816*2d543d20SAndroid Build Coastguard Worker 			modinfo,
817*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_LANG_EXT,
818*2d543d20SAndroid Build Coastguard Worker 			fn,
819*2d543d20SAndroid Build Coastguard Worker 			sizeof(fn));
820*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
821*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
822*2d543d20SAndroid Build Coastguard Worker 	}
823*2d543d20SAndroid Build Coastguard Worker 
824*2d543d20SAndroid Build Coastguard Worker 	fp = fopen(fn, "w");
825*2d543d20SAndroid Build Coastguard Worker 	if (fp == NULL) {
826*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to open %s module ext file.", modinfo->name);
827*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
828*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
829*2d543d20SAndroid Build Coastguard Worker 	}
830*2d543d20SAndroid Build Coastguard Worker 
831*2d543d20SAndroid Build Coastguard Worker 	if (fputs(lang_ext, fp) < 0) {
832*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to write %s module ext file.", modinfo->name);
833*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
834*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
835*2d543d20SAndroid Build Coastguard Worker 	}
836*2d543d20SAndroid Build Coastguard Worker 
837*2d543d20SAndroid Build Coastguard Worker 	if (fclose(fp) != 0) {
838*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to close %s module ext file.", modinfo->name);
839*2d543d20SAndroid Build Coastguard Worker 		fp = NULL;
840*2d543d20SAndroid Build Coastguard Worker 		ret = -1;
841*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
842*2d543d20SAndroid Build Coastguard Worker 	}
843*2d543d20SAndroid Build Coastguard Worker 
844*2d543d20SAndroid Build Coastguard Worker 	fp = NULL;
845*2d543d20SAndroid Build Coastguard Worker 
846*2d543d20SAndroid Build Coastguard Worker 	ret = 0;
847*2d543d20SAndroid Build Coastguard Worker 
848*2d543d20SAndroid Build Coastguard Worker cleanup:
849*2d543d20SAndroid Build Coastguard Worker 	if (fp != NULL) fclose(fp);
850*2d543d20SAndroid Build Coastguard Worker 
851*2d543d20SAndroid Build Coastguard Worker 	return ret;
852*2d543d20SAndroid Build Coastguard Worker }
853*2d543d20SAndroid Build Coastguard Worker 
update_checksum_with_len(Sha256Context * context,size_t s)854*2d543d20SAndroid Build Coastguard Worker static void update_checksum_with_len(Sha256Context *context, size_t s)
855*2d543d20SAndroid Build Coastguard Worker {
856*2d543d20SAndroid Build Coastguard Worker 	int i;
857*2d543d20SAndroid Build Coastguard Worker 	uint8_t buffer[8];
858*2d543d20SAndroid Build Coastguard Worker 
859*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < 8; i++) {
860*2d543d20SAndroid Build Coastguard Worker 		buffer[i] = s & 0xff;
861*2d543d20SAndroid Build Coastguard Worker 		s >>= 8;
862*2d543d20SAndroid Build Coastguard Worker 	}
863*2d543d20SAndroid Build Coastguard Worker 	Sha256Update(context, buffer, 8);
864*2d543d20SAndroid Build Coastguard Worker }
865*2d543d20SAndroid Build Coastguard Worker 
update_checksum_with_bool(Sha256Context * context,bool b)866*2d543d20SAndroid Build Coastguard Worker static void update_checksum_with_bool(Sha256Context *context, bool b)
867*2d543d20SAndroid Build Coastguard Worker {
868*2d543d20SAndroid Build Coastguard Worker 	uint8_t byte;
869*2d543d20SAndroid Build Coastguard Worker 
870*2d543d20SAndroid Build Coastguard Worker 	byte = b ? UINT8_C(1) : UINT8_C(0);
871*2d543d20SAndroid Build Coastguard Worker 	Sha256Update(context, &byte, 1);
872*2d543d20SAndroid Build Coastguard Worker }
873*2d543d20SAndroid Build Coastguard Worker 
semanage_compile_module(semanage_handle_t * sh,semanage_module_info_t * modinfo,Sha256Context * context)874*2d543d20SAndroid Build Coastguard Worker static int semanage_compile_module(semanage_handle_t *sh,
875*2d543d20SAndroid Build Coastguard Worker 				   semanage_module_info_t *modinfo,
876*2d543d20SAndroid Build Coastguard Worker 				   Sha256Context *context)
877*2d543d20SAndroid Build Coastguard Worker {
878*2d543d20SAndroid Build Coastguard Worker 	char cil_path[PATH_MAX];
879*2d543d20SAndroid Build Coastguard Worker 	char hll_path[PATH_MAX];
880*2d543d20SAndroid Build Coastguard Worker 	char *compiler_path = NULL;
881*2d543d20SAndroid Build Coastguard Worker 	char *cil_data = NULL;
882*2d543d20SAndroid Build Coastguard Worker 	char *err_data = NULL;
883*2d543d20SAndroid Build Coastguard Worker 	char *start = NULL;
884*2d543d20SAndroid Build Coastguard Worker 	char *end = NULL;
885*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
886*2d543d20SAndroid Build Coastguard Worker 	size_t cil_data_len = 0;
887*2d543d20SAndroid Build Coastguard Worker 	size_t err_data_len = 0;
888*2d543d20SAndroid Build Coastguard Worker 	struct file_contents hll_contents = {};
889*2d543d20SAndroid Build Coastguard Worker 
890*2d543d20SAndroid Build Coastguard Worker 	if (!strcasecmp(modinfo->lang_ext, "cil")) {
891*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
892*2d543d20SAndroid Build Coastguard Worker 	}
893*2d543d20SAndroid Build Coastguard Worker 
894*2d543d20SAndroid Build Coastguard Worker 	status = semanage_get_hll_compiler_path(sh, modinfo->lang_ext, &compiler_path);
895*2d543d20SAndroid Build Coastguard Worker 	if (status != 0) {
896*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
897*2d543d20SAndroid Build Coastguard Worker 	}
898*2d543d20SAndroid Build Coastguard Worker 
899*2d543d20SAndroid Build Coastguard Worker 	status = semanage_module_get_path(
900*2d543d20SAndroid Build Coastguard Worker 			sh,
901*2d543d20SAndroid Build Coastguard Worker 			modinfo,
902*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_CIL,
903*2d543d20SAndroid Build Coastguard Worker 			cil_path,
904*2d543d20SAndroid Build Coastguard Worker 			sizeof(cil_path));
905*2d543d20SAndroid Build Coastguard Worker 	if (status != 0) {
906*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
907*2d543d20SAndroid Build Coastguard Worker 	}
908*2d543d20SAndroid Build Coastguard Worker 
909*2d543d20SAndroid Build Coastguard Worker 	status = semanage_module_get_path(
910*2d543d20SAndroid Build Coastguard Worker 			sh,
911*2d543d20SAndroid Build Coastguard Worker 			modinfo,
912*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_HLL,
913*2d543d20SAndroid Build Coastguard Worker 			hll_path,
914*2d543d20SAndroid Build Coastguard Worker 			sizeof(hll_path));
915*2d543d20SAndroid Build Coastguard Worker 	if (status != 0) {
916*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
917*2d543d20SAndroid Build Coastguard Worker 	}
918*2d543d20SAndroid Build Coastguard Worker 
919*2d543d20SAndroid Build Coastguard Worker 	status = map_compressed_file(sh, hll_path, &hll_contents);
920*2d543d20SAndroid Build Coastguard Worker 	if (status < 0) {
921*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to read file %s\n", hll_path);
922*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
923*2d543d20SAndroid Build Coastguard Worker 	}
924*2d543d20SAndroid Build Coastguard Worker 
925*2d543d20SAndroid Build Coastguard Worker 	status = semanage_pipe_data(sh, compiler_path, hll_contents.data,
926*2d543d20SAndroid Build Coastguard Worker 				    hll_contents.len, &cil_data, &cil_data_len,
927*2d543d20SAndroid Build Coastguard Worker 				    &err_data, &err_data_len);
928*2d543d20SAndroid Build Coastguard Worker 	if (err_data_len > 0) {
929*2d543d20SAndroid Build Coastguard Worker 		for (start = end = err_data; end < err_data + err_data_len; end++) {
930*2d543d20SAndroid Build Coastguard Worker 			if (*end == '\n') {
931*2d543d20SAndroid Build Coastguard Worker 				fprintf(stderr, "%s: ", modinfo->name);
932*2d543d20SAndroid Build Coastguard Worker 				fwrite(start, 1, end - start + 1, stderr);
933*2d543d20SAndroid Build Coastguard Worker 				start = end + 1;
934*2d543d20SAndroid Build Coastguard Worker 			}
935*2d543d20SAndroid Build Coastguard Worker 		}
936*2d543d20SAndroid Build Coastguard Worker 
937*2d543d20SAndroid Build Coastguard Worker 		if (end != start) {
938*2d543d20SAndroid Build Coastguard Worker 			fprintf(stderr, "%s: ", modinfo->name);
939*2d543d20SAndroid Build Coastguard Worker 			fwrite(start, 1, end - start, stderr);
940*2d543d20SAndroid Build Coastguard Worker 			fprintf(stderr, "\n");
941*2d543d20SAndroid Build Coastguard Worker 		}
942*2d543d20SAndroid Build Coastguard Worker 	}
943*2d543d20SAndroid Build Coastguard Worker 	if (status != 0) {
944*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
945*2d543d20SAndroid Build Coastguard Worker 	}
946*2d543d20SAndroid Build Coastguard Worker 
947*2d543d20SAndroid Build Coastguard Worker 	if (context) {
948*2d543d20SAndroid Build Coastguard Worker 		update_checksum_with_len(context, cil_data_len);
949*2d543d20SAndroid Build Coastguard Worker 		Sha256Update(context, cil_data, cil_data_len);
950*2d543d20SAndroid Build Coastguard Worker 	}
951*2d543d20SAndroid Build Coastguard Worker 
952*2d543d20SAndroid Build Coastguard Worker 	status = write_compressed_file(sh, cil_path, cil_data, cil_data_len);
953*2d543d20SAndroid Build Coastguard Worker 	if (status == -1) {
954*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Failed to write %s\n", cil_path);
955*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
956*2d543d20SAndroid Build Coastguard Worker 	}
957*2d543d20SAndroid Build Coastguard Worker 
958*2d543d20SAndroid Build Coastguard Worker 	if (sh->conf->remove_hll == 1) {
959*2d543d20SAndroid Build Coastguard Worker 		status = unlink(hll_path);
960*2d543d20SAndroid Build Coastguard Worker 		if (status != 0) {
961*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error while removing HLL file %s: %s", hll_path, strerror(errno));
962*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
963*2d543d20SAndroid Build Coastguard Worker 		}
964*2d543d20SAndroid Build Coastguard Worker 
965*2d543d20SAndroid Build Coastguard Worker 		status = semanage_direct_write_langext(sh, "cil", modinfo);
966*2d543d20SAndroid Build Coastguard Worker 		if (status != 0) {
967*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
968*2d543d20SAndroid Build Coastguard Worker 		}
969*2d543d20SAndroid Build Coastguard Worker 	}
970*2d543d20SAndroid Build Coastguard Worker 
971*2d543d20SAndroid Build Coastguard Worker cleanup:
972*2d543d20SAndroid Build Coastguard Worker 	unmap_compressed_file(&hll_contents);
973*2d543d20SAndroid Build Coastguard Worker 	free(cil_data);
974*2d543d20SAndroid Build Coastguard Worker 	free(err_data);
975*2d543d20SAndroid Build Coastguard Worker 	free(compiler_path);
976*2d543d20SAndroid Build Coastguard Worker 
977*2d543d20SAndroid Build Coastguard Worker 	return status;
978*2d543d20SAndroid Build Coastguard Worker }
979*2d543d20SAndroid Build Coastguard Worker 
modinfo_cmp(const void * a,const void * b)980*2d543d20SAndroid Build Coastguard Worker static int modinfo_cmp(const void *a, const void *b)
981*2d543d20SAndroid Build Coastguard Worker {
982*2d543d20SAndroid Build Coastguard Worker 	const semanage_module_info_t *ma = a;
983*2d543d20SAndroid Build Coastguard Worker 	const semanage_module_info_t *mb = b;
984*2d543d20SAndroid Build Coastguard Worker 
985*2d543d20SAndroid Build Coastguard Worker 	return strcmp(ma->name, mb->name);
986*2d543d20SAndroid Build Coastguard Worker }
987*2d543d20SAndroid Build Coastguard Worker 
988*2d543d20SAndroid Build Coastguard Worker struct extra_checksum_params {
989*2d543d20SAndroid Build Coastguard Worker 	int disable_dontaudit;
990*2d543d20SAndroid Build Coastguard Worker 	int preserve_tunables;
991*2d543d20SAndroid Build Coastguard Worker 	int target_platform;
992*2d543d20SAndroid Build Coastguard Worker 	int policyvers;
993*2d543d20SAndroid Build Coastguard Worker };
994*2d543d20SAndroid Build Coastguard Worker 
semanage_compile_hll_modules(semanage_handle_t * sh,semanage_module_info_t * modinfos,int num_modinfos,const struct extra_checksum_params * extra,char * cil_checksum)995*2d543d20SAndroid Build Coastguard Worker static int semanage_compile_hll_modules(semanage_handle_t *sh,
996*2d543d20SAndroid Build Coastguard Worker 					semanage_module_info_t *modinfos,
997*2d543d20SAndroid Build Coastguard Worker 					int num_modinfos,
998*2d543d20SAndroid Build Coastguard Worker 					const struct extra_checksum_params *extra,
999*2d543d20SAndroid Build Coastguard Worker 					char *cil_checksum)
1000*2d543d20SAndroid Build Coastguard Worker {
1001*2d543d20SAndroid Build Coastguard Worker 	/* to be incremented when checksum input data format changes */
1002*2d543d20SAndroid Build Coastguard Worker 	static const size_t CHECKSUM_EPOCH = 2;
1003*2d543d20SAndroid Build Coastguard Worker 
1004*2d543d20SAndroid Build Coastguard Worker 	int i, status = 0;
1005*2d543d20SAndroid Build Coastguard Worker 	char cil_path[PATH_MAX];
1006*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
1007*2d543d20SAndroid Build Coastguard Worker 	Sha256Context context;
1008*2d543d20SAndroid Build Coastguard Worker 	SHA256_HASH hash;
1009*2d543d20SAndroid Build Coastguard Worker 	struct file_contents contents = {};
1010*2d543d20SAndroid Build Coastguard Worker 
1011*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
1012*2d543d20SAndroid Build Coastguard Worker 	assert(modinfos);
1013*2d543d20SAndroid Build Coastguard Worker 
1014*2d543d20SAndroid Build Coastguard Worker 	/* Sort modules by name to get consistent ordering. */
1015*2d543d20SAndroid Build Coastguard Worker 	qsort(modinfos, num_modinfos, sizeof(*modinfos), &modinfo_cmp);
1016*2d543d20SAndroid Build Coastguard Worker 
1017*2d543d20SAndroid Build Coastguard Worker 	Sha256Initialise(&context);
1018*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_len(&context, CHECKSUM_EPOCH);
1019*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_bool(&context, !!extra->disable_dontaudit);
1020*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_bool(&context, !!extra->preserve_tunables);
1021*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_len(&context, (size_t)extra->target_platform);
1022*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_len(&context, (size_t)extra->policyvers);
1023*2d543d20SAndroid Build Coastguard Worker 
1024*2d543d20SAndroid Build Coastguard Worker 	/* prefix with module count to avoid collisions */
1025*2d543d20SAndroid Build Coastguard Worker 	update_checksum_with_len(&context, num_modinfos);
1026*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modinfos; i++) {
1027*2d543d20SAndroid Build Coastguard Worker 		status = semanage_module_get_path(
1028*2d543d20SAndroid Build Coastguard Worker 				sh,
1029*2d543d20SAndroid Build Coastguard Worker 				&modinfos[i],
1030*2d543d20SAndroid Build Coastguard Worker 				SEMANAGE_MODULE_PATH_CIL,
1031*2d543d20SAndroid Build Coastguard Worker 				cil_path,
1032*2d543d20SAndroid Build Coastguard Worker 				sizeof(cil_path));
1033*2d543d20SAndroid Build Coastguard Worker 		if (status != 0)
1034*2d543d20SAndroid Build Coastguard Worker 			return -1;
1035*2d543d20SAndroid Build Coastguard Worker 
1036*2d543d20SAndroid Build Coastguard Worker 		if (!semanage_get_ignore_module_cache(sh)) {
1037*2d543d20SAndroid Build Coastguard Worker 			status = stat(cil_path, &sb);
1038*2d543d20SAndroid Build Coastguard Worker 			if (status == 0) {
1039*2d543d20SAndroid Build Coastguard Worker 				status = map_compressed_file(sh, cil_path, &contents);
1040*2d543d20SAndroid Build Coastguard Worker 				if (status < 0) {
1041*2d543d20SAndroid Build Coastguard Worker 					ERR(sh, "Error mapping file: %s", cil_path);
1042*2d543d20SAndroid Build Coastguard Worker 					return -1;
1043*2d543d20SAndroid Build Coastguard Worker 				}
1044*2d543d20SAndroid Build Coastguard Worker 
1045*2d543d20SAndroid Build Coastguard Worker 				/* prefix with length to avoid collisions */
1046*2d543d20SAndroid Build Coastguard Worker 				update_checksum_with_len(&context, contents.len);
1047*2d543d20SAndroid Build Coastguard Worker 				Sha256Update(&context, contents.data, contents.len);
1048*2d543d20SAndroid Build Coastguard Worker 
1049*2d543d20SAndroid Build Coastguard Worker 				unmap_compressed_file(&contents);
1050*2d543d20SAndroid Build Coastguard Worker 				continue;
1051*2d543d20SAndroid Build Coastguard Worker 			} else if (errno != ENOENT) {
1052*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Unable to access %s: %s\n", cil_path,
1053*2d543d20SAndroid Build Coastguard Worker 				    strerror(errno));
1054*2d543d20SAndroid Build Coastguard Worker 				return -1; //an error in the "stat" call
1055*2d543d20SAndroid Build Coastguard Worker 			}
1056*2d543d20SAndroid Build Coastguard Worker 		}
1057*2d543d20SAndroid Build Coastguard Worker 
1058*2d543d20SAndroid Build Coastguard Worker 		status = semanage_compile_module(sh, &modinfos[i], &context);
1059*2d543d20SAndroid Build Coastguard Worker 		if (status < 0)
1060*2d543d20SAndroid Build Coastguard Worker 			return -1;
1061*2d543d20SAndroid Build Coastguard Worker 	}
1062*2d543d20SAndroid Build Coastguard Worker 	Sha256Finalise(&context, &hash);
1063*2d543d20SAndroid Build Coastguard Worker 
1064*2d543d20SAndroid Build Coastguard Worker 	semanage_hash_to_checksum_string(hash.bytes, cil_checksum);
1065*2d543d20SAndroid Build Coastguard Worker 	return 0;
1066*2d543d20SAndroid Build Coastguard Worker }
1067*2d543d20SAndroid Build Coastguard Worker 
semanage_compare_checksum(semanage_handle_t * sh,const char * reference)1068*2d543d20SAndroid Build Coastguard Worker static int semanage_compare_checksum(semanage_handle_t *sh, const char *reference)
1069*2d543d20SAndroid Build Coastguard Worker {
1070*2d543d20SAndroid Build Coastguard Worker 	const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
1071*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
1072*2d543d20SAndroid Build Coastguard Worker 	int fd, retval;
1073*2d543d20SAndroid Build Coastguard Worker 	char *data;
1074*2d543d20SAndroid Build Coastguard Worker 
1075*2d543d20SAndroid Build Coastguard Worker 	fd = open(path, O_RDONLY);
1076*2d543d20SAndroid Build Coastguard Worker 	if (fd == -1) {
1077*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
1078*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to open %s: %s\n", path, strerror(errno));
1079*2d543d20SAndroid Build Coastguard Worker 			return -1;
1080*2d543d20SAndroid Build Coastguard Worker 		}
1081*2d543d20SAndroid Build Coastguard Worker 		/* Checksum file not present - force a rebuild. */
1082*2d543d20SAndroid Build Coastguard Worker 		return 1;
1083*2d543d20SAndroid Build Coastguard Worker 	}
1084*2d543d20SAndroid Build Coastguard Worker 
1085*2d543d20SAndroid Build Coastguard Worker 	if (fstat(fd, &sb) == -1) {
1086*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to stat %s\n", path);
1087*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1088*2d543d20SAndroid Build Coastguard Worker 		goto out_close;
1089*2d543d20SAndroid Build Coastguard Worker 	}
1090*2d543d20SAndroid Build Coastguard Worker 
1091*2d543d20SAndroid Build Coastguard Worker 	if (sb.st_size != (off_t)CHECKSUM_CONTENT_SIZE) {
1092*2d543d20SAndroid Build Coastguard Worker 		/* Incompatible/invalid hash type - just force a rebuild. */
1093*2d543d20SAndroid Build Coastguard Worker 		WARN(sh, "Module checksum invalid - forcing a rebuild\n");
1094*2d543d20SAndroid Build Coastguard Worker 		retval = 1;
1095*2d543d20SAndroid Build Coastguard Worker 		goto out_close;
1096*2d543d20SAndroid Build Coastguard Worker 	}
1097*2d543d20SAndroid Build Coastguard Worker 
1098*2d543d20SAndroid Build Coastguard Worker 	data = mmap(NULL, CHECKSUM_CONTENT_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
1099*2d543d20SAndroid Build Coastguard Worker 	if (data == MAP_FAILED) {
1100*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to mmap %s\n", path);
1101*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1102*2d543d20SAndroid Build Coastguard Worker 		goto out_close;
1103*2d543d20SAndroid Build Coastguard Worker 	}
1104*2d543d20SAndroid Build Coastguard Worker 
1105*2d543d20SAndroid Build Coastguard Worker 	retval = memcmp(data, reference, CHECKSUM_CONTENT_SIZE) != 0;
1106*2d543d20SAndroid Build Coastguard Worker 	munmap(data, sb.st_size);
1107*2d543d20SAndroid Build Coastguard Worker out_close:
1108*2d543d20SAndroid Build Coastguard Worker 	close(fd);
1109*2d543d20SAndroid Build Coastguard Worker 	return retval;
1110*2d543d20SAndroid Build Coastguard Worker }
1111*2d543d20SAndroid Build Coastguard Worker 
semanage_write_modules_checksum(semanage_handle_t * sh,const char * checksum)1112*2d543d20SAndroid Build Coastguard Worker static int semanage_write_modules_checksum(semanage_handle_t *sh,
1113*2d543d20SAndroid Build Coastguard Worker 					   const char *checksum)
1114*2d543d20SAndroid Build Coastguard Worker {
1115*2d543d20SAndroid Build Coastguard Worker 	const char *path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_CHECKSUM);
1116*2d543d20SAndroid Build Coastguard Worker 
1117*2d543d20SAndroid Build Coastguard Worker 	return write_file(sh, path, checksum, CHECKSUM_CONTENT_SIZE);
1118*2d543d20SAndroid Build Coastguard Worker }
1119*2d543d20SAndroid Build Coastguard Worker 
1120*2d543d20SAndroid Build Coastguard Worker /* Files that must exist in order to skip policy rebuild. */
1121*2d543d20SAndroid Build Coastguard Worker static const int semanage_computed_files[] = {
1122*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_STORE_KERNEL,
1123*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_STORE_FC,
1124*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_STORE_SEUSERS,
1125*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_LINKED,
1126*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_SEUSERS_LINKED,
1127*2d543d20SAndroid Build Coastguard Worker 	SEMANAGE_USERS_EXTRA_LINKED
1128*2d543d20SAndroid Build Coastguard Worker };
1129*2d543d20SAndroid Build Coastguard Worker 
1130*2d543d20SAndroid Build Coastguard Worker /* Copies a file from src to dst. If dst already exists then
1131*2d543d20SAndroid Build Coastguard Worker  * overwrite it. If source doesn't exist then return success.
1132*2d543d20SAndroid Build Coastguard Worker  * Returns 0 on success, -1 on error. */
copy_file_if_exists(const char * src,const char * dst,mode_t mode)1133*2d543d20SAndroid Build Coastguard Worker static int copy_file_if_exists(const char *src, const char *dst, mode_t mode){
1134*2d543d20SAndroid Build Coastguard Worker 	int rc = semanage_copy_file(src, dst, mode, false);
1135*2d543d20SAndroid Build Coastguard Worker 	return (rc < 0 && errno != ENOENT) ? rc : 0;
1136*2d543d20SAndroid Build Coastguard Worker }
1137*2d543d20SAndroid Build Coastguard Worker 
1138*2d543d20SAndroid Build Coastguard Worker /********************* direct API functions ********************/
1139*2d543d20SAndroid Build Coastguard Worker 
1140*2d543d20SAndroid Build Coastguard Worker /* Commits all changes in sandbox to the actual kernel policy.
1141*2d543d20SAndroid Build Coastguard Worker  * Returns commit number on success, -1 on error.
1142*2d543d20SAndroid Build Coastguard Worker  */
semanage_direct_commit(semanage_handle_t * sh)1143*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_commit(semanage_handle_t * sh)
1144*2d543d20SAndroid Build Coastguard Worker {
1145*2d543d20SAndroid Build Coastguard Worker 	char **mod_filenames = NULL;
1146*2d543d20SAndroid Build Coastguard Worker 	char *fc_buffer = NULL;
1147*2d543d20SAndroid Build Coastguard Worker 	size_t fc_buffer_len = 0;
1148*2d543d20SAndroid Build Coastguard Worker 	const char *ofilename = NULL;
1149*2d543d20SAndroid Build Coastguard Worker 	const char *path;
1150*2d543d20SAndroid Build Coastguard Worker 	int retval = -1, num_modinfos = 0, i;
1151*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_t *out = NULL;
1152*2d543d20SAndroid Build Coastguard Worker 	struct cil_db *cildb = NULL;
1153*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfos = NULL;
1154*2d543d20SAndroid Build Coastguard Worker 	mode_t mask = umask(0077);
1155*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
1156*2d543d20SAndroid Build Coastguard Worker 	char modules_checksum[CHECKSUM_CONTENT_SIZE + 1 /* '\0' */];
1157*2d543d20SAndroid Build Coastguard Worker 	struct extra_checksum_params extra;
1158*2d543d20SAndroid Build Coastguard Worker 
1159*2d543d20SAndroid Build Coastguard Worker 	int do_rebuild, do_write_kernel, do_install;
1160*2d543d20SAndroid Build Coastguard Worker 	int fcontexts_modified, ports_modified, seusers_modified,
1161*2d543d20SAndroid Build Coastguard Worker 		disable_dontaudit, preserve_tunables, ibpkeys_modified,
1162*2d543d20SAndroid Build Coastguard Worker 		ibendports_modified;
1163*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *users = semanage_user_dbase_local(sh);
1164*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *users_base = semanage_user_base_dbase_local(sh);
1165*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pusers_base = semanage_user_base_dbase_policy(sh);
1166*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pusers_extra = semanage_user_extra_dbase_policy(sh);
1167*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *ports = semanage_port_dbase_local(sh);
1168*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pports = semanage_port_dbase_policy(sh);
1169*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *ibpkeys = semanage_ibpkey_dbase_local(sh);
1170*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pibpkeys = semanage_ibpkey_dbase_policy(sh);
1171*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *ibendports = semanage_ibendport_dbase_local(sh);
1172*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pibendports = semanage_ibendport_dbase_policy(sh);
1173*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *bools = semanage_bool_dbase_local(sh);
1174*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pbools = semanage_bool_dbase_policy(sh);
1175*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *ifaces = semanage_iface_dbase_local(sh);
1176*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pifaces = semanage_iface_dbase_policy(sh);
1177*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *nodes = semanage_node_dbase_local(sh);
1178*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pnodes = semanage_node_dbase_policy(sh);
1179*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *fcontexts = semanage_fcontext_dbase_local(sh);
1180*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pfcontexts = semanage_fcontext_dbase_policy(sh);
1181*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *seusers = semanage_seuser_dbase_local(sh);
1182*2d543d20SAndroid Build Coastguard Worker 	dbase_config_t *pseusers = semanage_seuser_dbase_policy(sh);
1183*2d543d20SAndroid Build Coastguard Worker 
1184*2d543d20SAndroid Build Coastguard Worker 	/* Modified flags that we need to use more than once. */
1185*2d543d20SAndroid Build Coastguard Worker 	ports_modified = ports->dtable->is_modified(ports->dbase);
1186*2d543d20SAndroid Build Coastguard Worker 	ibpkeys_modified = ibpkeys->dtable->is_modified(ibpkeys->dbase);
1187*2d543d20SAndroid Build Coastguard Worker 	ibendports_modified = ibendports->dtable->is_modified(ibendports->dbase);
1188*2d543d20SAndroid Build Coastguard Worker 	seusers_modified = seusers->dtable->is_modified(seusers->dbase);
1189*2d543d20SAndroid Build Coastguard Worker 	fcontexts_modified = fcontexts->dtable->is_modified(fcontexts->dbase);
1190*2d543d20SAndroid Build Coastguard Worker 
1191*2d543d20SAndroid Build Coastguard Worker 	/* Before we do anything else, flush the join to its component parts.
1192*2d543d20SAndroid Build Coastguard Worker 	 * This *does not* flush to disk automatically */
1193*2d543d20SAndroid Build Coastguard Worker 	if (users->dtable->is_modified(users->dbase)) {
1194*2d543d20SAndroid Build Coastguard Worker 		retval = users->dtable->flush(sh, users->dbase);
1195*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1196*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1197*2d543d20SAndroid Build Coastguard Worker 	}
1198*2d543d20SAndroid Build Coastguard Worker 
1199*2d543d20SAndroid Build Coastguard Worker 	/* Rebuild if explicitly requested or any module changes occurred. */
1200*2d543d20SAndroid Build Coastguard Worker 	do_rebuild = sh->do_rebuild | sh->modules_modified;
1201*2d543d20SAndroid Build Coastguard Worker 
1202*2d543d20SAndroid Build Coastguard Worker 	/* Create or remove the disable_dontaudit flag file. */
1203*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_TMP, SEMANAGE_DISABLE_DONTAUDIT);
1204*2d543d20SAndroid Build Coastguard Worker 	if (stat(path, &sb) == 0)
1205*2d543d20SAndroid Build Coastguard Worker 		do_rebuild |= !(sepol_get_disable_dontaudit(sh->sepolh) == 1);
1206*2d543d20SAndroid Build Coastguard Worker 	else if (errno == ENOENT) {
1207*2d543d20SAndroid Build Coastguard Worker 		/* The file does not exist */
1208*2d543d20SAndroid Build Coastguard Worker 		do_rebuild |= (sepol_get_disable_dontaudit(sh->sepolh) == 1);
1209*2d543d20SAndroid Build Coastguard Worker 	} else {
1210*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1211*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1212*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1213*2d543d20SAndroid Build Coastguard Worker 	}
1214*2d543d20SAndroid Build Coastguard Worker 	if (sepol_get_disable_dontaudit(sh->sepolh) == 1) {
1215*2d543d20SAndroid Build Coastguard Worker 		FILE *touch;
1216*2d543d20SAndroid Build Coastguard Worker 		touch = fopen(path, "w");
1217*2d543d20SAndroid Build Coastguard Worker 		if (touch != NULL) {
1218*2d543d20SAndroid Build Coastguard Worker 			if (fclose(touch) != 0) {
1219*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Error attempting to create disable_dontaudit flag.");
1220*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1221*2d543d20SAndroid Build Coastguard Worker 			}
1222*2d543d20SAndroid Build Coastguard Worker 		} else {
1223*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error attempting to create disable_dontaudit flag.");
1224*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1225*2d543d20SAndroid Build Coastguard Worker 		}
1226*2d543d20SAndroid Build Coastguard Worker 	} else {
1227*2d543d20SAndroid Build Coastguard Worker 		if (remove(path) == -1 && errno != ENOENT) {
1228*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error removing the disable_dontaudit flag.");
1229*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1230*2d543d20SAndroid Build Coastguard Worker 		}
1231*2d543d20SAndroid Build Coastguard Worker 	}
1232*2d543d20SAndroid Build Coastguard Worker 
1233*2d543d20SAndroid Build Coastguard Worker 	/* Create or remove the preserve_tunables flag file. */
1234*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_TMP, SEMANAGE_PRESERVE_TUNABLES);
1235*2d543d20SAndroid Build Coastguard Worker 	if (stat(path, &sb) == 0)
1236*2d543d20SAndroid Build Coastguard Worker 		do_rebuild |= !(sepol_get_preserve_tunables(sh->sepolh) == 1);
1237*2d543d20SAndroid Build Coastguard Worker 	else if (errno == ENOENT) {
1238*2d543d20SAndroid Build Coastguard Worker 		/* The file does not exist */
1239*2d543d20SAndroid Build Coastguard Worker 		do_rebuild |= (sepol_get_preserve_tunables(sh->sepolh) == 1);
1240*2d543d20SAndroid Build Coastguard Worker 	} else {
1241*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1242*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1243*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1244*2d543d20SAndroid Build Coastguard Worker 	}
1245*2d543d20SAndroid Build Coastguard Worker 
1246*2d543d20SAndroid Build Coastguard Worker 	if (sepol_get_preserve_tunables(sh->sepolh) == 1) {
1247*2d543d20SAndroid Build Coastguard Worker 		FILE *touch;
1248*2d543d20SAndroid Build Coastguard Worker 		touch = fopen(path, "w");
1249*2d543d20SAndroid Build Coastguard Worker 		if (touch != NULL) {
1250*2d543d20SAndroid Build Coastguard Worker 			if (fclose(touch) != 0) {
1251*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Error attempting to create preserve_tunable flag.");
1252*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1253*2d543d20SAndroid Build Coastguard Worker 			}
1254*2d543d20SAndroid Build Coastguard Worker 		} else {
1255*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error attempting to create preserve_tunable flag.");
1256*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1257*2d543d20SAndroid Build Coastguard Worker 		}
1258*2d543d20SAndroid Build Coastguard Worker 	} else {
1259*2d543d20SAndroid Build Coastguard Worker 		if (remove(path) == -1 && errno != ENOENT) {
1260*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error removing the preserve_tunables flag.");
1261*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1262*2d543d20SAndroid Build Coastguard Worker 		}
1263*2d543d20SAndroid Build Coastguard Worker 	}
1264*2d543d20SAndroid Build Coastguard Worker 
1265*2d543d20SAndroid Build Coastguard Worker 	/*
1266*2d543d20SAndroid Build Coastguard Worker 	 * This is for systems that have already migrated with an older version
1267*2d543d20SAndroid Build Coastguard Worker 	 * of semanage_migrate_store. The older version did not copy
1268*2d543d20SAndroid Build Coastguard Worker 	 * policy.kern so the policy binary must be rebuilt here.
1269*2d543d20SAndroid Build Coastguard Worker 	 * This also ensures that any linked files that are required
1270*2d543d20SAndroid Build Coastguard Worker 	 * in order to skip re-linking are present; otherwise, we force
1271*2d543d20SAndroid Build Coastguard Worker 	 * a rebuild.
1272*2d543d20SAndroid Build Coastguard Worker 	 */
1273*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; !do_rebuild && i < (int)ARRAY_SIZE(semanage_computed_files); i++) {
1274*2d543d20SAndroid Build Coastguard Worker 		path = semanage_path(SEMANAGE_TMP, semanage_computed_files[i]);
1275*2d543d20SAndroid Build Coastguard Worker 		if (stat(path, &sb) != 0) {
1276*2d543d20SAndroid Build Coastguard Worker 			if (errno != ENOENT) {
1277*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1278*2d543d20SAndroid Build Coastguard Worker 				retval = -1;
1279*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1280*2d543d20SAndroid Build Coastguard Worker 			}
1281*2d543d20SAndroid Build Coastguard Worker 
1282*2d543d20SAndroid Build Coastguard Worker 			do_rebuild = 1;
1283*2d543d20SAndroid Build Coastguard Worker 			break;
1284*2d543d20SAndroid Build Coastguard Worker 		}
1285*2d543d20SAndroid Build Coastguard Worker 	}
1286*2d543d20SAndroid Build Coastguard Worker 
1287*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || sh->check_ext_changes) {
1288*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_get_active_modules(sh, &modinfos, &num_modinfos);
1289*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0) {
1290*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1291*2d543d20SAndroid Build Coastguard Worker 		}
1292*2d543d20SAndroid Build Coastguard Worker 
1293*2d543d20SAndroid Build Coastguard Worker 		/* No modules - nothing to rebuild. */
1294*2d543d20SAndroid Build Coastguard Worker 		if (num_modinfos == 0) {
1295*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1296*2d543d20SAndroid Build Coastguard Worker 		}
1297*2d543d20SAndroid Build Coastguard Worker 
1298*2d543d20SAndroid Build Coastguard Worker 		extra = (struct extra_checksum_params){
1299*2d543d20SAndroid Build Coastguard Worker 			.disable_dontaudit = sepol_get_disable_dontaudit(sh->sepolh),
1300*2d543d20SAndroid Build Coastguard Worker 			.preserve_tunables = sepol_get_preserve_tunables(sh->sepolh),
1301*2d543d20SAndroid Build Coastguard Worker 			.target_platform = sh->conf->target_platform,
1302*2d543d20SAndroid Build Coastguard Worker 			.policyvers = sh->conf->policyvers,
1303*2d543d20SAndroid Build Coastguard Worker 		};
1304*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_compile_hll_modules(sh, modinfos, num_modinfos,
1305*2d543d20SAndroid Build Coastguard Worker 						      &extra, modules_checksum);
1306*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0) {
1307*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Failed to compile hll files into cil files.\n");
1308*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1309*2d543d20SAndroid Build Coastguard Worker 		}
1310*2d543d20SAndroid Build Coastguard Worker 
1311*2d543d20SAndroid Build Coastguard Worker 		if (!do_rebuild && sh->check_ext_changes) {
1312*2d543d20SAndroid Build Coastguard Worker 			retval = semanage_compare_checksum(sh, modules_checksum);
1313*2d543d20SAndroid Build Coastguard Worker 			if (retval < 0)
1314*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1315*2d543d20SAndroid Build Coastguard Worker 			do_rebuild = retval;
1316*2d543d20SAndroid Build Coastguard Worker 		}
1317*2d543d20SAndroid Build Coastguard Worker 
1318*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_write_modules_checksum(sh, modules_checksum);
1319*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0) {
1320*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Failed to write module checksum file.\n");
1321*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1322*2d543d20SAndroid Build Coastguard Worker 		}
1323*2d543d20SAndroid Build Coastguard Worker 	}
1324*2d543d20SAndroid Build Coastguard Worker 
1325*2d543d20SAndroid Build Coastguard Worker 	/*
1326*2d543d20SAndroid Build Coastguard Worker 	 * If there were policy changes, or explicitly requested, or
1327*2d543d20SAndroid Build Coastguard Worker 	 * any required files are missing, rebuild the policy.
1328*2d543d20SAndroid Build Coastguard Worker 	 */
1329*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild) {
1330*2d543d20SAndroid Build Coastguard Worker 		/* =================== Module expansion =============== */
1331*2d543d20SAndroid Build Coastguard Worker 
1332*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_get_cil_paths(sh, modinfos, num_modinfos, &mod_filenames);
1333*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1334*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1335*2d543d20SAndroid Build Coastguard Worker 
1336*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_verify_modules(sh, mod_filenames, num_modinfos);
1337*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1338*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1339*2d543d20SAndroid Build Coastguard Worker 
1340*2d543d20SAndroid Build Coastguard Worker 		cil_db_init(&cildb);
1341*2d543d20SAndroid Build Coastguard Worker 
1342*2d543d20SAndroid Build Coastguard Worker 		disable_dontaudit = sepol_get_disable_dontaudit(sh->sepolh);
1343*2d543d20SAndroid Build Coastguard Worker 		preserve_tunables = sepol_get_preserve_tunables(sh->sepolh);
1344*2d543d20SAndroid Build Coastguard Worker 		cil_set_disable_dontaudit(cildb, disable_dontaudit);
1345*2d543d20SAndroid Build Coastguard Worker 		cil_set_disable_neverallow(cildb, !(sh->conf->expand_check));
1346*2d543d20SAndroid Build Coastguard Worker 		cil_set_preserve_tunables(cildb, preserve_tunables);
1347*2d543d20SAndroid Build Coastguard Worker 		cil_set_target_platform(cildb, sh->conf->target_platform);
1348*2d543d20SAndroid Build Coastguard Worker 		cil_set_policy_version(cildb, sh->conf->policyvers);
1349*2d543d20SAndroid Build Coastguard Worker 
1350*2d543d20SAndroid Build Coastguard Worker 		if (sh->conf->handle_unknown != -1) {
1351*2d543d20SAndroid Build Coastguard Worker 			cil_set_handle_unknown(cildb, sh->conf->handle_unknown);
1352*2d543d20SAndroid Build Coastguard Worker 		}
1353*2d543d20SAndroid Build Coastguard Worker 
1354*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_load_files(sh, cildb, mod_filenames, num_modinfos);
1355*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0) {
1356*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1357*2d543d20SAndroid Build Coastguard Worker 		}
1358*2d543d20SAndroid Build Coastguard Worker 
1359*2d543d20SAndroid Build Coastguard Worker 		retval = cil_compile(cildb);
1360*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1361*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1362*2d543d20SAndroid Build Coastguard Worker 
1363*2d543d20SAndroid Build Coastguard Worker 		retval = cil_build_policydb(cildb, &out);
1364*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1365*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1366*2d543d20SAndroid Build Coastguard Worker 
1367*2d543d20SAndroid Build Coastguard Worker 		/* File Contexts */
1368*2d543d20SAndroid Build Coastguard Worker 		retval = cil_filecons_to_string(cildb, &fc_buffer, &fc_buffer_len);
1369*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1370*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1371*2d543d20SAndroid Build Coastguard Worker 
1372*2d543d20SAndroid Build Coastguard Worker 		/* Write the contexts (including template contexts) to a single file. */
1373*2d543d20SAndroid Build Coastguard Worker 		ofilename = semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL);
1374*2d543d20SAndroid Build Coastguard Worker 		if (ofilename == NULL) {
1375*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1376*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1377*2d543d20SAndroid Build Coastguard Worker 		}
1378*2d543d20SAndroid Build Coastguard Worker 		retval = write_file(sh, ofilename, fc_buffer, fc_buffer_len);
1379*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1380*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1381*2d543d20SAndroid Build Coastguard Worker 
1382*2d543d20SAndroid Build Coastguard Worker 		/* Split complete and template file contexts into their separate files. */
1383*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_split_fc(sh);
1384*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1385*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1386*2d543d20SAndroid Build Coastguard Worker 
1387*2d543d20SAndroid Build Coastguard Worker 		/* remove FC_TMPL now that it is now longer needed */
1388*2d543d20SAndroid Build Coastguard Worker 		unlink(semanage_path(SEMANAGE_TMP, SEMANAGE_FC_TMPL));
1389*2d543d20SAndroid Build Coastguard Worker 
1390*2d543d20SAndroid Build Coastguard Worker 		pfcontexts->dtable->drop_cache(pfcontexts->dbase);
1391*2d543d20SAndroid Build Coastguard Worker 
1392*2d543d20SAndroid Build Coastguard Worker 		/* SEUsers */
1393*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_direct_update_seuser(sh, cildb);
1394*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1395*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1396*2d543d20SAndroid Build Coastguard Worker 
1397*2d543d20SAndroid Build Coastguard Worker 		/* User Extra */
1398*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_direct_update_user_extra(sh, cildb);
1399*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1400*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1401*2d543d20SAndroid Build Coastguard Worker 
1402*2d543d20SAndroid Build Coastguard Worker 		cil_db_destroy(&cildb);
1403*2d543d20SAndroid Build Coastguard Worker 
1404*2d543d20SAndroid Build Coastguard Worker 		/* Remove redundancies in binary policy if requested. */
1405*2d543d20SAndroid Build Coastguard Worker 		if (sh->conf->optimize_policy) {
1406*2d543d20SAndroid Build Coastguard Worker 			retval = sepol_policydb_optimize(out);
1407*2d543d20SAndroid Build Coastguard Worker 			if (retval < 0)
1408*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1409*2d543d20SAndroid Build Coastguard Worker 		}
1410*2d543d20SAndroid Build Coastguard Worker 
1411*2d543d20SAndroid Build Coastguard Worker 		/* Write the linked policy before merging local changes. */
1412*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_write_policydb(sh, out,
1413*2d543d20SAndroid Build Coastguard Worker 						 SEMANAGE_LINKED);
1414*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1415*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1416*2d543d20SAndroid Build Coastguard Worker 	} else {
1417*2d543d20SAndroid Build Coastguard Worker 		/* Load the existing linked policy, w/o local changes */
1418*2d543d20SAndroid Build Coastguard Worker 		retval = sepol_policydb_create(&out);
1419*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1420*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1421*2d543d20SAndroid Build Coastguard Worker 
1422*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_read_policydb(sh, out, SEMANAGE_LINKED);
1423*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1424*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1425*2d543d20SAndroid Build Coastguard Worker 
1426*2d543d20SAndroid Build Coastguard Worker 		path = semanage_path(SEMANAGE_TMP, SEMANAGE_SEUSERS_LINKED);
1427*2d543d20SAndroid Build Coastguard Worker 		if (stat(path, &sb) == 0) {
1428*2d543d20SAndroid Build Coastguard Worker 			retval = semanage_copy_file(path,
1429*2d543d20SAndroid Build Coastguard Worker 						    semanage_path(SEMANAGE_TMP,
1430*2d543d20SAndroid Build Coastguard Worker 								  SEMANAGE_STORE_SEUSERS),
1431*2d543d20SAndroid Build Coastguard Worker 						    0, false);
1432*2d543d20SAndroid Build Coastguard Worker 			if (retval < 0)
1433*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1434*2d543d20SAndroid Build Coastguard Worker 			pseusers->dtable->drop_cache(pseusers->dbase);
1435*2d543d20SAndroid Build Coastguard Worker 		} else if (errno == ENOENT) {
1436*2d543d20SAndroid Build Coastguard Worker 			/* The file does not exist */
1437*2d543d20SAndroid Build Coastguard Worker 			pseusers->dtable->clear(sh, pseusers->dbase);
1438*2d543d20SAndroid Build Coastguard Worker 		} else {
1439*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1440*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1441*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1442*2d543d20SAndroid Build Coastguard Worker 		}
1443*2d543d20SAndroid Build Coastguard Worker 
1444*2d543d20SAndroid Build Coastguard Worker 		path = semanage_path(SEMANAGE_TMP, SEMANAGE_USERS_EXTRA_LINKED);
1445*2d543d20SAndroid Build Coastguard Worker 		if (stat(path, &sb) == 0) {
1446*2d543d20SAndroid Build Coastguard Worker 			retval = semanage_copy_file(path,
1447*2d543d20SAndroid Build Coastguard Worker 						    semanage_path(SEMANAGE_TMP,
1448*2d543d20SAndroid Build Coastguard Worker 								  SEMANAGE_USERS_EXTRA),
1449*2d543d20SAndroid Build Coastguard Worker 						    0, false);
1450*2d543d20SAndroid Build Coastguard Worker 			if (retval < 0)
1451*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1452*2d543d20SAndroid Build Coastguard Worker 			pusers_extra->dtable->drop_cache(pusers_extra->dbase);
1453*2d543d20SAndroid Build Coastguard Worker 		} else if (errno == ENOENT) {
1454*2d543d20SAndroid Build Coastguard Worker 			/* The file does not exist */
1455*2d543d20SAndroid Build Coastguard Worker 			pusers_extra->dtable->clear(sh, pusers_extra->dbase);
1456*2d543d20SAndroid Build Coastguard Worker 		} else {
1457*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
1458*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1459*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1460*2d543d20SAndroid Build Coastguard Worker 		}
1461*2d543d20SAndroid Build Coastguard Worker 	}
1462*2d543d20SAndroid Build Coastguard Worker 
1463*2d543d20SAndroid Build Coastguard Worker 	/*
1464*2d543d20SAndroid Build Coastguard Worker 	 * Determine what else needs to be done.
1465*2d543d20SAndroid Build Coastguard Worker 	 * We need to write the kernel policy if we are rebuilding
1466*2d543d20SAndroid Build Coastguard Worker 	 * or if any other policy component that lives in the kernel
1467*2d543d20SAndroid Build Coastguard Worker 	 * policy has been modified. We also want to force it when
1468*2d543d20SAndroid Build Coastguard Worker 	 * check_ext_changes was specified as the various dbases may have
1469*2d543d20SAndroid Build Coastguard Worker 	 * changes as well.
1470*2d543d20SAndroid Build Coastguard Worker 	 * We need to install the policy files if any of the managed files
1471*2d543d20SAndroid Build Coastguard Worker 	 * that live under /etc/selinux (kernel policy, seusers, file contexts)
1472*2d543d20SAndroid Build Coastguard Worker 	 * will be modified.
1473*2d543d20SAndroid Build Coastguard Worker 	 */
1474*2d543d20SAndroid Build Coastguard Worker 	do_write_kernel = do_rebuild | sh->check_ext_changes |
1475*2d543d20SAndroid Build Coastguard Worker 		ports_modified | ibpkeys_modified | ibendports_modified |
1476*2d543d20SAndroid Build Coastguard Worker 		bools->dtable->is_modified(bools->dbase) |
1477*2d543d20SAndroid Build Coastguard Worker 		ifaces->dtable->is_modified(ifaces->dbase) |
1478*2d543d20SAndroid Build Coastguard Worker 		nodes->dtable->is_modified(nodes->dbase) |
1479*2d543d20SAndroid Build Coastguard Worker 		users->dtable->is_modified(users_base->dbase);
1480*2d543d20SAndroid Build Coastguard Worker 	do_install = do_write_kernel | seusers_modified | fcontexts_modified;
1481*2d543d20SAndroid Build Coastguard Worker 
1482*2d543d20SAndroid Build Coastguard Worker 	/* Attach our databases to the policydb we just created or loaded. */
1483*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pusers_base->dbase, out);
1484*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pports->dbase, out);
1485*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pibpkeys->dbase, out);
1486*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pibendports->dbase, out);
1487*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pifaces->dbase, out);
1488*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pbools->dbase, out);
1489*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_attach((dbase_policydb_t *) pnodes->dbase, out);
1490*2d543d20SAndroid Build Coastguard Worker 
1491*2d543d20SAndroid Build Coastguard Worker 	/* Merge local changes */
1492*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_base_merge_components(sh);
1493*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0)
1494*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1495*2d543d20SAndroid Build Coastguard Worker 
1496*2d543d20SAndroid Build Coastguard Worker 	if (do_write_kernel) {
1497*2d543d20SAndroid Build Coastguard Worker 		/* Write new kernel policy. */
1498*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_write_policydb(sh, out,
1499*2d543d20SAndroid Build Coastguard Worker 						 SEMANAGE_STORE_KERNEL);
1500*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1501*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1502*2d543d20SAndroid Build Coastguard Worker 
1503*2d543d20SAndroid Build Coastguard Worker 		/* Run the kernel policy verifier, if any. */
1504*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_verify_kernel(sh);
1505*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1506*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1507*2d543d20SAndroid Build Coastguard Worker 	}
1508*2d543d20SAndroid Build Coastguard Worker 
1509*2d543d20SAndroid Build Coastguard Worker 	/* ======= Post-process: Validate non-policydb components ===== */
1510*2d543d20SAndroid Build Coastguard Worker 
1511*2d543d20SAndroid Build Coastguard Worker 	/* Validate local modifications to file contexts.
1512*2d543d20SAndroid Build Coastguard Worker 	 * Note: those are still cached, even though they've been
1513*2d543d20SAndroid Build Coastguard Worker 	 * merged into the main file_contexts. We won't check the
1514*2d543d20SAndroid Build Coastguard Worker 	 * large file_contexts - checked at compile time */
1515*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || fcontexts_modified) {
1516*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_fcontext_validate_local(sh, out);
1517*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1518*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1519*2d543d20SAndroid Build Coastguard Worker 	}
1520*2d543d20SAndroid Build Coastguard Worker 
1521*2d543d20SAndroid Build Coastguard Worker 	/* Validate local seusers against policy */
1522*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || seusers_modified) {
1523*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_seuser_validate_local(sh, out);
1524*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1525*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1526*2d543d20SAndroid Build Coastguard Worker 	}
1527*2d543d20SAndroid Build Coastguard Worker 
1528*2d543d20SAndroid Build Coastguard Worker 	/* Validate local ports for overlap */
1529*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || ports_modified) {
1530*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_port_validate_local(sh);
1531*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1532*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1533*2d543d20SAndroid Build Coastguard Worker 	}
1534*2d543d20SAndroid Build Coastguard Worker 
1535*2d543d20SAndroid Build Coastguard Worker 	/* Validate local ibpkeys for overlap */
1536*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || ibpkeys_modified) {
1537*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_ibpkey_validate_local(sh);
1538*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1539*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1540*2d543d20SAndroid Build Coastguard Worker 	}
1541*2d543d20SAndroid Build Coastguard Worker 
1542*2d543d20SAndroid Build Coastguard Worker 	/* Validate local ibendports */
1543*2d543d20SAndroid Build Coastguard Worker 	if (do_rebuild || ibendports_modified) {
1544*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_ibendport_validate_local(sh);
1545*2d543d20SAndroid Build Coastguard Worker 		if (retval < 0)
1546*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1547*2d543d20SAndroid Build Coastguard Worker 	}
1548*2d543d20SAndroid Build Coastguard Worker 	/* ================== Write non-policydb components ========= */
1549*2d543d20SAndroid Build Coastguard Worker 
1550*2d543d20SAndroid Build Coastguard Worker 	/* Commit changes to components */
1551*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_commit_components(sh);
1552*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0)
1553*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1554*2d543d20SAndroid Build Coastguard Worker 
1555*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_copy_file(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_KERNEL),
1556*2d543d20SAndroid Build Coastguard Worker 			semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_KERNEL),
1557*2d543d20SAndroid Build Coastguard Worker 			sh->conf->file_mode, false);
1558*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1559*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1560*2d543d20SAndroid Build Coastguard Worker 	}
1561*2d543d20SAndroid Build Coastguard Worker 
1562*2d543d20SAndroid Build Coastguard Worker 	retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_LOCAL),
1563*2d543d20SAndroid Build Coastguard Worker 						semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC_LOCAL),
1564*2d543d20SAndroid Build Coastguard Worker 						sh->conf->file_mode);
1565*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1566*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1567*2d543d20SAndroid Build Coastguard Worker 	}
1568*2d543d20SAndroid Build Coastguard Worker 
1569*2d543d20SAndroid Build Coastguard Worker 	retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC),
1570*2d543d20SAndroid Build Coastguard Worker 						semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_FC),
1571*2d543d20SAndroid Build Coastguard Worker 						sh->conf->file_mode);
1572*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1573*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1574*2d543d20SAndroid Build Coastguard Worker 	}
1575*2d543d20SAndroid Build Coastguard Worker 
1576*2d543d20SAndroid Build Coastguard Worker 	retval = copy_file_if_exists(semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_SEUSERS),
1577*2d543d20SAndroid Build Coastguard Worker 						semanage_final_path(SEMANAGE_FINAL_TMP, SEMANAGE_SEUSERS),
1578*2d543d20SAndroid Build Coastguard Worker 						sh->conf->file_mode);
1579*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1580*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1581*2d543d20SAndroid Build Coastguard Worker 	}
1582*2d543d20SAndroid Build Coastguard Worker 
1583*2d543d20SAndroid Build Coastguard Worker 	/* run genhomedircon if its enabled, this should be the last operation
1584*2d543d20SAndroid Build Coastguard Worker 	 * which requires the out policydb */
1585*2d543d20SAndroid Build Coastguard Worker 	if (!sh->conf->disable_genhomedircon) {
1586*2d543d20SAndroid Build Coastguard Worker 		if (out){
1587*2d543d20SAndroid Build Coastguard Worker 			if ((retval = semanage_genhomedircon(sh, out, sh->conf->usepasswd,
1588*2d543d20SAndroid Build Coastguard Worker 								sh->conf->ignoredirs)) != 0) {
1589*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "semanage_genhomedircon returned error code %d.", retval);
1590*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1591*2d543d20SAndroid Build Coastguard Worker 			}
1592*2d543d20SAndroid Build Coastguard Worker 			/* file_contexts.homedirs was created in SEMANAGE_TMP store */
1593*2d543d20SAndroid Build Coastguard Worker 			retval = semanage_copy_file(
1594*2d543d20SAndroid Build Coastguard Worker 						semanage_path(SEMANAGE_TMP, SEMANAGE_STORE_FC_HOMEDIRS),
1595*2d543d20SAndroid Build Coastguard Worker 						semanage_final_path(SEMANAGE_FINAL_TMP,	SEMANAGE_FC_HOMEDIRS),
1596*2d543d20SAndroid Build Coastguard Worker 						sh->conf->file_mode, false);
1597*2d543d20SAndroid Build Coastguard Worker 			if (retval < 0) {
1598*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
1599*2d543d20SAndroid Build Coastguard Worker 			}
1600*2d543d20SAndroid Build Coastguard Worker 		}
1601*2d543d20SAndroid Build Coastguard Worker 	} else {
1602*2d543d20SAndroid Build Coastguard Worker 		WARN(sh, "WARNING: genhomedircon is disabled. \
1603*2d543d20SAndroid Build Coastguard Worker                                See /etc/selinux/semanage.conf if you need to enable it.");
1604*2d543d20SAndroid Build Coastguard Worker         }
1605*2d543d20SAndroid Build Coastguard Worker 
1606*2d543d20SAndroid Build Coastguard Worker 	/* free out, if we don't free it before calling semanage_install_sandbox
1607*2d543d20SAndroid Build Coastguard Worker 	 * then fork() may fail on low memory machines */
1608*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_free(out);
1609*2d543d20SAndroid Build Coastguard Worker 	out = NULL;
1610*2d543d20SAndroid Build Coastguard Worker 
1611*2d543d20SAndroid Build Coastguard Worker 	if (do_install)
1612*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_install_sandbox(sh);
1613*2d543d20SAndroid Build Coastguard Worker 
1614*2d543d20SAndroid Build Coastguard Worker cleanup:
1615*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; i < num_modinfos; i++) {
1616*2d543d20SAndroid Build Coastguard Worker 		semanage_module_info_destroy(sh, &modinfos[i]);
1617*2d543d20SAndroid Build Coastguard Worker 	}
1618*2d543d20SAndroid Build Coastguard Worker 	free(modinfos);
1619*2d543d20SAndroid Build Coastguard Worker 
1620*2d543d20SAndroid Build Coastguard Worker 	for (i = 0; mod_filenames != NULL && i < num_modinfos; i++) {
1621*2d543d20SAndroid Build Coastguard Worker 		free(mod_filenames[i]);
1622*2d543d20SAndroid Build Coastguard Worker 	}
1623*2d543d20SAndroid Build Coastguard Worker 
1624*2d543d20SAndroid Build Coastguard Worker 	/* Detach from policydb, so it can be freed */
1625*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pusers_base->dbase);
1626*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pports->dbase);
1627*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pibpkeys->dbase);
1628*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pibendports->dbase);
1629*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pifaces->dbase);
1630*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pnodes->dbase);
1631*2d543d20SAndroid Build Coastguard Worker 	dbase_policydb_detach((dbase_policydb_t *) pbools->dbase);
1632*2d543d20SAndroid Build Coastguard Worker 
1633*2d543d20SAndroid Build Coastguard Worker 	free(mod_filenames);
1634*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_free(out);
1635*2d543d20SAndroid Build Coastguard Worker 	cil_db_destroy(&cildb);
1636*2d543d20SAndroid Build Coastguard Worker 
1637*2d543d20SAndroid Build Coastguard Worker 	free(fc_buffer);
1638*2d543d20SAndroid Build Coastguard Worker 
1639*2d543d20SAndroid Build Coastguard Worker 	/* Set commit_err so other functions can detect any errors. Note that
1640*2d543d20SAndroid Build Coastguard Worker 	 * retval > 0 will be the commit number.
1641*2d543d20SAndroid Build Coastguard Worker 	 */
1642*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0)
1643*2d543d20SAndroid Build Coastguard Worker 		sh->commit_err = retval;
1644*2d543d20SAndroid Build Coastguard Worker 
1645*2d543d20SAndroid Build Coastguard Worker 	if (semanage_remove_tmps(sh) != 0)
1646*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1647*2d543d20SAndroid Build Coastguard Worker 
1648*2d543d20SAndroid Build Coastguard Worker 	semanage_release_trans_lock(sh);
1649*2d543d20SAndroid Build Coastguard Worker 	umask(mask);
1650*2d543d20SAndroid Build Coastguard Worker 
1651*2d543d20SAndroid Build Coastguard Worker 	return retval;
1652*2d543d20SAndroid Build Coastguard Worker }
1653*2d543d20SAndroid Build Coastguard Worker 
1654*2d543d20SAndroid Build Coastguard Worker /* Writes a module to the sandbox's module directory, overwriting any
1655*2d543d20SAndroid Build Coastguard Worker  * previous module stored within.  Note that module data are not
1656*2d543d20SAndroid Build Coastguard Worker  * free()d by this function; caller is responsible for deallocating it
1657*2d543d20SAndroid Build Coastguard Worker  * if necessary.  Returns 0 on success, -1 if out of memory, -2 if the
1658*2d543d20SAndroid Build Coastguard Worker  * data does not represent a valid module file, -3 if error while
1659*2d543d20SAndroid Build Coastguard Worker  * writing file. */
semanage_direct_install(semanage_handle_t * sh,char * data,size_t data_len,const char * module_name,const char * lang_ext)1660*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install(semanage_handle_t * sh,
1661*2d543d20SAndroid Build Coastguard Worker 				   char *data, size_t data_len,
1662*2d543d20SAndroid Build Coastguard Worker 				   const char *module_name, const char *lang_ext)
1663*2d543d20SAndroid Build Coastguard Worker {
1664*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
1665*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
1666*2d543d20SAndroid Build Coastguard Worker 
1667*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t modinfo;
1668*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_init(sh, &modinfo);
1669*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1670*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1671*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1672*2d543d20SAndroid Build Coastguard Worker 	}
1673*2d543d20SAndroid Build Coastguard Worker 
1674*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_priority(sh, &modinfo, sh->priority);
1675*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1676*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1677*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1678*2d543d20SAndroid Build Coastguard Worker 	}
1679*2d543d20SAndroid Build Coastguard Worker 
1680*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_name(sh, &modinfo, module_name);
1681*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1682*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1683*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1684*2d543d20SAndroid Build Coastguard Worker 	}
1685*2d543d20SAndroid Build Coastguard Worker 
1686*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_lang_ext(sh, &modinfo, lang_ext);
1687*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1688*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1689*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1690*2d543d20SAndroid Build Coastguard Worker 	}
1691*2d543d20SAndroid Build Coastguard Worker 
1692*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_enabled(sh, &modinfo, -1);
1693*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1694*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1695*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1696*2d543d20SAndroid Build Coastguard Worker 	}
1697*2d543d20SAndroid Build Coastguard Worker 
1698*2d543d20SAndroid Build Coastguard Worker 	status = semanage_direct_install_info(sh, &modinfo, data, data_len);
1699*2d543d20SAndroid Build Coastguard Worker 
1700*2d543d20SAndroid Build Coastguard Worker cleanup:
1701*2d543d20SAndroid Build Coastguard Worker 
1702*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, &modinfo);
1703*2d543d20SAndroid Build Coastguard Worker 
1704*2d543d20SAndroid Build Coastguard Worker 	return status;
1705*2d543d20SAndroid Build Coastguard Worker }
1706*2d543d20SAndroid Build Coastguard Worker 
1707*2d543d20SAndroid Build Coastguard Worker /* Attempts to link a module to the sandbox's module directory, unlinking any
1708*2d543d20SAndroid Build Coastguard Worker  * previous module stored within.  Returns 0 on success, -1 if out of memory, -2 if the
1709*2d543d20SAndroid Build Coastguard Worker  * data does not represent a valid module file, -3 if error while
1710*2d543d20SAndroid Build Coastguard Worker  * writing file. */
1711*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_install_file(semanage_handle_t * sh,const char * install_filename)1712*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install_file(semanage_handle_t * sh,
1713*2d543d20SAndroid Build Coastguard Worker 					const char *install_filename)
1714*2d543d20SAndroid Build Coastguard Worker {
1715*2d543d20SAndroid Build Coastguard Worker 
1716*2d543d20SAndroid Build Coastguard Worker 	int retval = -1;
1717*2d543d20SAndroid Build Coastguard Worker 	char *path = NULL;
1718*2d543d20SAndroid Build Coastguard Worker 	char *filename;
1719*2d543d20SAndroid Build Coastguard Worker 	char *lang_ext = NULL;
1720*2d543d20SAndroid Build Coastguard Worker 	char *module_name = NULL;
1721*2d543d20SAndroid Build Coastguard Worker 	char *separator;
1722*2d543d20SAndroid Build Coastguard Worker 	char *version = NULL;
1723*2d543d20SAndroid Build Coastguard Worker 	struct file_contents contents = {};
1724*2d543d20SAndroid Build Coastguard Worker 
1725*2d543d20SAndroid Build Coastguard Worker 	retval = map_compressed_file(sh, install_filename, &contents);
1726*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1727*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to read file %s\n", install_filename);
1728*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1729*2d543d20SAndroid Build Coastguard Worker 	}
1730*2d543d20SAndroid Build Coastguard Worker 
1731*2d543d20SAndroid Build Coastguard Worker 	path = strdup(install_filename);
1732*2d543d20SAndroid Build Coastguard Worker 	if (path == NULL) {
1733*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "No memory available for strdup.\n");
1734*2d543d20SAndroid Build Coastguard Worker 		retval = -1;
1735*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1736*2d543d20SAndroid Build Coastguard Worker 	}
1737*2d543d20SAndroid Build Coastguard Worker 
1738*2d543d20SAndroid Build Coastguard Worker 	filename = basename(path);
1739*2d543d20SAndroid Build Coastguard Worker 
1740*2d543d20SAndroid Build Coastguard Worker 	if (contents.compressed) {
1741*2d543d20SAndroid Build Coastguard Worker 		separator = strrchr(filename, '.');
1742*2d543d20SAndroid Build Coastguard Worker 		if (separator == NULL) {
1743*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Compressed module does not have a valid extension.");
1744*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1745*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1746*2d543d20SAndroid Build Coastguard Worker 		}
1747*2d543d20SAndroid Build Coastguard Worker 		*separator = '\0';
1748*2d543d20SAndroid Build Coastguard Worker 		lang_ext = separator + 1;
1749*2d543d20SAndroid Build Coastguard Worker 	}
1750*2d543d20SAndroid Build Coastguard Worker 
1751*2d543d20SAndroid Build Coastguard Worker 	separator = strrchr(filename, '.');
1752*2d543d20SAndroid Build Coastguard Worker 	if (separator == NULL) {
1753*2d543d20SAndroid Build Coastguard Worker 		if (lang_ext == NULL) {
1754*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Module does not have a valid extension.");
1755*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1756*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1757*2d543d20SAndroid Build Coastguard Worker 		}
1758*2d543d20SAndroid Build Coastguard Worker 	} else {
1759*2d543d20SAndroid Build Coastguard Worker 		*separator = '\0';
1760*2d543d20SAndroid Build Coastguard Worker 		lang_ext = separator + 1;
1761*2d543d20SAndroid Build Coastguard Worker 	}
1762*2d543d20SAndroid Build Coastguard Worker 
1763*2d543d20SAndroid Build Coastguard Worker 	if (strcmp(lang_ext, "pp") == 0) {
1764*2d543d20SAndroid Build Coastguard Worker 		retval = parse_module_headers(sh, contents.data, contents.len,
1765*2d543d20SAndroid Build Coastguard Worker 					      &module_name, &version);
1766*2d543d20SAndroid Build Coastguard Worker 		free(version);
1767*2d543d20SAndroid Build Coastguard Worker 		if (retval != 0)
1768*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1769*2d543d20SAndroid Build Coastguard Worker 	}
1770*2d543d20SAndroid Build Coastguard Worker 
1771*2d543d20SAndroid Build Coastguard Worker 	if (module_name == NULL) {
1772*2d543d20SAndroid Build Coastguard Worker 		module_name = strdup(filename);
1773*2d543d20SAndroid Build Coastguard Worker 		if (module_name == NULL) {
1774*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "No memory available for module_name.\n");
1775*2d543d20SAndroid Build Coastguard Worker 			retval = -1;
1776*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1777*2d543d20SAndroid Build Coastguard Worker 		}
1778*2d543d20SAndroid Build Coastguard Worker 	} else if (strcmp(module_name, filename) != 0) {
1779*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "Warning: SELinux userspace will refer to the module from %s as %s rather than %s\n", install_filename, module_name, filename);
1780*2d543d20SAndroid Build Coastguard Worker 	}
1781*2d543d20SAndroid Build Coastguard Worker 
1782*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_direct_install(sh, contents.data, contents.len,
1783*2d543d20SAndroid Build Coastguard Worker 					 module_name, lang_ext);
1784*2d543d20SAndroid Build Coastguard Worker 
1785*2d543d20SAndroid Build Coastguard Worker cleanup:
1786*2d543d20SAndroid Build Coastguard Worker 	unmap_compressed_file(&contents);
1787*2d543d20SAndroid Build Coastguard Worker 	free(module_name);
1788*2d543d20SAndroid Build Coastguard Worker 	free(path);
1789*2d543d20SAndroid Build Coastguard Worker 
1790*2d543d20SAndroid Build Coastguard Worker 	return retval;
1791*2d543d20SAndroid Build Coastguard Worker }
1792*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_extract(semanage_handle_t * sh,semanage_module_key_t * modkey,int extract_cil,void ** mapped_data,size_t * data_len,semanage_module_info_t ** modinfo)1793*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_extract(semanage_handle_t * sh,
1794*2d543d20SAndroid Build Coastguard Worker 				   semanage_module_key_t *modkey,
1795*2d543d20SAndroid Build Coastguard Worker 				   int extract_cil,
1796*2d543d20SAndroid Build Coastguard Worker 				   void **mapped_data,
1797*2d543d20SAndroid Build Coastguard Worker 				   size_t *data_len,
1798*2d543d20SAndroid Build Coastguard Worker 				   semanage_module_info_t **modinfo)
1799*2d543d20SAndroid Build Coastguard Worker {
1800*2d543d20SAndroid Build Coastguard Worker 	char module_path[PATH_MAX];
1801*2d543d20SAndroid Build Coastguard Worker 	char input_file[PATH_MAX];
1802*2d543d20SAndroid Build Coastguard Worker 	enum semanage_module_path_type file_type;
1803*2d543d20SAndroid Build Coastguard Worker 	int rc = -1;
1804*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *_modinfo = NULL;
1805*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
1806*2d543d20SAndroid Build Coastguard Worker 	struct file_contents contents = {};
1807*2d543d20SAndroid Build Coastguard Worker 
1808*2d543d20SAndroid Build Coastguard Worker 	/* get path of module */
1809*2d543d20SAndroid Build Coastguard Worker 	rc = semanage_module_get_path(
1810*2d543d20SAndroid Build Coastguard Worker 			sh,
1811*2d543d20SAndroid Build Coastguard Worker 			(const semanage_module_info_t *)modkey,
1812*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_NAME,
1813*2d543d20SAndroid Build Coastguard Worker 			module_path,
1814*2d543d20SAndroid Build Coastguard Worker 			sizeof(module_path));
1815*2d543d20SAndroid Build Coastguard Worker 	if (rc != 0) {
1816*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1817*2d543d20SAndroid Build Coastguard Worker 	}
1818*2d543d20SAndroid Build Coastguard Worker 
1819*2d543d20SAndroid Build Coastguard Worker 	if (stat(module_path, &sb) != 0) {
1820*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to access %s: %s\n", module_path, strerror(errno));
1821*2d543d20SAndroid Build Coastguard Worker 		rc = -1;
1822*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1823*2d543d20SAndroid Build Coastguard Worker 	}
1824*2d543d20SAndroid Build Coastguard Worker 
1825*2d543d20SAndroid Build Coastguard Worker 	rc = semanage_module_get_module_info(sh,
1826*2d543d20SAndroid Build Coastguard Worker 			modkey,
1827*2d543d20SAndroid Build Coastguard Worker 			&_modinfo);
1828*2d543d20SAndroid Build Coastguard Worker 	if (rc != 0) {
1829*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1830*2d543d20SAndroid Build Coastguard Worker 	}
1831*2d543d20SAndroid Build Coastguard Worker 
1832*2d543d20SAndroid Build Coastguard Worker 	if (extract_cil || strcmp(_modinfo->lang_ext, "cil") == 0) {
1833*2d543d20SAndroid Build Coastguard Worker 		file_type = SEMANAGE_MODULE_PATH_CIL;
1834*2d543d20SAndroid Build Coastguard Worker 	} else {
1835*2d543d20SAndroid Build Coastguard Worker 		file_type = SEMANAGE_MODULE_PATH_HLL;
1836*2d543d20SAndroid Build Coastguard Worker 	}
1837*2d543d20SAndroid Build Coastguard Worker 
1838*2d543d20SAndroid Build Coastguard Worker 	/* get path of what to extract */
1839*2d543d20SAndroid Build Coastguard Worker 	rc = semanage_module_get_path(
1840*2d543d20SAndroid Build Coastguard Worker 			sh,
1841*2d543d20SAndroid Build Coastguard Worker 			_modinfo,
1842*2d543d20SAndroid Build Coastguard Worker 			file_type,
1843*2d543d20SAndroid Build Coastguard Worker 			input_file,
1844*2d543d20SAndroid Build Coastguard Worker 			sizeof(input_file));
1845*2d543d20SAndroid Build Coastguard Worker 	if (rc != 0) {
1846*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1847*2d543d20SAndroid Build Coastguard Worker 	}
1848*2d543d20SAndroid Build Coastguard Worker 
1849*2d543d20SAndroid Build Coastguard Worker 	if (extract_cil == 1 && strcmp(_modinfo->lang_ext, "cil") && stat(input_file, &sb) != 0) {
1850*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
1851*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to access %s: %s\n", input_file, strerror(errno));
1852*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
1853*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1854*2d543d20SAndroid Build Coastguard Worker 		}
1855*2d543d20SAndroid Build Coastguard Worker 
1856*2d543d20SAndroid Build Coastguard Worker 		rc = semanage_compile_module(sh, _modinfo, NULL);
1857*2d543d20SAndroid Build Coastguard Worker 		if (rc < 0) {
1858*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1859*2d543d20SAndroid Build Coastguard Worker 		}
1860*2d543d20SAndroid Build Coastguard Worker 	}
1861*2d543d20SAndroid Build Coastguard Worker 
1862*2d543d20SAndroid Build Coastguard Worker 	rc = map_compressed_file(sh, input_file, &contents);
1863*2d543d20SAndroid Build Coastguard Worker 	if (rc < 0) {
1864*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Error mapping file: %s", input_file);
1865*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1866*2d543d20SAndroid Build Coastguard Worker 	}
1867*2d543d20SAndroid Build Coastguard Worker 
1868*2d543d20SAndroid Build Coastguard Worker 	/* The API promises an mmap'ed pointer */
1869*2d543d20SAndroid Build Coastguard Worker 	if (contents.compressed) {
1870*2d543d20SAndroid Build Coastguard Worker 		*mapped_data = mmap(NULL, contents.len, PROT_READ|PROT_WRITE,
1871*2d543d20SAndroid Build Coastguard Worker 				    MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
1872*2d543d20SAndroid Build Coastguard Worker 		if (*mapped_data == MAP_FAILED) {
1873*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to map memory");
1874*2d543d20SAndroid Build Coastguard Worker 			rc = -1;
1875*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
1876*2d543d20SAndroid Build Coastguard Worker 		}
1877*2d543d20SAndroid Build Coastguard Worker 		memcpy(*mapped_data, contents.data, contents.len);
1878*2d543d20SAndroid Build Coastguard Worker 		free(contents.data);
1879*2d543d20SAndroid Build Coastguard Worker 	} else {
1880*2d543d20SAndroid Build Coastguard Worker 		*mapped_data = contents.data;
1881*2d543d20SAndroid Build Coastguard Worker 	}
1882*2d543d20SAndroid Build Coastguard Worker 
1883*2d543d20SAndroid Build Coastguard Worker 	*modinfo = _modinfo;
1884*2d543d20SAndroid Build Coastguard Worker 	*data_len = contents.len;
1885*2d543d20SAndroid Build Coastguard Worker 
1886*2d543d20SAndroid Build Coastguard Worker cleanup:
1887*2d543d20SAndroid Build Coastguard Worker 	if (rc != 0) {
1888*2d543d20SAndroid Build Coastguard Worker 		unmap_compressed_file(&contents);
1889*2d543d20SAndroid Build Coastguard Worker 		semanage_module_info_destroy(sh, _modinfo);
1890*2d543d20SAndroid Build Coastguard Worker 		free(_modinfo);
1891*2d543d20SAndroid Build Coastguard Worker 	}
1892*2d543d20SAndroid Build Coastguard Worker 
1893*2d543d20SAndroid Build Coastguard Worker 	return rc;
1894*2d543d20SAndroid Build Coastguard Worker }
1895*2d543d20SAndroid Build Coastguard Worker 
1896*2d543d20SAndroid Build Coastguard Worker /* Removes a module from the sandbox.  Returns 0 on success, -1 if out
1897*2d543d20SAndroid Build Coastguard Worker  * of memory, -2 if module not found or could not be removed. */
semanage_direct_remove(semanage_handle_t * sh,char * module_name)1898*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_remove(semanage_handle_t * sh, char *module_name)
1899*2d543d20SAndroid Build Coastguard Worker {
1900*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
1901*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
1902*2d543d20SAndroid Build Coastguard Worker 
1903*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_t modkey;
1904*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_init(sh, &modkey);
1905*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1906*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1907*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1908*2d543d20SAndroid Build Coastguard Worker 	}
1909*2d543d20SAndroid Build Coastguard Worker 
1910*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_set_priority(sh, &modkey, sh->priority);
1911*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1912*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1913*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1914*2d543d20SAndroid Build Coastguard Worker 	}
1915*2d543d20SAndroid Build Coastguard Worker 
1916*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_set_name(sh, &modkey, module_name);
1917*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1918*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1919*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1920*2d543d20SAndroid Build Coastguard Worker 	}
1921*2d543d20SAndroid Build Coastguard Worker 
1922*2d543d20SAndroid Build Coastguard Worker 	status = semanage_direct_remove_key(sh, &modkey);
1923*2d543d20SAndroid Build Coastguard Worker 
1924*2d543d20SAndroid Build Coastguard Worker cleanup:
1925*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_destroy(sh, &modkey);
1926*2d543d20SAndroid Build Coastguard Worker 	return status;
1927*2d543d20SAndroid Build Coastguard Worker }
1928*2d543d20SAndroid Build Coastguard Worker 
1929*2d543d20SAndroid Build Coastguard Worker /* Allocate an array of module_info structures for each readable
1930*2d543d20SAndroid Build Coastguard Worker  * module within the store.  Note that if the calling program has
1931*2d543d20SAndroid Build Coastguard Worker  * already begun a transaction then this function will get a list of
1932*2d543d20SAndroid Build Coastguard Worker  * modules within the sandbox.	The caller is responsible for calling
1933*2d543d20SAndroid Build Coastguard Worker  * semanage_module_info_datum_destroy() on each element of the array
1934*2d543d20SAndroid Build Coastguard Worker  * as well as free()ing the entire list.
1935*2d543d20SAndroid Build Coastguard Worker  */
semanage_direct_list(semanage_handle_t * sh,semanage_module_info_t ** modinfo,int * num_modules)1936*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_list(semanage_handle_t * sh,
1937*2d543d20SAndroid Build Coastguard Worker 				semanage_module_info_t ** modinfo,
1938*2d543d20SAndroid Build Coastguard Worker 				int *num_modules)
1939*2d543d20SAndroid Build Coastguard Worker {
1940*2d543d20SAndroid Build Coastguard Worker 	int i, retval = -1;
1941*2d543d20SAndroid Build Coastguard Worker 	*modinfo = NULL;
1942*2d543d20SAndroid Build Coastguard Worker 	*num_modules = 0;
1943*2d543d20SAndroid Build Coastguard Worker 
1944*2d543d20SAndroid Build Coastguard Worker 	/* get the read lock when reading from the active
1945*2d543d20SAndroid Build Coastguard Worker 	   (non-transaction) directory */
1946*2d543d20SAndroid Build Coastguard Worker 	if (!sh->is_in_transaction)
1947*2d543d20SAndroid Build Coastguard Worker 		if (semanage_get_active_lock(sh) < 0)
1948*2d543d20SAndroid Build Coastguard Worker 			return -1;
1949*2d543d20SAndroid Build Coastguard Worker 
1950*2d543d20SAndroid Build Coastguard Worker 	if (semanage_get_active_modules(sh, modinfo, num_modules) == -1) {
1951*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1952*2d543d20SAndroid Build Coastguard Worker 	}
1953*2d543d20SAndroid Build Coastguard Worker 
1954*2d543d20SAndroid Build Coastguard Worker 	if (num_modules == 0) {
1955*2d543d20SAndroid Build Coastguard Worker 		retval = semanage_direct_get_serial(sh);
1956*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
1957*2d543d20SAndroid Build Coastguard Worker 	}
1958*2d543d20SAndroid Build Coastguard Worker 
1959*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_direct_get_serial(sh);
1960*2d543d20SAndroid Build Coastguard Worker 
1961*2d543d20SAndroid Build Coastguard Worker       cleanup:
1962*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0) {
1963*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < *num_modules; i++) {
1964*2d543d20SAndroid Build Coastguard Worker 			semanage_module_info_destroy(sh, &(*modinfo[i]));
1965*2d543d20SAndroid Build Coastguard Worker 			modinfo[i] = NULL;
1966*2d543d20SAndroid Build Coastguard Worker 		}
1967*2d543d20SAndroid Build Coastguard Worker 		free(*modinfo);
1968*2d543d20SAndroid Build Coastguard Worker 		*modinfo = NULL;
1969*2d543d20SAndroid Build Coastguard Worker 	}
1970*2d543d20SAndroid Build Coastguard Worker 
1971*2d543d20SAndroid Build Coastguard Worker 	if (!sh->is_in_transaction) {
1972*2d543d20SAndroid Build Coastguard Worker 		semanage_release_active_lock(sh);
1973*2d543d20SAndroid Build Coastguard Worker 	}
1974*2d543d20SAndroid Build Coastguard Worker 	return retval;
1975*2d543d20SAndroid Build Coastguard Worker }
1976*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_get_enabled(semanage_handle_t * sh,const semanage_module_key_t * modkey,int * enabled)1977*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_get_enabled(semanage_handle_t *sh,
1978*2d543d20SAndroid Build Coastguard Worker 				       const semanage_module_key_t *modkey,
1979*2d543d20SAndroid Build Coastguard Worker 				       int *enabled)
1980*2d543d20SAndroid Build Coastguard Worker {
1981*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
1982*2d543d20SAndroid Build Coastguard Worker 	assert(modkey);
1983*2d543d20SAndroid Build Coastguard Worker 	assert(enabled);
1984*2d543d20SAndroid Build Coastguard Worker 
1985*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
1986*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
1987*2d543d20SAndroid Build Coastguard Worker 
1988*2d543d20SAndroid Build Coastguard Worker 	char path[PATH_MAX];
1989*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
1990*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfo = NULL;
1991*2d543d20SAndroid Build Coastguard Worker 
1992*2d543d20SAndroid Build Coastguard Worker 	/* get module info */
1993*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_module_info(
1994*2d543d20SAndroid Build Coastguard Worker 			sh,
1995*2d543d20SAndroid Build Coastguard Worker 			modkey,
1996*2d543d20SAndroid Build Coastguard Worker 			&modinfo);
1997*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
1998*2d543d20SAndroid Build Coastguard Worker 		status = -1;
1999*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2000*2d543d20SAndroid Build Coastguard Worker 	}
2001*2d543d20SAndroid Build Coastguard Worker 
2002*2d543d20SAndroid Build Coastguard Worker 	/* get disabled file path */
2003*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(
2004*2d543d20SAndroid Build Coastguard Worker 			sh,
2005*2d543d20SAndroid Build Coastguard Worker 			modinfo,
2006*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_DISABLED,
2007*2d543d20SAndroid Build Coastguard Worker 			path,
2008*2d543d20SAndroid Build Coastguard Worker 			sizeof(path));
2009*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2010*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2011*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2012*2d543d20SAndroid Build Coastguard Worker 	}
2013*2d543d20SAndroid Build Coastguard Worker 
2014*2d543d20SAndroid Build Coastguard Worker 	if (stat(path, &sb) < 0) {
2015*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
2016*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to access %s: %s\n", path, strerror(errno));
2017*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2018*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2019*2d543d20SAndroid Build Coastguard Worker 		}
2020*2d543d20SAndroid Build Coastguard Worker 
2021*2d543d20SAndroid Build Coastguard Worker 		*enabled = 1;
2022*2d543d20SAndroid Build Coastguard Worker 	}
2023*2d543d20SAndroid Build Coastguard Worker 	else {
2024*2d543d20SAndroid Build Coastguard Worker 		*enabled = 0;
2025*2d543d20SAndroid Build Coastguard Worker 	}
2026*2d543d20SAndroid Build Coastguard Worker 
2027*2d543d20SAndroid Build Coastguard Worker cleanup:
2028*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, modinfo);
2029*2d543d20SAndroid Build Coastguard Worker 	free(modinfo);
2030*2d543d20SAndroid Build Coastguard Worker 
2031*2d543d20SAndroid Build Coastguard Worker 	return status;
2032*2d543d20SAndroid Build Coastguard Worker }
2033*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_set_enabled(semanage_handle_t * sh,const semanage_module_key_t * modkey,int enabled)2034*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_set_enabled(semanage_handle_t *sh,
2035*2d543d20SAndroid Build Coastguard Worker 				       const semanage_module_key_t *modkey,
2036*2d543d20SAndroid Build Coastguard Worker 				       int enabled)
2037*2d543d20SAndroid Build Coastguard Worker {
2038*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
2039*2d543d20SAndroid Build Coastguard Worker 	assert(modkey);
2040*2d543d20SAndroid Build Coastguard Worker 
2041*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2042*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2043*2d543d20SAndroid Build Coastguard Worker 
2044*2d543d20SAndroid Build Coastguard Worker 	char fn[PATH_MAX];
2045*2d543d20SAndroid Build Coastguard Worker 	const char *path = NULL;
2046*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
2047*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfo = NULL;
2048*2d543d20SAndroid Build Coastguard Worker 	mode_t mask;
2049*2d543d20SAndroid Build Coastguard Worker 
2050*2d543d20SAndroid Build Coastguard Worker 	/* check transaction */
2051*2d543d20SAndroid Build Coastguard Worker 	if (!sh->is_in_transaction) {
2052*2d543d20SAndroid Build Coastguard Worker 		if (semanage_begin_transaction(sh) < 0) {
2053*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2054*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2055*2d543d20SAndroid Build Coastguard Worker 		}
2056*2d543d20SAndroid Build Coastguard Worker 	}
2057*2d543d20SAndroid Build Coastguard Worker 
2058*2d543d20SAndroid Build Coastguard Worker 	/* validate name */
2059*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_name(modkey->name);
2060*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2061*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2062*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Name %s is invalid.", modkey->name);
2063*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2064*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2065*2d543d20SAndroid Build Coastguard Worker 	}
2066*2d543d20SAndroid Build Coastguard Worker 
2067*2d543d20SAndroid Build Coastguard Worker 	/* validate enabled */
2068*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_enabled(enabled);
2069*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2070*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2071*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Enabled status %d is invalid.", enabled);
2072*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2073*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2074*2d543d20SAndroid Build Coastguard Worker 	}
2075*2d543d20SAndroid Build Coastguard Worker 
2076*2d543d20SAndroid Build Coastguard Worker 	/* check for disabled path, create if missing */
2077*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED);
2078*2d543d20SAndroid Build Coastguard Worker 
2079*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_mkdir(sh, path);
2080*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2081*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2082*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2083*2d543d20SAndroid Build Coastguard Worker 	}
2084*2d543d20SAndroid Build Coastguard Worker 
2085*2d543d20SAndroid Build Coastguard Worker 	/* get module info */
2086*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_module_info(
2087*2d543d20SAndroid Build Coastguard Worker 			sh,
2088*2d543d20SAndroid Build Coastguard Worker 			modkey,
2089*2d543d20SAndroid Build Coastguard Worker 			&modinfo);
2090*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2091*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2092*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2093*2d543d20SAndroid Build Coastguard Worker 	}
2094*2d543d20SAndroid Build Coastguard Worker 
2095*2d543d20SAndroid Build Coastguard Worker 	/* get module disabled file */
2096*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(
2097*2d543d20SAndroid Build Coastguard Worker 			sh,
2098*2d543d20SAndroid Build Coastguard Worker 			modinfo,
2099*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_DISABLED,
2100*2d543d20SAndroid Build Coastguard Worker 			fn,
2101*2d543d20SAndroid Build Coastguard Worker 			sizeof(fn));
2102*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2103*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2104*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2105*2d543d20SAndroid Build Coastguard Worker 	}
2106*2d543d20SAndroid Build Coastguard Worker 
2107*2d543d20SAndroid Build Coastguard Worker 	switch (enabled) {
2108*2d543d20SAndroid Build Coastguard Worker 		case 0: /* disable the module */
2109*2d543d20SAndroid Build Coastguard Worker 			mask = umask(0077);
2110*2d543d20SAndroid Build Coastguard Worker 			fp = fopen(fn, "w");
2111*2d543d20SAndroid Build Coastguard Worker 			umask(mask);
2112*2d543d20SAndroid Build Coastguard Worker 
2113*2d543d20SAndroid Build Coastguard Worker 			if (fp == NULL) {
2114*2d543d20SAndroid Build Coastguard Worker 				ERR(sh,
2115*2d543d20SAndroid Build Coastguard Worker 				    "Unable to disable module %s",
2116*2d543d20SAndroid Build Coastguard Worker 				    modkey->name);
2117*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2118*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2119*2d543d20SAndroid Build Coastguard Worker 			}
2120*2d543d20SAndroid Build Coastguard Worker 
2121*2d543d20SAndroid Build Coastguard Worker 			ret = fclose(fp);
2122*2d543d20SAndroid Build Coastguard Worker 			fp = NULL;
2123*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2124*2d543d20SAndroid Build Coastguard Worker 				ERR(sh,
2125*2d543d20SAndroid Build Coastguard Worker 				    "Unable to close disabled file for module %s",
2126*2d543d20SAndroid Build Coastguard Worker 				    modkey->name);
2127*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2128*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2129*2d543d20SAndroid Build Coastguard Worker 			}
2130*2d543d20SAndroid Build Coastguard Worker 
2131*2d543d20SAndroid Build Coastguard Worker 			break;
2132*2d543d20SAndroid Build Coastguard Worker 		case 1: /* enable the module */
2133*2d543d20SAndroid Build Coastguard Worker 			if (unlink(fn) < 0) {
2134*2d543d20SAndroid Build Coastguard Worker 				if (errno != ENOENT) {
2135*2d543d20SAndroid Build Coastguard Worker 					ERR(sh,
2136*2d543d20SAndroid Build Coastguard Worker 					    "Unable to enable module %s",
2137*2d543d20SAndroid Build Coastguard Worker 					    modkey->name);
2138*2d543d20SAndroid Build Coastguard Worker 					status = -1;
2139*2d543d20SAndroid Build Coastguard Worker 					goto cleanup;
2140*2d543d20SAndroid Build Coastguard Worker 				}
2141*2d543d20SAndroid Build Coastguard Worker 				else {
2142*2d543d20SAndroid Build Coastguard Worker 					/* module already enabled */
2143*2d543d20SAndroid Build Coastguard Worker 					errno = 0;
2144*2d543d20SAndroid Build Coastguard Worker 				}
2145*2d543d20SAndroid Build Coastguard Worker 			}
2146*2d543d20SAndroid Build Coastguard Worker 
2147*2d543d20SAndroid Build Coastguard Worker 			break;
2148*2d543d20SAndroid Build Coastguard Worker 		case -1: /* warn about ignored setting to default */
2149*2d543d20SAndroid Build Coastguard Worker 			WARN(sh,
2150*2d543d20SAndroid Build Coastguard Worker 			     "Setting module %s to 'default' state has no effect",
2151*2d543d20SAndroid Build Coastguard Worker 			     modkey->name);
2152*2d543d20SAndroid Build Coastguard Worker 			break;
2153*2d543d20SAndroid Build Coastguard Worker 	}
2154*2d543d20SAndroid Build Coastguard Worker 
2155*2d543d20SAndroid Build Coastguard Worker cleanup:
2156*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, modinfo);
2157*2d543d20SAndroid Build Coastguard Worker 	free(modinfo);
2158*2d543d20SAndroid Build Coastguard Worker 
2159*2d543d20SAndroid Build Coastguard Worker 	if (fp != NULL) fclose(fp);
2160*2d543d20SAndroid Build Coastguard Worker 	return status;
2161*2d543d20SAndroid Build Coastguard Worker }
2162*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_access_check(semanage_handle_t * sh)2163*2d543d20SAndroid Build Coastguard Worker int semanage_direct_access_check(semanage_handle_t * sh)
2164*2d543d20SAndroid Build Coastguard Worker {
2165*2d543d20SAndroid Build Coastguard Worker 	if (semanage_check_init(sh, sh->conf->store_root_path))
2166*2d543d20SAndroid Build Coastguard Worker 		return -1;
2167*2d543d20SAndroid Build Coastguard Worker 
2168*2d543d20SAndroid Build Coastguard Worker 	return semanage_store_access_check();
2169*2d543d20SAndroid Build Coastguard Worker }
2170*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_mls_enabled(semanage_handle_t * sh)2171*2d543d20SAndroid Build Coastguard Worker int semanage_direct_mls_enabled(semanage_handle_t * sh)
2172*2d543d20SAndroid Build Coastguard Worker {
2173*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_t *p = NULL;
2174*2d543d20SAndroid Build Coastguard Worker 	int retval;
2175*2d543d20SAndroid Build Coastguard Worker 
2176*2d543d20SAndroid Build Coastguard Worker 	retval = sepol_policydb_create(&p);
2177*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0)
2178*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2179*2d543d20SAndroid Build Coastguard Worker 
2180*2d543d20SAndroid Build Coastguard Worker 	retval = semanage_read_policydb(sh, p, SEMANAGE_STORE_KERNEL);
2181*2d543d20SAndroid Build Coastguard Worker 	if (retval < 0)
2182*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2183*2d543d20SAndroid Build Coastguard Worker 
2184*2d543d20SAndroid Build Coastguard Worker 	retval = sepol_policydb_mls_enabled(p);
2185*2d543d20SAndroid Build Coastguard Worker cleanup:
2186*2d543d20SAndroid Build Coastguard Worker 	sepol_policydb_free(p);
2187*2d543d20SAndroid Build Coastguard Worker 	return retval;
2188*2d543d20SAndroid Build Coastguard Worker }
2189*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_get_module_info(semanage_handle_t * sh,const semanage_module_key_t * modkey,semanage_module_info_t ** modinfo)2190*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_get_module_info(semanage_handle_t *sh,
2191*2d543d20SAndroid Build Coastguard Worker 					   const semanage_module_key_t *modkey,
2192*2d543d20SAndroid Build Coastguard Worker 					   semanage_module_info_t **modinfo)
2193*2d543d20SAndroid Build Coastguard Worker {
2194*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
2195*2d543d20SAndroid Build Coastguard Worker 	assert(modkey);
2196*2d543d20SAndroid Build Coastguard Worker 	assert(modinfo);
2197*2d543d20SAndroid Build Coastguard Worker 
2198*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2199*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2200*2d543d20SAndroid Build Coastguard Worker 
2201*2d543d20SAndroid Build Coastguard Worker 	char fn[PATH_MAX];
2202*2d543d20SAndroid Build Coastguard Worker 	FILE *fp = NULL;
2203*2d543d20SAndroid Build Coastguard Worker 	size_t size = 0;
2204*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
2205*2d543d20SAndroid Build Coastguard Worker 	char *tmp = NULL;
2206*2d543d20SAndroid Build Coastguard Worker 
2207*2d543d20SAndroid Build Coastguard Worker 	int i = 0;
2208*2d543d20SAndroid Build Coastguard Worker 
2209*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfos = NULL;
2210*2d543d20SAndroid Build Coastguard Worker 	int modinfos_len = 0;
2211*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *highest = NULL;
2212*2d543d20SAndroid Build Coastguard Worker 
2213*2d543d20SAndroid Build Coastguard Worker 	/* check module name */
2214*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_name(modkey->name);
2215*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0) {
2216*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2217*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Name %s is invalid.", modkey->name);
2218*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2219*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2220*2d543d20SAndroid Build Coastguard Worker 	}
2221*2d543d20SAndroid Build Coastguard Worker 
2222*2d543d20SAndroid Build Coastguard Worker 	/* if priority == 0, then find the highest priority available */
2223*2d543d20SAndroid Build Coastguard Worker 	if (modkey->priority == 0) {
2224*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_direct_list_all(sh, &modinfos, &modinfos_len);
2225*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2226*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2227*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2228*2d543d20SAndroid Build Coastguard Worker 		}
2229*2d543d20SAndroid Build Coastguard Worker 
2230*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < modinfos_len; i++) {
2231*2d543d20SAndroid Build Coastguard Worker 			ret = strcmp(modinfos[i].name, modkey->name);
2232*2d543d20SAndroid Build Coastguard Worker 			if (ret == 0) {
2233*2d543d20SAndroid Build Coastguard Worker 				highest = &modinfos[i];
2234*2d543d20SAndroid Build Coastguard Worker 				break;
2235*2d543d20SAndroid Build Coastguard Worker 			}
2236*2d543d20SAndroid Build Coastguard Worker 		}
2237*2d543d20SAndroid Build Coastguard Worker 
2238*2d543d20SAndroid Build Coastguard Worker 		if (highest == NULL) {
2239*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2240*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2241*2d543d20SAndroid Build Coastguard Worker 		}
2242*2d543d20SAndroid Build Coastguard Worker 
2243*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_info_create(sh, modinfo);
2244*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2245*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2246*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2247*2d543d20SAndroid Build Coastguard Worker 		}
2248*2d543d20SAndroid Build Coastguard Worker 
2249*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_info_clone(sh, highest, *modinfo);
2250*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2251*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2252*2d543d20SAndroid Build Coastguard Worker 		}
2253*2d543d20SAndroid Build Coastguard Worker 
2254*2d543d20SAndroid Build Coastguard Worker 		/* skip to cleanup, module was found */
2255*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2256*2d543d20SAndroid Build Coastguard Worker 	}
2257*2d543d20SAndroid Build Coastguard Worker 
2258*2d543d20SAndroid Build Coastguard Worker 	/* check module priority */
2259*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_priority(modkey->priority);
2260*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2261*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2262*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Priority %d is invalid.", modkey->priority);
2263*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2264*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2265*2d543d20SAndroid Build Coastguard Worker 	}
2266*2d543d20SAndroid Build Coastguard Worker 
2267*2d543d20SAndroid Build Coastguard Worker 	/* copy in key values */
2268*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_create(sh, modinfo);
2269*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2270*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2271*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2272*2d543d20SAndroid Build Coastguard Worker 	}
2273*2d543d20SAndroid Build Coastguard Worker 
2274*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_priority(sh, *modinfo, modkey->priority);
2275*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2276*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2277*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2278*2d543d20SAndroid Build Coastguard Worker 	}
2279*2d543d20SAndroid Build Coastguard Worker 
2280*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_name(sh, *modinfo, modkey->name);
2281*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2282*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2283*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2284*2d543d20SAndroid Build Coastguard Worker 	}
2285*2d543d20SAndroid Build Coastguard Worker 
2286*2d543d20SAndroid Build Coastguard Worker 	/* lookup module ext */
2287*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
2288*2d543d20SAndroid Build Coastguard Worker 				       *modinfo,
2289*2d543d20SAndroid Build Coastguard Worker 				       SEMANAGE_MODULE_PATH_LANG_EXT,
2290*2d543d20SAndroid Build Coastguard Worker 				       fn,
2291*2d543d20SAndroid Build Coastguard Worker 				       sizeof(fn));
2292*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2293*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2294*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2295*2d543d20SAndroid Build Coastguard Worker 	}
2296*2d543d20SAndroid Build Coastguard Worker 
2297*2d543d20SAndroid Build Coastguard Worker 	fp = fopen(fn, "r");
2298*2d543d20SAndroid Build Coastguard Worker 
2299*2d543d20SAndroid Build Coastguard Worker 	if (fp == NULL) {
2300*2d543d20SAndroid Build Coastguard Worker 		ERR(sh,
2301*2d543d20SAndroid Build Coastguard Worker 		    "Unable to open %s module lang ext file at %s.",
2302*2d543d20SAndroid Build Coastguard Worker 		    (*modinfo)->name, fn);
2303*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2304*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2305*2d543d20SAndroid Build Coastguard Worker 	}
2306*2d543d20SAndroid Build Coastguard Worker 
2307*2d543d20SAndroid Build Coastguard Worker 	/* set module ext */
2308*2d543d20SAndroid Build Coastguard Worker 	if (getline(&tmp, &size, fp) < 0) {
2309*2d543d20SAndroid Build Coastguard Worker 		ERR(sh,
2310*2d543d20SAndroid Build Coastguard Worker 		    "Unable to read %s module lang ext file.",
2311*2d543d20SAndroid Build Coastguard Worker 		    (*modinfo)->name);
2312*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2313*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2314*2d543d20SAndroid Build Coastguard Worker 	}
2315*2d543d20SAndroid Build Coastguard Worker 
2316*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_set_lang_ext(sh, *modinfo, tmp);
2317*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2318*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2319*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2320*2d543d20SAndroid Build Coastguard Worker 	}
2321*2d543d20SAndroid Build Coastguard Worker 	free(tmp);
2322*2d543d20SAndroid Build Coastguard Worker 	tmp = NULL;
2323*2d543d20SAndroid Build Coastguard Worker 
2324*2d543d20SAndroid Build Coastguard Worker 	if (fclose(fp) != 0) {
2325*2d543d20SAndroid Build Coastguard Worker 		fp = NULL;
2326*2d543d20SAndroid Build Coastguard Worker 		ERR(sh,
2327*2d543d20SAndroid Build Coastguard Worker 		    "Unable to close %s module lang ext file.",
2328*2d543d20SAndroid Build Coastguard Worker 		    (*modinfo)->name);
2329*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2330*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2331*2d543d20SAndroid Build Coastguard Worker 	}
2332*2d543d20SAndroid Build Coastguard Worker 
2333*2d543d20SAndroid Build Coastguard Worker 	fp = NULL;
2334*2d543d20SAndroid Build Coastguard Worker 
2335*2d543d20SAndroid Build Coastguard Worker 	/* lookup enabled/disabled status */
2336*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
2337*2d543d20SAndroid Build Coastguard Worker 				       *modinfo,
2338*2d543d20SAndroid Build Coastguard Worker 				       SEMANAGE_MODULE_PATH_DISABLED,
2339*2d543d20SAndroid Build Coastguard Worker 				       fn,
2340*2d543d20SAndroid Build Coastguard Worker 				       sizeof(fn));
2341*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2342*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2343*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2344*2d543d20SAndroid Build Coastguard Worker 	}
2345*2d543d20SAndroid Build Coastguard Worker 
2346*2d543d20SAndroid Build Coastguard Worker 	/* set enabled/disabled status */
2347*2d543d20SAndroid Build Coastguard Worker 	if (stat(fn, &sb) < 0) {
2348*2d543d20SAndroid Build Coastguard Worker 		if (errno != ENOENT) {
2349*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Unable to access %s: %s\n", fn, strerror(errno));
2350*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2351*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2352*2d543d20SAndroid Build Coastguard Worker 		}
2353*2d543d20SAndroid Build Coastguard Worker 
2354*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_info_set_enabled(sh, *modinfo, 1);
2355*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2356*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2357*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2358*2d543d20SAndroid Build Coastguard Worker 		}
2359*2d543d20SAndroid Build Coastguard Worker 	}
2360*2d543d20SAndroid Build Coastguard Worker 	else {
2361*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_info_set_enabled(sh, *modinfo, 0);
2362*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2363*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2364*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2365*2d543d20SAndroid Build Coastguard Worker 		}
2366*2d543d20SAndroid Build Coastguard Worker 	}
2367*2d543d20SAndroid Build Coastguard Worker 
2368*2d543d20SAndroid Build Coastguard Worker cleanup:
2369*2d543d20SAndroid Build Coastguard Worker 	free(tmp);
2370*2d543d20SAndroid Build Coastguard Worker 
2371*2d543d20SAndroid Build Coastguard Worker 	if (modinfos != NULL) {
2372*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < modinfos_len; i++) {
2373*2d543d20SAndroid Build Coastguard Worker 			semanage_module_info_destroy(sh, &modinfos[i]);
2374*2d543d20SAndroid Build Coastguard Worker 		}
2375*2d543d20SAndroid Build Coastguard Worker 		free(modinfos);
2376*2d543d20SAndroid Build Coastguard Worker 	}
2377*2d543d20SAndroid Build Coastguard Worker 
2378*2d543d20SAndroid Build Coastguard Worker 	if (fp != NULL) fclose(fp);
2379*2d543d20SAndroid Build Coastguard Worker 	return status;
2380*2d543d20SAndroid Build Coastguard Worker }
2381*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_set_module_info(semanage_handle_t * sh,const semanage_module_info_t * modinfo)2382*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_set_module_info(semanage_handle_t *sh,
2383*2d543d20SAndroid Build Coastguard Worker 					   const semanage_module_info_t *modinfo)
2384*2d543d20SAndroid Build Coastguard Worker {
2385*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2386*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2387*2d543d20SAndroid Build Coastguard Worker 
2388*2d543d20SAndroid Build Coastguard Worker 	char fn[PATH_MAX];
2389*2d543d20SAndroid Build Coastguard Worker 	const char *path = NULL;
2390*2d543d20SAndroid Build Coastguard Worker 	int enabled = 0;
2391*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfo_tmp = NULL;
2392*2d543d20SAndroid Build Coastguard Worker 
2393*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_t modkey;
2394*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_init(sh, &modkey);
2395*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2396*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2397*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2398*2d543d20SAndroid Build Coastguard Worker 	}
2399*2d543d20SAndroid Build Coastguard Worker 
2400*2d543d20SAndroid Build Coastguard Worker 	/* check transaction */
2401*2d543d20SAndroid Build Coastguard Worker 	if (!sh->is_in_transaction) {
2402*2d543d20SAndroid Build Coastguard Worker 		if (semanage_begin_transaction(sh) < 0) {
2403*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2404*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2405*2d543d20SAndroid Build Coastguard Worker 		}
2406*2d543d20SAndroid Build Coastguard Worker 	}
2407*2d543d20SAndroid Build Coastguard Worker 
2408*2d543d20SAndroid Build Coastguard Worker 	/* validate module */
2409*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_validate(modinfo);
2410*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2411*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2412*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2413*2d543d20SAndroid Build Coastguard Worker 	}
2414*2d543d20SAndroid Build Coastguard Worker 
2415*2d543d20SAndroid Build Coastguard Worker 	sh->modules_modified = 1;
2416*2d543d20SAndroid Build Coastguard Worker 
2417*2d543d20SAndroid Build Coastguard Worker 	/* check for modules path, create if missing */
2418*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
2419*2d543d20SAndroid Build Coastguard Worker 
2420*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_mkdir(sh, path);
2421*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2422*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2423*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2424*2d543d20SAndroid Build Coastguard Worker 	}
2425*2d543d20SAndroid Build Coastguard Worker 
2426*2d543d20SAndroid Build Coastguard Worker 	/* write priority */
2427*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
2428*2d543d20SAndroid Build Coastguard Worker 				       modinfo,
2429*2d543d20SAndroid Build Coastguard Worker 				       SEMANAGE_MODULE_PATH_PRIORITY,
2430*2d543d20SAndroid Build Coastguard Worker 				       fn,
2431*2d543d20SAndroid Build Coastguard Worker 				       sizeof(fn));
2432*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2433*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2434*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2435*2d543d20SAndroid Build Coastguard Worker 	}
2436*2d543d20SAndroid Build Coastguard Worker 
2437*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_mkdir(sh, fn);
2438*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2439*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2440*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2441*2d543d20SAndroid Build Coastguard Worker 	}
2442*2d543d20SAndroid Build Coastguard Worker 
2443*2d543d20SAndroid Build Coastguard Worker 	/* write name */
2444*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
2445*2d543d20SAndroid Build Coastguard Worker 				       modinfo,
2446*2d543d20SAndroid Build Coastguard Worker 				       SEMANAGE_MODULE_PATH_NAME,
2447*2d543d20SAndroid Build Coastguard Worker 				       fn,
2448*2d543d20SAndroid Build Coastguard Worker 				       sizeof(fn));
2449*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2450*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2451*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2452*2d543d20SAndroid Build Coastguard Worker 	}
2453*2d543d20SAndroid Build Coastguard Worker 
2454*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_mkdir(sh, fn);
2455*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2456*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2457*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2458*2d543d20SAndroid Build Coastguard Worker 	}
2459*2d543d20SAndroid Build Coastguard Worker 
2460*2d543d20SAndroid Build Coastguard Worker 	/* write ext */
2461*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_direct_write_langext(sh, modinfo->lang_ext, modinfo);
2462*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2463*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2464*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2465*2d543d20SAndroid Build Coastguard Worker 	}
2466*2d543d20SAndroid Build Coastguard Worker 
2467*2d543d20SAndroid Build Coastguard Worker 	/* write enabled/disabled status */
2468*2d543d20SAndroid Build Coastguard Worker 
2469*2d543d20SAndroid Build Coastguard Worker 	/* check for disabled path, create if missing */
2470*2d543d20SAndroid Build Coastguard Worker 	path = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES_DISABLED);
2471*2d543d20SAndroid Build Coastguard Worker 
2472*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_mkdir(sh, path);
2473*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2474*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2475*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2476*2d543d20SAndroid Build Coastguard Worker 	}
2477*2d543d20SAndroid Build Coastguard Worker 
2478*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(sh,
2479*2d543d20SAndroid Build Coastguard Worker 				       modinfo,
2480*2d543d20SAndroid Build Coastguard Worker 				       SEMANAGE_MODULE_PATH_DISABLED,
2481*2d543d20SAndroid Build Coastguard Worker 				       fn,
2482*2d543d20SAndroid Build Coastguard Worker 				       sizeof(fn));
2483*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2484*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2485*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2486*2d543d20SAndroid Build Coastguard Worker 	}
2487*2d543d20SAndroid Build Coastguard Worker 
2488*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_set_name(sh, &modkey, modinfo->name);
2489*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2490*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2491*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2492*2d543d20SAndroid Build Coastguard Worker 	}
2493*2d543d20SAndroid Build Coastguard Worker 
2494*2d543d20SAndroid Build Coastguard Worker 	if (modinfo->enabled == -1) {
2495*2d543d20SAndroid Build Coastguard Worker 		/* default to enabled */
2496*2d543d20SAndroid Build Coastguard Worker 		enabled = 1;
2497*2d543d20SAndroid Build Coastguard Worker 
2498*2d543d20SAndroid Build Coastguard Worker 		/* check if a module is already installed */
2499*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_get_module_info(sh,
2500*2d543d20SAndroid Build Coastguard Worker 						      &modkey,
2501*2d543d20SAndroid Build Coastguard Worker 						      &modinfo_tmp);
2502*2d543d20SAndroid Build Coastguard Worker 		if (ret == 0) {
2503*2d543d20SAndroid Build Coastguard Worker 			/* set enabled status to current one */
2504*2d543d20SAndroid Build Coastguard Worker 			enabled = modinfo_tmp->enabled;
2505*2d543d20SAndroid Build Coastguard Worker 		}
2506*2d543d20SAndroid Build Coastguard Worker 	}
2507*2d543d20SAndroid Build Coastguard Worker 	else {
2508*2d543d20SAndroid Build Coastguard Worker 		enabled = modinfo->enabled;
2509*2d543d20SAndroid Build Coastguard Worker 	}
2510*2d543d20SAndroid Build Coastguard Worker 
2511*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_set_enabled(sh, &modkey, enabled);
2512*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2513*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2514*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2515*2d543d20SAndroid Build Coastguard Worker 	}
2516*2d543d20SAndroid Build Coastguard Worker 
2517*2d543d20SAndroid Build Coastguard Worker cleanup:
2518*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_destroy(sh, &modkey);
2519*2d543d20SAndroid Build Coastguard Worker 
2520*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, modinfo_tmp);
2521*2d543d20SAndroid Build Coastguard Worker 	free(modinfo_tmp);
2522*2d543d20SAndroid Build Coastguard Worker 
2523*2d543d20SAndroid Build Coastguard Worker 	return status;
2524*2d543d20SAndroid Build Coastguard Worker }
2525*2d543d20SAndroid Build Coastguard Worker 
semanage_priorities_filename_select(const struct dirent * d)2526*2d543d20SAndroid Build Coastguard Worker static int semanage_priorities_filename_select(const struct dirent *d)
2527*2d543d20SAndroid Build Coastguard Worker {
2528*2d543d20SAndroid Build Coastguard Worker 	if (d->d_name[0] == '.' ||
2529*2d543d20SAndroid Build Coastguard Worker 	    strcmp(d->d_name, "disabled") == 0)
2530*2d543d20SAndroid Build Coastguard Worker 		return 0;
2531*2d543d20SAndroid Build Coastguard Worker 	return 1;
2532*2d543d20SAndroid Build Coastguard Worker }
2533*2d543d20SAndroid Build Coastguard Worker 
semanage_modules_filename_select(const struct dirent * d)2534*2d543d20SAndroid Build Coastguard Worker static int semanage_modules_filename_select(const struct dirent *d)
2535*2d543d20SAndroid Build Coastguard Worker {
2536*2d543d20SAndroid Build Coastguard Worker 	if (d->d_name[0] == '.')
2537*2d543d20SAndroid Build Coastguard Worker 		return 0;
2538*2d543d20SAndroid Build Coastguard Worker 	return 1;
2539*2d543d20SAndroid Build Coastguard Worker }
2540*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_list_all(semanage_handle_t * sh,semanage_module_info_t ** modinfos,int * modinfos_len)2541*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_list_all(semanage_handle_t *sh,
2542*2d543d20SAndroid Build Coastguard Worker 				    semanage_module_info_t **modinfos,
2543*2d543d20SAndroid Build Coastguard Worker 				    int *modinfos_len)
2544*2d543d20SAndroid Build Coastguard Worker {
2545*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
2546*2d543d20SAndroid Build Coastguard Worker 	assert(modinfos);
2547*2d543d20SAndroid Build Coastguard Worker 	assert(modinfos_len);
2548*2d543d20SAndroid Build Coastguard Worker 
2549*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2550*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2551*2d543d20SAndroid Build Coastguard Worker 
2552*2d543d20SAndroid Build Coastguard Worker 	int i = 0;
2553*2d543d20SAndroid Build Coastguard Worker 	int j = 0;
2554*2d543d20SAndroid Build Coastguard Worker 
2555*2d543d20SAndroid Build Coastguard Worker 	*modinfos = NULL;
2556*2d543d20SAndroid Build Coastguard Worker 	*modinfos_len = 0;
2557*2d543d20SAndroid Build Coastguard Worker 	void *tmp = NULL;
2558*2d543d20SAndroid Build Coastguard Worker 
2559*2d543d20SAndroid Build Coastguard Worker 	const char *toplevel = NULL;
2560*2d543d20SAndroid Build Coastguard Worker 
2561*2d543d20SAndroid Build Coastguard Worker 	struct dirent **priorities = NULL;
2562*2d543d20SAndroid Build Coastguard Worker 	int priorities_len = 0;
2563*2d543d20SAndroid Build Coastguard Worker 	char priority_path[PATH_MAX];
2564*2d543d20SAndroid Build Coastguard Worker 
2565*2d543d20SAndroid Build Coastguard Worker 	struct dirent **modules = NULL;
2566*2d543d20SAndroid Build Coastguard Worker 	int modules_len = 0;
2567*2d543d20SAndroid Build Coastguard Worker 
2568*2d543d20SAndroid Build Coastguard Worker 	uint16_t priority = 0;
2569*2d543d20SAndroid Build Coastguard Worker 
2570*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfo_tmp = NULL;
2571*2d543d20SAndroid Build Coastguard Worker 
2572*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t modinfo;
2573*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_init(sh, &modinfo);
2574*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2575*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2576*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2577*2d543d20SAndroid Build Coastguard Worker 	}
2578*2d543d20SAndroid Build Coastguard Worker 
2579*2d543d20SAndroid Build Coastguard Worker 	if (sh->is_in_transaction) {
2580*2d543d20SAndroid Build Coastguard Worker 		toplevel = semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES);
2581*2d543d20SAndroid Build Coastguard Worker 	} else {
2582*2d543d20SAndroid Build Coastguard Worker 		toplevel = semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
2583*2d543d20SAndroid Build Coastguard Worker 	}
2584*2d543d20SAndroid Build Coastguard Worker 
2585*2d543d20SAndroid Build Coastguard Worker 	/* find priorities */
2586*2d543d20SAndroid Build Coastguard Worker 	priorities_len = scandir(toplevel,
2587*2d543d20SAndroid Build Coastguard Worker 				 &priorities,
2588*2d543d20SAndroid Build Coastguard Worker 				 semanage_priorities_filename_select,
2589*2d543d20SAndroid Build Coastguard Worker 				 versionsort);
2590*2d543d20SAndroid Build Coastguard Worker 	if (priorities_len == -1) {
2591*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Error while scanning directory %s.", toplevel);
2592*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2593*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2594*2d543d20SAndroid Build Coastguard Worker 	}
2595*2d543d20SAndroid Build Coastguard Worker 
2596*2d543d20SAndroid Build Coastguard Worker 	/* for each priority directory */
2597*2d543d20SAndroid Build Coastguard Worker 	/* loop through in reverse so that highest priority is first */
2598*2d543d20SAndroid Build Coastguard Worker 	for (i = priorities_len - 1; i >= 0; i--) {
2599*2d543d20SAndroid Build Coastguard Worker 		/* convert priority string to uint16_t */
2600*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_string_to_priority(priorities[i]->d_name,
2601*2d543d20SAndroid Build Coastguard Worker 						  &priority);
2602*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2603*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2604*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2605*2d543d20SAndroid Build Coastguard Worker 		}
2606*2d543d20SAndroid Build Coastguard Worker 
2607*2d543d20SAndroid Build Coastguard Worker 		/* set our priority */
2608*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_info_set_priority(sh,
2609*2d543d20SAndroid Build Coastguard Worker 							&modinfo,
2610*2d543d20SAndroid Build Coastguard Worker 							priority);
2611*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2612*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2613*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2614*2d543d20SAndroid Build Coastguard Worker 		}
2615*2d543d20SAndroid Build Coastguard Worker 
2616*2d543d20SAndroid Build Coastguard Worker 		/* get the priority path */
2617*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_get_path(sh,
2618*2d543d20SAndroid Build Coastguard Worker 					       &modinfo,
2619*2d543d20SAndroid Build Coastguard Worker 					       SEMANAGE_MODULE_PATH_PRIORITY,
2620*2d543d20SAndroid Build Coastguard Worker 					       priority_path,
2621*2d543d20SAndroid Build Coastguard Worker 					       sizeof(priority_path));
2622*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2623*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2624*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2625*2d543d20SAndroid Build Coastguard Worker 		}
2626*2d543d20SAndroid Build Coastguard Worker 
2627*2d543d20SAndroid Build Coastguard Worker 		/* cleanup old modules */
2628*2d543d20SAndroid Build Coastguard Worker 		if (modules != NULL) {
2629*2d543d20SAndroid Build Coastguard Worker 			for (j = 0; j < modules_len; j++) {
2630*2d543d20SAndroid Build Coastguard Worker 				free(modules[j]);
2631*2d543d20SAndroid Build Coastguard Worker 				modules[j] = NULL;
2632*2d543d20SAndroid Build Coastguard Worker 			}
2633*2d543d20SAndroid Build Coastguard Worker 			free(modules);
2634*2d543d20SAndroid Build Coastguard Worker 			modules = NULL;
2635*2d543d20SAndroid Build Coastguard Worker 			modules_len = 0;
2636*2d543d20SAndroid Build Coastguard Worker 		}
2637*2d543d20SAndroid Build Coastguard Worker 
2638*2d543d20SAndroid Build Coastguard Worker 		/* find modules at this priority */
2639*2d543d20SAndroid Build Coastguard Worker 		modules_len = scandir(priority_path,
2640*2d543d20SAndroid Build Coastguard Worker 				      &modules,
2641*2d543d20SAndroid Build Coastguard Worker 				      semanage_modules_filename_select,
2642*2d543d20SAndroid Build Coastguard Worker 				      versionsort);
2643*2d543d20SAndroid Build Coastguard Worker 		if (modules_len == -1) {
2644*2d543d20SAndroid Build Coastguard Worker 			ERR(sh,
2645*2d543d20SAndroid Build Coastguard Worker 			    "Error while scanning directory %s.",
2646*2d543d20SAndroid Build Coastguard Worker 			    priority_path);
2647*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2648*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2649*2d543d20SAndroid Build Coastguard Worker 		}
2650*2d543d20SAndroid Build Coastguard Worker 
2651*2d543d20SAndroid Build Coastguard Worker 		if (modules_len == 0) continue;
2652*2d543d20SAndroid Build Coastguard Worker 
2653*2d543d20SAndroid Build Coastguard Worker 		/* add space for modules */
2654*2d543d20SAndroid Build Coastguard Worker 		tmp = realloc(*modinfos,
2655*2d543d20SAndroid Build Coastguard Worker 			      sizeof(semanage_module_info_t) *
2656*2d543d20SAndroid Build Coastguard Worker 				(*modinfos_len + modules_len));
2657*2d543d20SAndroid Build Coastguard Worker 		if (tmp == NULL) {
2658*2d543d20SAndroid Build Coastguard Worker 			ERR(sh, "Error allocating memory for module array.");
2659*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2660*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2661*2d543d20SAndroid Build Coastguard Worker 		}
2662*2d543d20SAndroid Build Coastguard Worker 		*modinfos = tmp;
2663*2d543d20SAndroid Build Coastguard Worker 
2664*2d543d20SAndroid Build Coastguard Worker 		/* for each module directory */
2665*2d543d20SAndroid Build Coastguard Worker 		for(j = 0; j < modules_len; j++) {
2666*2d543d20SAndroid Build Coastguard Worker 			/* set module name */
2667*2d543d20SAndroid Build Coastguard Worker 			ret = semanage_module_info_set_name(
2668*2d543d20SAndroid Build Coastguard Worker 					sh,
2669*2d543d20SAndroid Build Coastguard Worker 					&modinfo,
2670*2d543d20SAndroid Build Coastguard Worker 					modules[j]->d_name);
2671*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2672*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2673*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2674*2d543d20SAndroid Build Coastguard Worker 			}
2675*2d543d20SAndroid Build Coastguard Worker 
2676*2d543d20SAndroid Build Coastguard Worker 			/* get module values */
2677*2d543d20SAndroid Build Coastguard Worker 			ret = semanage_direct_get_module_info(
2678*2d543d20SAndroid Build Coastguard Worker 					sh,
2679*2d543d20SAndroid Build Coastguard Worker 					(const semanage_module_key_t *)
2680*2d543d20SAndroid Build Coastguard Worker 						(&modinfo),
2681*2d543d20SAndroid Build Coastguard Worker 					&modinfo_tmp);
2682*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2683*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2684*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2685*2d543d20SAndroid Build Coastguard Worker 			}
2686*2d543d20SAndroid Build Coastguard Worker 
2687*2d543d20SAndroid Build Coastguard Worker 			/* copy into array */
2688*2d543d20SAndroid Build Coastguard Worker 			ret = semanage_module_info_init(
2689*2d543d20SAndroid Build Coastguard Worker 					sh,
2690*2d543d20SAndroid Build Coastguard Worker 					&((*modinfos)[*modinfos_len]));
2691*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2692*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2693*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2694*2d543d20SAndroid Build Coastguard Worker 			}
2695*2d543d20SAndroid Build Coastguard Worker 
2696*2d543d20SAndroid Build Coastguard Worker 			ret = semanage_module_info_clone(
2697*2d543d20SAndroid Build Coastguard Worker 					sh,
2698*2d543d20SAndroid Build Coastguard Worker 					modinfo_tmp,
2699*2d543d20SAndroid Build Coastguard Worker 					&((*modinfos)[*modinfos_len]));
2700*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2701*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2702*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2703*2d543d20SAndroid Build Coastguard Worker 			}
2704*2d543d20SAndroid Build Coastguard Worker 
2705*2d543d20SAndroid Build Coastguard Worker 			semanage_module_info_destroy(sh, modinfo_tmp);
2706*2d543d20SAndroid Build Coastguard Worker 			free(modinfo_tmp);
2707*2d543d20SAndroid Build Coastguard Worker 			modinfo_tmp = NULL;
2708*2d543d20SAndroid Build Coastguard Worker 
2709*2d543d20SAndroid Build Coastguard Worker 			*modinfos_len += 1;
2710*2d543d20SAndroid Build Coastguard Worker 		}
2711*2d543d20SAndroid Build Coastguard Worker 	}
2712*2d543d20SAndroid Build Coastguard Worker 
2713*2d543d20SAndroid Build Coastguard Worker cleanup:
2714*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, &modinfo);
2715*2d543d20SAndroid Build Coastguard Worker 
2716*2d543d20SAndroid Build Coastguard Worker 	if (priorities != NULL) {
2717*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < priorities_len; i++) {
2718*2d543d20SAndroid Build Coastguard Worker 			free(priorities[i]);
2719*2d543d20SAndroid Build Coastguard Worker 		}
2720*2d543d20SAndroid Build Coastguard Worker 		free(priorities);
2721*2d543d20SAndroid Build Coastguard Worker 	}
2722*2d543d20SAndroid Build Coastguard Worker 
2723*2d543d20SAndroid Build Coastguard Worker 	if (modules != NULL) {
2724*2d543d20SAndroid Build Coastguard Worker 		for (i = 0; i < modules_len; i++) {
2725*2d543d20SAndroid Build Coastguard Worker 			free(modules[i]);
2726*2d543d20SAndroid Build Coastguard Worker 		}
2727*2d543d20SAndroid Build Coastguard Worker 		free(modules);
2728*2d543d20SAndroid Build Coastguard Worker 	}
2729*2d543d20SAndroid Build Coastguard Worker 
2730*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, modinfo_tmp);
2731*2d543d20SAndroid Build Coastguard Worker 	free(modinfo_tmp);
2732*2d543d20SAndroid Build Coastguard Worker 	modinfo_tmp = NULL;
2733*2d543d20SAndroid Build Coastguard Worker 
2734*2d543d20SAndroid Build Coastguard Worker 	if (status != 0) {
2735*2d543d20SAndroid Build Coastguard Worker 		if (modinfos != NULL) {
2736*2d543d20SAndroid Build Coastguard Worker 			for (i = 0; i < *modinfos_len; i++) {
2737*2d543d20SAndroid Build Coastguard Worker 				semanage_module_info_destroy(
2738*2d543d20SAndroid Build Coastguard Worker 						sh,
2739*2d543d20SAndroid Build Coastguard Worker 						&(*modinfos)[i]);
2740*2d543d20SAndroid Build Coastguard Worker 			}
2741*2d543d20SAndroid Build Coastguard Worker 			free(*modinfos);
2742*2d543d20SAndroid Build Coastguard Worker 			*modinfos = NULL;
2743*2d543d20SAndroid Build Coastguard Worker 			*modinfos_len = 0;
2744*2d543d20SAndroid Build Coastguard Worker 		}
2745*2d543d20SAndroid Build Coastguard Worker 	}
2746*2d543d20SAndroid Build Coastguard Worker 
2747*2d543d20SAndroid Build Coastguard Worker 	return status;
2748*2d543d20SAndroid Build Coastguard Worker }
2749*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_install_info(semanage_handle_t * sh,const semanage_module_info_t * modinfo,char * data,size_t data_len)2750*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_install_info(semanage_handle_t *sh,
2751*2d543d20SAndroid Build Coastguard Worker 					const semanage_module_info_t *modinfo,
2752*2d543d20SAndroid Build Coastguard Worker 					char *data,
2753*2d543d20SAndroid Build Coastguard Worker 					size_t data_len)
2754*2d543d20SAndroid Build Coastguard Worker {
2755*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
2756*2d543d20SAndroid Build Coastguard Worker 	assert(modinfo);
2757*2d543d20SAndroid Build Coastguard Worker 	assert(data);
2758*2d543d20SAndroid Build Coastguard Worker 
2759*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2760*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2761*2d543d20SAndroid Build Coastguard Worker 	int type;
2762*2d543d20SAndroid Build Coastguard Worker 	struct stat sb;
2763*2d543d20SAndroid Build Coastguard Worker 
2764*2d543d20SAndroid Build Coastguard Worker 	char path[PATH_MAX];
2765*2d543d20SAndroid Build Coastguard Worker 	mode_t mask = umask(0077);
2766*2d543d20SAndroid Build Coastguard Worker 
2767*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *higher_info = NULL;
2768*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_t higher_key;
2769*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_init(sh, &higher_key);
2770*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2771*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2772*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2773*2d543d20SAndroid Build Coastguard Worker 	}
2774*2d543d20SAndroid Build Coastguard Worker 
2775*2d543d20SAndroid Build Coastguard Worker 	/* validate module info */
2776*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_info_validate(modinfo);
2777*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2778*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "%s failed module validation.\n", modinfo->name);
2779*2d543d20SAndroid Build Coastguard Worker 		status = -2;
2780*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2781*2d543d20SAndroid Build Coastguard Worker 	}
2782*2d543d20SAndroid Build Coastguard Worker 
2783*2d543d20SAndroid Build Coastguard Worker 	/* Check for higher priority module and warn if there is one as
2784*2d543d20SAndroid Build Coastguard Worker 	 * it will override the module currently being installed.
2785*2d543d20SAndroid Build Coastguard Worker 	 */
2786*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_set_name(sh, &higher_key, modinfo->name);
2787*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2788*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2789*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2790*2d543d20SAndroid Build Coastguard Worker 	}
2791*2d543d20SAndroid Build Coastguard Worker 
2792*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_direct_get_module_info(sh, &higher_key, &higher_info);
2793*2d543d20SAndroid Build Coastguard Worker 	if (ret == 0) {
2794*2d543d20SAndroid Build Coastguard Worker 		if (higher_info->priority > modinfo->priority) {
2795*2d543d20SAndroid Build Coastguard Worker 			errno = 0;
2796*2d543d20SAndroid Build Coastguard Worker 			WARN(sh,
2797*2d543d20SAndroid Build Coastguard Worker 			     "A higher priority %s module exists at priority %d and will override the module currently being installed at priority %d.",
2798*2d543d20SAndroid Build Coastguard Worker 			     modinfo->name,
2799*2d543d20SAndroid Build Coastguard Worker 			     higher_info->priority,
2800*2d543d20SAndroid Build Coastguard Worker 			     modinfo->priority);
2801*2d543d20SAndroid Build Coastguard Worker 		}
2802*2d543d20SAndroid Build Coastguard Worker 		else if (higher_info->priority < modinfo->priority) {
2803*2d543d20SAndroid Build Coastguard Worker 			errno = 0;
2804*2d543d20SAndroid Build Coastguard Worker 			INFO(sh,
2805*2d543d20SAndroid Build Coastguard Worker 			     "Overriding %s module at lower priority %d with module at priority %d.",
2806*2d543d20SAndroid Build Coastguard Worker 			     modinfo->name,
2807*2d543d20SAndroid Build Coastguard Worker 			     higher_info->priority,
2808*2d543d20SAndroid Build Coastguard Worker 			     modinfo->priority);
2809*2d543d20SAndroid Build Coastguard Worker 		}
2810*2d543d20SAndroid Build Coastguard Worker 
2811*2d543d20SAndroid Build Coastguard Worker 		if (higher_info->enabled == 0 && modinfo->enabled == -1) {
2812*2d543d20SAndroid Build Coastguard Worker 			errno = 0;
2813*2d543d20SAndroid Build Coastguard Worker 			WARN(sh,
2814*2d543d20SAndroid Build Coastguard Worker 			     "%s module will be disabled after install as there is a disabled instance of this module present in the system.",
2815*2d543d20SAndroid Build Coastguard Worker 			     modinfo->name);
2816*2d543d20SAndroid Build Coastguard Worker 		}
2817*2d543d20SAndroid Build Coastguard Worker 	}
2818*2d543d20SAndroid Build Coastguard Worker 
2819*2d543d20SAndroid Build Coastguard Worker 	/* set module meta data */
2820*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_direct_set_module_info(sh, modinfo);
2821*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2822*2d543d20SAndroid Build Coastguard Worker 		status = -2;
2823*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2824*2d543d20SAndroid Build Coastguard Worker 	}
2825*2d543d20SAndroid Build Coastguard Worker 
2826*2d543d20SAndroid Build Coastguard Worker 	/* install module source file */
2827*2d543d20SAndroid Build Coastguard Worker 	if (!strcasecmp(modinfo->lang_ext, "cil")) {
2828*2d543d20SAndroid Build Coastguard Worker 		type = SEMANAGE_MODULE_PATH_CIL;
2829*2d543d20SAndroid Build Coastguard Worker 	} else {
2830*2d543d20SAndroid Build Coastguard Worker 		type = SEMANAGE_MODULE_PATH_HLL;
2831*2d543d20SAndroid Build Coastguard Worker 	}
2832*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(
2833*2d543d20SAndroid Build Coastguard Worker 			sh,
2834*2d543d20SAndroid Build Coastguard Worker 			modinfo,
2835*2d543d20SAndroid Build Coastguard Worker 			type,
2836*2d543d20SAndroid Build Coastguard Worker 			path,
2837*2d543d20SAndroid Build Coastguard Worker 			sizeof(path));
2838*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2839*2d543d20SAndroid Build Coastguard Worker 		status = -3;
2840*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2841*2d543d20SAndroid Build Coastguard Worker 	}
2842*2d543d20SAndroid Build Coastguard Worker 
2843*2d543d20SAndroid Build Coastguard Worker 	ret = write_compressed_file(sh, path, data, data_len);
2844*2d543d20SAndroid Build Coastguard Worker 	if (ret < 0) {
2845*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Error while writing to %s.", path);
2846*2d543d20SAndroid Build Coastguard Worker 		status = -3;
2847*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2848*2d543d20SAndroid Build Coastguard Worker 	}
2849*2d543d20SAndroid Build Coastguard Worker 
2850*2d543d20SAndroid Build Coastguard Worker 	/* if this is an HLL, delete the CIL cache if it exists so it will get recompiled */
2851*2d543d20SAndroid Build Coastguard Worker 	if (type == SEMANAGE_MODULE_PATH_HLL) {
2852*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_get_path(
2853*2d543d20SAndroid Build Coastguard Worker 				sh,
2854*2d543d20SAndroid Build Coastguard Worker 				modinfo,
2855*2d543d20SAndroid Build Coastguard Worker 				SEMANAGE_MODULE_PATH_CIL,
2856*2d543d20SAndroid Build Coastguard Worker 				path,
2857*2d543d20SAndroid Build Coastguard Worker 				sizeof(path));
2858*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2859*2d543d20SAndroid Build Coastguard Worker 			status = -3;
2860*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2861*2d543d20SAndroid Build Coastguard Worker 		}
2862*2d543d20SAndroid Build Coastguard Worker 
2863*2d543d20SAndroid Build Coastguard Worker 		if (stat(path, &sb) == 0) {
2864*2d543d20SAndroid Build Coastguard Worker 			ret = unlink(path);
2865*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2866*2d543d20SAndroid Build Coastguard Worker 				ERR(sh, "Error while removing cached CIL file %s: %s", path, strerror(errno));
2867*2d543d20SAndroid Build Coastguard Worker 				status = -3;
2868*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2869*2d543d20SAndroid Build Coastguard Worker 			}
2870*2d543d20SAndroid Build Coastguard Worker 		}
2871*2d543d20SAndroid Build Coastguard Worker 	}
2872*2d543d20SAndroid Build Coastguard Worker 
2873*2d543d20SAndroid Build Coastguard Worker cleanup:
2874*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_destroy(sh, &higher_key);
2875*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, higher_info);
2876*2d543d20SAndroid Build Coastguard Worker 	free(higher_info);
2877*2d543d20SAndroid Build Coastguard Worker 	umask(mask);
2878*2d543d20SAndroid Build Coastguard Worker 
2879*2d543d20SAndroid Build Coastguard Worker 	return status;
2880*2d543d20SAndroid Build Coastguard Worker }
2881*2d543d20SAndroid Build Coastguard Worker 
semanage_direct_remove_key(semanage_handle_t * sh,const semanage_module_key_t * modkey)2882*2d543d20SAndroid Build Coastguard Worker static int semanage_direct_remove_key(semanage_handle_t *sh,
2883*2d543d20SAndroid Build Coastguard Worker 				      const semanage_module_key_t *modkey)
2884*2d543d20SAndroid Build Coastguard Worker {
2885*2d543d20SAndroid Build Coastguard Worker 	assert(sh);
2886*2d543d20SAndroid Build Coastguard Worker 	assert(modkey);
2887*2d543d20SAndroid Build Coastguard Worker 
2888*2d543d20SAndroid Build Coastguard Worker 	int status = 0;
2889*2d543d20SAndroid Build Coastguard Worker 	int ret = 0;
2890*2d543d20SAndroid Build Coastguard Worker 
2891*2d543d20SAndroid Build Coastguard Worker 	char path[PATH_MAX];
2892*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_t *modinfo = NULL;
2893*2d543d20SAndroid Build Coastguard Worker 
2894*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_t modkey_tmp;
2895*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_init(sh, &modkey_tmp);
2896*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2897*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2898*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2899*2d543d20SAndroid Build Coastguard Worker 	}
2900*2d543d20SAndroid Build Coastguard Worker 
2901*2d543d20SAndroid Build Coastguard Worker 	/* validate module key */
2902*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_priority(modkey->priority);
2903*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2904*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2905*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Priority %d is invalid.", modkey->priority);
2906*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2907*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2908*2d543d20SAndroid Build Coastguard Worker 	}
2909*2d543d20SAndroid Build Coastguard Worker 
2910*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_validate_name(modkey->name);
2911*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2912*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2913*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Name %s is invalid.", modkey->name);
2914*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2915*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2916*2d543d20SAndroid Build Coastguard Worker 	}
2917*2d543d20SAndroid Build Coastguard Worker 
2918*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_key_set_name(sh, &modkey_tmp, modkey->name);
2919*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2920*2d543d20SAndroid Build Coastguard Worker 		status = -1;
2921*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2922*2d543d20SAndroid Build Coastguard Worker 	}
2923*2d543d20SAndroid Build Coastguard Worker 
2924*2d543d20SAndroid Build Coastguard Worker 	/* get module path */
2925*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_path(
2926*2d543d20SAndroid Build Coastguard Worker 			sh,
2927*2d543d20SAndroid Build Coastguard Worker 			(const semanage_module_info_t *)modkey,
2928*2d543d20SAndroid Build Coastguard Worker 			SEMANAGE_MODULE_PATH_NAME,
2929*2d543d20SAndroid Build Coastguard Worker 			path,
2930*2d543d20SAndroid Build Coastguard Worker 			sizeof(path));
2931*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2932*2d543d20SAndroid Build Coastguard Worker 		status = -2;
2933*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2934*2d543d20SAndroid Build Coastguard Worker 	}
2935*2d543d20SAndroid Build Coastguard Worker 
2936*2d543d20SAndroid Build Coastguard Worker 	/* remove directory */
2937*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_remove_directory(path);
2938*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2939*2d543d20SAndroid Build Coastguard Worker 		ERR(sh, "Unable to remove module %s at priority %d.", modkey->name, modkey->priority);
2940*2d543d20SAndroid Build Coastguard Worker 		status = -2;
2941*2d543d20SAndroid Build Coastguard Worker 		goto cleanup;
2942*2d543d20SAndroid Build Coastguard Worker 	}
2943*2d543d20SAndroid Build Coastguard Worker 
2944*2d543d20SAndroid Build Coastguard Worker 	/* check if its the last module at any priority */
2945*2d543d20SAndroid Build Coastguard Worker 	ret = semanage_module_get_module_info(sh, &modkey_tmp, &modinfo);
2946*2d543d20SAndroid Build Coastguard Worker 	if (ret != 0) {
2947*2d543d20SAndroid Build Coastguard Worker 		/* info that no other module will override */
2948*2d543d20SAndroid Build Coastguard Worker 		errno = 0;
2949*2d543d20SAndroid Build Coastguard Worker 		INFO(sh,
2950*2d543d20SAndroid Build Coastguard Worker 		     "Removing last %s module (no other %s module exists at another priority).",
2951*2d543d20SAndroid Build Coastguard Worker 		     modkey->name,
2952*2d543d20SAndroid Build Coastguard Worker 		     modkey->name);
2953*2d543d20SAndroid Build Coastguard Worker 
2954*2d543d20SAndroid Build Coastguard Worker 		/* remove disabled status file */
2955*2d543d20SAndroid Build Coastguard Worker 		ret = semanage_module_get_path(
2956*2d543d20SAndroid Build Coastguard Worker 				sh,
2957*2d543d20SAndroid Build Coastguard Worker 				(const semanage_module_info_t *)modkey,
2958*2d543d20SAndroid Build Coastguard Worker 				SEMANAGE_MODULE_PATH_DISABLED,
2959*2d543d20SAndroid Build Coastguard Worker 				path,
2960*2d543d20SAndroid Build Coastguard Worker 				sizeof(path));
2961*2d543d20SAndroid Build Coastguard Worker 		if (ret != 0) {
2962*2d543d20SAndroid Build Coastguard Worker 			status = -1;
2963*2d543d20SAndroid Build Coastguard Worker 			goto cleanup;
2964*2d543d20SAndroid Build Coastguard Worker 		}
2965*2d543d20SAndroid Build Coastguard Worker 
2966*2d543d20SAndroid Build Coastguard Worker 		struct stat sb;
2967*2d543d20SAndroid Build Coastguard Worker 		if (stat(path, &sb) == 0) {
2968*2d543d20SAndroid Build Coastguard Worker 			ret = unlink(path);
2969*2d543d20SAndroid Build Coastguard Worker 			if (ret != 0) {
2970*2d543d20SAndroid Build Coastguard Worker 				status = -1;
2971*2d543d20SAndroid Build Coastguard Worker 				goto cleanup;
2972*2d543d20SAndroid Build Coastguard Worker 			}
2973*2d543d20SAndroid Build Coastguard Worker 		}
2974*2d543d20SAndroid Build Coastguard Worker 	}
2975*2d543d20SAndroid Build Coastguard Worker 	else {
2976*2d543d20SAndroid Build Coastguard Worker 		/* if a lower priority module is going to become active */
2977*2d543d20SAndroid Build Coastguard Worker 		if (modkey->priority > modinfo->priority) {
2978*2d543d20SAndroid Build Coastguard Worker 			/* inform what the new active module will be */
2979*2d543d20SAndroid Build Coastguard Worker 			errno = 0;
2980*2d543d20SAndroid Build Coastguard Worker 			INFO(sh,
2981*2d543d20SAndroid Build Coastguard Worker 			     "%s module at priority %d is now active.",
2982*2d543d20SAndroid Build Coastguard Worker 			     modinfo->name,
2983*2d543d20SAndroid Build Coastguard Worker 			     modinfo->priority);
2984*2d543d20SAndroid Build Coastguard Worker 		}
2985*2d543d20SAndroid Build Coastguard Worker 	}
2986*2d543d20SAndroid Build Coastguard Worker 
2987*2d543d20SAndroid Build Coastguard Worker cleanup:
2988*2d543d20SAndroid Build Coastguard Worker 	semanage_module_key_destroy(sh, &modkey_tmp);
2989*2d543d20SAndroid Build Coastguard Worker 
2990*2d543d20SAndroid Build Coastguard Worker 	semanage_module_info_destroy(sh, modinfo);
2991*2d543d20SAndroid Build Coastguard Worker 	free(modinfo);
2992*2d543d20SAndroid Build Coastguard Worker 
2993*2d543d20SAndroid Build Coastguard Worker 	return status;
2994*2d543d20SAndroid Build Coastguard Worker }
2995*2d543d20SAndroid Build Coastguard Worker 
2996