blob: 233e16c297a3003c97f432cffc582cd0a7b279d5 [file] [log] [blame]
/*
* Copyright (C) 2019 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 com.android.server.om
import android.content.om.OverlayInfo
import android.content.om.OverlayableInfo
import android.content.pm.ApplicationInfo
import android.content.pm.PackageInfo
import android.os.Process
import org.junit.Rule
import org.junit.Test
import org.junit.rules.ExpectedException
class OverlayActorEnforcerTests {
companion object {
private const val NAMESPACE = "testnamespace"
private const val ACTOR_NAME = "testactor"
private const val ACTOR_PKG_NAME = "com.test.actor.one"
private const val OVERLAYABLE_NAME = "TestOverlayable"
private const val UID = 3536
private const val USER_ID = 55
}
@get:Rule
val expectedException = ExpectedException.none()!!
@Test
fun isRoot() {
verify(callingUid = Process.ROOT_UID)
}
@Test(expected = SecurityException::class)
fun isShell() {
verify(callingUid = Process.SHELL_UID)
}
@Test
fun isSystem() {
verify(callingUid = Process.SYSTEM_UID)
}
@Test(expected = SecurityException::class)
fun noOverlayable_noTarget() {
verify(targetOverlayableName = null)
}
@Test
fun noOverlayable_noTarget_withPermission() {
verify(targetOverlayableName = null, hasPermission = true)
}
@Test(expected = SecurityException::class)
fun noOverlayable_withTarget() {
verify(targetOverlayableName = OVERLAYABLE_NAME)
}
@Test(expected = SecurityException::class)
fun withOverlayable_noTarget() {
verify(
targetOverlayableName = null,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
)
}
@Test(expected = SecurityException::class)
fun withOverlayable_noActor() {
verify(
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
)
}
@Test
fun withOverlayable_noActor_withPermission() {
verify(
hasPermission = true,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, null)
)
}
@Test(expected = SecurityException::class)
fun withOverlayable_withActor_notActor() {
verify(
isActor = false,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
"overlay://$NAMESPACE/$ACTOR_NAME")
)
}
@Test(expected = SecurityException::class)
fun withOverlayable_withActor_isActor_notPreInstalled() {
verify(
isActor = true,
isPreInstalled = false,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
"overlay://$NAMESPACE/$ACTOR_NAME")
)
}
@Test
fun withOverlayable_withActor_isActor_isPreInstalled() {
verify(
isActor = true,
isPreInstalled = true,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME,
"overlay://$NAMESPACE/$ACTOR_NAME")
)
}
@Test(expected = SecurityException::class)
fun withOverlayable_invalidActor() {
verify(
isActor = true,
isPreInstalled = true,
overlayableInfo = OverlayableInfo(OVERLAYABLE_NAME, "notValidActor")
)
}
private fun verify(
isActor: Boolean = false,
isPreInstalled: Boolean = false,
hasPermission: Boolean = false,
overlayableInfo: OverlayableInfo? = null,
callingUid: Int = UID,
targetOverlayableName: String? = OVERLAYABLE_NAME
) {
val callback = MockCallback(
isActor = isActor,
isPreInstalled = isPreInstalled,
hasPermission = hasPermission,
overlayableInfo = overlayableInfo
)
val overlayInfo = overlayInfo(targetOverlayableName)
OverlayActorEnforcer(callback)
.enforceActor(overlayInfo, "test", callingUid, USER_ID)
}
private fun overlayInfo(targetOverlayableName: String?) = OverlayInfo("com.test.overlay",
"com.test.target", targetOverlayableName, null, "/path", OverlayInfo.STATE_UNKNOWN, 0,
0, false)
private class MockCallback(
private val isActor: Boolean = false,
private val isPreInstalled: Boolean = false,
private val hasPermission: Boolean = false,
private val overlayableInfo: OverlayableInfo? = null,
private vararg val packageNames: String = arrayOf("com.test.actor.one")
) : OverlayActorEnforcer.VerifyCallback {
override fun getNamedActors() = if (isActor) {
mapOf(NAMESPACE to mapOf(ACTOR_NAME to ACTOR_PKG_NAME))
} else {
emptyMap()
}
override fun getOverlayableForTarget(
packageName: String,
targetOverlayableName: String?,
userId: Int
) = overlayableInfo
override fun getPackagesForUid(uid: Int) = when (uid) {
UID -> packageNames
else -> null
}
override fun getPackageInfo(packageName: String, userId: Int) = PackageInfo().apply {
applicationInfo = ApplicationInfo().apply {
flags = if (isPreInstalled) ApplicationInfo.FLAG_SYSTEM else 0
}
}
override fun doesTargetDefineOverlayable(targetPackageName: String?, userId: Int): Boolean {
return overlayableInfo != null
}
override fun enforcePermission(permission: String?, message: String?) {
if (!hasPermission) {
throw SecurityException()
}
}
}
}