Loading camera/camera_platform.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -164,3 +164,10 @@ flag { description: "Enable stream reconfiguration for unchanged streams" bug: "341740105" } flag { namespace: "camera_platform" name: "use_context_attribution_source" description: "Use the context-provided AttributionSource when checking for client permissions" bug: "190657833" } services/camera/libcameraservice/CameraService.cpp +50 −92 Original line number Diff line number Diff line Loading @@ -1725,20 +1725,6 @@ Status CameraService::validateConnectLocked(const std::string& cameraId, return Status::ok(); } Status CameraService::errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId, const std::string& clientName, bool isPid) const { int callingPid = getCallingPid(); int callingUid = getCallingUid(); ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected " "(don't trust %s %d)", callingPid, callingUid, isPid ? "clientPid" : "clientUid", isPid ? clientPid : clientUid); return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED, "Untrusted caller (calling PID %d, UID %d) trying to " "forward camera access to camera %s for client %s (PID %d, UID %d)", getCallingPid(), getCallingUid(), cameraId.c_str(), clientName.c_str(), clientPid, clientUid); } Status CameraService::validateClientPermissionsLocked(const std::string& cameraId, const std::string& clientName, int clientUid, int clientPid) const { int callingPid = getCallingPid(); Loading Loading @@ -2131,27 +2117,21 @@ Status CameraService::connect( std::string clientPackageNameMaybe = clientAttribution.packageName.value_or(""); bool isNonSystemNdk = clientPackageNameMaybe.size() == 0; std::string clientPackageName = resolvePackageName(clientAttribution.uid, clientPackageNameMaybe); logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraIdStr, API_1); int clientUid = clientAttribution.uid; int clientPid = clientAttribution.pid; // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and // need a way to guarantee the caller identity early. // Check if we can trust clientUid if (!resolveClientUid(clientUid)) { return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName, /* isPid=*/ false); AttributionSourceState resolvedClientAttribution(clientAttribution); ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraIdStr); if (!ret.isOk()) { logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or("<unknown>"), toStdString(ret.toString8())); return ret; } // Check if we can trust clientUid if (!resolveClientPid(clientPid)) { return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName, /* isPid= */ true); } const int clientPid = resolvedClientAttribution.pid; const int clientUid = resolvedClientAttribution.uid; const std::string& clientPackageName = *resolvedClientAttribution.packageName; logConnectionAttempt(clientPid, clientPackageName, cameraIdStr, API_1); sp<Client> client = nullptr; ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId, Loading @@ -2161,7 +2141,8 @@ Status CameraService::connect( rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client); if (!ret.isOk()) { logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or(""), logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or("<unknown>"), toStdString(ret.toString8())); return ret; } Loading Loading @@ -2268,31 +2249,30 @@ Status CameraService::connectDevice( std::string cameraId = cameraIdOptional.value(); bool isNonSystemNdk = clientPackageNameMaybe.size() == 0; std::string clientPackageName = resolvePackageName(clientAttribution.uid, clientPackageNameMaybe); logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraId, API_2); userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid); if (clientAttribution.uid == USE_CALLING_UID) { clientUserId = multiuser_get_user_id(callingUid); AttributionSourceState resolvedClientAttribution(clientAttribution); if (!flags::use_context_attribution_source()) { resolvedClientAttribution.pid = USE_CALLING_PID; } ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraId); if (!ret.isOk()) { logRejected(cameraId, getCallingPid(), clientAttribution.packageName.value_or(""), toStdString(ret.toString8())); return ret; } // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and // need a way to guarantee the caller identity early. const int clientPid = resolvedClientAttribution.pid; const int clientUid = resolvedClientAttribution.uid; const std::string& clientPackageName = *resolvedClientAttribution.packageName; userid_t clientUserId = multiuser_get_user_id(resolvedClientAttribution.uid); int clientUid = clientAttribution.uid; int clientPid = callingPid; // Check if we can trust clientUid if (!resolveClientUid(clientUid)) { return errorNotTrusted(clientPid, clientUid, cameraId, clientPackageName, /* isPid= */ false); } logConnectionAttempt(clientPid, clientPackageName, cameraId, API_2); if (oomScoreOffset < 0) { std::string msg = fmt::sprintf("Cannot increase the priority of a client %s pid %d for " "camera id %s", clientPackageName.c_str(), callingPid, cameraId.c_str()); std::string msg = fmt::sprintf( "Cannot increase the priority of a client %s pid %d for " "camera id %s", clientPackageName.c_str(), clientPid, cameraId.c_str()); ALOGE("%s: %s", __FUNCTION__, msg.c_str()); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str()); } Loading @@ -2307,25 +2287,24 @@ Status CameraService::connectDevice( } // enforce system camera permissions if (oomScoreOffset > 0 && !hasPermissionsForSystemCamera(cameraId, callingPid, callingUid) && !isTrustedCallingUid(callingUid)) { std::string msg = fmt::sprintf("Cannot change the priority of a client %s pid %d for " if (oomScoreOffset > 0 && !hasPermissionsForSystemCamera(cameraId, clientPid, callingUid) && !isTrustedCallingUid(callingUid)) { std::string msg = fmt::sprintf( "Cannot change the priority of a client %s pid %d for " "camera id %s without SYSTEM_CAMERA permissions", clientPackageName.c_str(), callingPid, cameraId.c_str()); clientPackageName.c_str(), clientPid, cameraId.c_str()); ALOGE("%s: %s", __FUNCTION__, msg.c_str()); return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.c_str()); } ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient, clientAttribution.attributionTag, clientUid, clientPid, API_2, ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks, CameraDeviceClient>( cameraCb, cameraId, /*api1CameraId*/ -1, clientPackageName, systemNativeClient, resolvedClientAttribution.attributionTag, clientUid, clientPid, API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride, /*forceSlowJpegMode*/ false, unresolvedCameraId, isNonSystemNdk, /*out*/ client); if (!ret.isOk()) { logRejected(cameraId, callingPid, clientPackageName, toStdString(ret.toString8())); logRejected(cameraId, clientPid, clientPackageName, toStdString(ret.toString8())); return ret; } Loading Loading @@ -2386,30 +2365,14 @@ bool CameraService::isCameraPrivacyEnabled(const String16& packageName, const st } void CameraService::logConnectionAttempt(int clientPid, const std::string& clientPackageName, const std::string& cameraId, apiLevel effectiveApiLevel) const { int packagePid = (clientPid == USE_CALLING_PID) ? getCallingPid() : clientPid; const std::string& cameraId, apiLevel effectiveApiLevel) const { ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and " "Camera API version %d", packagePid, clientPackageName.c_str(), cameraId.c_str(), "Camera API version %d", clientPid, clientPackageName.c_str(), cameraId.c_str(), static_cast<int>(effectiveApiLevel)); } std::string CameraService::resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const { if (clientPackageNameMaybe.size() <= 0) { int packageUid = (clientUid == USE_CALLING_UID) ? getCallingUid() : clientUid; // NDK calls don't come with package names, but we need one for various cases. // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs // do exist. For all authentication cases, all packages under the same UID get the // same permissions, so picking any associated package name is sufficient. For some // other cases, this may give inaccurate names for clients in logs. return getPackageNameFromUid(packageUid); } else { return clientPackageNameMaybe; } } template<class CALLBACK, class CLIENT> Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId, int api1CameraId, const std::string& clientPackageName, bool systemNativeClient, Loading @@ -2419,11 +2382,6 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str const std::string& originalCameraId, bool isNonSystemNdk, /*out*/sp<CLIENT>& device) { binder::Status ret = binder::Status::ok(); int packageUid = (clientUid == USE_CALLING_UID) ? getCallingUid() : clientUid; int packagePid = (clientPid == USE_CALLING_PID) ? getCallingPid() : clientPid; nsecs_t openTimeNs = systemTime(); sp<CLIENT> client = nullptr; Loading Loading @@ -2643,7 +2601,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str if (flags::camera_privacy_allowlist()) { // Set camera muting behavior. isCameraPrivacyEnabled = this->isCameraPrivacyEnabled( toString16(client->getPackageName()), cameraId, packagePid, packageUid); toString16(client->getPackageName()), cameraId, clientPid, clientUid); } else { isCameraPrivacyEnabled = mSensorPrivacyPolicy->isCameraPrivacyEnabled(); Loading services/camera/libcameraservice/CameraService.h +0 −4 Original line number Diff line number Diff line Loading @@ -934,12 +934,8 @@ private: binder::Status validateClientPermissionsLocked(const std::string& cameraId, const std::string& clientName, int clientUid, int clientPid) const; // If clientPackageNameMaybe is empty, attempts to resolve the package name. std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const; void logConnectionAttempt(int clientPid, const std::string& clientPackageName, const std::string& cameraId, apiLevel effectiveApiLevel) const; binder::Status errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId, const std::string& clientName, bool isPid) const; bool isCameraPrivacyEnabled(const String16& packageName,const std::string& cameraId, int clientPid, int ClientUid); Loading services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp +138 −74 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ * limitations under the License. */ #define LOG_TAG "AttributionAndPermissionUtils" #define ATRACE_TAG ATRACE_TAG_CAMERA #include "AttributionAndPermissionUtils.h" #include <binder/AppOpsManager.h> Loading @@ -25,12 +28,12 @@ #include "CameraService.h" #include <binder/IPCThreadState.h> #include <hwbinder/IPCThreadState.h> #include <binderthreadstate/CallerUtils.h> #include <hwbinder/IPCThreadState.h> namespace { static const std::string kPermissionServiceName = "permission"; } // namespace anonymous } // namespace namespace android { Loading @@ -39,8 +42,7 @@ namespace flags = com::android::internal::camera::flags; const std::string AttributionAndPermissionUtils::sDumpPermission("android.permission.DUMP"); const std::string AttributionAndPermissionUtils::sManageCameraPermission( "android.permission.MANAGE_CAMERA"); const std::string AttributionAndPermissionUtils::sCameraPermission( "android.permission.CAMERA"); const std::string AttributionAndPermissionUtils::sCameraPermission("android.permission.CAMERA"); const std::string AttributionAndPermissionUtils::sSystemCameraPermission( "android.permission.SYSTEM_CAMERA"); const std::string AttributionAndPermissionUtils::sCameraHeadlessSystemUserPermission( Loading @@ -54,14 +56,14 @@ const std::string AttributionAndPermissionUtils::sCameraOpenCloseListenerPermiss const std::string AttributionAndPermissionUtils::sCameraInjectExternalCameraPermission( "android.permission.CAMERA_INJECT_EXTERNAL_CAMERA"); int AttributionAndPermissionUtils::getCallingUid() { int AttributionAndPermissionUtils::getCallingUid() const { if (getCurrentServingCall() == BinderCallType::HWBINDER) { return hardware::IPCThreadState::self()->getCallingUid(); } return IPCThreadState::self()->getCallingUid(); } int AttributionAndPermissionUtils::getCallingPid() { int AttributionAndPermissionUtils::getCallingPid() const { if (getCurrentServingCall() == BinderCallType::HWBINDER) { return hardware::IPCThreadState::self()->getCallingPid(); } Loading @@ -84,60 +86,31 @@ void AttributionAndPermissionUtils::restoreCallingIdentity(int64_t token) { return; } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) { int callingUid = getCallingUid(); if (clientUid == hardware::ICameraService::USE_CALLING_UID) { clientUid = callingUid; } else if (!isTrustedCallingUid(callingUid)) { return false; } return true; binder::Status AttributionAndPermissionUtils::resolveAttributionSource( /*inout*/ AttributionSourceState& resolvedAttributionSource, const std::string& methodName, const std::optional<std::string>& cameraIdMaybe) { // Check if we can trust clientUid if (!resolveClientUid(resolvedAttributionSource.uid)) { return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid, methodName, cameraIdMaybe, *resolvedAttributionSource.packageName, /* isPid= */ false); } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) { int callingUid = getCallingUid(); int callingPid = getCallingPid(); resolveAttributionPackage(resolvedAttributionSource); if (clientPid == hardware::ICameraService::USE_CALLING_PID) { clientPid = callingPid; } else if (!isTrustedCallingUid(callingUid)) { return false; if (!resolveClientPid(resolvedAttributionSource.pid)) { return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid, methodName, cameraIdMaybe, *resolvedAttributionSource.packageName, /* isPid= */ true); } return true; return binder::Status::ok(); } bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId, const AttributionSourceState &attributionSource) { if (isAutomotivePrivilegedClient(attributionSource.uid)) { // If cameraId is empty, then it means that this check is not used for the // purpose of accessing a specific camera, hence grant permission just // based on uid to the automotive privileged client. if (cameraId.empty()) return true; auto cameraService = mCameraService.promote(); if (cameraService == nullptr) { ALOGE("%s: CameraService unavailable.", __FUNCTION__); return false; } // If this call is used for accessing a specific camera then cam_id must be provided. // In that case, only pre-grants the permission for accessing the exterior system only // camera. return cameraService->isAutomotiveExteriorSystemCamera(cameraId); } return false; } bool AttributionAndPermissionUtils::checkPermissionForPreflight(const std::string &cameraId, const std::string &permission, const AttributionSourceState &attributionSource, const std::string& message, int32_t attributedOpCode) { bool AttributionAndPermissionUtils::checkPermissionForPreflight( const std::string& cameraId, const std::string& permission, const AttributionSourceState& attributionSource, const std::string& message, int32_t attributedOpCode) { if (checkAutomotivePrivilegedClient(cameraId, attributionSource)) { return true; } Loading Loading @@ -177,8 +150,7 @@ bool AttributionAndPermissionUtils::isHeadlessSystemUserMode() { bool AttributionAndPermissionUtils::isAutomotivePrivilegedClient(int32_t uid) { // Returns false if this is not an automotive device type. if (!isAutomotiveDevice()) return false; if (!isAutomotiveDevice()) return false; // Returns true if the uid is AID_AUTOMOTIVE_EVS which is a // privileged client uid used for safety critical use cases such as Loading Loading @@ -213,8 +185,8 @@ std::string AttributionAndPermissionUtils::getPackageNameFromUid(int clientUid) return packageName; } status_t AttributionAndPermissionUtils::getUidForPackage(const std::string &packageName, int userId, /*inout*/uid_t& uid, int err) { status_t AttributionAndPermissionUtils::getUidForPackage(const std::string& packageName, int userId, /*inout*/ uid_t& uid, int err) { PermissionController pc; uid = pc.getPackageUid(toString16(packageName), 0); if (uid <= 0) { Loading @@ -237,18 +209,20 @@ bool AttributionAndPermissionUtils::isCallerCameraServerNotDelegating() { return (getCallingPid() == getpid()); } bool AttributionAndPermissionUtils::hasPermissionsForCamera(const std::string& cameraId, const AttributionSourceState& attributionSource) { return checkPermissionForPreflight(cameraId, sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); bool AttributionAndPermissionUtils::hasPermissionsForCamera( const std::string& cameraId, const AttributionSourceState& attributionSource) { return checkPermissionForPreflight(cameraId, sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); } bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera(const std::string& cameraId, const AttributionSourceState& attributionSource, bool checkCameraPermissions) { bool systemCameraPermission = checkPermissionForPreflight(cameraId, sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); return systemCameraPermission && (!checkCameraPermissions || hasPermissionsForCamera(cameraId, attributionSource)); bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera( const std::string& cameraId, const AttributionSourceState& attributionSource, bool checkCameraPermissions) { bool systemCameraPermission = checkPermissionForPreflight(cameraId, sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); return systemCameraPermission && (!checkCameraPermissions || hasPermissionsForCamera(cameraId, attributionSource)); } bool AttributionAndPermissionUtils::hasPermissionsForCameraHeadlessSystemUser( Loading @@ -269,6 +243,96 @@ bool AttributionAndPermissionUtils::hasPermissionsForOpenCloseListener( attributionSource, std::string(), AppOpsManager::OP_NONE); } bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient( const std::string& cameraId, const AttributionSourceState& attributionSource) { if (isAutomotivePrivilegedClient(attributionSource.uid)) { // If cameraId is empty, then it means that this check is not used for the // purpose of accessing a specific camera, hence grant permission just // based on uid to the automotive privileged client. if (cameraId.empty()) return true; auto cameraService = mCameraService.promote(); if (cameraService == nullptr) { ALOGE("%s: CameraService unavailable.", __FUNCTION__); return false; } // If this call is used for accessing a specific camera then cam_id must be provided. // In that case, only pre-grants the permission for accessing the exterior system only // camera. return cameraService->isAutomotiveExteriorSystemCamera(cameraId); } return false; } void AttributionAndPermissionUtils::resolveAttributionPackage( AttributionSourceState& resolvedAttributionSource) { if (resolvedAttributionSource.packageName.has_value() && resolvedAttributionSource.packageName->size() > 0) { return; } // NDK calls don't come with package names, but we need one for various cases. // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs // do exist. For all authentication cases, all packages under the same UID get the // same permissions, so picking any associated package name is sufficient. For some // other cases, this may give inaccurate names for clients in logs. resolvedAttributionSource.packageName = getPackageNameFromUid(resolvedAttributionSource.uid); } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) { int callingUid = getCallingUid(); bool validUid = true; if (clientUid == hardware::ICameraService::USE_CALLING_UID) { clientUid = callingUid; } else { validUid = isTrustedCallingUid(callingUid); if (flags::use_context_attribution_source()) { validUid = validUid || (clientUid == callingUid); } } return validUid; } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) { int callingUid = getCallingUid(); int callingPid = getCallingPid(); bool validPid = true; if (clientPid == hardware::ICameraService::USE_CALLING_PID) { clientPid = callingPid; } else { validPid = isTrustedCallingUid(callingUid); if (flags::use_context_attribution_source()) { validPid = validPid || (clientPid == callingPid); } } return validPid; } binder::Status AttributionAndPermissionUtils::errorNotTrusted( int clientPid, int clientUid, const std::string& methodName, const std::optional<std::string>& cameraIdMaybe, const std::string& clientName, bool isPid) const { int callingPid = getCallingPid(); int callingUid = getCallingUid(); ALOGE("CameraService::%s X (calling PID %d, calling UID %d) rejected " "(don't trust %s %d)", methodName.c_str(), callingPid, callingUid, isPid ? "clientPid" : "clientUid", isPid ? clientPid : clientUid); return STATUS_ERROR_FMT(hardware::ICameraService::ERROR_PERMISSION_DENIED, "Untrusted caller (calling PID %d, UID %d) trying to " "forward camera access to camera %s for client %s (PID %d, UID %d)", getCallingPid(), getCallingUid(), cameraIdMaybe.value_or("N/A").c_str(), clientName.c_str(), clientPid, clientUid); } const sp<IPermissionController>& AttributionAndPermissionUtils::getPermissionController() const { static const char* kPermissionControllerService = "permission"; static thread_local sp<IPermissionController> sPermissionController = nullptr; Loading services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h +79 −65 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
camera/camera_platform.aconfig +7 −0 Original line number Diff line number Diff line Loading @@ -164,3 +164,10 @@ flag { description: "Enable stream reconfiguration for unchanged streams" bug: "341740105" } flag { namespace: "camera_platform" name: "use_context_attribution_source" description: "Use the context-provided AttributionSource when checking for client permissions" bug: "190657833" }
services/camera/libcameraservice/CameraService.cpp +50 −92 Original line number Diff line number Diff line Loading @@ -1725,20 +1725,6 @@ Status CameraService::validateConnectLocked(const std::string& cameraId, return Status::ok(); } Status CameraService::errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId, const std::string& clientName, bool isPid) const { int callingPid = getCallingPid(); int callingUid = getCallingUid(); ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected " "(don't trust %s %d)", callingPid, callingUid, isPid ? "clientPid" : "clientUid", isPid ? clientPid : clientUid); return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED, "Untrusted caller (calling PID %d, UID %d) trying to " "forward camera access to camera %s for client %s (PID %d, UID %d)", getCallingPid(), getCallingUid(), cameraId.c_str(), clientName.c_str(), clientPid, clientUid); } Status CameraService::validateClientPermissionsLocked(const std::string& cameraId, const std::string& clientName, int clientUid, int clientPid) const { int callingPid = getCallingPid(); Loading Loading @@ -2131,27 +2117,21 @@ Status CameraService::connect( std::string clientPackageNameMaybe = clientAttribution.packageName.value_or(""); bool isNonSystemNdk = clientPackageNameMaybe.size() == 0; std::string clientPackageName = resolvePackageName(clientAttribution.uid, clientPackageNameMaybe); logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraIdStr, API_1); int clientUid = clientAttribution.uid; int clientPid = clientAttribution.pid; // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and // need a way to guarantee the caller identity early. // Check if we can trust clientUid if (!resolveClientUid(clientUid)) { return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName, /* isPid=*/ false); AttributionSourceState resolvedClientAttribution(clientAttribution); ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraIdStr); if (!ret.isOk()) { logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or("<unknown>"), toStdString(ret.toString8())); return ret; } // Check if we can trust clientUid if (!resolveClientPid(clientPid)) { return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName, /* isPid= */ true); } const int clientPid = resolvedClientAttribution.pid; const int clientUid = resolvedClientAttribution.uid; const std::string& clientPackageName = *resolvedClientAttribution.packageName; logConnectionAttempt(clientPid, clientPackageName, cameraIdStr, API_1); sp<Client> client = nullptr; ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId, Loading @@ -2161,7 +2141,8 @@ Status CameraService::connect( rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client); if (!ret.isOk()) { logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or(""), logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or("<unknown>"), toStdString(ret.toString8())); return ret; } Loading Loading @@ -2268,31 +2249,30 @@ Status CameraService::connectDevice( std::string cameraId = cameraIdOptional.value(); bool isNonSystemNdk = clientPackageNameMaybe.size() == 0; std::string clientPackageName = resolvePackageName(clientAttribution.uid, clientPackageNameMaybe); logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraId, API_2); userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid); if (clientAttribution.uid == USE_CALLING_UID) { clientUserId = multiuser_get_user_id(callingUid); AttributionSourceState resolvedClientAttribution(clientAttribution); if (!flags::use_context_attribution_source()) { resolvedClientAttribution.pid = USE_CALLING_PID; } ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraId); if (!ret.isOk()) { logRejected(cameraId, getCallingPid(), clientAttribution.packageName.value_or(""), toStdString(ret.toString8())); return ret; } // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and // need a way to guarantee the caller identity early. const int clientPid = resolvedClientAttribution.pid; const int clientUid = resolvedClientAttribution.uid; const std::string& clientPackageName = *resolvedClientAttribution.packageName; userid_t clientUserId = multiuser_get_user_id(resolvedClientAttribution.uid); int clientUid = clientAttribution.uid; int clientPid = callingPid; // Check if we can trust clientUid if (!resolveClientUid(clientUid)) { return errorNotTrusted(clientPid, clientUid, cameraId, clientPackageName, /* isPid= */ false); } logConnectionAttempt(clientPid, clientPackageName, cameraId, API_2); if (oomScoreOffset < 0) { std::string msg = fmt::sprintf("Cannot increase the priority of a client %s pid %d for " "camera id %s", clientPackageName.c_str(), callingPid, cameraId.c_str()); std::string msg = fmt::sprintf( "Cannot increase the priority of a client %s pid %d for " "camera id %s", clientPackageName.c_str(), clientPid, cameraId.c_str()); ALOGE("%s: %s", __FUNCTION__, msg.c_str()); return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str()); } Loading @@ -2307,25 +2287,24 @@ Status CameraService::connectDevice( } // enforce system camera permissions if (oomScoreOffset > 0 && !hasPermissionsForSystemCamera(cameraId, callingPid, callingUid) && !isTrustedCallingUid(callingUid)) { std::string msg = fmt::sprintf("Cannot change the priority of a client %s pid %d for " if (oomScoreOffset > 0 && !hasPermissionsForSystemCamera(cameraId, clientPid, callingUid) && !isTrustedCallingUid(callingUid)) { std::string msg = fmt::sprintf( "Cannot change the priority of a client %s pid %d for " "camera id %s without SYSTEM_CAMERA permissions", clientPackageName.c_str(), callingPid, cameraId.c_str()); clientPackageName.c_str(), clientPid, cameraId.c_str()); ALOGE("%s: %s", __FUNCTION__, msg.c_str()); return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.c_str()); } ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb, cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient, clientAttribution.attributionTag, clientUid, clientPid, API_2, ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks, CameraDeviceClient>( cameraCb, cameraId, /*api1CameraId*/ -1, clientPackageName, systemNativeClient, resolvedClientAttribution.attributionTag, clientUid, clientPid, API_2, /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride, /*forceSlowJpegMode*/ false, unresolvedCameraId, isNonSystemNdk, /*out*/ client); if (!ret.isOk()) { logRejected(cameraId, callingPid, clientPackageName, toStdString(ret.toString8())); logRejected(cameraId, clientPid, clientPackageName, toStdString(ret.toString8())); return ret; } Loading Loading @@ -2386,30 +2365,14 @@ bool CameraService::isCameraPrivacyEnabled(const String16& packageName, const st } void CameraService::logConnectionAttempt(int clientPid, const std::string& clientPackageName, const std::string& cameraId, apiLevel effectiveApiLevel) const { int packagePid = (clientPid == USE_CALLING_PID) ? getCallingPid() : clientPid; const std::string& cameraId, apiLevel effectiveApiLevel) const { ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and " "Camera API version %d", packagePid, clientPackageName.c_str(), cameraId.c_str(), "Camera API version %d", clientPid, clientPackageName.c_str(), cameraId.c_str(), static_cast<int>(effectiveApiLevel)); } std::string CameraService::resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const { if (clientPackageNameMaybe.size() <= 0) { int packageUid = (clientUid == USE_CALLING_UID) ? getCallingUid() : clientUid; // NDK calls don't come with package names, but we need one for various cases. // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs // do exist. For all authentication cases, all packages under the same UID get the // same permissions, so picking any associated package name is sufficient. For some // other cases, this may give inaccurate names for clients in logs. return getPackageNameFromUid(packageUid); } else { return clientPackageNameMaybe; } } template<class CALLBACK, class CLIENT> Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId, int api1CameraId, const std::string& clientPackageName, bool systemNativeClient, Loading @@ -2419,11 +2382,6 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str const std::string& originalCameraId, bool isNonSystemNdk, /*out*/sp<CLIENT>& device) { binder::Status ret = binder::Status::ok(); int packageUid = (clientUid == USE_CALLING_UID) ? getCallingUid() : clientUid; int packagePid = (clientPid == USE_CALLING_PID) ? getCallingPid() : clientPid; nsecs_t openTimeNs = systemTime(); sp<CLIENT> client = nullptr; Loading Loading @@ -2643,7 +2601,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str if (flags::camera_privacy_allowlist()) { // Set camera muting behavior. isCameraPrivacyEnabled = this->isCameraPrivacyEnabled( toString16(client->getPackageName()), cameraId, packagePid, packageUid); toString16(client->getPackageName()), cameraId, clientPid, clientUid); } else { isCameraPrivacyEnabled = mSensorPrivacyPolicy->isCameraPrivacyEnabled(); Loading
services/camera/libcameraservice/CameraService.h +0 −4 Original line number Diff line number Diff line Loading @@ -934,12 +934,8 @@ private: binder::Status validateClientPermissionsLocked(const std::string& cameraId, const std::string& clientName, int clientUid, int clientPid) const; // If clientPackageNameMaybe is empty, attempts to resolve the package name. std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const; void logConnectionAttempt(int clientPid, const std::string& clientPackageName, const std::string& cameraId, apiLevel effectiveApiLevel) const; binder::Status errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId, const std::string& clientName, bool isPid) const; bool isCameraPrivacyEnabled(const String16& packageName,const std::string& cameraId, int clientPid, int ClientUid); Loading
services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp +138 −74 Original line number Diff line number Diff line Loading @@ -14,6 +14,9 @@ * limitations under the License. */ #define LOG_TAG "AttributionAndPermissionUtils" #define ATRACE_TAG ATRACE_TAG_CAMERA #include "AttributionAndPermissionUtils.h" #include <binder/AppOpsManager.h> Loading @@ -25,12 +28,12 @@ #include "CameraService.h" #include <binder/IPCThreadState.h> #include <hwbinder/IPCThreadState.h> #include <binderthreadstate/CallerUtils.h> #include <hwbinder/IPCThreadState.h> namespace { static const std::string kPermissionServiceName = "permission"; } // namespace anonymous } // namespace namespace android { Loading @@ -39,8 +42,7 @@ namespace flags = com::android::internal::camera::flags; const std::string AttributionAndPermissionUtils::sDumpPermission("android.permission.DUMP"); const std::string AttributionAndPermissionUtils::sManageCameraPermission( "android.permission.MANAGE_CAMERA"); const std::string AttributionAndPermissionUtils::sCameraPermission( "android.permission.CAMERA"); const std::string AttributionAndPermissionUtils::sCameraPermission("android.permission.CAMERA"); const std::string AttributionAndPermissionUtils::sSystemCameraPermission( "android.permission.SYSTEM_CAMERA"); const std::string AttributionAndPermissionUtils::sCameraHeadlessSystemUserPermission( Loading @@ -54,14 +56,14 @@ const std::string AttributionAndPermissionUtils::sCameraOpenCloseListenerPermiss const std::string AttributionAndPermissionUtils::sCameraInjectExternalCameraPermission( "android.permission.CAMERA_INJECT_EXTERNAL_CAMERA"); int AttributionAndPermissionUtils::getCallingUid() { int AttributionAndPermissionUtils::getCallingUid() const { if (getCurrentServingCall() == BinderCallType::HWBINDER) { return hardware::IPCThreadState::self()->getCallingUid(); } return IPCThreadState::self()->getCallingUid(); } int AttributionAndPermissionUtils::getCallingPid() { int AttributionAndPermissionUtils::getCallingPid() const { if (getCurrentServingCall() == BinderCallType::HWBINDER) { return hardware::IPCThreadState::self()->getCallingPid(); } Loading @@ -84,60 +86,31 @@ void AttributionAndPermissionUtils::restoreCallingIdentity(int64_t token) { return; } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) { int callingUid = getCallingUid(); if (clientUid == hardware::ICameraService::USE_CALLING_UID) { clientUid = callingUid; } else if (!isTrustedCallingUid(callingUid)) { return false; } return true; binder::Status AttributionAndPermissionUtils::resolveAttributionSource( /*inout*/ AttributionSourceState& resolvedAttributionSource, const std::string& methodName, const std::optional<std::string>& cameraIdMaybe) { // Check if we can trust clientUid if (!resolveClientUid(resolvedAttributionSource.uid)) { return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid, methodName, cameraIdMaybe, *resolvedAttributionSource.packageName, /* isPid= */ false); } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) { int callingUid = getCallingUid(); int callingPid = getCallingPid(); resolveAttributionPackage(resolvedAttributionSource); if (clientPid == hardware::ICameraService::USE_CALLING_PID) { clientPid = callingPid; } else if (!isTrustedCallingUid(callingUid)) { return false; if (!resolveClientPid(resolvedAttributionSource.pid)) { return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid, methodName, cameraIdMaybe, *resolvedAttributionSource.packageName, /* isPid= */ true); } return true; return binder::Status::ok(); } bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId, const AttributionSourceState &attributionSource) { if (isAutomotivePrivilegedClient(attributionSource.uid)) { // If cameraId is empty, then it means that this check is not used for the // purpose of accessing a specific camera, hence grant permission just // based on uid to the automotive privileged client. if (cameraId.empty()) return true; auto cameraService = mCameraService.promote(); if (cameraService == nullptr) { ALOGE("%s: CameraService unavailable.", __FUNCTION__); return false; } // If this call is used for accessing a specific camera then cam_id must be provided. // In that case, only pre-grants the permission for accessing the exterior system only // camera. return cameraService->isAutomotiveExteriorSystemCamera(cameraId); } return false; } bool AttributionAndPermissionUtils::checkPermissionForPreflight(const std::string &cameraId, const std::string &permission, const AttributionSourceState &attributionSource, const std::string& message, int32_t attributedOpCode) { bool AttributionAndPermissionUtils::checkPermissionForPreflight( const std::string& cameraId, const std::string& permission, const AttributionSourceState& attributionSource, const std::string& message, int32_t attributedOpCode) { if (checkAutomotivePrivilegedClient(cameraId, attributionSource)) { return true; } Loading Loading @@ -177,8 +150,7 @@ bool AttributionAndPermissionUtils::isHeadlessSystemUserMode() { bool AttributionAndPermissionUtils::isAutomotivePrivilegedClient(int32_t uid) { // Returns false if this is not an automotive device type. if (!isAutomotiveDevice()) return false; if (!isAutomotiveDevice()) return false; // Returns true if the uid is AID_AUTOMOTIVE_EVS which is a // privileged client uid used for safety critical use cases such as Loading Loading @@ -213,8 +185,8 @@ std::string AttributionAndPermissionUtils::getPackageNameFromUid(int clientUid) return packageName; } status_t AttributionAndPermissionUtils::getUidForPackage(const std::string &packageName, int userId, /*inout*/uid_t& uid, int err) { status_t AttributionAndPermissionUtils::getUidForPackage(const std::string& packageName, int userId, /*inout*/ uid_t& uid, int err) { PermissionController pc; uid = pc.getPackageUid(toString16(packageName), 0); if (uid <= 0) { Loading @@ -237,18 +209,20 @@ bool AttributionAndPermissionUtils::isCallerCameraServerNotDelegating() { return (getCallingPid() == getpid()); } bool AttributionAndPermissionUtils::hasPermissionsForCamera(const std::string& cameraId, const AttributionSourceState& attributionSource) { return checkPermissionForPreflight(cameraId, sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); bool AttributionAndPermissionUtils::hasPermissionsForCamera( const std::string& cameraId, const AttributionSourceState& attributionSource) { return checkPermissionForPreflight(cameraId, sCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); } bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera(const std::string& cameraId, const AttributionSourceState& attributionSource, bool checkCameraPermissions) { bool systemCameraPermission = checkPermissionForPreflight(cameraId, sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); return systemCameraPermission && (!checkCameraPermissions || hasPermissionsForCamera(cameraId, attributionSource)); bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera( const std::string& cameraId, const AttributionSourceState& attributionSource, bool checkCameraPermissions) { bool systemCameraPermission = checkPermissionForPreflight(cameraId, sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE); return systemCameraPermission && (!checkCameraPermissions || hasPermissionsForCamera(cameraId, attributionSource)); } bool AttributionAndPermissionUtils::hasPermissionsForCameraHeadlessSystemUser( Loading @@ -269,6 +243,96 @@ bool AttributionAndPermissionUtils::hasPermissionsForOpenCloseListener( attributionSource, std::string(), AppOpsManager::OP_NONE); } bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient( const std::string& cameraId, const AttributionSourceState& attributionSource) { if (isAutomotivePrivilegedClient(attributionSource.uid)) { // If cameraId is empty, then it means that this check is not used for the // purpose of accessing a specific camera, hence grant permission just // based on uid to the automotive privileged client. if (cameraId.empty()) return true; auto cameraService = mCameraService.promote(); if (cameraService == nullptr) { ALOGE("%s: CameraService unavailable.", __FUNCTION__); return false; } // If this call is used for accessing a specific camera then cam_id must be provided. // In that case, only pre-grants the permission for accessing the exterior system only // camera. return cameraService->isAutomotiveExteriorSystemCamera(cameraId); } return false; } void AttributionAndPermissionUtils::resolveAttributionPackage( AttributionSourceState& resolvedAttributionSource) { if (resolvedAttributionSource.packageName.has_value() && resolvedAttributionSource.packageName->size() > 0) { return; } // NDK calls don't come with package names, but we need one for various cases. // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs // do exist. For all authentication cases, all packages under the same UID get the // same permissions, so picking any associated package name is sufficient. For some // other cases, this may give inaccurate names for clients in logs. resolvedAttributionSource.packageName = getPackageNameFromUid(resolvedAttributionSource.uid); } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) { int callingUid = getCallingUid(); bool validUid = true; if (clientUid == hardware::ICameraService::USE_CALLING_UID) { clientUid = callingUid; } else { validUid = isTrustedCallingUid(callingUid); if (flags::use_context_attribution_source()) { validUid = validUid || (clientUid == callingUid); } } return validUid; } // TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum. bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) { int callingUid = getCallingUid(); int callingPid = getCallingPid(); bool validPid = true; if (clientPid == hardware::ICameraService::USE_CALLING_PID) { clientPid = callingPid; } else { validPid = isTrustedCallingUid(callingUid); if (flags::use_context_attribution_source()) { validPid = validPid || (clientPid == callingPid); } } return validPid; } binder::Status AttributionAndPermissionUtils::errorNotTrusted( int clientPid, int clientUid, const std::string& methodName, const std::optional<std::string>& cameraIdMaybe, const std::string& clientName, bool isPid) const { int callingPid = getCallingPid(); int callingUid = getCallingUid(); ALOGE("CameraService::%s X (calling PID %d, calling UID %d) rejected " "(don't trust %s %d)", methodName.c_str(), callingPid, callingUid, isPid ? "clientPid" : "clientUid", isPid ? clientPid : clientUid); return STATUS_ERROR_FMT(hardware::ICameraService::ERROR_PERMISSION_DENIED, "Untrusted caller (calling PID %d, UID %d) trying to " "forward camera access to camera %s for client %s (PID %d, UID %d)", getCallingPid(), getCallingUid(), cameraIdMaybe.value_or("N/A").c_str(), clientName.c_str(), clientPid, clientUid); } const sp<IPermissionController>& AttributionAndPermissionUtils::getPermissionController() const { static const char* kPermissionControllerService = "permission"; static thread_local sp<IPermissionController> sPermissionController = nullptr; Loading
services/camera/libcameraservice/utils/AttributionAndPermissionUtils.h +79 −65 File changed.Preview size limit exceeded, changes collapsed. Show changes