1 /*
2  * Copyright (C) 2021 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 
17 package com.android.server.permission.access
18 
19 import android.content.Context
20 import android.content.pm.PackageManager
21 import android.content.pm.PackageManagerInternal
22 import android.os.SystemProperties
23 import android.os.UserHandle
24 import com.android.internal.annotations.Keep
25 import com.android.server.LocalManagerRegistry
26 import com.android.server.LocalServices
27 import com.android.server.SystemConfig
28 import com.android.server.SystemService
29 import com.android.server.appop.AppOpsCheckingServiceInterface
30 import com.android.server.permission.access.appop.AppOpService
31 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
32 import com.android.server.permission.access.permission.PermissionService
33 import com.android.server.pm.KnownPackages
34 import com.android.server.pm.PackageManagerLocal
35 import com.android.server.pm.UserManagerService
36 import com.android.server.pm.permission.PermissionManagerServiceInterface
37 import com.android.server.pm.pkg.PackageState
38 import kotlin.contracts.ExperimentalContracts
39 import kotlin.contracts.InvocationKind
40 import kotlin.contracts.contract
41 
42 @Keep
43 class AccessCheckingService(context: Context) : SystemService(context) {
44     @Volatile
45     private lateinit var state: AccessState
46     private val stateLock = Any()
47 
48     private val policy = AccessPolicy()
49 
50     private val persistence = AccessPersistence(policy)
51 
52     private lateinit var appOpService: AppOpService
53     private lateinit var permissionService: PermissionService
54 
55     private lateinit var packageManagerInternal: PackageManagerInternal
56     private lateinit var packageManagerLocal: PackageManagerLocal
57     private lateinit var userManagerService: UserManagerService
58     private lateinit var systemConfig: SystemConfig
59 
60     override fun onStart() {
61         appOpService = AppOpService(this)
62         permissionService = PermissionService(this)
63 
64         LocalServices.addService(AppOpsCheckingServiceInterface::class.java, appOpService)
65         LocalServices.addService(PermissionManagerServiceInterface::class.java, permissionService)
66     }
67 
68     fun initialize() {
69         packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java)
70         packageManagerLocal =
71             LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
72         userManagerService = UserManagerService.getInstance()
73         systemConfig = SystemConfig.getInstance()
74 
75         val userIds = IntSet(userManagerService.userIdsIncludingPreCreated)
76         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
77         val knownPackages = packageManagerInternal.knownPackages
78         val isLeanback = systemConfig.isLeanback
79         val configPermissions = systemConfig.permissions
80         val privilegedPermissionAllowlistPackages =
81             systemConfig.privilegedPermissionAllowlistPackages
82         val permissionAllowlist = systemConfig.permissionAllowlist
83         val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions
84 
85         val state = AccessState()
86         policy.initialize(
87             state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback,
88             configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist,
89             implicitToSourcePermissions
90         )
91         persistence.initialize()
92         persistence.read(state)
93         this.state = state
94 
95         mutateState {
96             with(policy) { onInitialized() }
97         }
98 
99         appOpService.initialize()
100         permissionService.initialize()
101     }
102 
103     private val SystemConfig.isLeanback: Boolean
104         get() = PackageManager.FEATURE_LEANBACK in availableFeatures
105 
106     private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String>
107         get() = IndexedListSet<String>().apply {
108             this += "android"
109             if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) {
110                 // Note that SystemProperties.get(String, String) forces returning an empty string
111                 // even if we pass null for the def parameter.
112                 val carServicePackage = SystemProperties.get("ro.android.car.carservice.package")
113                 if (carServicePackage.isNotEmpty()) {
114                     this += carServicePackage
115                 }
116             }
117         }
118 
119     private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>
120         get() = IndexedMap<String, IndexedListSet<String>>().apply {
121             splitPermissions.forEach { splitPermissionInfo ->
122                 val sourcePermissionName = splitPermissionInfo.splitPermission
123                 splitPermissionInfo.newPermissions.forEach { implicitPermissionName ->
124                     getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName
125                 }
126             }
127         }
128 
129     fun getDecision(subject: AccessUri, `object`: AccessUri): Int =
130         getState {
131             with(policy) { getDecision(subject, `object`) }
132         }
133 
134     fun setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
135         mutateState {
136             with(policy) { setDecision(subject, `object`, decision) }
137         }
138     }
139 
140     internal fun onUserAdded(userId: Int) {
141         mutateState {
142             with(policy) { onUserAdded(userId) }
143         }
144     }
145 
146     internal fun onUserRemoved(userId: Int) {
147         mutateState {
148             with(policy) { onUserRemoved(userId) }
149         }
150     }
151 
152     internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) {
153         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
154         val knownPackages = packageManagerInternal.knownPackages
155         mutateState {
156             with(policy) {
157                 onStorageVolumeMounted(
158                     packageStates, disabledSystemPackageStates, knownPackages, volumeUuid,
159                     isSystemUpdated
160                 )
161             }
162         }
163     }
164 
165     internal fun onPackageAdded(packageName: String) {
166         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
167         val knownPackages = packageManagerInternal.knownPackages
168         mutateState {
169             with(policy) {
170                 onPackageAdded(
171                     packageStates, disabledSystemPackageStates, knownPackages, packageName
172                 )
173             }
174         }
175     }
176 
177     internal fun onPackageRemoved(packageName: String, appId: Int) {
178         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
179         val knownPackages = packageManagerInternal.knownPackages
180         mutateState {
181             with(policy) {
182                 onPackageRemoved(
183                     packageStates, disabledSystemPackageStates, knownPackages, packageName, appId
184                 )
185             }
186         }
187     }
188 
189     internal fun onPackageInstalled(packageName: String, userId: Int) {
190         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
191         val knownPackages = packageManagerInternal.knownPackages
192         mutateState {
193             with(policy) {
194                 onPackageInstalled(
195                     packageStates, disabledSystemPackageStates, knownPackages, packageName, userId
196                 )
197             }
198         }
199     }
200 
201     internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) {
202         val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
203         val knownPackages = packageManagerInternal.knownPackages
204         mutateState {
205             with(policy) {
206                 onPackageUninstalled(
207                     packageStates, disabledSystemPackageStates, knownPackages, packageName, appId,
208                     userId
209                 )
210             }
211         }
212     }
213 
214     internal fun onSystemReady() {
215         mutateState {
216             with(policy) { onSystemReady() }
217         }
218     }
219 
220     private val PackageManagerLocal.allPackageStates:
221         Pair<Map<String, PackageState>, Map<String, PackageState>>
222         get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }
223 
224     private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
225         get() = IntMap<Array<String>>().apply {
226             this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
227                 KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
228             )
229             this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
230                 KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
231             )
232             this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames(
233                 KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM
234             )
235             this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames(
236                 KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM
237             )
238             this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
239                 KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
240             )
241             this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames(
242                 KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM
243             )
244             this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
245                 KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
246             )
247             this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames(
248                 KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM
249             )
250             this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames(
251                 KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM
252             )
253             this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames(
254                 KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM
255             )
256             this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames(
257                 KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM
258             )
259         }
260 
261     @OptIn(ExperimentalContracts::class)
262     internal inline fun <T> getState(action: GetStateScope.() -> T): T {
263         contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
264         return GetStateScope(state).action()
265     }
266 
267     @OptIn(ExperimentalContracts::class)
268     internal inline fun mutateState(crossinline action: MutateStateScope.() -> Unit) {
269         contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }
270         synchronized(stateLock) {
271             val oldState = state
272             val newState = oldState.copy()
273             MutateStateScope(oldState, newState).action()
274             persistence.write(newState)
275             state = newState
276             with(policy) { GetStateScope(newState).onStateMutated() }
277         }
278     }
279 
280     internal fun getSchemePolicy(subjectScheme: String, objectScheme: String): SchemePolicy =
281         policy.getSchemePolicy(subjectScheme, objectScheme)
282 }
283