diff options
Diffstat (limited to 'tests/test-downgrade.c')
-rw-r--r-- | tests/test-downgrade.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/tests/test-downgrade.c b/tests/test-downgrade.c new file mode 100644 index 0000000..1ee7ff4 --- /dev/null +++ b/tests/test-downgrade.c @@ -0,0 +1,273 @@ +/* + * Author: Mary Garvin <mgarvin@tresys.com> + * + * Copyright (C) 2007-2008 Tresys Technology, LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "test-downgrade.h" +#include "parse_util.h" +#include "helpers.h" + +#include <sepol/debug.h> +#include <sepol/handle.h> +#include <sepol/policydb/policydb.h> +#include <sepol/policydb/link.h> +#include <sepol/policydb/expand.h> +#include <sepol/policydb/conditional.h> +#include <limits.h> +#include <CUnit/Basic.h> + +#define POLICY_BIN_HI "policies/test-downgrade/policy.hi" +#define POLICY_BIN_LO "policies/test-downgrade/policy.lo" + +static policydb_t policydb; + +/* + * Function Name: downgrade_test_init + * + * Input: None + * + * Output: None + * + * Description: Initialize the policydb (policy data base structure) + */ +int downgrade_test_init(void) +{ + /* Initialize the policydb_t structure */ + if (policydb_init(&policydb)) { + fprintf(stderr, "%s: Out of memory!\n", __FUNCTION__); + return -1; + } + + return 0; +} + +/* + * Function Name: downgrade_test_cleanup + * + * Input: None + * + * Output: None + * + * Description: Destroys policydb structure + */ +int downgrade_test_cleanup(void) +{ + policydb_destroy(&policydb); + + return 0; +} + +/* + * Function Name: downgrade_add_tests + * + * Input: CU_pSuite + * + * Output: Returns 0 upon success. Returns a CUnit error value on failure. + * + * Description: Add the given downgrade tests to the downgrade suite. + */ +int downgrade_add_tests(CU_pSuite suite) +{ + if (CU_add_test(suite, "downgrade", test_downgrade) == NULL) + return CU_get_error(); + + return 0; +} + +/* + * Function Name: test_downgrade_possible + * + * Input: None + * + * Output: None + * + * Description: + * Tests the backward compatability of MLS and Non-MLS binary policy versions. + */ +void test_downgrade(void) +{ + if (do_downgrade_test(0) < 0) + fprintf(stderr, + "\nError during downgrade testing of Non-MLS policy\n"); + + + if (do_downgrade_test(1) < 0) + fprintf(stderr, + "\nError during downgrade testing of MLS policy\n"); +} + +/* + * Function Name: do_downgrade_test + * + * Input: 0 for Non-MLS policy and 1 for MLS policy downgrade testing + * + * Output: 0 on success, negative number upon failure + * + * Description: This function handles the downgrade testing. + * A binary policy is read into the policydb structure, the + * policy version is decreased by a specific amount, written + * back out and then read back in again. The process is + * repeated until the minimum policy version is reached. + */ +int do_downgrade_test(int mls) +{ + policydb_t policydb_tmp; + int hi, lo, version; + + /* Reset policydb for re-use */ + policydb_destroy(&policydb); + downgrade_test_init(); + + /* Read in the hi policy from file */ + if (read_binary_policy(POLICY_BIN_HI, &policydb) != 0) { + fprintf(stderr, "error reading %spolicy binary\n", mls ? "mls " : ""); + CU_FAIL("Unable to read the binary policy"); + return -1; + } + + /* Change MLS value based on parameter */ + policydb.mls = mls ? 1 : 0; + + for (hi = policydb.policyvers; hi >= POLICYDB_VERSION_MIN; hi--) { + /* Stash old version number */ + version = policydb.policyvers; + + /* Try downgrading to each possible version. */ + for (lo = hi - 1; lo >= POLICYDB_VERSION_MIN; lo--) { + + /* Reduce policy version */ + policydb.policyvers = lo; + + /* Write out modified binary policy */ + if (write_binary_policy(POLICY_BIN_LO, &policydb) != 0) { + /* + * Error from MLS to pre-MLS is expected due + * to MLS re-implementation in version 19. + */ + if (mls && lo < POLICYDB_VERSION_MLS) + continue; + + fprintf(stderr, "error writing %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); + CU_FAIL("Failed to write downgraded binary policy"); + return -1; + } + + /* Make sure we can read back what we wrote. */ + if (policydb_init(&policydb_tmp)) { + fprintf(stderr, "%s: Out of memory!\n", + __FUNCTION__); + return -1; + } + if (read_binary_policy(POLICY_BIN_LO, &policydb_tmp) != 0) { + fprintf(stderr, "error reading %spolicy binary, version %d (downgraded from %d)\n", mls ? "mls " : "", lo, hi); + CU_FAIL("Unable to read downgraded binary policy"); + return -1; + } + policydb_destroy(&policydb_tmp); + } + /* Restore version number */ + policydb.policyvers = version; + } + + return 0; +} + +/* + * Function Name: read_binary_policy + * + * Input: char * which is the path to the file containing the binary policy + * + * Output: Returns 0 upon success. Upon failure, -1 is returned. + * Possible failures are, filename with given path does not exist, + * a failure to open the file, or a failure from prolicydb_read + * function call. + * + * Description: Get a filename, open file and read binary policy into policydb + * structure. + */ +int read_binary_policy(const char *path, policydb_t *p) +{ + FILE *in_fp = NULL; + struct policy_file f; + int rc; + + /* Open the binary policy file */ + if ((in_fp = fopen(path, "rb")) == NULL) { + fprintf(stderr, "Unable to open %s: %s\n", path, + strerror(errno)); + sepol_handle_destroy(f.handle); + return -1; + } + + /* Read in the binary policy. */ + memset(&f, 0, sizeof(struct policy_file)); + f.type = PF_USE_STDIO; + f.fp = in_fp; + rc = policydb_read(p, &f, 0); + + sepol_handle_destroy(f.handle); + fclose(in_fp); + return rc; +} + +/* + * Function Name: write_binary_policy + * + * Input: char * which is the path to the file containing the binary policy + * + * Output: Returns 0 upon success. Upon failure, -1 is returned. + * Possible failures are, filename with given path does not exist, + * a failure to open the file, or a failure from prolicydb_read + * function call. + * + * Description: open file and write the binary policy from policydb structure. + */ +int write_binary_policy(const char *path, policydb_t *p) +{ + FILE *out_fp = NULL; + struct policy_file f; + sepol_handle_t *handle; + int rc; + + /* We don't want libsepol to print warnings to stderr */ + handle = sepol_handle_create(); + if (handle == NULL) { + fprintf(stderr, "Out of memory!\n"); + return -1; + } + sepol_msg_set_callback(handle, NULL, NULL); + + /* Open the binary policy file for writing */ + if ((out_fp = fopen(path, "w" )) == NULL) { + fprintf(stderr, "Unable to open %s: %s\n", path, + strerror(errno)); + sepol_handle_destroy(f.handle); + return -1; + } + + /* Write the binary policy */ + memset(&f, 0, sizeof(struct policy_file)); + f.type = PF_USE_STDIO; + f.fp = out_fp; + f.handle = handle; + rc = policydb_write(p, &f); + + sepol_handle_destroy(f.handle); + fclose(out_fp); + return rc; +} |