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>
gugelfrei
Jayant Chowdhary 5 years ago
parent 20ea1ca9e0
commit 847947d80d

@ -135,6 +135,7 @@ sp<hardware::ICameraServiceProxy> CameraService::sCameraServiceProxy;
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 @@ void CameraService::onNewProviderRegistered() {
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 @@ void CameraService::onTorchStatusChangedLocked(const String8& cameraId,
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 @@ Status CameraService::getCameraInfo(int cameraId,
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 @@ Status CameraService::getCameraInfo(int cameraId,
}
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 @@ Status CameraService::connectLegacy(
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 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {
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());
}

@ -667,6 +667,13 @@ private:
return mCameraProviderManager->getSystemCameraKind(cameraId.c_str());
}
// Update the set of API1Compatible camera devices without including system
// cameras and secure cameras. This is used for hiding system only cameras
// from clients using camera1 api and not having android.permission.SYSTEM_CAMERA.
// This function expects @param normalDeviceIds, to have normalDeviceIds
// sorted in alpha-numeric order.
void filterAPI1SystemCameraLocked(const std::vector<std::string> &normalDeviceIds);
// Single implementation shared between the various connect calls
template<class CALLBACK, class CLIENT>
binder::Status connectHelper(const sp<CALLBACK>& cameraCb, const String8& cameraId,
@ -821,9 +828,14 @@ private:
*/
void updateCameraNumAndIds();
// Number of camera devices (excluding hidden secure cameras)
int mNumberOfCameras;
// Number of camera devices (excluding hidden secure cameras and
// system cameras)
int mNumberOfCamerasWithoutSystemCamera;
std::vector<std::string> mNormalDeviceIds;
std::vector<std::string> mNormalDeviceIdsWithoutSystemCamera;
// sounds
sp<MediaPlayer> newMediaPlayer(const char *file);

@ -104,13 +104,25 @@ status_t CameraProviderManager::initialize(wp<CameraProviderManager::StatusListe
return OK;
}
int CameraProviderManager::getCameraCount() const {
std::pair<int, int> CameraProviderManager::getCameraCount() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
int count = 0;
int systemCameraCount = 0;
int publicCameraCount = 0;
for (auto& provider : mProviders) {
count += provider->mUniqueCameraIds.size();
for (auto &id : provider->mUniqueCameraIds) {
switch(getSystemCameraKindLocked(id)) {
case SystemCameraKind::PUBLIC:
publicCameraCount++;
break;
case SystemCameraKind::SYSTEM_ONLY_CAMERA:
systemCameraCount++;
break;
default:
break;
}
}
}
return count;
return std::make_pair(systemCameraCount, publicCameraCount);
}
std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
@ -124,21 +136,38 @@ std::vector<std::string> CameraProviderManager::getCameraDeviceIds() const {
return deviceIds;
}
void CameraProviderManager::collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& publicDeviceIds,
std::vector<std::string>& systemDeviceIds) const {
for (auto &deviceId : deviceIds) {
if (getSystemCameraKindLocked(deviceId) == SystemCameraKind::SYSTEM_ONLY_CAMERA) {
systemDeviceIds.push_back(deviceId);
} else {
publicDeviceIds.push_back(deviceId);
}
}
}
std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds() const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
std::vector<std::string> publicDeviceIds;
std::vector<std::string> systemDeviceIds;
std::vector<std::string> deviceIds;
for (auto& provider : mProviders) {
std::vector<std::string> providerDeviceIds = provider->mUniqueAPI1CompatibleCameraIds;
// Secure cameras should not be exposed through camera 1 api
providerDeviceIds.erase(std::remove_if(providerDeviceIds.begin(), providerDeviceIds.end(),
[this](const std::string& s) {
bool rem = this->getSystemCameraKindLocked(s) ==
SystemCameraKind::HIDDEN_SECURE_CAMERA;
return rem;}), providerDeviceIds.end());
// API1 app doesn't handle logical and physical camera devices well. So
// for each camera facing, only take the first id advertised by HAL in
// all [logical, physical1, physical2, ...] id combos, and filter out the rest.
filterLogicalCameraIdsLocked(providerDeviceIds);
deviceIds.insert(deviceIds.end(), providerDeviceIds.begin(), providerDeviceIds.end());
collectDeviceIdsLocked(providerDeviceIds, publicDeviceIds, systemDeviceIds);
}
std::sort(deviceIds.begin(), deviceIds.end(),
auto sortFunc =
[](const std::string& a, const std::string& b) -> bool {
uint32_t aUint = 0, bUint = 0;
bool aIsUint = base::ParseUint(a, &aUint);
@ -154,7 +183,13 @@ std::vector<std::string> CameraProviderManager::getAPI1CompatibleCameraDeviceIds
}
// Simple string compare if both id are not uint
return a < b;
});
};
// We put device ids for system cameras at the end since they will be pared
// off for processes not having system camera permissions.
std::sort(publicDeviceIds.begin(), publicDeviceIds.end(), sortFunc);
std::sort(systemDeviceIds.begin(), systemDeviceIds.end(), sortFunc);
deviceIds.insert(deviceIds.end(), publicDeviceIds.begin(), publicDeviceIds.end());
deviceIds.insert(deviceIds.end(), systemDeviceIds.begin(), systemDeviceIds.end());
return deviceIds;
}
@ -1054,9 +1089,12 @@ bool CameraProviderManager::isLogicalCamera(const std::string& id,
return deviceInfo->mIsLogicalCamera;
}
SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) {
SystemCameraKind CameraProviderManager::getSystemCameraKind(const std::string& id) const {
std::lock_guard<std::mutex> lock(mInterfaceMutex);
return getSystemCameraKindLocked(id);
}
SystemCameraKind CameraProviderManager::getSystemCameraKindLocked(const std::string& id) const {
auto deviceInfo = findDeviceInfoLocked(id);
if (deviceInfo == nullptr) {
return SystemCameraKind::PUBLIC;

@ -152,10 +152,10 @@ public:
ServiceInteractionProxy *proxy = &sHardwareServiceInteractionProxy);
/**
* Retrieve the total number of available cameras. This value may change dynamically as cameras
* are added or removed.
* Retrieve the total number of available cameras.
* This value may change dynamically as cameras are added or removed.
*/
int getCameraCount() const;
std::pair<int, int> getCameraCount() const;
std::vector<std::string> getCameraDeviceIds() const;
@ -292,7 +292,7 @@ public:
*/
bool isLogicalCamera(const std::string& id, std::vector<std::string>* physicalCameraIds);
SystemCameraKind getSystemCameraKind(const std::string& id);
SystemCameraKind getSystemCameraKind(const std::string& id) const;
bool isHiddenPhysicalCamera(const std::string& cameraId);
static const float kDepthARTolerance;
@ -615,6 +615,12 @@ private:
status_t getCameraCharacteristicsLocked(const std::string &id,
CameraMetadata* characteristics) const;
void filterLogicalCameraIdsLocked(std::vector<std::string>& deviceIds) const;
SystemCameraKind getSystemCameraKindLocked(const std::string& id) const;
void collectDeviceIdsLocked(const std::vector<std::string> deviceIds,
std::vector<std::string>& normalDeviceIds,
std::vector<std::string>& systemCameraDeviceIds) const;
};
} // namespace android

Loading…
Cancel
Save