xref: /aosp_15_r20/frameworks/av/media/libaudiopermission/NativePermissionController.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2024 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker #include <media/NativePermissionController.h>
18*ec779b8eSAndroid Build Coastguard Worker 
19*ec779b8eSAndroid Build Coastguard Worker #include <algorithm>
20*ec779b8eSAndroid Build Coastguard Worker #include <optional>
21*ec779b8eSAndroid Build Coastguard Worker #include <utility>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <android-base/expected.h>
24*ec779b8eSAndroid Build Coastguard Worker #include <cutils/android_filesystem_config.h>
25*ec779b8eSAndroid Build Coastguard Worker #include <utils/Errors.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker using ::android::binder::Status;
28*ec779b8eSAndroid Build Coastguard Worker using ::android::error::BinderResult;
29*ec779b8eSAndroid Build Coastguard Worker using ::android::error::unexpectedExceptionCode;
30*ec779b8eSAndroid Build Coastguard Worker 
31*ec779b8eSAndroid Build Coastguard Worker namespace com::android::media::permission {
getFixedPackageName(uid_t uid)32*ec779b8eSAndroid Build Coastguard Worker static std::optional<std::string> getFixedPackageName(uid_t uid) {
33*ec779b8eSAndroid Build Coastguard Worker     // These values are in sync with AppOpsService
34*ec779b8eSAndroid Build Coastguard Worker     switch (uid % AID_USER_OFFSET) {
35*ec779b8eSAndroid Build Coastguard Worker         case AID_ROOT:
36*ec779b8eSAndroid Build Coastguard Worker             return "root";
37*ec779b8eSAndroid Build Coastguard Worker         case AID_SYSTEM:
38*ec779b8eSAndroid Build Coastguard Worker             return "system";
39*ec779b8eSAndroid Build Coastguard Worker         case AID_SHELL:
40*ec779b8eSAndroid Build Coastguard Worker             return "shell";
41*ec779b8eSAndroid Build Coastguard Worker         case AID_MEDIA:
42*ec779b8eSAndroid Build Coastguard Worker             return "media";
43*ec779b8eSAndroid Build Coastguard Worker         case AID_AUDIOSERVER:
44*ec779b8eSAndroid Build Coastguard Worker             return "audioserver";
45*ec779b8eSAndroid Build Coastguard Worker         case AID_CAMERASERVER:
46*ec779b8eSAndroid Build Coastguard Worker             return "cameraserver";
47*ec779b8eSAndroid Build Coastguard Worker         default:
48*ec779b8eSAndroid Build Coastguard Worker             return std::nullopt;
49*ec779b8eSAndroid Build Coastguard Worker     }
50*ec779b8eSAndroid Build Coastguard Worker }
51*ec779b8eSAndroid Build Coastguard Worker 
52*ec779b8eSAndroid Build Coastguard Worker // -- Begin Binder methods
populatePackagesForUids(const std::vector<UidPackageState> & initialPackageStates)53*ec779b8eSAndroid Build Coastguard Worker Status NativePermissionController::populatePackagesForUids(
54*ec779b8eSAndroid Build Coastguard Worker         const std::vector<UidPackageState>& initialPackageStates) {
55*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
56*ec779b8eSAndroid Build Coastguard Worker     if (!is_package_populated_) is_package_populated_ = true;
57*ec779b8eSAndroid Build Coastguard Worker     package_map_.clear();
58*ec779b8eSAndroid Build Coastguard Worker     std::transform(initialPackageStates.begin(), initialPackageStates.end(),
59*ec779b8eSAndroid Build Coastguard Worker                    std::inserter(package_map_, package_map_.end()),
60*ec779b8eSAndroid Build Coastguard Worker                    [](const auto& x) -> std::pair<uid_t, std::vector<std::string>> {
61*ec779b8eSAndroid Build Coastguard Worker                        return {x.uid, x.packageNames};
62*ec779b8eSAndroid Build Coastguard Worker                    });
63*ec779b8eSAndroid Build Coastguard Worker     std::erase_if(package_map_, [](const auto& x) { return x.second.empty(); });
64*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
65*ec779b8eSAndroid Build Coastguard Worker }
66*ec779b8eSAndroid Build Coastguard Worker 
updatePackagesForUid(const UidPackageState & newPackageState)67*ec779b8eSAndroid Build Coastguard Worker Status NativePermissionController::updatePackagesForUid(const UidPackageState& newPackageState) {
68*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
69*ec779b8eSAndroid Build Coastguard Worker     package_map_.insert_or_assign(newPackageState.uid, newPackageState.packageNames);
70*ec779b8eSAndroid Build Coastguard Worker     const auto& cursor = package_map_.find(newPackageState.uid);
71*ec779b8eSAndroid Build Coastguard Worker 
72*ec779b8eSAndroid Build Coastguard Worker     if (newPackageState.packageNames.empty()) {
73*ec779b8eSAndroid Build Coastguard Worker         if (cursor != package_map_.end()) {
74*ec779b8eSAndroid Build Coastguard Worker             package_map_.erase(cursor);
75*ec779b8eSAndroid Build Coastguard Worker         }
76*ec779b8eSAndroid Build Coastguard Worker     } else {
77*ec779b8eSAndroid Build Coastguard Worker         if (cursor != package_map_.end()) {
78*ec779b8eSAndroid Build Coastguard Worker             cursor->second = newPackageState.packageNames;
79*ec779b8eSAndroid Build Coastguard Worker         } else {
80*ec779b8eSAndroid Build Coastguard Worker             package_map_.insert({newPackageState.uid, newPackageState.packageNames});
81*ec779b8eSAndroid Build Coastguard Worker         }
82*ec779b8eSAndroid Build Coastguard Worker     }
83*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
84*ec779b8eSAndroid Build Coastguard Worker }
85*ec779b8eSAndroid Build Coastguard Worker 
populatePermissionState(PermissionEnum perm,const std::vector<int> & uids)86*ec779b8eSAndroid Build Coastguard Worker Status NativePermissionController::populatePermissionState(PermissionEnum perm,
87*ec779b8eSAndroid Build Coastguard Worker                                                            const std::vector<int>& uids) {
88*ec779b8eSAndroid Build Coastguard Worker     if (perm >= PermissionEnum::ENUM_SIZE || static_cast<int>(perm) < 0) {
89*ec779b8eSAndroid Build Coastguard Worker         return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
90*ec779b8eSAndroid Build Coastguard Worker     }
91*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
92*ec779b8eSAndroid Build Coastguard Worker     auto& cursor = permission_map_[static_cast<size_t>(perm)];
93*ec779b8eSAndroid Build Coastguard Worker     cursor = std::vector<uid_t>{uids.begin(), uids.end()};
94*ec779b8eSAndroid Build Coastguard Worker     // should be sorted
95*ec779b8eSAndroid Build Coastguard Worker     std::sort(cursor.begin(), cursor.end());
96*ec779b8eSAndroid Build Coastguard Worker     return Status::ok();
97*ec779b8eSAndroid Build Coastguard Worker }
98*ec779b8eSAndroid Build Coastguard Worker 
99*ec779b8eSAndroid Build Coastguard Worker // -- End Binder methods
100*ec779b8eSAndroid Build Coastguard Worker 
getPackagesForUid(uid_t uid) const101*ec779b8eSAndroid Build Coastguard Worker BinderResult<std::vector<std::string>> NativePermissionController::getPackagesForUid(
102*ec779b8eSAndroid Build Coastguard Worker         uid_t uid) const {
103*ec779b8eSAndroid Build Coastguard Worker     uid = uid % AID_USER_OFFSET;
104*ec779b8eSAndroid Build Coastguard Worker     const auto fixed_package_opt = getFixedPackageName(uid);
105*ec779b8eSAndroid Build Coastguard Worker     if (fixed_package_opt.has_value()) {
106*ec779b8eSAndroid Build Coastguard Worker         return BinderResult<std::vector<std::string>>{std::in_place_t{},
107*ec779b8eSAndroid Build Coastguard Worker                                                       {fixed_package_opt.value()}};
108*ec779b8eSAndroid Build Coastguard Worker     }
109*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
110*ec779b8eSAndroid Build Coastguard Worker     if (!is_package_populated_) {
111*ec779b8eSAndroid Build Coastguard Worker         return unexpectedExceptionCode(
112*ec779b8eSAndroid Build Coastguard Worker                 Status::EX_ILLEGAL_STATE,
113*ec779b8eSAndroid Build Coastguard Worker                 "NPC::getPackagesForUid: controller never populated by system_server");
114*ec779b8eSAndroid Build Coastguard Worker     }
115*ec779b8eSAndroid Build Coastguard Worker     const auto cursor = package_map_.find(uid);
116*ec779b8eSAndroid Build Coastguard Worker     if (cursor != package_map_.end()) {
117*ec779b8eSAndroid Build Coastguard Worker         return cursor->second;
118*ec779b8eSAndroid Build Coastguard Worker     } else {
119*ec779b8eSAndroid Build Coastguard Worker         return unexpectedExceptionCode(
120*ec779b8eSAndroid Build Coastguard Worker                 Status::EX_ILLEGAL_ARGUMENT,
121*ec779b8eSAndroid Build Coastguard Worker                 ("NPC::getPackagesForUid: uid not found: " + std::to_string(uid)).c_str());
122*ec779b8eSAndroid Build Coastguard Worker     }
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker 
validateUidPackagePair(uid_t uid,const std::string & packageName) const125*ec779b8eSAndroid Build Coastguard Worker BinderResult<bool> NativePermissionController::validateUidPackagePair(
126*ec779b8eSAndroid Build Coastguard Worker         uid_t uid, const std::string& packageName) const {
127*ec779b8eSAndroid Build Coastguard Worker     if (uid == AID_ROOT || uid == AID_SYSTEM) return true;
128*ec779b8eSAndroid Build Coastguard Worker     uid = uid % AID_USER_OFFSET;
129*ec779b8eSAndroid Build Coastguard Worker     const auto fixed_package_opt = getFixedPackageName(uid);
130*ec779b8eSAndroid Build Coastguard Worker     if (fixed_package_opt.has_value()) {
131*ec779b8eSAndroid Build Coastguard Worker         return (uid == AID_ROOT || uid == AID_SYSTEM) ? true :
132*ec779b8eSAndroid Build Coastguard Worker                 packageName == fixed_package_opt.value();
133*ec779b8eSAndroid Build Coastguard Worker     }
134*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
135*ec779b8eSAndroid Build Coastguard Worker     if (!is_package_populated_) {
136*ec779b8eSAndroid Build Coastguard Worker         return unexpectedExceptionCode(
137*ec779b8eSAndroid Build Coastguard Worker                 Status::EX_ILLEGAL_STATE,
138*ec779b8eSAndroid Build Coastguard Worker                 "NPC::validatedUidPackagePair: controller never populated by system_server");
139*ec779b8eSAndroid Build Coastguard Worker     }
140*ec779b8eSAndroid Build Coastguard Worker     const auto cursor = package_map_.find(uid);
141*ec779b8eSAndroid Build Coastguard Worker     return (cursor != package_map_.end()) &&
142*ec779b8eSAndroid Build Coastguard Worker            (std::find(cursor->second.begin(), cursor->second.end(), packageName) !=
143*ec779b8eSAndroid Build Coastguard Worker             cursor->second.end());
144*ec779b8eSAndroid Build Coastguard Worker }
145*ec779b8eSAndroid Build Coastguard Worker 
checkPermission(PermissionEnum perm,uid_t uid) const146*ec779b8eSAndroid Build Coastguard Worker BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum perm,
147*ec779b8eSAndroid Build Coastguard Worker                                                                uid_t uid) const {
148*ec779b8eSAndroid Build Coastguard Worker     if (uid == AID_ROOT || uid == AID_SYSTEM || uid == getuid()) return true;
149*ec779b8eSAndroid Build Coastguard Worker     std::lock_guard l{m_};
150*ec779b8eSAndroid Build Coastguard Worker     const auto& uids = permission_map_[static_cast<size_t>(perm)];
151*ec779b8eSAndroid Build Coastguard Worker     if (!uids.empty()) {
152*ec779b8eSAndroid Build Coastguard Worker         return std::binary_search(uids.begin(), uids.end(), uid);
153*ec779b8eSAndroid Build Coastguard Worker     } else {
154*ec779b8eSAndroid Build Coastguard Worker         return unexpectedExceptionCode(
155*ec779b8eSAndroid Build Coastguard Worker                 Status::EX_ILLEGAL_STATE,
156*ec779b8eSAndroid Build Coastguard Worker                 "NPC::checkPermission: controller never populated by system_server");
157*ec779b8eSAndroid Build Coastguard Worker     }
158*ec779b8eSAndroid Build Coastguard Worker }
159*ec779b8eSAndroid Build Coastguard Worker 
160*ec779b8eSAndroid Build Coastguard Worker }  // namespace com::android::media::permission
161