1#!/usr/bin/env python
2
3src_header = """/*
4 * Copyright (C) 2014 The Android Open Source Project
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 *      http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19package android.security.cts;
20
21import android.platform.test.annotations.RestrictedBuildTest;
22import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
23import com.android.compatibility.common.util.PropertyUtil;
24import com.android.tradefed.build.IBuildInfo;
25import com.android.tradefed.device.ITestDevice;
26import com.android.tradefed.testtype.DeviceTestCase;
27import com.android.tradefed.testtype.IBuildReceiver;
28import com.android.tradefed.testtype.IDeviceTest;
29
30import java.io.BufferedReader;
31import java.io.File;
32import java.io.InputStream;
33import java.io.InputStreamReader;
34
35/**
36 * Neverallow Rules SELinux tests.
37 */
38public class SELinuxNeverallowRulesTest extends DeviceTestCase implements IBuildReceiver, IDeviceTest {
39    private File sepolicyAnalyze;
40    private File devicePolicyFile;
41    private File deviceSystemPolicyFile;
42
43    private IBuildInfo mBuild;
44    private int mVendorSepolicyVersion = -1;
45    private int mSystemSepolicyVersion = -1;
46
47    /**
48     * A reference to the device under test.
49     */
50    private ITestDevice mDevice;
51
52    /**
53     * {@inheritDoc}
54     */
55    @Override
56    public void setBuild(IBuildInfo build) {
57        mBuild = build;
58    }
59
60    /**
61     * {@inheritDoc}
62     */
63    @Override
64    public void setDevice(ITestDevice device) {
65        super.setDevice(device);
66        mDevice = device;
67    }
68    @Override
69    protected void setUp() throws Exception {
70        super.setUp();
71        CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(mBuild);
72        sepolicyAnalyze = android.security.cts.SELinuxHostTest.copyResourceToTempFile("/sepolicy-analyze");
73        sepolicyAnalyze.setExecutable(true);
74
75        devicePolicyFile = android.security.cts.SELinuxHostTest.getDevicePolicyFile(mDevice);
76
77        if (isSepolicySplit()) {
78            deviceSystemPolicyFile =
79                    android.security.cts.SELinuxHostTest.getDeviceSystemPolicyFile(mDevice);
80
81            // Caching this variable to save time.
82            if (mVendorSepolicyVersion == -1) {
83                mVendorSepolicyVersion =
84                        android.security.cts.SELinuxHostTest.getVendorSepolicyVersion(mBuild, mDevice);
85            }
86            if (mSystemSepolicyVersion == -1) {
87                mSystemSepolicyVersion =
88                        android.security.cts.SELinuxHostTest.getSystemSepolicyVersion(mBuild);
89            }
90        }
91    }
92
93    private boolean isFullTrebleDevice() throws Exception {
94        return android.security.cts.SELinuxHostTest.isFullTrebleDevice(mDevice);
95    }
96
97    private boolean isDeviceLaunchingWithR() throws Exception {
98        return PropertyUtil.getFirstApiLevel(mDevice) > 29;
99    }
100
101    private boolean isDeviceLaunchingWithS() throws Exception {
102        return PropertyUtil.getFirstApiLevel(mDevice) > 30;
103    }
104
105    private boolean isCompatiblePropertyEnforcedDevice() throws Exception {
106        return android.security.cts.SELinuxHostTest.isCompatiblePropertyEnforcedDevice(mDevice);
107    }
108
109    private boolean isSepolicySplit() throws Exception {
110        return android.security.cts.SELinuxHostTest.isSepolicySplit(mDevice);
111    }
112"""
113src_body = ""
114src_footer = """}
115"""
116
117src_method = """
118    @RestrictedBuildTest
119    public void testNeverallowRules() throws Exception {
120        String neverallowRule = "$NEVERALLOW_RULE_HERE$";
121        boolean fullTrebleOnly = $TREBLE_ONLY_BOOL_HERE$;
122        boolean launchingWithROnly = $LAUNCHING_WITH_R_ONLY_BOOL_HERE$;
123        boolean launchingWithSOnly = $LAUNCHING_WITH_S_ONLY_BOOL_HERE$;
124        boolean compatiblePropertyOnly = $COMPATIBLE_PROPERTY_ONLY_BOOL_HERE$;
125
126        if ((fullTrebleOnly) && (!isFullTrebleDevice())) {
127            // This test applies only to Treble devices but this device isn't one
128            return;
129        }
130        if ((launchingWithROnly) && (!isDeviceLaunchingWithR())) {
131            // This test applies only to devices launching with R or later but this device isn't one
132            return;
133        }
134        if ((launchingWithSOnly) && (!isDeviceLaunchingWithS())) {
135            // This test applies only to devices launching with S or later but this device isn't one
136            return;
137        }
138        if ((compatiblePropertyOnly) && (!isCompatiblePropertyEnforcedDevice())) {
139            // This test applies only to devices on which compatible property is enforced but this
140            // device isn't one
141            return;
142        }
143
144        // If sepolicy is split and vendor sepolicy version is behind platform's,
145        // only test against platform policy.
146        File policyFile =
147                (isSepolicySplit() && mVendorSepolicyVersion < mSystemSepolicyVersion) ?
148                deviceSystemPolicyFile :
149                devicePolicyFile;
150
151        /* run sepolicy-analyze neverallow check on policy file using given neverallow rules */
152        ProcessBuilder pb = new ProcessBuilder(sepolicyAnalyze.getAbsolutePath(),
153                policyFile.getAbsolutePath(), "neverallow", "-w", "-n",
154                neverallowRule);
155        pb.redirectOutput(ProcessBuilder.Redirect.PIPE);
156        pb.redirectErrorStream(true);
157        Process p = pb.start();
158        p.waitFor();
159        BufferedReader result = new BufferedReader(new InputStreamReader(p.getInputStream()));
160        String line;
161        StringBuilder errorString = new StringBuilder();
162        while ((line = result.readLine()) != null) {
163            errorString.append(line);
164            errorString.append("\\n");
165        }
166        assertTrue("The following errors were encountered when validating the SELinux"
167                   + "neverallow rule:\\n" + neverallowRule + "\\n" + errorString,
168                   errorString.length() == 0);
169    }
170"""
171