Use context AttributionSource as the identity source-of-truth for connection
CameraService::connect and ::connectDevice allow an argument of USE_CALLING_*
for both the pid and uid of the client. In this change, USE_CALLING_* is
retired in favor of using the AttributionSource provided by the calling
Context. The AttributionSource pid/uid is verified to be truthful via
getCallingPid() / getCallingUid().
This change has no impact on APIs which do not pass the pid/uid through
ICameraService - the AttributionSource pid/uid are ignored for those
APIs and the calling pid / uid are still universally used.
Bug: 190657833
Bug: 369850244
Change-Id: I622c24b7ace926645b64ac70650e401dc7ad5f1e
Flag: com.android.internal.camera.flags.use_context_attribution_source
Test: smoke test GCA
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
index 6c16317..37903e1 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
@@ -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>
@@ -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
+static const std::string kPermissionServiceName = "permission";
+} // namespace
namespace android {
@@ -39,8 +42,7 @@
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(
@@ -54,14 +56,14 @@
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();
}
@@ -84,67 +86,38 @@
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;
+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);
}
- return true;
-}
+ resolveAttributionPackage(resolvedAttributionSource);
-// TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum.
-bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) {
- int callingUid = getCallingUid();
- int callingPid = getCallingPid();
-
- 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;
}
return mPermissionChecker->checkPermissionForPreflight(
- toString16(permission), attributionSource, toString16(message),
- attributedOpCode) != PermissionChecker::PERMISSION_HARD_DENIED;
+ toString16(permission), attributionSource, toString16(message),
+ attributedOpCode) != PermissionChecker::PERMISSION_HARD_DENIED;
}
// Can camera service trust the caller based on the calling UID?
@@ -177,8 +150,7 @@
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
@@ -213,8 +185,8 @@
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) {
@@ -237,36 +209,128 @@
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(
const std::string& cameraId, const AttributionSourceState& attributionSource) {
return checkPermissionForPreflight(cameraId, sCameraHeadlessSystemUserPermission,
- attributionSource, std::string(), AppOpsManager::OP_NONE);
+ attributionSource, std::string(), AppOpsManager::OP_NONE);
}
bool AttributionAndPermissionUtils::hasPermissionsForCameraPrivacyAllowlist(
const AttributionSourceState& attributionSource) {
return checkPermissionForPreflight(std::string(), sCameraPrivacyAllowlistPermission,
- attributionSource, std::string(), AppOpsManager::OP_NONE);
+ attributionSource, std::string(), AppOpsManager::OP_NONE);
}
bool AttributionAndPermissionUtils::hasPermissionsForOpenCloseListener(
const AttributionSourceState& attributionSource) {
return checkPermissionForPreflight(std::string(), sCameraOpenCloseListenerPermission,
- attributionSource, std::string(), AppOpsManager::OP_NONE);
+ 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 {
@@ -274,7 +338,7 @@
static thread_local sp<IPermissionController> sPermissionController = nullptr;
if (sPermissionController == nullptr ||
- !IInterface::asBinder(sPermissionController)->isBinderAlive()) {
+ !IInterface::asBinder(sPermissionController)->isBinderAlive()) {
sp<IServiceManager> sm = defaultServiceManager();
sp<IBinder> binder = sm->checkService(toString16(kPermissionControllerService));
if (binder == nullptr) {