Split SELinux neverallow rules test.
automerge: 8e1f6e4
* commit '8e1f6e4a0868bb0bfce4341b068898ec615cd6b8':
Split SELinux neverallow rules test.
diff --git a/build/test_host_java_library.mk b/build/test_host_java_library.mk
index baf9e75..8e071e4 100644
--- a/build/test_host_java_library.mk
+++ b/build/test_host_java_library.mk
@@ -21,14 +21,18 @@
cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
-$(cts_library_xml): PRIVATE_PATH := $(LOCAL_PATH)/src
+cts_src_dirs := $(LOCAL_PATH)/src
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
+$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
$(cts_library_xml): PRIVATE_LIBRARY := $(LOCAL_MODULE)
$(cts_library_xml): PRIVATE_JAR_PATH := $(LOCAL_MODULE).jar
$(cts_library_xml): $(HOST_OUT_JAVA_LIBRARIES)/$(LOCAL_MODULE).jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
$(hide) echo Generating test description for host library $(PRIVATE_LIBRARY)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
- $(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
+ $(hide) $(CTS_JAVA_TEST_SCANNER) $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) -t hostSideOnly \
-j $(PRIVATE_JAR_PATH) \
diff --git a/build/test_package.mk b/build/test_package.mk
index 353ae07..acb8121 100644
--- a/build/test_package.mk
+++ b/build/test_package.mk
@@ -28,12 +28,16 @@
cts_package_apk := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).apk
cts_package_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_PACKAGE_NAME).xml
+cts_src_dirs := $(LOCAL_PATH)
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
$(cts_package_apk): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
$(cts_package_apk): $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME))/package.apk | $(ACP)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(ACP) -fp $(call intermediates-dir-for,APPS,$(PRIVATE_PACKAGE))/package.apk $@
-$(cts_package_xml): PRIVATE_PATH := $(LOCAL_PATH)
+$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_package_xml): PRIVATE_INSTRUMENTATION := $(LOCAL_INSTRUMENTATION_FOR)
$(cts_package_xml): PRIVATE_PACKAGE := $(LOCAL_PACKAGE_NAME)
ifneq ($(filter cts/suite/cts/%, $(LOCAL_PATH)),)
@@ -48,7 +52,7 @@
$(hide) echo Generating test description for java package $(PRIVATE_PACKAGE)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(CTS_JAVA_TEST_SCANNER) \
- -s $(PRIVATE_PATH) \
+ $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) \
-t $(PRIVATE_TEST_TYPE) \
diff --git a/build/test_uiautomator.mk b/build/test_uiautomator.mk
index 5e2f07a..085d672 100644
--- a/build/test_uiautomator.mk
+++ b/build/test_uiautomator.mk
@@ -24,12 +24,16 @@
cts_library_xml := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).xml
cts_library_jar := $(CTS_TESTCASES_OUT)/$(LOCAL_MODULE).jar
+cts_src_dirs := $(LOCAL_PATH)/src
+cts_src_dirs += $(sort $(dir $(LOCAL_GENERATED_SOURCES)))
+cts_src_dirs := $(addprefix -s , $(cts_src_dirs))
+
$(cts_library_jar): PRIVATE_MODULE := $(LOCAL_MODULE)
$(cts_library_jar): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar | $(ACP)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
$(hide) $(ACP) -fp $(call intermediates-dir-for,JAVA_LIBRARIES,$(PRIVATE_MODULE))/javalib.jar $@
-$(cts_library_xml): PRIVATE_PATH := $(LOCAL_PATH)/src
+$(cts_library_xml): PRIVATE_SRC_DIRS := $(cts_src_dirs)
$(cts_library_xml): PRIVATE_TEST_APP_PACKAGE := $(LOCAL_CTS_TEST_APP_PACKAGE)
$(cts_library_xml): PRIVATE_TEST_PACKAGE := $(LOCAL_CTS_TEST_PACKAGE)
$(cts_library_xml): PRIVATE_TEST_APK := $(LOCAL_CTS_TEST_APK)
@@ -38,7 +42,7 @@
$(cts_library_xml): $(call intermediates-dir-for,JAVA_LIBRARIES,$(LOCAL_MODULE))/javalib.jar $(CTS_EXPECTATIONS) $(CTS_UNSUPPORTED_ABIS) $(CTS_JAVA_TEST_SCANNER_DOCLET) $(CTS_JAVA_TEST_SCANNER) $(CTS_XML_GENERATOR)
$(hide) echo Generating test description for uiautomator library $(PRIVATE_LIBRARY)
$(hide) mkdir -p $(CTS_TESTCASES_OUT)
- $(hide) $(CTS_JAVA_TEST_SCANNER) -s $(PRIVATE_PATH) \
+ $(hide) $(CTS_JAVA_TEST_SCANNER) $(PRIVATE_SRC_DIRS) \
-d $(CTS_JAVA_TEST_SCANNER_DOCLET) | \
$(CTS_XML_GENERATOR) -t uiAutomator \
-i $(PRIVATE_TEST_APK) \
diff --git a/hostsidetests/security/Android.mk b/hostsidetests/security/Android.mk
index 50e0226..6ff0ebf 100644
--- a/hostsidetests/security/Android.mk
+++ b/hostsidetests/security/Android.mk
@@ -23,12 +23,26 @@
# Must match the package name in CtsTestCaseList.mk
LOCAL_MODULE := CtsSecurityHostTestCases
-LOCAL_JAVA_LIBRARIES := cts-tradefed tradefed-prebuilt
+LOCAL_MODULE_CLASS := JAVA_LIBRARIES
+
+LOCAL_JAVA_LIBRARIES := cts-tradefed ddmlib-prebuilt tradefed-prebuilt
LOCAL_CTS_TEST_PACKAGE := android.host.security
LOCAL_JAVA_RESOURCE_FILES := $(HOST_OUT_EXECUTABLES)/sepolicy-analyze
-LOCAL_JAVA_RESOURCE_FILES += $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
+
+selinux_general_policy := $(call intermediates-dir-for,ETC,general_sepolicy.conf)/general_sepolicy.conf
+
+selinux_neverallow_gen := cts/tools/selinux/SELinuxNeverallowTestGen.py
+
+selinux_neverallow_gen_data := cts/tools/selinux/SELinuxNeverallowTestFrame.py
+
+LOCAL_GENERATED_SOURCES := $(call local-generated-sources-dir)/android/cts/security/SELinuxNeverallowRulesTest.java
+
+$(LOCAL_GENERATED_SOURCES) : PRIVATE_SELINUX_GENERAL_POLICY := $(selinux_general_policy)
+$(LOCAL_GENERATED_SOURCES) : $(selinux_neverallow_gen) $(selinux_general_policy) $(selinux_neverallow_gen_data)
+ mkdir -p $(dir $@)
+ $< $(PRIVATE_SELINUX_GENERAL_POLICY) $@
include $(BUILD_CTS_HOST_JAVA_LIBRARY)
diff --git a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
index 1a88ea0..96845b1 100644
--- a/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
+++ b/hostsidetests/security/src/android/cts/security/SELinuxHostTest.java
@@ -105,32 +105,4 @@
assertTrue("The following SELinux domains were found to be in permissive mode:\n"
+ errorString, errorString.length() == 0);
}
-
- /**
- * Checks the policy running on-device against a set of neverallow rules
- *
- * @throws Exception
- */
- public void testNeverallowRules() throws Exception {
-
- File neverallowRules = copyResourceToTempFile("/general_sepolicy.conf");
-
- /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
- ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
- devicePolicyFile.getAbsolutePath(), "neverallow", "-f",
- neverallowRules.getAbsolutePath());
- pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
- pb.redirectErrorStream(true);
- Process p = pb.start();
- p.waitFor();
- 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");
- }
- assertTrue("The following errors were encountered when validating the SELinux"
- + "neverallow rules:\n" + errorString, errorString.length() == 0);
- }
}
diff --git a/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
index a843fc6..fc774e9 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/CtsJavaScanner.java
@@ -16,7 +16,9 @@
package com.android.cts.javascanner;
import java.io.File;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.List;
/**
* Class that searches a source directory for native gTests and outputs a
@@ -31,12 +33,12 @@
}
public static void main(String[] args) throws Exception {
- File sourceDir = null;
+ List<File> sourceDirs = new ArrayList<File>();
File docletPath = null;
for (int i = 0; i < args.length; i++) {
if ("-s".equals(args[i])) {
- sourceDir = new File(getArg(args, ++i, "Missing value for source directory"));
+ sourceDirs.add(new File(getArg(args, ++i, "Missing value for source directory")));
} else if ("-d".equals(args[i])) {
docletPath = new File(getArg(args, ++i, "Missing value for docletPath"));
} else {
@@ -45,7 +47,7 @@
}
}
- if (sourceDir == null) {
+ if (sourceDirs.isEmpty()) {
System.err.println("Source directory is required");
usage(args);
}
@@ -55,7 +57,7 @@
usage(args);
}
- DocletRunner runner = new DocletRunner(sourceDir, docletPath);
+ DocletRunner runner = new DocletRunner(sourceDirs, docletPath);
System.exit(runner.runJavaDoc());
}
diff --git a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
index 06951b9..94761fb 100644
--- a/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
+++ b/tools/cts-java-scanner/src/com/android/cts/javascanner/DocletRunner.java
@@ -25,11 +25,11 @@
class DocletRunner {
- private final File mSourceDir;
+ private final List<File> mSourceDirs;
private final File mDocletPath;
- DocletRunner(File sourceDir, File docletPath) {
- mSourceDir = sourceDir;
+ DocletRunner(List<File> sourceDirs, File docletPath) {
+ mSourceDirs = sourceDirs;
mDocletPath = docletPath;
}
@@ -41,10 +41,12 @@
args.add("-docletpath");
args.add(mDocletPath.toString());
args.add("-sourcepath");
- args.add(getSourcePath(mSourceDir));
+ args.add(getSourcePath(mSourceDirs));
args.add("-classpath");
args.add(getClassPath());
- args.addAll(getSourceFiles(mSourceDir));
+ for (File sourceDir : mSourceDirs) {
+ args.addAll(getSourceFiles(sourceDir));
+ }
// NOTE: We redirect the error stream to make sure the child process
@@ -67,7 +69,7 @@
return process.waitFor();
}
- private String getSourcePath(File sourceDir) {
+ private String getSourcePath(List<File> sourceDirs) {
List<String> sourcePath = new ArrayList<String>();
sourcePath.add("./frameworks/base/core/java");
sourcePath.add("./frameworks/base/test-runner/src");
@@ -77,7 +79,9 @@
sourcePath.add("./cts/tests/src");
sourcePath.add("./cts/libs/commonutil/src");
sourcePath.add("./cts/libs/deviceutil/src");
- sourcePath.add(sourceDir.toString());
+ for (File sourceDir : sourceDirs) {
+ sourcePath.add(sourceDir.toString());
+ }
return join(sourcePath, ":");
}
diff --git a/tools/selinux/SELinuxNeverallowTestFrame.py b/tools/selinux/SELinuxNeverallowTestFrame.py
new file mode 100644
index 0000000..932014a
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestFrame.py
@@ -0,0 +1,106 @@
+#!/usr/bin/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.cts.security;
+
+import com.android.cts.tradefed.build.CtsBuildHelper;
+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 java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.FileOutputStream;
+import java.lang.String;
+import java.net.URL;
+import java.util.Scanner;
+
+/**
+ * Neverallow Rules SELinux tests.
+ */
+public class SELinuxNeverallowRulesTest extends DeviceTestCase {
+ private File sepolicyAnalyze;
+ private File devicePolicyFile;
+
+ /**
+ * A reference to the device under test.
+ */
+ private ITestDevice mDevice;
+
+ private File copyResourceToTempFile(String resName) throws IOException {
+ InputStream is = this.getClass().getResourceAsStream(resName);
+ File tempFile = File.createTempFile("SELinuxHostTest", ".tmp");
+ FileOutputStream os = new FileOutputStream(tempFile);
+ int rByte = 0;
+ while ((rByte = is.read()) != -1) {
+ os.write(rByte);
+ }
+ os.flush();
+ os.close();
+ tempFile.deleteOnExit();
+ return tempFile;
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ mDevice = getDevice();
+
+ /* retrieve the sepolicy-analyze executable from jar */
+ sepolicyAnalyze = copyResourceToTempFile("/sepolicy-analyze");
+ sepolicyAnalyze.setExecutable(true);
+
+ /* obtain sepolicy file from running device */
+ devicePolicyFile = File.createTempFile("sepolicy", ".tmp");
+ devicePolicyFile.deleteOnExit();
+ mDevice.executeAdbCommand("pull", "/sys/fs/selinux/policy",
+ devicePolicyFile.getAbsolutePath());
+ }
+"""
+src_body = ""
+src_footer = """}
+"""
+
+src_method = """
+ public void testNeverallowRules() throws Exception {
+ String neverallowRule = "$NEVERALLOW_RULE_HERE$";
+
+ /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
+ ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
+ devicePolicyFile.getAbsolutePath(), "neverallow", "-n",
+ neverallowRule);
+ pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
+ pb.redirectErrorStream(true);
+ Process p = pb.start();
+ p.waitFor();
+ 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");
+ }
+ 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..9cb1e24
--- /dev/null
+++ b/tools/selinux/SELinuxNeverallowTestGen.py
@@ -0,0 +1,53 @@
+#!/usr/bin/python
+
+import re
+import sys
+import SELinuxNeverallowTestFrame
+
+usage = "Usage: ./gen_SELinux_CTS_neverallows.py <input policy file> <output cts java source>"
+
+# 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 strings representing these rules
+def extract_neverallow_rules(policy_file):
+ with open(policy_file, 'r') as in_file:
+ policy_str = in_file.read()
+ # remove comments
+ no_comments = re.sub(r'#.+?$', r'', policy_str, flags = re.M)
+ # match neverallow rules
+ return re.findall(r'(^neverallow\s.+?;)', no_comments, flags = re.M |re.S);
+
+# 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(neverallow_rule, test_num):
+ squashed_neverallow = neverallow_rule.replace("\n", " ")
+ method = SELinuxNeverallowTestFrame.src_method
+ method = method.replace("testNeverallowRules()",
+ "testNeverallowRules" + str(test_num) + "()")
+ return method.replace("$NEVERALLOW_RULE_HERE$", squashed_neverallow)
+
+if __name__ == "__main__":
+ # check usage
+ if len(sys.argv) != 3:
+ print usage
+ exit()
+ 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)