Merge "Revert "Refactor neverallow tests to be parameterized""
diff --git a/hostsidetests/security/Android.bp b/hostsidetests/security/Android.bp
index b30c9f6..4798f0c 100644
--- a/hostsidetests/security/Android.bp
+++ b/hostsidetests/security/Android.bp
@@ -23,6 +23,7 @@
defaults: ["cts_defaults"],
srcs: [
"src/**/*.java",
+ ":CtsSecurityHostTestCases_LocalGeneratedSources",
],
// tag this module as a cts test artifact
test_suites: [
@@ -33,7 +34,6 @@
"cts-tradefed",
"tradefed",
"compatibility-host-util",
- "cts-host-utils",
],
java_resources: [
":plat_seapp_contexts",
@@ -60,6 +60,19 @@
target_required: ["CtsDeviceInfo"],
}
+genrule {
+ name: "CtsSecurityHostTestCases_LocalGeneratedSources",
+ tools: [
+ "SELinuxNeverallowTestGen",
+ "soong_zip",
+ ],
+ srcs: [":general_sepolicy.conf"],
+ out: ["SELinuxNeverallowRulesTest.srcjar"],
+ cmd: "mkdir -p $(genDir)/android/cts/security && " +
+ "$(location SELinuxNeverallowTestGen) $(in) $(genDir)/android/cts/security/SELinuxNeverallowRulesTest.java && " +
+ "$(location soong_zip) -jar -o $(out) -C $(genDir) -D $(genDir)",
+}
+
java_genrule_host {
name: "CtsSecurityHostTestCases_StaticLibs",
tools: [
@@ -77,7 +90,6 @@
tool_files: [
":apex_sepolicy-33.cil",
":apex_sepolicy-33.decompiled.cil",
- ":general_sepolicy.conf",
],
out: ["CtsSecurityHostTestCases_StaticLibs.jar"],
cmd: "$(location soong_zip) -jar -o $(location CtsSecurityHostTestCases_StaticLibs.jar) -j " +
@@ -91,6 +103,5 @@
"-f $(location sepolicy_tests) " +
"-f $(location treble_sepolicy_tests) " +
"-f $(location :apex_sepolicy-33.cil) " +
- "-f $(location :apex_sepolicy-33.decompiled.cil) " +
- "-f $(location :general_sepolicy.conf)",
+ "-f $(location :apex_sepolicy-33.decompiled.cil)",
}
diff --git a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java b/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java
deleted file mode 100644
index 3946185..0000000
--- a/hostsidetests/security/src/android/security/cts/SELinuxNeverallowRulesTest.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.security.cts;
-
-import static org.junit.Assert.assertTrue;
-
-import android.cts.host.utils.DeviceJUnit4ClassRunnerWithParameters;
-import android.cts.host.utils.DeviceJUnit4Parameterized;
-import android.platform.test.annotations.RestrictedBuildTest;
-
-import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
-import com.android.compatibility.common.util.PropertyUtil;
-import com.android.tradefed.build.IBuildInfo;
-import com.android.tradefed.device.ITestDevice;
-import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
-
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized.Parameter;
-import org.junit.runners.Parameterized.Parameters;
-import org.junit.runners.Parameterized.UseParametersRunnerFactory;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-/**
- * Neverallow Rules SELinux tests.
- *
- * This is a parametrised test. It extracts the neverallow rules from the
- * platform policy which is embedded in the CTS distribution. Each rule
- * generates its own test to ensure that it is not violated by the device
- * policy.
- *
- * A set of criteria can be used in the platform policy to skip the test
- * depending on the device (e.g., launching version). See sConditions below.
- *
- */
-@RunWith(DeviceJUnit4Parameterized.class)
-@UseParametersRunnerFactory(DeviceJUnit4ClassRunnerWithParameters.RunnerFactory.class)
-public class SELinuxNeverallowRulesTest extends BaseHostJUnit4Test {
- private File sepolicyAnalyze;
- private File devicePolicyFile;
- private File deviceSystemPolicyFile;
-
- private IBuildInfo mBuild;
- private int mVendorSepolicyVersion = -1;
- private int mSystemSepolicyVersion = -1;
-
- /**
- * A reference to the device under test.
- */
- private ITestDevice mDevice;
-
- private static String[] sConditions = {
- "TREBLE_ONLY",
- "COMPATIBLE_PROPERTY_ONLY",
- "LAUNCHING_WITH_R_ONLY",
- "LAUNCHING_WITH_S_ONLY",
- };
-
- private static class NeverAllowRule {
- public String mText;
- public boolean fullTrebleOnly;
- public boolean launchingWithROnly;
- public boolean launchingWithSOnly;
- public boolean compatiblePropertyOnly;
-
- NeverAllowRule(String text, HashMap<String, Integer> conditions) {
- mText = text;
- if (conditions.getOrDefault("TREBLE_ONLY", 0) > 0) {
- fullTrebleOnly = true;
- }
- if (conditions.getOrDefault("COMPATIBLE_PROPERTY_ONLY", 0) > 0) {
- compatiblePropertyOnly = true;
- }
- if (conditions.getOrDefault("LAUNCHING_WITH_R_ONLY", 0) > 0) {
- launchingWithROnly = true;
- }
- if (conditions.getOrDefault("LAUNCHING_WITH_S_ONLY", 0) > 0) {
- launchingWithSOnly = true;
- }
- }
-
- public String toString() {
- return "Rule [text= " + mText
- + ", fullTrebleOnly=" + fullTrebleOnly
- + ", compatiblePropertyOnly=" + compatiblePropertyOnly
- + ", launchingWithROnly=" + launchingWithROnly
- + ", launchingWithSOnly=" + launchingWithSOnly
- + "]";
- }
- }
-
- /**
- * Generate the test parameters based on the embedded policy (general_sepolicy.conf).
- */
- @Parameters
- public static Iterable<NeverAllowRule> generateRules() throws Exception {
- File publicPolicy = SELinuxHostTest.copyResourceToTempFile("/general_sepolicy.conf");
- String policy = Files.readString(publicPolicy.toPath());
-
- String patternConditions = Arrays.stream(sConditions)
- .flatMap(condition -> Stream.of("BEGIN_" + condition, "END_" + condition))
- .collect(Collectors.joining("|"));
-
- /* Uncomment conditions delimiter lines. */
- Pattern uncommentConditions = Pattern.compile("^\\s*#\\s*(" + patternConditions + ")\\s*$",
- Pattern.MULTILINE);
- Matcher matcher = uncommentConditions.matcher(policy);
- policy = matcher.replaceAll("$1");
-
- /* Remove all comments. */
- Pattern comments = Pattern.compile("#.*?$", Pattern.MULTILINE);
- matcher = comments.matcher(policy);
- policy = matcher.replaceAll("");
-
- /* Use a pattern to match all the neverallow rules or a condition. */
- Pattern neverAllowPattern = Pattern.compile(
- "^\\s*(neverallow\\s.+?;|" + patternConditions + ")",
- Pattern.MULTILINE | Pattern.DOTALL);
-
- ArrayList<NeverAllowRule> rules = new ArrayList();
- HashMap<String, Integer> conditions = new HashMap();
-
- matcher = neverAllowPattern.matcher(policy);
- while (matcher.find()) {
- String rule = matcher.group(1).replace("\n", " ");
- if (rule.startsWith("BEGIN_")) {
- String section = rule.substring(6);
- conditions.put(section, conditions.getOrDefault(section, 0) + 1);
- } else if (rule.startsWith("END_")) {
- String section = rule.substring(4);
- Integer v = conditions.getOrDefault(section, 0);
- assertTrue("Condition " + rule + " found without BEGIN", v > 0);
- conditions.put(section, v - 1);
- } else if (rule.startsWith("neverallow")) {
- rules.add(new NeverAllowRule(rule, conditions));
- } else {
- throw new Exception("Unknown rule: " + rule);
- }
- }
-
- for (Map.Entry<String, Integer> condition : conditions.entrySet()) {
- assertTrue("End of input while inside " + condition.getKey() + " section",
- condition.getValue() == 0);
- }
-
- assertTrue("No test generated from the CTS-embedded policy", !rules.isEmpty());
- return rules;
- }
-
- /* Parameter generated by generateRules() and available to testNeverallowRules */
- @Parameter
- public NeverAllowRule mRule;
-
- @Before
- public void setUp() throws Exception {
- mDevice = getDevice();
- mBuild = getBuild();
-
- CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
- sepolicyAnalyze = SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
- sepolicyAnalyze.setExecutable(true);
-
- devicePolicyFile = SELinuxHostTest.getDevicePolicyFile(mDevice);
-
- if (isSepolicySplit()) {
- deviceSystemPolicyFile =
- SELinuxHostTest.getDeviceSystemPolicyFile(mDevice);
-
- // Caching this variable to save time.
- if (mVendorSepolicyVersion == -1) {
- mVendorSepolicyVersion =
- SELinuxHostTest.getVendorSepolicyVersion(mBuild, mDevice);
- }
- if (mSystemSepolicyVersion == -1) {
- mSystemSepolicyVersion =
- SELinuxHostTest.getSystemSepolicyVersion(mBuild);
- }
- }
- }
-
- @After
- public void tearDown() throws Exception {
- sepolicyAnalyze.delete();
- }
-
- private boolean isFullTrebleDevice() throws Exception {
- return SELinuxHostTest.isFullTrebleDevice(mDevice);
- }
-
- private boolean isDeviceLaunchingWithR() throws Exception {
- return PropertyUtil.getFirstApiLevel(mDevice) > 29;
- }
-
- private boolean isDeviceLaunchingWithS() throws Exception {
- return PropertyUtil.getFirstApiLevel(mDevice) > 30;
- }
-
- private boolean isCompatiblePropertyEnforcedDevice() throws Exception {
- return SELinuxHostTest.isCompatiblePropertyEnforcedDevice(mDevice);
- }
-
- private boolean isSepolicySplit() throws Exception {
- return SELinuxHostTest.isSepolicySplit(mDevice);
- }
-
- @Test
- @RestrictedBuildTest
- public void testNeverallowRules() throws Exception {
-
- if ((mRule.fullTrebleOnly) && (!isFullTrebleDevice())) {
- // This test applies only to Treble devices but this device isn't one
- return;
- }
- if ((mRule.launchingWithROnly) && (!isDeviceLaunchingWithR())) {
- // This test applies only to devices launching with R or later but this device isn't one
- return;
- }
- if ((mRule.launchingWithSOnly) && (!isDeviceLaunchingWithS())) {
- // This test applies only to devices launching with S or later but this device isn't one
- return;
- }
- if ((mRule.compatiblePropertyOnly) && (!isCompatiblePropertyEnforcedDevice())) {
- // This test applies only to devices on which compatible property is enforced but this
- // device isn't one
- return;
- }
-
- // If sepolicy is split and vendor sepolicy version is behind platform's,
- // only test against platform policy.
- File policyFile =
- (isSepolicySplit() && mVendorSepolicyVersion < mSystemSepolicyVersion)
- ? deviceSystemPolicyFile : devicePolicyFile;
-
- /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- policyFile.getAbsolutePath(), "neverallow", "-n",
- mRule.mText);
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
- String line;
- StringBuilder errorString = new StringBuilder();
- while ((line = result.readLine()) != null) {
- errorString.append(line);
- errorString.append("\n");
- }
- p.waitFor();
- assertTrue("The following errors were encountered when validating the SELinux"
- + "neverallow rule:\n" + mRule.mText + "\n" + errorString,
- errorString.length() == 0);
- }
-}
diff --git a/tools/selinux/Android.bp b/tools/selinux/Android.bp
index c3bee29..1339557 100644
--- a/tools/selinux/Android.bp
+++ b/tools/selinux/Android.bp
@@ -17,6 +17,17 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+python_library_host {
+ name: "SELinuxNeverallowTestFrame",
+ srcs: ["SELinuxNeverallowTestFrame.py"],
+}
+
+python_binary_host {
+ name: "SELinuxNeverallowTestGen",
+ srcs: ["SELinuxNeverallowTestGen.py"],
+ libs: ["SELinuxNeverallowTestFrame"],
+}
+
sh_test_host {
name: "seamendc-test",
src: "seamendc-test.sh",
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
new file mode 100644
index 0000000..ad7557a
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -0,0 +1,176 @@
+#!/usr/bin/env python
+
+src_header = """/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.security.cts;
+
+import android.platform.test.annotations.RestrictedBuildTest;
+import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
+import com.android.compatibility.common.util.PropertyUtil;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.device.ITestDevice;
+import com.android.tradefed.testtype.DeviceTestCase;
+import com.android.tradefed.testtype.IBuildReceiver;
+import com.android.tradefed.testtype.IDeviceTest;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/**
+ * Neverallow Rules SELinux tests.
+ */
+public class SELinuxNeverallowRulesTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest {
+ private File sepolicyAnalyze;
+ private File devicePolicyFile;
+ private File deviceSystemPolicyFile;
+
+ private IBuildInfo mBuild;
+ private int mVendorSepolicyVersion = -1;
+ private int mSystemSepolicyVersion = -1;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setBuild(IBuildInfo build) {
+ mBuild = build;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setDevice(ITestDevice device) {
+ super.setDevice(device);
+ mDevice = device;
+ }
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
+ sepolicyAnalyze = android.security.cts.SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+
+ devicePolicyFile = android.security.cts.SELinuxHostTest.getDevicePolicyFile(mDevice);
+
+ if (isSepolicySplit()) {
+ deviceSystemPolicyFile =
+ android.security.cts.SELinuxHostTest.getDeviceSystemPolicyFile(mDevice);
+
+ // Caching this variable to save time.
+ if (mVendorSepolicyVersion == -1) {
+ mVendorSepolicyVersion =
+ android.security.cts.SELinuxHostTest.getVendorSepolicyVersion(mBuild, mDevice);
+ }
+ if (mSystemSepolicyVersion == -1) {
+ mSystemSepolicyVersion =
+ android.security.cts.SELinuxHostTest.getSystemSepolicyVersion(mBuild);
+ }
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ sepolicyAnalyze.delete();
+ }
+
+ private boolean isFullTrebleDevice() throws Exception {
+ return android.security.cts.SELinuxHostTest.isFullTrebleDevice(mDevice);
+ }
+
+ private boolean isDeviceLaunchingWithR() throws Exception {
+ return PropertyUtil.getFirstApiLevel(mDevice) > 29;
+ }
+
+ private boolean isDeviceLaunchingWithS() throws Exception {
+ return PropertyUtil.getFirstApiLevel(mDevice) > 30;
+ }
+
+ private boolean isCompatiblePropertyEnforcedDevice() throws Exception {
+ return android.security.cts.SELinuxHostTest.isCompatiblePropertyEnforcedDevice(mDevice);
+ }
+
+ private boolean isSepolicySplit() throws Exception {
+ return android.security.cts.SELinuxHostTest.isSepolicySplit(mDevice);
+ }
+"""
+src_body = ""
+src_footer = """}
+"""
+
+src_method = """
+ @RestrictedBuildTest
+ public void testNeverallowRules() throws Exception {
+ String neverallowRule = "$NEVERALLOW_RULE_HERE$";
+ boolean fullTrebleOnly = $TREBLE_ONLY_BOOL_HERE$;
+ boolean launchingWithROnly = $LAUNCHING_WITH_R_ONLY_BOOL_HERE$;
+ boolean launchingWithSOnly = $LAUNCHING_WITH_S_ONLY_BOOL_HERE$;
+ boolean compatiblePropertyOnly = $COMPATIBLE_PROPERTY_ONLY_BOOL_HERE$;
+
+ if ((fullTrebleOnly) && (!isFullTrebleDevice())) {
+ // This test applies only to Treble devices but this device isn't one
+ return;
+ }
+ if ((launchingWithROnly) && (!isDeviceLaunchingWithR())) {
+ // This test applies only to devices launching with R or later but this device isn't one
+ return;
+ }
+ if ((launchingWithSOnly) && (!isDeviceLaunchingWithS())) {
+ // This test applies only to devices launching with S or later but this device isn't one
+ return;
+ }
+ if ((compatiblePropertyOnly) && (!isCompatiblePropertyEnforcedDevice())) {
+ // This test applies only to devices on which compatible property is enforced but this
+ // device isn't one
+ return;
+ }
+
+ // If sepolicy is split and vendor sepolicy version is behind platform's,
+ // only test against platform policy.
+ File policyFile =
+ (isSepolicySplit() && mVendorSepolicyVersion < mSystemSepolicyVersion) ?
+ deviceSystemPolicyFile :
+ devicePolicyFile;
+
+ /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ policyFile.getAbsolutePath(), "neverallow", "-n",
+ neverallowRule);
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String line;
+ StringBuilder errorString = new StringBuilder();
+ while ((line = result.readLine()) != null) {
+ errorString.append(line);
+ errorString.append("\\n");
+ }
+ p.waitFor();
+ assertTrue("The following errors were encountered when validating the SELinux"
+ + "neverallow rule:\\n" + neverallowRule + "\\n" + errorString,
+ errorString.length() == 0);
+ }
+"""
diff --git a/tools/selinux/SELinuxNeverallowTestGen.py b/tools/selinux/SELinuxNeverallowTestGen.py
new file mode 100755
index 0000000..78b0631
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestGen.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+import copy
+import re
+import sys
+import SELinuxNeverallowTestFrame
+
+usage = "Usage: ./SELinuxNeverallowTestGen.py <input policy file> <output cts java source>"
+
+
+class NeverallowRule:
+ statement = ''
+ depths = None
+
+ def __init__(self, statement, depths):
+ self.statement = statement
+ self.depths = copy.deepcopy(depths)
+
+# full-Treble only tests are inside sections delimited by BEGIN_{section} and
+# END_{section} comments.
+sections = [
+ "TREBLE_ONLY",
+ "COMPATIBLE_PROPERTY_ONLY",
+ "LAUNCHING_WITH_R_ONLY",
+ "LAUNCHING_WITH_S_ONLY",
+]
+
+# extract_neverallow_rules - takes an intermediate policy file and pulls out the
+# neverallow rules by taking all of the non-commented text between the 'neverallow'
+# keyword and a terminating ';'
+# returns: a list of rules
+def extract_neverallow_rules(policy_file):
+ with open(policy_file, 'r') as in_file:
+ policy_str = in_file.read()
+
+ # uncomment section delimiter lines
+ section_headers = '|'.join(['BEGIN_%s|END_%s' % (s, s) for s in sections])
+ remaining = re.sub(
+ r'^\s*#\s*(' + section_headers + ')',
+ r'\1',
+ policy_str,
+ flags = re.M)
+ # remove comments
+ remaining = re.sub(r'#.+?$', r'', remaining, flags = re.M)
+ # match neverallow rules
+ lines = re.findall(
+ r'^\s*(neverallow\s.+?;|' + section_headers + ')',
+ remaining,
+ flags = re.M |re.S)
+
+ # extract neverallow rules from the remaining lines
+ rules = list()
+ depths = dict()
+ for section in sections:
+ depths[section] = 0
+ for line in lines:
+ is_header = False
+ for section in sections:
+ if line.startswith("BEGIN_%s" % section):
+ depths[section] += 1
+ is_header = True
+ break
+ elif line.startswith("END_%s" % section):
+ if depths[section] < 1:
+ exit("ERROR: END_%s outside of %s section" % (section, section))
+ depths[section] -= 1
+ is_header = True
+ break
+ if not is_header:
+ rule = NeverallowRule(line, depths)
+ rules.append(rule)
+
+ for section in sections:
+ if depths[section] != 0:
+ exit("ERROR: end of input while inside %s section" % section)
+
+ return rules
+
+# neverallow_rule_to_test - takes a neverallow statement and transforms it into
+# the output necessary to form a cts unit test in a java source file.
+# returns: a string representing a generic test method based on this rule.
+def neverallow_rule_to_test(rule, test_num):
+ squashed_neverallow = rule.statement.replace("\n", " ")
+ method = SELinuxNeverallowTestFrame.src_method
+ method = method.replace("testNeverallowRules()",
+ "testNeverallowRules" + str(test_num) + "()")
+ method = method.replace("$NEVERALLOW_RULE_HERE$", squashed_neverallow)
+ for section in sections:
+ method = method.replace(
+ "$%s_BOOL_HERE$" % section,
+ "true" if rule.depths[section] else "false")
+ return method
+
+if __name__ == "__main__":
+ # check usage
+ if len(sys.argv) != 3:
+ print (usage)
+ exit(1)
+ input_file = sys.argv[1]
+ output_file = sys.argv[2]
+
+ src_header = SELinuxNeverallowTestFrame.src_header
+ src_body = SELinuxNeverallowTestFrame.src_body
+ src_footer = SELinuxNeverallowTestFrame.src_footer
+
+ # grab the neverallow rules from the policy file and transform into tests
+ neverallow_rules = extract_neverallow_rules(input_file)
+ i = 0
+ for rule in neverallow_rules:
+ src_body += neverallow_rule_to_test(rule, i)
+ i += 1
+
+ with open(output_file, 'w') as out_file:
+ out_file.write(src_header)
+ out_file.write(src_body)
+ out_file.write(src_footer)