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