xref: /aosp_15_r20/external/selinux/libsepol/tests/test-downgrade.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1*2d543d20SAndroid Build Coastguard Worker /*
2*2d543d20SAndroid Build Coastguard Worker  * Author: Mary Garvin <[email protected]>
3*2d543d20SAndroid Build Coastguard Worker  *
4*2d543d20SAndroid Build Coastguard Worker  * Copyright (C) 2007-2008 Tresys Technology, LLC
5*2d543d20SAndroid Build Coastguard Worker  *
6*2d543d20SAndroid Build Coastguard Worker  *  This library is free software; you can redistribute it and/or
7*2d543d20SAndroid Build Coastguard Worker  *  modify it under the terms of the GNU Lesser General Public
8*2d543d20SAndroid Build Coastguard Worker  *  License as published by the Free Software Foundation; either
9*2d543d20SAndroid Build Coastguard Worker  *  version 2.1 of the License, or (at your option) any later version.
10*2d543d20SAndroid Build Coastguard Worker  *
11*2d543d20SAndroid Build Coastguard Worker  *  This library is distributed in the hope that it will be useful,
12*2d543d20SAndroid Build Coastguard Worker  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13*2d543d20SAndroid Build Coastguard Worker  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14*2d543d20SAndroid Build Coastguard Worker  *  Lesser General Public License for more details.
15*2d543d20SAndroid Build Coastguard Worker  *
16*2d543d20SAndroid Build Coastguard Worker  *  You should have received a copy of the GNU Lesser General Public
17*2d543d20SAndroid Build Coastguard Worker  *  License along with this library; if not, write to the Free Software
18*2d543d20SAndroid Build Coastguard Worker  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19*2d543d20SAndroid Build Coastguard Worker  */
20*2d543d20SAndroid Build Coastguard Worker 
21*2d543d20SAndroid Build Coastguard Worker #include "test-downgrade.h"
22*2d543d20SAndroid Build Coastguard Worker #include "parse_util.h"
23*2d543d20SAndroid Build Coastguard Worker #include "helpers.h"
24*2d543d20SAndroid Build Coastguard Worker 
25*2d543d20SAndroid Build Coastguard Worker #include <sepol/debug.h>
26*2d543d20SAndroid Build Coastguard Worker #include <sepol/handle.h>
27*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/policydb.h>
28*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/link.h>
29*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/expand.h>
30*2d543d20SAndroid Build Coastguard Worker #include <sepol/policydb/conditional.h>
31*2d543d20SAndroid Build Coastguard Worker #include <limits.h>
32*2d543d20SAndroid Build Coastguard Worker #include <CUnit/Basic.h>
33*2d543d20SAndroid Build Coastguard Worker 
34*2d543d20SAndroid Build Coastguard Worker #define POLICY_BIN_HI	"policies/test-downgrade/policy.hi"
35*2d543d20SAndroid Build Coastguard Worker #define POLICY_BIN_LO	"policies/test-downgrade/policy.lo"
36*2d543d20SAndroid Build Coastguard Worker 
37*2d543d20SAndroid Build Coastguard Worker static policydb_t policydb;
38*2d543d20SAndroid Build Coastguard Worker 
39*2d543d20SAndroid Build Coastguard Worker /*
40*2d543d20SAndroid Build Coastguard Worker  * Function Name:  downgrade_test_init
41*2d543d20SAndroid Build Coastguard Worker  *
42*2d543d20SAndroid Build Coastguard Worker  * Input: None
43*2d543d20SAndroid Build Coastguard Worker  *
44*2d543d20SAndroid Build Coastguard Worker  * Output: None
45*2d543d20SAndroid Build Coastguard Worker  *
46*2d543d20SAndroid Build Coastguard Worker  * Description: Initialize the policydb (policy data base structure)
47*2d543d20SAndroid Build Coastguard Worker  */
downgrade_test_init(void)48*2d543d20SAndroid Build Coastguard Worker int downgrade_test_init(void)
49*2d543d20SAndroid Build Coastguard Worker {
50*2d543d20SAndroid Build Coastguard Worker 	/* Initialize the policydb_t structure */
51*2d543d20SAndroid Build Coastguard Worker 	if (policydb_init(&policydb)) {
52*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
53*2d543d20SAndroid Build Coastguard Worker 		return -1;
54*2d543d20SAndroid Build Coastguard Worker 	}
55*2d543d20SAndroid Build Coastguard Worker 
56*2d543d20SAndroid Build Coastguard Worker 	return 0;
57*2d543d20SAndroid Build Coastguard Worker }
58*2d543d20SAndroid Build Coastguard Worker 
59*2d543d20SAndroid Build Coastguard Worker /*
60*2d543d20SAndroid Build Coastguard Worker  * Function Name:  downgrade_test_cleanup
61*2d543d20SAndroid Build Coastguard Worker  *
62*2d543d20SAndroid Build Coastguard Worker  * Input: None
63*2d543d20SAndroid Build Coastguard Worker  *
64*2d543d20SAndroid Build Coastguard Worker  * Output: None
65*2d543d20SAndroid Build Coastguard Worker  *
66*2d543d20SAndroid Build Coastguard Worker  * Description: Destroys policydb structure
67*2d543d20SAndroid Build Coastguard Worker  */
downgrade_test_cleanup(void)68*2d543d20SAndroid Build Coastguard Worker int downgrade_test_cleanup(void)
69*2d543d20SAndroid Build Coastguard Worker {
70*2d543d20SAndroid Build Coastguard Worker 	policydb_destroy(&policydb);
71*2d543d20SAndroid Build Coastguard Worker 
72*2d543d20SAndroid Build Coastguard Worker 	return 0;
73*2d543d20SAndroid Build Coastguard Worker }
74*2d543d20SAndroid Build Coastguard Worker 
75*2d543d20SAndroid Build Coastguard Worker /*
76*2d543d20SAndroid Build Coastguard Worker  * Function Name: downgrade_add_tests
77*2d543d20SAndroid Build Coastguard Worker  *
78*2d543d20SAndroid Build Coastguard Worker  * Input: CU_pSuite
79*2d543d20SAndroid Build Coastguard Worker  *
80*2d543d20SAndroid Build Coastguard Worker  * Output: Returns 0 upon success.  Returns a CUnit error value on failure.
81*2d543d20SAndroid Build Coastguard Worker  *
82*2d543d20SAndroid Build Coastguard Worker  * Description:  Add the given downgrade tests to the downgrade suite.
83*2d543d20SAndroid Build Coastguard Worker  */
downgrade_add_tests(CU_pSuite suite)84*2d543d20SAndroid Build Coastguard Worker int downgrade_add_tests(CU_pSuite suite)
85*2d543d20SAndroid Build Coastguard Worker {
86*2d543d20SAndroid Build Coastguard Worker 	if (CU_add_test(suite, "downgrade", test_downgrade) == NULL)
87*2d543d20SAndroid Build Coastguard Worker 		return CU_get_error();
88*2d543d20SAndroid Build Coastguard Worker 
89*2d543d20SAndroid Build Coastguard Worker 	return 0;
90*2d543d20SAndroid Build Coastguard Worker }
91*2d543d20SAndroid Build Coastguard Worker 
92*2d543d20SAndroid Build Coastguard Worker /*
93*2d543d20SAndroid Build Coastguard Worker  * Function Name:  test_downgrade_possible
94*2d543d20SAndroid Build Coastguard Worker  *
95*2d543d20SAndroid Build Coastguard Worker  * Input: None
96*2d543d20SAndroid Build Coastguard Worker  *
97*2d543d20SAndroid Build Coastguard Worker  * Output: None
98*2d543d20SAndroid Build Coastguard Worker  *
99*2d543d20SAndroid Build Coastguard Worker  * Description:
100*2d543d20SAndroid Build Coastguard Worker  * Tests the backward compatibility of MLS and Non-MLS binary policy versions.
101*2d543d20SAndroid Build Coastguard Worker  */
test_downgrade(void)102*2d543d20SAndroid Build Coastguard Worker void test_downgrade(void)
103*2d543d20SAndroid Build Coastguard Worker {
104*2d543d20SAndroid Build Coastguard Worker 	if (do_downgrade_test(0) < 0)
105*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr,
106*2d543d20SAndroid Build Coastguard Worker 		        "\nError during downgrade testing of Non-MLS policy\n");
107*2d543d20SAndroid Build Coastguard Worker 
108*2d543d20SAndroid Build Coastguard Worker 
109*2d543d20SAndroid Build Coastguard Worker 	if (do_downgrade_test(1) < 0)
110*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr,
111*2d543d20SAndroid Build Coastguard Worker 			"\nError during downgrade testing of MLS policy\n");
112*2d543d20SAndroid Build Coastguard Worker }
113*2d543d20SAndroid Build Coastguard Worker 
114*2d543d20SAndroid Build Coastguard Worker /*
115*2d543d20SAndroid Build Coastguard Worker  * Function Name:  do_downgrade_test
116*2d543d20SAndroid Build Coastguard Worker  *
117*2d543d20SAndroid Build Coastguard Worker  * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing
118*2d543d20SAndroid Build Coastguard Worker  *
119*2d543d20SAndroid Build Coastguard Worker  * Output: 0 on success, negative number upon failure
120*2d543d20SAndroid Build Coastguard Worker  *
121*2d543d20SAndroid Build Coastguard Worker  * Description: This function handles the downgrade testing.
122*2d543d20SAndroid Build Coastguard Worker  *              A binary policy is read into the policydb structure, the
123*2d543d20SAndroid Build Coastguard Worker  *              policy version is decreased by a specific amount, written
124*2d543d20SAndroid Build Coastguard Worker  *              back out and then read back in again.  The process is
125*2d543d20SAndroid Build Coastguard Worker  *              repeated until the minimum policy version is reached.
126*2d543d20SAndroid Build Coastguard Worker  */
do_downgrade_test(int mls)127*2d543d20SAndroid Build Coastguard Worker int do_downgrade_test(int mls)
128*2d543d20SAndroid Build Coastguard Worker {
129*2d543d20SAndroid Build Coastguard Worker 	policydb_t policydb_tmp;
130*2d543d20SAndroid Build Coastguard Worker 	int hi, lo, version;
131*2d543d20SAndroid Build Coastguard Worker 
132*2d543d20SAndroid Build Coastguard Worker 	/* Reset policydb for re-use */
133*2d543d20SAndroid Build Coastguard Worker 	policydb_destroy(&policydb);
134*2d543d20SAndroid Build Coastguard Worker 	downgrade_test_init();
135*2d543d20SAndroid Build Coastguard Worker 
136*2d543d20SAndroid Build Coastguard Worker 	/* Read in the hi policy from file */
137*2d543d20SAndroid Build Coastguard Worker 	if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) {
138*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "error reading %spolicy binary\n", mls ? "mls " : "");
139*2d543d20SAndroid Build Coastguard Worker 		CU_FAIL("Unable to read the binary policy");
140*2d543d20SAndroid Build Coastguard Worker 		return -1;
141*2d543d20SAndroid Build Coastguard Worker 	}
142*2d543d20SAndroid Build Coastguard Worker 
143*2d543d20SAndroid Build Coastguard Worker 	/* Change MLS value based on parameter */
144*2d543d20SAndroid Build Coastguard Worker 	policydb.mls = mls ? 1 : 0;
145*2d543d20SAndroid Build Coastguard Worker 
146*2d543d20SAndroid Build Coastguard Worker 	for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) {
147*2d543d20SAndroid Build Coastguard Worker 		/* Stash old version number */
148*2d543d20SAndroid Build Coastguard Worker 		version = policydb.policyvers;
149*2d543d20SAndroid Build Coastguard Worker 
150*2d543d20SAndroid Build Coastguard Worker 		/* Try downgrading to each possible version. */
151*2d543d20SAndroid Build Coastguard Worker 		for (lo = hi - 1; lo >= POLICYDB_VERSION_MIN; lo--) {
152*2d543d20SAndroid Build Coastguard Worker 
153*2d543d20SAndroid Build Coastguard Worker 			/* Reduce policy version */
154*2d543d20SAndroid Build Coastguard Worker 			policydb.policyvers = lo;
155*2d543d20SAndroid Build Coastguard Worker 
156*2d543d20SAndroid Build Coastguard Worker 			/* Write out modified binary policy */
157*2d543d20SAndroid Build Coastguard Worker 			if (write_binary_policy(POLICY_BIN_LO, &policydb) != 0) {
158*2d543d20SAndroid Build Coastguard Worker 				/*
159*2d543d20SAndroid Build Coastguard Worker 				 * Error from MLS to pre-MLS is expected due
160*2d543d20SAndroid Build Coastguard Worker 				 * to MLS re-implementation in version 19.
161*2d543d20SAndroid Build Coastguard Worker 				 */
162*2d543d20SAndroid Build Coastguard Worker 				if (mls && lo < POLICYDB_VERSION_MLS)
163*2d543d20SAndroid Build Coastguard Worker 					continue;
164*2d543d20SAndroid Build Coastguard Worker 
165*2d543d20SAndroid Build Coastguard Worker 				fprintf(stderr, "error writing %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi);
166*2d543d20SAndroid Build Coastguard Worker 				CU_FAIL("Failed to write downgraded binary policy");
167*2d543d20SAndroid Build Coastguard Worker 					return -1;
168*2d543d20SAndroid Build Coastguard Worker 			}
169*2d543d20SAndroid Build Coastguard Worker 
170*2d543d20SAndroid Build Coastguard Worker 			/* Make sure we can read back what we wrote. */
171*2d543d20SAndroid Build Coastguard Worker 			if (policydb_init(&policydb_tmp)) {
172*2d543d20SAndroid Build Coastguard Worker 				fprintf(stderr, "%s:  Out of memory!\n",
173*2d543d20SAndroid Build Coastguard Worker 					__FUNCTION__);
174*2d543d20SAndroid Build Coastguard Worker 				return -1;
175*2d543d20SAndroid Build Coastguard Worker 			}
176*2d543d20SAndroid Build Coastguard Worker 			if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) != 0) {
177*2d543d20SAndroid Build Coastguard Worker 				fprintf(stderr, "error reading %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi);
178*2d543d20SAndroid Build Coastguard Worker 				CU_FAIL("Unable to read downgraded binary policy");
179*2d543d20SAndroid Build Coastguard Worker 				return -1;
180*2d543d20SAndroid Build Coastguard Worker 			}
181*2d543d20SAndroid Build Coastguard Worker 			policydb_destroy(&policydb_tmp);
182*2d543d20SAndroid Build Coastguard Worker 		}
183*2d543d20SAndroid Build Coastguard Worker 		/* Restore version number */
184*2d543d20SAndroid Build Coastguard Worker 		policydb.policyvers = version;
185*2d543d20SAndroid Build Coastguard Worker     }
186*2d543d20SAndroid Build Coastguard Worker 
187*2d543d20SAndroid Build Coastguard Worker     return 0;
188*2d543d20SAndroid Build Coastguard Worker }
189*2d543d20SAndroid Build Coastguard Worker 
190*2d543d20SAndroid Build Coastguard Worker /*
191*2d543d20SAndroid Build Coastguard Worker  * Function Name: read_binary_policy
192*2d543d20SAndroid Build Coastguard Worker  *
193*2d543d20SAndroid Build Coastguard Worker  * Input: char * which is the path to the file containing the binary policy
194*2d543d20SAndroid Build Coastguard Worker  *
195*2d543d20SAndroid Build Coastguard Worker  * Output: Returns 0 upon success.  Upon failure, -1 is returned.
196*2d543d20SAndroid Build Coastguard Worker  *	   Possible failures are, filename with given path does not exist,
197*2d543d20SAndroid Build Coastguard Worker  *	   a failure to open the file, or a failure from prolicydb_read
198*2d543d20SAndroid Build Coastguard Worker  *	   function call.
199*2d543d20SAndroid Build Coastguard Worker  *
200*2d543d20SAndroid Build Coastguard Worker  * Description:  Get a filename, open file and read binary policy into policydb
201*2d543d20SAndroid Build Coastguard Worker  * 				 structure.
202*2d543d20SAndroid Build Coastguard Worker  */
read_binary_policy(const char * path,policydb_t * p)203*2d543d20SAndroid Build Coastguard Worker int read_binary_policy(const char *path, policydb_t *p)
204*2d543d20SAndroid Build Coastguard Worker {
205*2d543d20SAndroid Build Coastguard Worker 	FILE *in_fp = NULL;
206*2d543d20SAndroid Build Coastguard Worker 	struct policy_file f;
207*2d543d20SAndroid Build Coastguard Worker 	int rc;
208*2d543d20SAndroid Build Coastguard Worker 
209*2d543d20SAndroid Build Coastguard Worker 	/* Open the binary policy file */
210*2d543d20SAndroid Build Coastguard Worker 	if ((in_fp = fopen(path, "rb")) == NULL) {
211*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "Unable to open %s: %s\n", path,
212*2d543d20SAndroid Build Coastguard Worker 			strerror(errno));
213*2d543d20SAndroid Build Coastguard Worker 		return -1;
214*2d543d20SAndroid Build Coastguard Worker 	}
215*2d543d20SAndroid Build Coastguard Worker 
216*2d543d20SAndroid Build Coastguard Worker 	/* Read in the binary policy.  */
217*2d543d20SAndroid Build Coastguard Worker 	memset(&f, 0, sizeof(struct policy_file));
218*2d543d20SAndroid Build Coastguard Worker 	f.type = PF_USE_STDIO;
219*2d543d20SAndroid Build Coastguard Worker 	f.fp = in_fp;
220*2d543d20SAndroid Build Coastguard Worker 	rc = policydb_read(p, &f, 0);
221*2d543d20SAndroid Build Coastguard Worker 
222*2d543d20SAndroid Build Coastguard Worker 	fclose(in_fp);
223*2d543d20SAndroid Build Coastguard Worker 	return rc;
224*2d543d20SAndroid Build Coastguard Worker }
225*2d543d20SAndroid Build Coastguard Worker 
226*2d543d20SAndroid Build Coastguard Worker /*
227*2d543d20SAndroid Build Coastguard Worker  * Function Name: write_binary_policy
228*2d543d20SAndroid Build Coastguard Worker  *
229*2d543d20SAndroid Build Coastguard Worker  * Input: char * which is the path to the file containing the binary policy
230*2d543d20SAndroid Build Coastguard Worker  *
231*2d543d20SAndroid Build Coastguard Worker  * Output: Returns 0 upon success.  Upon failure, -1 is returned.
232*2d543d20SAndroid Build Coastguard Worker  *	   Possible failures are, filename with given path does not exist,
233*2d543d20SAndroid Build Coastguard Worker  *	   a failure to open the file, or a failure from prolicydb_read
234*2d543d20SAndroid Build Coastguard Worker  *	   function call.
235*2d543d20SAndroid Build Coastguard Worker  *
236*2d543d20SAndroid Build Coastguard Worker  * Description:  open file and write the binary policy from policydb structure.
237*2d543d20SAndroid Build Coastguard Worker  */
write_binary_policy(const char * path,policydb_t * p)238*2d543d20SAndroid Build Coastguard Worker int write_binary_policy(const char *path, policydb_t *p)
239*2d543d20SAndroid Build Coastguard Worker {
240*2d543d20SAndroid Build Coastguard Worker 	FILE *out_fp = NULL;
241*2d543d20SAndroid Build Coastguard Worker 	struct policy_file f;
242*2d543d20SAndroid Build Coastguard Worker 	sepol_handle_t *handle;
243*2d543d20SAndroid Build Coastguard Worker 	int rc;
244*2d543d20SAndroid Build Coastguard Worker 
245*2d543d20SAndroid Build Coastguard Worker 	/* We don't want libsepol to print warnings to stderr */
246*2d543d20SAndroid Build Coastguard Worker 	handle = sepol_handle_create();
247*2d543d20SAndroid Build Coastguard Worker 	if (handle == NULL) {
248*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "Out of memory!\n");
249*2d543d20SAndroid Build Coastguard Worker 		return -1;
250*2d543d20SAndroid Build Coastguard Worker 	}
251*2d543d20SAndroid Build Coastguard Worker 	sepol_msg_set_callback(handle, NULL, NULL);
252*2d543d20SAndroid Build Coastguard Worker 
253*2d543d20SAndroid Build Coastguard Worker 	/* Open the binary policy file for writing */
254*2d543d20SAndroid Build Coastguard Worker 	if ((out_fp = fopen(path, "w" )) == NULL) {
255*2d543d20SAndroid Build Coastguard Worker 		fprintf(stderr, "Unable to open %s: %s\n", path,
256*2d543d20SAndroid Build Coastguard Worker 			strerror(errno));
257*2d543d20SAndroid Build Coastguard Worker 		sepol_handle_destroy(handle);
258*2d543d20SAndroid Build Coastguard Worker 		return -1;
259*2d543d20SAndroid Build Coastguard Worker 	}
260*2d543d20SAndroid Build Coastguard Worker 
261*2d543d20SAndroid Build Coastguard Worker 	/* Write the binary policy */
262*2d543d20SAndroid Build Coastguard Worker 	memset(&f, 0, sizeof(struct policy_file));
263*2d543d20SAndroid Build Coastguard Worker 	f.type = PF_USE_STDIO;
264*2d543d20SAndroid Build Coastguard Worker 	f.fp = out_fp;
265*2d543d20SAndroid Build Coastguard Worker 	f.handle = handle;
266*2d543d20SAndroid Build Coastguard Worker 	rc = policydb_write(p, &f);
267*2d543d20SAndroid Build Coastguard Worker 
268*2d543d20SAndroid Build Coastguard Worker 	sepol_handle_destroy(f.handle);
269*2d543d20SAndroid Build Coastguard Worker 	fclose(out_fp);
270*2d543d20SAndroid Build Coastguard Worker 	return rc;
271*2d543d20SAndroid Build Coastguard Worker }
272