Loading services/audiopolicy/permission/NativePermissionController.cpp +25 −10 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ #include <cutils/android_filesystem_config.h> #include <utils/Errors.h> using ::android::base::unexpected; using ::android::binder::Status; using ::android::error::Result; using ::android::error::BinderResult; using ::android::error::unexpectedExceptionCode; namespace com::android::media::permission { static std::optional<std::string> getFixedPackageName(uid_t uid) { Loading Loading @@ -103,23 +103,31 @@ Status NativePermissionController::populatePermissionState(PermissionEnum perm, // -- End Binder methods Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const { BinderResult<std::vector<std::string>> NativePermissionController::getPackagesForUid( uid_t uid) const { uid = uid % AID_USER_OFFSET; const auto fixed_package_opt = getFixedPackageName(uid); if (fixed_package_opt.has_value()) { return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}}; return BinderResult<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}}; } std::lock_guard l{m_}; if (!is_package_populated_) return unexpected{::android::NO_INIT}; if (!is_package_populated_) { return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::getPackagesForUid: controller never populated by system_server"); } const auto cursor = package_map_.find(uid); if (cursor != package_map_.end()) { return cursor->second; } else { return unexpected{::android::BAD_VALUE}; return unexpectedExceptionCode( Status::EX_ILLEGAL_ARGUMENT, ("NPC::getPackagesForUid: uid not found: " + std::to_string(uid)).c_str()); } } Result<bool> NativePermissionController::validateUidPackagePair( BinderResult<bool> NativePermissionController::validateUidPackagePair( uid_t uid, const std::string& packageName) const { uid = uid % AID_USER_OFFSET; const auto fixed_package_opt = getFixedPackageName(uid); Loading @@ -127,20 +135,27 @@ Result<bool> NativePermissionController::validateUidPackagePair( return packageName == fixed_package_opt.value(); } std::lock_guard l{m_}; if (!is_package_populated_) return unexpected{::android::NO_INIT}; if (!is_package_populated_) { return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::validatedUidPackagePair: controller never populated by system_server"); } const auto cursor = package_map_.find(uid); return (cursor != package_map_.end()) && (std::find(cursor->second.begin(), cursor->second.end(), packageName) != cursor->second.end()); } Result<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const { BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const { std::lock_guard l{m_}; const auto& uids = permission_map_[static_cast<size_t>(perm)]; if (!uids.empty()) { return std::binary_search(uids.begin(), uids.end(), uid); } else { return unexpected{::android::NO_INIT}; return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::checkPermission: controller never populated by system_server"); } } Loading services/audiopolicy/permission/ValidatedAttributionSourceState.cpp +15 −7 Original line number Diff line number Diff line Loading @@ -20,31 +20,39 @@ #include <error/expected_utils.h> #include <utils/Log.h> namespace com::android::media::permission { using ::android::binder::Status; using ::android::error::BinderResult; using ::android::error::unexpectedExceptionCode; using ::android::base::unexpected; namespace com::android::media::permission { Result<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromBinderContext( AttributionSourceState attr, const IPermissionProvider& provider) { BinderResult<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromBinderContext(AttributionSourceState attr, const IPermissionProvider& provider) { attr.pid = ::android::IPCThreadState::self()->getCallingPid(); attr.uid = ::android::IPCThreadState::self()->getCallingUid(); return createFromTrustedUidNoPackage(std::move(attr), provider); } Result<ValidatedAttributionSourceState> BinderResult<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromTrustedUidNoPackage( AttributionSourceState attr, const IPermissionProvider& provider) { if (attr.packageName.has_value() && attr.packageName->size() != 0) { if (VALUE_OR_RETURN(provider.validateUidPackagePair(attr.uid, attr.packageName.value()))) { return ValidatedAttributionSourceState{std::move(attr)}; } else { return unexpected{::android::PERMISSION_DENIED}; return unexpectedExceptionCode(Status::EX_SECURITY, attr.toString() .insert(0, ": invalid attr ") .insert(0, __PRETTY_FUNCTION__) .c_str()); } } else { // For APIs which don't appropriately pass attribution sources or packages, we need // to populate the package name with our best guess. const auto packageNames = VALUE_OR_RETURN(provider.getPackagesForUid(attr.uid)); LOG_ALWAYS_FATAL_IF(packageNames.empty()); LOG_ALWAYS_FATAL_IF(packageNames.empty(), "%s BUG: empty package list from controller", __PRETTY_FUNCTION__); attr.packageName = std::move(packageNames[0]); return ValidatedAttributionSourceState{std::move(attr)}; } Loading services/audiopolicy/permission/include/media/IPermissionProvider.h +8 −7 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include <vector> #include <com/android/media/permission/PermissionEnum.h> #include <error/Result.h> #include <error/BinderResult.h> namespace com::android::media::permission { Loading @@ -31,18 +31,19 @@ class IPermissionProvider { // Get all package names which run under a certain app-id. Returns non-empty. // Not user specific, since packages are across users. Special app-ids (system, // shell, etc.) are handled. Fails if the provider does not know about the // app-id. virtual ::android::error::Result<std::vector<std::string>> getPackagesForUid( // app-id or if the provider has not been initialized. virtual ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid( uid_t uid) const = 0; // True iff the provided package name runs under the app-id of uid. // Special app-ids (system, shell, etc.) are handled. // Fails if the provider does not know about the app-id. virtual ::android::error::Result<bool> validateUidPackagePair( // Fails if the provider does not know about the app-id or if the provider has not been // initialized. virtual ::android::error::BinderResult<bool> validateUidPackagePair( uid_t uid, const std::string& packageName) const = 0; // True iff the uid holds the permission (user aware). // Fails with NO_INIT if cache hasn't been populated. virtual ::android::error::Result<bool> checkPermission(PermissionEnum permission, virtual ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission, uid_t uid) const = 0; virtual ~IPermissionProvider() = default; }; Loading services/audiopolicy/permission/include/media/NativePermissionController.h +6 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <android-base/thread_annotations.h> #include <com/android/media/permission/BnNativePermissionController.h> #include <error/BinderResult.h> namespace com::android::media::permission { Loading @@ -36,10 +37,11 @@ class NativePermissionController : public BnNativePermissionController, public I Status populatePermissionState(PermissionEnum permission, const std::vector<int>& uids) final; // end binder methods ::android::error::Result<std::vector<std::string>> getPackagesForUid(uid_t uid) const final; ::android::error::Result<bool> validateUidPackagePair( ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid( uid_t uid) const final; ::android::error::BinderResult<bool> validateUidPackagePair( uid_t uid, const std::string& packageName) const final; ::android::error::Result<bool> checkPermission(PermissionEnum permission, ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission, uid_t uid) const final; private: Loading services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h +7 −6 Original line number Diff line number Diff line Loading @@ -17,22 +17,22 @@ #pragma once #include <android/content/AttributionSourceState.h> #include <error/Result.h> #include <error/BinderResult.h> #include "IPermissionProvider.h" namespace com::android::media::permission { using ::android::content::AttributionSourceState; using ::android::error::Result; class ValidatedAttributionSourceState { public: /** * Validates an attribution source from within the context of a binder transaction. * Overwrites the uid/pid and validates the packageName * Overwrites the uid/pid and validates the packageName. * Returns EX_SECURITY on package validation fail. */ static Result<ValidatedAttributionSourceState> createFromBinderContext( static ::android::error::BinderResult<ValidatedAttributionSourceState> createFromBinderContext( AttributionSourceState attr, const IPermissionProvider& provider); /** Loading @@ -47,9 +47,10 @@ class ValidatedAttributionSourceState { * Create a ValidatedAttribubtionSourceState in cases where the uid/pid is trusted, but the * packages have not been validated. Proper use of the previous two methods should avoid the * necessity of this, but it is useful for migration purposes as well as testing this class. * Returns EX_SECURITY on package validation fail. */ static Result<ValidatedAttributionSourceState> createFromTrustedUidNoPackage( AttributionSourceState attr, const IPermissionProvider& provider); static ::android::error::BinderResult<ValidatedAttributionSourceState> createFromTrustedUidNoPackage(AttributionSourceState attr, const IPermissionProvider& provider); operator AttributionSourceState() const { return state_; } Loading Loading
services/audiopolicy/permission/NativePermissionController.cpp +25 −10 Original line number Diff line number Diff line Loading @@ -24,9 +24,9 @@ #include <cutils/android_filesystem_config.h> #include <utils/Errors.h> using ::android::base::unexpected; using ::android::binder::Status; using ::android::error::Result; using ::android::error::BinderResult; using ::android::error::unexpectedExceptionCode; namespace com::android::media::permission { static std::optional<std::string> getFixedPackageName(uid_t uid) { Loading Loading @@ -103,23 +103,31 @@ Status NativePermissionController::populatePermissionState(PermissionEnum perm, // -- End Binder methods Result<std::vector<std::string>> NativePermissionController::getPackagesForUid(uid_t uid) const { BinderResult<std::vector<std::string>> NativePermissionController::getPackagesForUid( uid_t uid) const { uid = uid % AID_USER_OFFSET; const auto fixed_package_opt = getFixedPackageName(uid); if (fixed_package_opt.has_value()) { return Result<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}}; return BinderResult<std::vector<std::string>>{std::in_place_t{}, {fixed_package_opt.value()}}; } std::lock_guard l{m_}; if (!is_package_populated_) return unexpected{::android::NO_INIT}; if (!is_package_populated_) { return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::getPackagesForUid: controller never populated by system_server"); } const auto cursor = package_map_.find(uid); if (cursor != package_map_.end()) { return cursor->second; } else { return unexpected{::android::BAD_VALUE}; return unexpectedExceptionCode( Status::EX_ILLEGAL_ARGUMENT, ("NPC::getPackagesForUid: uid not found: " + std::to_string(uid)).c_str()); } } Result<bool> NativePermissionController::validateUidPackagePair( BinderResult<bool> NativePermissionController::validateUidPackagePair( uid_t uid, const std::string& packageName) const { uid = uid % AID_USER_OFFSET; const auto fixed_package_opt = getFixedPackageName(uid); Loading @@ -127,20 +135,27 @@ Result<bool> NativePermissionController::validateUidPackagePair( return packageName == fixed_package_opt.value(); } std::lock_guard l{m_}; if (!is_package_populated_) return unexpected{::android::NO_INIT}; if (!is_package_populated_) { return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::validatedUidPackagePair: controller never populated by system_server"); } const auto cursor = package_map_.find(uid); return (cursor != package_map_.end()) && (std::find(cursor->second.begin(), cursor->second.end(), packageName) != cursor->second.end()); } Result<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const { BinderResult<bool> NativePermissionController::checkPermission(PermissionEnum perm, uid_t uid) const { std::lock_guard l{m_}; const auto& uids = permission_map_[static_cast<size_t>(perm)]; if (!uids.empty()) { return std::binary_search(uids.begin(), uids.end(), uid); } else { return unexpected{::android::NO_INIT}; return unexpectedExceptionCode( Status::EX_ILLEGAL_STATE, "NPC::checkPermission: controller never populated by system_server"); } } Loading
services/audiopolicy/permission/ValidatedAttributionSourceState.cpp +15 −7 Original line number Diff line number Diff line Loading @@ -20,31 +20,39 @@ #include <error/expected_utils.h> #include <utils/Log.h> namespace com::android::media::permission { using ::android::binder::Status; using ::android::error::BinderResult; using ::android::error::unexpectedExceptionCode; using ::android::base::unexpected; namespace com::android::media::permission { Result<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromBinderContext( AttributionSourceState attr, const IPermissionProvider& provider) { BinderResult<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromBinderContext(AttributionSourceState attr, const IPermissionProvider& provider) { attr.pid = ::android::IPCThreadState::self()->getCallingPid(); attr.uid = ::android::IPCThreadState::self()->getCallingUid(); return createFromTrustedUidNoPackage(std::move(attr), provider); } Result<ValidatedAttributionSourceState> BinderResult<ValidatedAttributionSourceState> ValidatedAttributionSourceState::createFromTrustedUidNoPackage( AttributionSourceState attr, const IPermissionProvider& provider) { if (attr.packageName.has_value() && attr.packageName->size() != 0) { if (VALUE_OR_RETURN(provider.validateUidPackagePair(attr.uid, attr.packageName.value()))) { return ValidatedAttributionSourceState{std::move(attr)}; } else { return unexpected{::android::PERMISSION_DENIED}; return unexpectedExceptionCode(Status::EX_SECURITY, attr.toString() .insert(0, ": invalid attr ") .insert(0, __PRETTY_FUNCTION__) .c_str()); } } else { // For APIs which don't appropriately pass attribution sources or packages, we need // to populate the package name with our best guess. const auto packageNames = VALUE_OR_RETURN(provider.getPackagesForUid(attr.uid)); LOG_ALWAYS_FATAL_IF(packageNames.empty()); LOG_ALWAYS_FATAL_IF(packageNames.empty(), "%s BUG: empty package list from controller", __PRETTY_FUNCTION__); attr.packageName = std::move(packageNames[0]); return ValidatedAttributionSourceState{std::move(attr)}; } Loading
services/audiopolicy/permission/include/media/IPermissionProvider.h +8 −7 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ #include <vector> #include <com/android/media/permission/PermissionEnum.h> #include <error/Result.h> #include <error/BinderResult.h> namespace com::android::media::permission { Loading @@ -31,18 +31,19 @@ class IPermissionProvider { // Get all package names which run under a certain app-id. Returns non-empty. // Not user specific, since packages are across users. Special app-ids (system, // shell, etc.) are handled. Fails if the provider does not know about the // app-id. virtual ::android::error::Result<std::vector<std::string>> getPackagesForUid( // app-id or if the provider has not been initialized. virtual ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid( uid_t uid) const = 0; // True iff the provided package name runs under the app-id of uid. // Special app-ids (system, shell, etc.) are handled. // Fails if the provider does not know about the app-id. virtual ::android::error::Result<bool> validateUidPackagePair( // Fails if the provider does not know about the app-id or if the provider has not been // initialized. virtual ::android::error::BinderResult<bool> validateUidPackagePair( uid_t uid, const std::string& packageName) const = 0; // True iff the uid holds the permission (user aware). // Fails with NO_INIT if cache hasn't been populated. virtual ::android::error::Result<bool> checkPermission(PermissionEnum permission, virtual ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission, uid_t uid) const = 0; virtual ~IPermissionProvider() = default; }; Loading
services/audiopolicy/permission/include/media/NativePermissionController.h +6 −4 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ #include <android-base/thread_annotations.h> #include <com/android/media/permission/BnNativePermissionController.h> #include <error/BinderResult.h> namespace com::android::media::permission { Loading @@ -36,10 +37,11 @@ class NativePermissionController : public BnNativePermissionController, public I Status populatePermissionState(PermissionEnum permission, const std::vector<int>& uids) final; // end binder methods ::android::error::Result<std::vector<std::string>> getPackagesForUid(uid_t uid) const final; ::android::error::Result<bool> validateUidPackagePair( ::android::error::BinderResult<std::vector<std::string>> getPackagesForUid( uid_t uid) const final; ::android::error::BinderResult<bool> validateUidPackagePair( uid_t uid, const std::string& packageName) const final; ::android::error::Result<bool> checkPermission(PermissionEnum permission, ::android::error::BinderResult<bool> checkPermission(PermissionEnum permission, uid_t uid) const final; private: Loading
services/audiopolicy/permission/include/media/ValidatedAttributionSourceState.h +7 −6 Original line number Diff line number Diff line Loading @@ -17,22 +17,22 @@ #pragma once #include <android/content/AttributionSourceState.h> #include <error/Result.h> #include <error/BinderResult.h> #include "IPermissionProvider.h" namespace com::android::media::permission { using ::android::content::AttributionSourceState; using ::android::error::Result; class ValidatedAttributionSourceState { public: /** * Validates an attribution source from within the context of a binder transaction. * Overwrites the uid/pid and validates the packageName * Overwrites the uid/pid and validates the packageName. * Returns EX_SECURITY on package validation fail. */ static Result<ValidatedAttributionSourceState> createFromBinderContext( static ::android::error::BinderResult<ValidatedAttributionSourceState> createFromBinderContext( AttributionSourceState attr, const IPermissionProvider& provider); /** Loading @@ -47,9 +47,10 @@ class ValidatedAttributionSourceState { * Create a ValidatedAttribubtionSourceState in cases where the uid/pid is trusted, but the * packages have not been validated. Proper use of the previous two methods should avoid the * necessity of this, but it is useful for migration purposes as well as testing this class. * Returns EX_SECURITY on package validation fail. */ static Result<ValidatedAttributionSourceState> createFromTrustedUidNoPackage( AttributionSourceState attr, const IPermissionProvider& provider); static ::android::error::BinderResult<ValidatedAttributionSourceState> createFromTrustedUidNoPackage(AttributionSourceState attr, const IPermissionProvider& provider); operator AttributionSourceState() const { return state_; } Loading