• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <mutex>
18 #include <include/android/permission/PermissionChecker.h>
19 #include <binder/Binder.h>
20 #include <binder/IServiceManager.h>
21 
22 #include <utils/SystemClock.h>
23 
24 #include <sys/types.h>
25 #include <private/android_filesystem_config.h>
26 
27 #ifdef LOG_TAG
28 #undef LOG_TAG
29 #endif
30 #define LOG_TAG "PermissionChecker"
31 
32 namespace android::permission {
33 
34 using android::content::AttributionSourceState;
35 
PermissionChecker()36 PermissionChecker::PermissionChecker()
37 {
38 }
39 
getService()40 sp<android::permission::IPermissionChecker> PermissionChecker::getService()
41 {
42     static String16 permission_checker("permission_checker");
43 
44     std::lock_guard<Mutex> scoped_lock(mLock);
45     int64_t startTime = 0;
46     sp<IPermissionChecker> service = mService;
47     while (service == nullptr || !IInterface::asBinder(service)->isBinderAlive()) {
48         sp<IBinder> binder = defaultServiceManager()->checkService(permission_checker);
49         if (binder == nullptr) {
50             // Wait for the permission checker service to come back...
51             if (startTime == 0) {
52                 startTime = uptimeMillis();
53                 ALOGW("Waiting for permission checker service");
54             } else if ((uptimeMillis() - startTime) > 10000) {
55                 ALOGE("Waiting too long for permission checker service, giving up");
56                 service = nullptr;
57                 break;
58             }
59             sleep(1);
60         } else {
61             mService = interface_cast<IPermissionChecker>(binder);
62             break;
63         }
64     }
65     return mService;
66 }
67 
checkPermissionForDataDeliveryFromDatasource(const String16 & permission,const AttributionSourceState & attributionSource,const String16 & message,int32_t attributedOpCode)68 PermissionChecker::PermissionResult PermissionChecker::checkPermissionForDataDeliveryFromDatasource(
69         const String16& permission, const AttributionSourceState& attributionSource,
70         const String16& message, int32_t attributedOpCode)
71 {
72     return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
73             /*startDataDelivery*/ false,/*fromDatasource*/ true, attributedOpCode);
74 }
75 
76 PermissionChecker::PermissionResult
checkPermissionForStartDataDeliveryFromDatasource(const String16 & permission,const AttributionSourceState & attributionSource,const String16 & message,int32_t attributedOpCode)77         PermissionChecker::checkPermissionForStartDataDeliveryFromDatasource(
78         const String16& permission, const AttributionSourceState& attributionSource,
79         const String16& message, int32_t attributedOpCode)
80 {
81     return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ true,
82             /*startDataDelivery*/ true, /*fromDatasource*/ true, attributedOpCode);
83 }
84 
checkPermissionForPreflight(const String16 & permission,const AttributionSourceState & attributionSource,const String16 & message,int32_t attributedOpCode)85 PermissionChecker::PermissionResult PermissionChecker::checkPermissionForPreflight(
86         const String16& permission, const AttributionSourceState& attributionSource,
87         const String16& message, int32_t attributedOpCode)
88 {
89     return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ false,
90             /*startDataDelivery*/ false, /*fromDatasource*/ false, attributedOpCode);
91 }
92 
checkPermissionForPreflightFromDatasource(const String16 & permission,const AttributionSourceState & attributionSource,const String16 & message,int32_t attributedOpCode)93 PermissionChecker::PermissionResult PermissionChecker::checkPermissionForPreflightFromDatasource(
94         const String16& permission, const AttributionSourceState& attributionSource,
95         const String16& message, int32_t attributedOpCode)
96 {
97     return checkPermission(permission, attributionSource, message, /*forDataDelivery*/ false,
98             /*startDataDelivery*/ false, /*fromDatasource*/ true, attributedOpCode);
99 }
100 
finishDataDeliveryFromDatasource(int32_t op,const AttributionSourceState & attributionSource)101 void PermissionChecker::finishDataDeliveryFromDatasource(int32_t op,
102         const AttributionSourceState& attributionSource)
103 {
104     sp<IPermissionChecker> service = getService();
105     if (service != nullptr) {
106         binder::Status status = service->finishDataDelivery(op, attributionSource,
107                 /*fromDatasource*/ true);
108         if (!status.isOk()) {
109             ALOGE("finishDataDelivery failed: %s", status.exceptionMessage().c_str());
110         }
111     }
112 }
113 
checkPermission(const String16 & permission,const AttributionSourceState & attributionSource,const String16 & message,bool forDataDelivery,bool startDataDelivery,bool fromDatasource,int32_t attributedOpCode)114 PermissionChecker::PermissionResult PermissionChecker::checkPermission(const String16& permission,
115         const AttributionSourceState& attributionSource, const String16& message,
116         bool forDataDelivery, bool startDataDelivery, bool fromDatasource,
117         int32_t attributedOpCode)
118 {
119     sp<IPermissionChecker> service = getService();
120     if (service != nullptr) {
121         int32_t result;
122         binder::Status status = service->checkPermission(permission, attributionSource, message,
123                 forDataDelivery, startDataDelivery, fromDatasource, attributedOpCode, &result);
124         if (status.isOk()) {
125             return static_cast<PermissionResult>(result);
126         }
127         ALOGE("checkPermission failed: %s", status.exceptionMessage().c_str());
128     }
129     return PERMISSION_HARD_DENIED;
130 }
131 
132 } // namespace android::permission
133