blob: 233e16c297a3003c97f432cffc582cd0a7b279d5 [file] [log] [blame]
Winsond9d17362019-10-02 12:41:29 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.om
18
19import android.content.om.OverlayInfo
20import android.content.om.OverlayableInfo
21import android.content.pm.ApplicationInfo
22import android.content.pm.PackageInfo
23import android.os.Process
24import org.junit.Rule
25import org.junit.Test
26import org.junit.rules.ExpectedException
27
28class OverlayActorEnforcerTests {
29 companion object {
30 private const val NAMESPACE = "testnamespace"
31 private const val ACTOR_NAME = "testactor"
32 private const val ACTOR_PKG_NAME = "com.test.actor.one"
33 private const val OVERLAYABLE_NAME = "TestOverlayable"
34 private const val UID = 3536
35 private const val USER_ID = 55
36 }
37
38 @get:Rule
39 val expectedException = ExpectedException.none()!!
40
41 @Test
42 fun isRoot() {
43 verify(callingUid = Process.ROOT_UID)
44 }
45
46 @Test(expected = SecurityException::class)
47 fun isShell() {
48 verify(callingUid = Process.SHELL_UID)
49 }
50
51 @Test
52 fun isSystem() {
53 verify(callingUid = Process.SYSTEM_UID)
54 }
55
56 @Test(expected = SecurityException::class)
57 fun noOverlayable_noTarget() {
58 verify(targetOverlayableName = null)
59 }
60
61 @Test
62 fun noOverlayable_noTarget_withPermission() {
63 verify(targetOverlayableName = null, hasPermission = true)
64 }
65
66 @Test(expected = SecurityException::class)
67 fun noOverlayable_withTarget() {
68 verify(targetOverlayableName = OVERLAYABLE_NAME)
69 }
70
71 @Test(expected = SecurityException::class)
72 fun withOverlayable_noTarget() {
73 verify(
74 targetOverlayableName = null,
75 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
76 )
77 }
78
79 @Test(expected = SecurityException::class)
80 fun withOverlayable_noActor() {
81 verify(
82 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
83 )
84 }
85
86 @Test
87 fun withOverlayable_noActor_withPermission() {
88 verify(
89 hasPermission = true,
90 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
91 )
92 }
93
94 @Test(expected = SecurityException::class)
95 fun withOverlayable_withActor_notActor() {
96 verify(
97 isActor = false,
98 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
99 "overlay://$NAMESPACE/$ACTOR_NAME")
100 )
101 }
102
103 @Test(expected = SecurityException::class)
104 fun withOverlayable_withActor_isActor_notPreInstalled() {
105 verify(
106 isActor = true,
107 isPreInstalled = false,
108 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
109 "overlay://$NAMESPACE/$ACTOR_NAME")
110 )
111 }
112
113 @Test
114 fun withOverlayable_withActor_isActor_isPreInstalled() {
115 verify(
116 isActor = true,
117 isPreInstalled = true,
118 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
119 "overlay://$NAMESPACE/$ACTOR_NAME")
120 )
121 }
122
123 @Test(expected = SecurityException::class)
124 fun withOverlayable_invalidActor() {
125 verify(
126 isActor = true,
127 isPreInstalled = true,
128 overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor")
129 )
130 }
131
132 private fun verify(
133 isActor: Boolean = false,
134 isPreInstalled: Boolean = false,
135 hasPermission: Boolean = false,
136 overlayableInfo: OverlayableInfo? = null,
137 callingUid: Int = UID,
138 targetOverlayableName: String? = OVERLAYABLE_NAME
139 ) {
140 val callback = MockCallback(
141 isActor = isActor,
142 isPreInstalled = isPreInstalled,
143 hasPermission = hasPermission,
144 overlayableInfo = overlayableInfo
145 )
146
147 val overlayInfo = overlayInfo(targetOverlayableName)
148 OverlayActorEnforcer(callback)
149 .enforceActor(overlayInfo, "test", callingUid, USER_ID)
150 }
151
152 private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay",
153 "com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0,
154 0, false)
155
156 private class MockCallback(
157 private val isActor: Boolean = false,
158 private val isPreInstalled: Boolean = false,
159 private val hasPermission: Boolean = false,
160 private val overlayableInfo: OverlayableInfo? = null,
161 private vararg val packageNames: String = arrayOf("com.test.actor.one")
162 ) : OverlayActorEnforcer.VerifyCallback {
163
164 override fun getNamedActors() = if (isActor) {
165 mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
166 } else {
167 emptyMap()
168 }
169
170 override fun getOverlayableForTarget(
171 packageName: String,
172 targetOverlayableName: String?,
173 userId: Int
174 ) = overlayableInfo
175
176 override fun getPackagesForUid(uid: Int) = when (uid) {
177 UID -> packageNames
178 else -> null
179 }
180
181 override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply {
182 applicationInfo = ApplicationInfo().apply {
183 flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0
184 }
185 }
186
187 override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean {
188 return overlayableInfo != null
189 }
190
191 override fun enforcePermission(permission: String?, message: String?) {
192 if (!hasPermission) {
193 throw SecurityException()
194 }
195 }
196 }
197}