Pass full context AttributionSource to permission checker during connect
Prior to this change, the root AttributionSource uid/pid/packageName were
passed through to validateClientPermissionsLocked and checkPermissionForPreflight
This means that subsequent AttributionSources in the chain were not checked.
This change plumbs the full AttributionSource to permission checker for the
purposes of opening a camera connection. If any app in the chain does not have
permissions, then the connect attempt will be blocked.
Bug: 190657833
Bug: 369841571
Test: CtsSecurityTestCases:CameraPermissionTest, VDM tests
Flag: com.android.internal.camera.flags.check_full_attribution_source_chain
Change-Id: I43d0e59e984131639833dc7c2f2013aabedf510e
diff --git a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
index 37903e1..b213218 100644
--- a/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
+++ b/services/camera/libcameraservice/utils/AttributionAndPermissionUtils.cpp
@@ -32,7 +32,32 @@
#include <hwbinder/IPCThreadState.h>
namespace {
+
+using android::content::AttributionSourceState;
+
static const std::string kPermissionServiceName = "permission";
+
+static std::string getAttributionString(const AttributionSourceState& attributionSource) {
+ std::ostringstream ret;
+ const AttributionSourceState* current = &attributionSource;
+ while (current != nullptr) {
+ if (current != &attributionSource) {
+ ret << ", ";
+ }
+
+ ret << "[uid " << current->uid << ", pid " << current->pid;
+ ret << ", packageName \"" << current->packageName.value_or("<unknown>");
+ ret << "\"]";
+
+ if (!current->next.empty()) {
+ current = ¤t->next[0];
+ } else {
+ current = nullptr;
+ }
+ }
+ return ret.str();
+}
+
} // namespace
namespace android {
@@ -111,13 +136,22 @@
const std::string& cameraId, const std::string& permission,
const AttributionSourceState& attributionSource, const std::string& message,
int32_t attributedOpCode) {
- if (checkAutomotivePrivilegedClient(cameraId, attributionSource)) {
+ AttributionSourceState clientAttribution = attributionSource;
+ if (!flags::check_full_attribution_source_chain() && !clientAttribution.next.empty()) {
+ clientAttribution.next.clear();
+ }
+
+ if (checkAutomotivePrivilegedClient(cameraId, clientAttribution)) {
return true;
}
- return mPermissionChecker->checkPermissionForPreflight(
- toString16(permission), attributionSource, toString16(message),
- attributedOpCode) != PermissionChecker::PERMISSION_HARD_DENIED;
+ PermissionChecker::PermissionResult result = mPermissionChecker->checkPermissionForPreflight(
+ toString16(permission), clientAttribution, toString16(message), attributedOpCode);
+ if (result == PermissionChecker::PERMISSION_HARD_DENIED) {
+ ALOGE("%s: Permission denied for client attribution %s", __FUNCTION__,
+ getAttributionString(clientAttribution).c_str());
+ }
+ return result != PermissionChecker::PERMISSION_HARD_DENIED;
}
// Can camera service trust the caller based on the calling UID?