cameraserver: Enforce system only camera permissions in camera1 api.
In camera1 api
- getNumberOfCameras won't count hidden secure cameras.
- getNumberOfCameras will return public non system cameras or public
cameras depending on whether the client has SYSTEM_CAMERA and CAMERA
permissions or not.
- getCameraInfo checks for SYSTEM_CAMERA and CAMERA permissions in case
the info is requested for a system camera.
Bug: 140243224
Test: Harcode all cameras as SYSTEM_ONLY_CAMERA; cts camera1 tests
get 0 on calling getNumberOfCameras() without using
adoptShellPermissionIdentity().
Test: Harcode all cameras as SYSTEM_ONLY_CAMERA; cts camera1 tests
get a finite number on calling getNumberOfCameras() when
adoptShellPermissionIdentity() is used.
Test: Harcode all cameras as HIDDEN_CAMERA; cts camera1 tests
get 0 when calling getNumberOfCameras.
Change-Id: I9d1721fd5e94fa7f692c3da52aa667ae9247d368
Signed-off-by: Jayant Chowdhary <jchowdhary@google.com>
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp
index a503838..b662a4d 100644
--- a/services/camera/libcameraservice/CameraService.cpp
+++ b/services/camera/libcameraservice/CameraService.cpp
@@ -135,6 +135,7 @@
CameraService::CameraService() :
mEventLog(DEFAULT_EVENT_LOG_LENGTH),
mNumberOfCameras(0),
+ mNumberOfCamerasWithoutSystemCamera(0),
mSoundRef(0), mInitialized(false),
mAudioRestriction(hardware::camera2::ICameraDeviceUser::AUDIO_RESTRICTION_NONE) {
ALOGI("CameraService started (pid=%d)", getpid());
@@ -260,11 +261,32 @@
enumerateProviders();
}
+void CameraService::filterAPI1SystemCameraLocked(
+ const std::vector<std::string> &normalDeviceIds) {
+ mNormalDeviceIdsWithoutSystemCamera.clear();
+ for (auto &deviceId : normalDeviceIds) {
+ if (getSystemCameraKind(String8(deviceId.c_str())) ==
+ SystemCameraKind::SYSTEM_ONLY_CAMERA) {
+ // All system camera ids will necessarily come after public camera
+ // device ids as per the HAL interface contract.
+ break;
+ }
+ mNormalDeviceIdsWithoutSystemCamera.push_back(deviceId);
+ }
+ ALOGV("%s: number of API1 compatible public cameras is %zu", __FUNCTION__,
+ mNormalDeviceIdsWithoutSystemCamera.size());
+}
+
void CameraService::updateCameraNumAndIds() {
Mutex::Autolock l(mServiceLock);
- mNumberOfCameras = mCameraProviderManager->getCameraCount();
+ std::pair<int, int> systemAndNonSystemCameras = mCameraProviderManager->getCameraCount();
+ // Excludes hidden secure cameras
+ mNumberOfCameras =
+ systemAndNonSystemCameras.first + systemAndNonSystemCameras.second;
+ mNumberOfCamerasWithoutSystemCamera = systemAndNonSystemCameras.second;
mNormalDeviceIds =
mCameraProviderManager->getAPI1CompatibleCameraDeviceIds();
+ filterAPI1SystemCameraLocked(mNormalDeviceIds);
}
void CameraService::addStates(const String8 id) {
@@ -446,15 +468,31 @@
broadcastTorchModeStatus(cameraId, newStatus);
}
+static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
+ return checkPermission(sSystemCameraPermission, callingPid, callingUid) &&
+ checkPermission(sCameraPermission, callingPid, callingUid);
+}
+
Status CameraService::getNumberOfCameras(int32_t type, int32_t* numCameras) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
+ bool hasSystemCameraPermissions =
+ hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+ CameraThreadState::getCallingUid());
switch (type) {
case CAMERA_TYPE_BACKWARD_COMPATIBLE:
- *numCameras = static_cast<int>(mNormalDeviceIds.size());
+ if (hasSystemCameraPermissions) {
+ *numCameras = static_cast<int>(mNormalDeviceIds.size());
+ } else {
+ *numCameras = static_cast<int>(mNormalDeviceIdsWithoutSystemCamera.size());
+ }
break;
case CAMERA_TYPE_ALL:
- *numCameras = mNumberOfCameras;
+ if (hasSystemCameraPermissions) {
+ *numCameras = mNumberOfCameras;
+ } else {
+ *numCameras = mNumberOfCamerasWithoutSystemCamera;
+ }
break;
default:
ALOGW("%s: Unknown camera type %d",
@@ -469,20 +507,31 @@
CameraInfo* cameraInfo) {
ATRACE_CALL();
Mutex::Autolock l(mServiceLock);
+ std::string cameraIdStr = cameraIdIntToStrLocked(cameraId);
+ if (shouldRejectSystemCameraConnection(String8(cameraIdStr.c_str()))) {
+ return STATUS_ERROR_FMT(ERROR_INVALID_OPERATION, "Unable to retrieve camera"
+ "characteristics for system only device %s: ", cameraIdStr.c_str());
+ }
if (!mInitialized) {
return STATUS_ERROR(ERROR_DISCONNECTED,
"Camera subsystem is not available");
}
-
- if (cameraId < 0 || cameraId >= mNumberOfCameras) {
+ bool hasSystemCameraPermissions =
+ hasPermissionsForSystemCamera(CameraThreadState::getCallingPid(),
+ CameraThreadState::getCallingUid());
+ int cameraIdBound = mNumberOfCamerasWithoutSystemCamera;
+ if (hasSystemCameraPermissions) {
+ cameraIdBound = mNumberOfCameras;
+ }
+ if (cameraId < 0 || cameraId >= cameraIdBound) {
return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT,
"CameraId is not valid");
}
Status ret = Status::ok();
status_t err = mCameraProviderManager->getCameraInfo(
- cameraIdIntToStrLocked(cameraId), cameraInfo);
+ cameraIdStr.c_str(), cameraInfo);
if (err != OK) {
ret = STATUS_ERROR_FMT(ERROR_INVALID_OPERATION,
"Error retrieving camera info from device %d: %s (%d)", cameraId,
@@ -493,13 +542,20 @@
}
std::string CameraService::cameraIdIntToStrLocked(int cameraIdInt) {
- if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(mNormalDeviceIds.size())) {
+ const std::vector<std::string> *deviceIds = &mNormalDeviceIdsWithoutSystemCamera;
+ auto callingPid = CameraThreadState::getCallingPid();
+ auto callingUid = CameraThreadState::getCallingUid();
+ if (checkPermission(sSystemCameraPermission, callingPid, callingUid) ||
+ getpid() == callingPid) {
+ deviceIds = &mNormalDeviceIds;
+ }
+ if (cameraIdInt < 0 || cameraIdInt >= static_cast<int>(deviceIds->size())) {
ALOGE("%s: input id %d invalid: valid range (0, %zu)",
- __FUNCTION__, cameraIdInt, mNormalDeviceIds.size());
+ __FUNCTION__, cameraIdInt, deviceIds->size());
return std::string{};
}
- return mNormalDeviceIds[cameraIdInt];
+ return (*deviceIds)[cameraIdInt];
}
String8 CameraService::cameraIdIntToStr(int cameraIdInt) {
@@ -1348,11 +1404,6 @@
return ret;
}
-static bool hasPermissionsForSystemCamera(int callingPid, int callingUid) {
- return checkPermission(sSystemCameraPermission, callingPid, callingUid) &&
- checkPermission(sCameraPermission, callingPid, callingUid);
-}
-
bool CameraService::shouldSkipStatusUpdates(const String8& cameraId, bool isVendorListener,
int clientPid, int clientUid) const {
SystemCameraKind systemCameraKind = getSystemCameraKind(cameraId);
@@ -3151,6 +3202,8 @@
dprintf(fd, "\n== Service global info: ==\n\n");
dprintf(fd, "Number of camera devices: %d\n", mNumberOfCameras);
dprintf(fd, "Number of normal camera devices: %zu\n", mNormalDeviceIds.size());
+ dprintf(fd, "Number of public camera devices visible to API1: %zu\n",
+ mNormalDeviceIdsWithoutSystemCamera.size());
for (size_t i = 0; i < mNormalDeviceIds.size(); i++) {
dprintf(fd, " Device %zu maps to \"%s\"\n", i, mNormalDeviceIds[i].c_str());
}