diff options
Diffstat (limited to 'services/camera')
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.cpp | 15 | ||||
-rw-r--r-- | services/camera/libcameraservice/Camera2Client.h | 2 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraClient.cpp | 18 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraClient.h | 2 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 171 | ||||
-rw-r--r-- | services/camera/libcameraservice/CameraService.h | 57 | ||||
-rw-r--r-- | services/camera/libcameraservice/ProCamera2Client.cpp | 6 | ||||
-rw-r--r-- | services/camera/libcameraservice/ProCamera2Client.h | 2 |
8 files changed, 228 insertions, 45 deletions
diff --git a/services/camera/libcameraservice/Camera2Client.cpp b/services/camera/libcameraservice/Camera2Client.cpp index e8b3b7f..38d6949 100644 --- a/services/camera/libcameraservice/Camera2Client.cpp +++ b/services/camera/libcameraservice/Camera2Client.cpp @@ -40,12 +40,14 @@ static int getCallingPid() { Camera2Client::Camera2Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid): - Client(cameraService, cameraClient, - cameraId, cameraFacing, clientPid, servicePid), + Client(cameraService, cameraClient, clientPackageName, + cameraId, cameraFacing, clientPid, clientUid, servicePid), mSharedCameraClient(cameraClient), mParameters(cameraId, cameraFacing) { @@ -73,6 +75,12 @@ status_t Camera2Client::initialize(camera_module_t *module) ALOGV("%s: Initializing client for camera %d", __FUNCTION__, mCameraId); status_t res; + // Verify ops permissions + res = startCameraOps(); + if (res != OK) { + return res; + } + res = mDevice->initialize(module); if (res != OK) { ALOGE("%s: Camera %d: unable to initialize device: %s (%d)", @@ -741,8 +749,7 @@ void Camera2Client::stopPreviewL() { switch (state) { case Parameters::DISCONNECTED: - ALOGE("%s: Camera %d: Call before initialized", - __FUNCTION__, mCameraId); + // Nothing to do. break; case Parameters::STOPPED: case Parameters::VIDEO_SNAPSHOT: diff --git a/services/camera/libcameraservice/Camera2Client.h b/services/camera/libcameraservice/Camera2Client.h index a4d4478..173b65e 100644 --- a/services/camera/libcameraservice/Camera2Client.h +++ b/services/camera/libcameraservice/Camera2Client.h @@ -72,9 +72,11 @@ public: Camera2Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid); virtual ~Camera2Client(); diff --git a/services/camera/libcameraservice/CameraClient.cpp b/services/camera/libcameraservice/CameraClient.cpp index f67c9f4..90f8f40 100644 --- a/services/camera/libcameraservice/CameraClient.cpp +++ b/services/camera/libcameraservice/CameraClient.cpp @@ -35,9 +35,12 @@ static int getCallingPid() { CameraClient::CameraClient(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, - int cameraId, int cameraFacing, int clientPid, int servicePid): - Client(cameraService, cameraClient, - cameraId, cameraFacing, clientPid, servicePid) + const String16& clientPackageName, + int cameraId, int cameraFacing, + int clientPid, int clientUid, + int servicePid): + Client(cameraService, cameraClient, clientPackageName, + cameraId, cameraFacing, clientPid, clientUid, servicePid) { int callingPid = getCallingPid(); LOG1("CameraClient::CameraClient E (pid %d, id %d)", callingPid, cameraId); @@ -57,10 +60,17 @@ CameraClient::CameraClient(const sp<CameraService>& cameraService, status_t CameraClient::initialize(camera_module_t *module) { int callingPid = getCallingPid(); + status_t res; + LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId); + // Verify ops permissions + res = startCameraOps(); + if (res != OK) { + return res; + } + char camera_device_name[10]; - status_t res; snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId); mHardware = new CameraHardwareInterface(camera_device_name); diff --git a/services/camera/libcameraservice/CameraClient.h b/services/camera/libcameraservice/CameraClient.h index 74829ce..00dc90c 100644 --- a/services/camera/libcameraservice/CameraClient.h +++ b/services/camera/libcameraservice/CameraClient.h @@ -53,9 +53,11 @@ public: // Interface used by CameraService CameraClient(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + int clientUid, int servicePid); ~CameraClient(); diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index eb8bc05..ec1c3f0 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -22,6 +22,7 @@ #include <sys/types.h> #include <pthread.h> +#include <binder/AppOpsManager.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/MemoryBase.h> @@ -72,7 +73,7 @@ static int getCallingUid() { static CameraService *gCameraService; CameraService::CameraService() -:mSoundRef(0), mModule(0) + :mSoundRef(0), mModule(0) { ALOGI("CameraService started (pid=%d)", getpid()); gCameraService = this; @@ -155,10 +156,27 @@ int CameraService::getDeviceVersion(int cameraId, int* facing) { } sp<ICamera> CameraService::connect( - const sp<ICameraClient>& cameraClient, int cameraId) { + const sp<ICameraClient>& cameraClient, + int cameraId, + const String16& clientPackageName, + int clientUid) { + + String8 clientName8(clientPackageName); int callingPid = getCallingPid(); - LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId); + LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid, + clientName8.string(), cameraId); + + if (clientUid == USE_CALLING_UID) { + clientUid = getCallingUid(); + } else { + // We only trust our own process to forward client UIDs + if (callingPid != getpid()) { + ALOGE("CameraService::connect X (pid %d) rejected (don't trust clientUid)", + callingPid); + return NULL; + } + } if (!mModule) { ALOGE("Camera HAL module not loaded"); @@ -208,8 +226,10 @@ sp<ICamera> CameraService::connect( would be fine */ if (mBusy[cameraId]) { - ALOGW("CameraService::connect X (pid %d) rejected" - " (camera %d is still busy).", callingPid, cameraId); + + ALOGW("CameraService::connect X (pid %d, \"%s\") rejected" + " (camera %d is still busy).", callingPid, + clientName8.string(), cameraId); return NULL; } @@ -218,13 +238,15 @@ sp<ICamera> CameraService::connect( switch(deviceVersion) { case CAMERA_DEVICE_API_VERSION_1_0: - client = new CameraClient(this, cameraClient, cameraId, - facing, callingPid, getpid()); + client = new CameraClient(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid()); break; case CAMERA_DEVICE_API_VERSION_2_0: case CAMERA_DEVICE_API_VERSION_2_1: - client = new Camera2Client(this, cameraClient, cameraId, - facing, callingPid, getpid()); + client = new Camera2Client(this, cameraClient, + clientPackageName, cameraId, + facing, callingPid, clientUid, getpid()); break; case -1: ALOGE("Invalid camera id %d", cameraId); @@ -283,8 +305,8 @@ sp<IProCameraUser> CameraService::connect( break; case CAMERA_DEVICE_API_VERSION_2_0: case CAMERA_DEVICE_API_VERSION_2_1: - client = new ProCamera2Client(this, cameraCb, cameraId, - facing, callingPid, getpid()); + client = new ProCamera2Client(this, cameraCb, String16(), + cameraId, facing, callingPid, USE_CALLING_UID, getpid()); break; case -1: ALOGE("Invalid camera id %d", cameraId); @@ -302,7 +324,8 @@ sp<IProCameraUser> CameraService::connect( cameraCb->asBinder()->linkToDeath(this); - LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid()); + LOG1("CameraService::connectPro X (id %d, this pid is %d)", cameraId, + getpid()); return client; @@ -522,10 +545,15 @@ void CameraService::playSound(sound_kind kind) { CameraService::Client::Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, - int cameraId, int cameraFacing, int clientPid, int servicePid) : + const String16& clientPackageName, + int cameraId, int cameraFacing, + int clientPid, uid_t clientUid, + int servicePid) : CameraService::BasicClient(cameraService, cameraClient->asBinder(), - cameraId, cameraFacing, - clientPid, servicePid) + clientPackageName, + cameraId, cameraFacing, + clientPid, clientUid, + servicePid) { int callingPid = getCallingPid(); LOG1("Client::Client E (pid %d, id %d)", callingPid, cameraId); @@ -534,6 +562,7 @@ CameraService::Client::Client(const sp<CameraService>& cameraService, cameraService->setCameraBusy(cameraId); cameraService->loadSound(); + LOG1("Client::Client X (pid %d, id %d)", callingPid, cameraId); } @@ -542,23 +571,27 @@ CameraService::Client::~Client() { mDestructionStarted = true; mCameraService->releaseSound(); - + finishCameraOps(); // unconditionally disconnect. function is idempotent Client::disconnect(); } CameraService::BasicClient::BasicClient(const sp<CameraService>& cameraService, - const sp<IBinder>& remoteCallback, - int cameraId, int cameraFacing, - int clientPid, int servicePid) + const sp<IBinder>& remoteCallback, + const String16& clientPackageName, + int cameraId, int cameraFacing, + int clientPid, uid_t clientUid, + int servicePid): + mClientPackageName(clientPackageName) { mCameraService = cameraService; mRemoteCallback = remoteCallback; mCameraId = cameraId; mCameraFacing = cameraFacing; mClientPid = clientPid; + mClientUid = clientUid; mServicePid = servicePid; - + mOpsActive = false; mDestructionStarted = false; } @@ -570,6 +603,66 @@ void CameraService::BasicClient::disconnect() { mCameraService->removeClientByRemote(mRemoteCallback); } +status_t CameraService::BasicClient::startCameraOps() { + int32_t res; + + mOpsCallback = new OpsCallback(this); + + mAppOpsManager.startWatchingMode(AppOpsManager::OP_CAMERA, + mClientPackageName, mOpsCallback); + res = mAppOpsManager.startOp(AppOpsManager::OP_CAMERA, + mClientUid, mClientPackageName); + + if (res != AppOpsManager::MODE_ALLOWED) { + ALOGI("Camera %d: Access for \"%s\" has been revoked", + mCameraId, String8(mClientPackageName).string()); + return PERMISSION_DENIED; + } + mOpsActive = true; + return OK; +} + +status_t CameraService::BasicClient::finishCameraOps() { + if (mOpsActive) { + mAppOpsManager.finishOp(AppOpsManager::OP_CAMERA, mClientUid, + mClientPackageName); + mOpsActive = false; + } + mAppOpsManager.stopWatchingMode(mOpsCallback); + mOpsCallback.clear(); + + return OK; +} + +void CameraService::BasicClient::opChanged(int32_t op, const String16& packageName) { + String8 name(packageName); + String8 myName(mClientPackageName); + + if (op != AppOpsManager::OP_CAMERA) { + ALOGW("Unexpected app ops notification received: %d", op); + return; + } + + int32_t res; + res = mAppOpsManager.checkOp(AppOpsManager::OP_CAMERA, + mClientUid, mClientPackageName); + ALOGV("checkOp returns: %d, %s ", res, + res == AppOpsManager::MODE_ALLOWED ? "ALLOWED" : + res == AppOpsManager::MODE_IGNORED ? "IGNORED" : + res == AppOpsManager::MODE_ERRORED ? "ERRORED" : + "UNKNOWN"); + + if (res != AppOpsManager::MODE_ALLOWED) { + ALOGI("Camera %d: Access for \"%s\" revoked", mCameraId, + myName.string()); + // Reset the client PID to allow server-initiated disconnect, + // and to prevent further calls by client. + mClientPid = getCallingPid(); + notifyError(); + disconnect(); + } +} + // ---------------------------------------------------------------------------- Mutex* CameraService::Client::getClientLockFromCookie(void* user) { @@ -592,25 +685,43 @@ CameraService::Client* CameraService::Client::getClientFromCookie(void* user) { return client; } +void CameraService::Client::notifyError() { + mCameraClient->notifyCallback(CAMERA_MSG_ERROR, CAMERA_ERROR_RELEASED, 0); +} + // NOTE: function is idempotent void CameraService::Client::disconnect() { BasicClient::disconnect(); mCameraService->setCameraFree(mCameraId); } +CameraService::Client::OpsCallback::OpsCallback(wp<BasicClient> client): + mClient(client) { +} + +void CameraService::Client::OpsCallback::opChanged(int32_t op, + const String16& packageName) { + sp<BasicClient> client = mClient.promote(); + if (client != NULL) { + client->opChanged(op, packageName); + } +} + // ---------------------------------------------------------------------------- // IProCamera // ---------------------------------------------------------------------------- CameraService::ProClient::ProClient(const sp<CameraService>& cameraService, - const sp<IProCameraCallbacks>& remoteCallback, - int cameraId, - int cameraFacing, - int clientPid, - int servicePid) - : CameraService::BasicClient(cameraService, remoteCallback->asBinder(), - cameraId, cameraFacing, - clientPid, servicePid) + const sp<IProCameraCallbacks>& remoteCallback, + const String16& clientPackageName, + int cameraId, + int cameraFacing, + int clientPid, + uid_t clientUid, + int servicePid) + : CameraService::BasicClient(cameraService, remoteCallback->asBinder(), + clientPackageName, cameraId, cameraFacing, + clientPid, clientUid, servicePid) { mRemoteCallback = remoteCallback; } @@ -683,6 +794,10 @@ status_t CameraService::ProClient::cancelStream(int streamId) { return INVALID_OPERATION; } +void CameraService::ProClient::notifyError() { + ALOGE("%s: not implemented yet", __FUNCTION__); +} + // ---------------------------------------------------------------------------- static const int kDumpLockRetries = 50; diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 9e0f62a..b017505 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -19,7 +19,9 @@ #define ANDROID_SERVERS_CAMERA_CAMERASERVICE_H #include <utils/Vector.h> +#include <binder/AppOpsManager.h> #include <binder/BinderService.h> +#include <binder/IAppOpsCallback.h> #include <camera/ICameraService.h> #include <hardware/camera.h> @@ -54,9 +56,11 @@ public: virtual int32_t getNumberOfCameras(); virtual status_t getCameraInfo(int cameraId, struct CameraInfo* cameraInfo); - virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId); - virtual sp<IProCameraUser> - connect(const sp<IProCameraCallbacks>& cameraCb, int cameraId); + + virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId, + const String16& clientPackageName, int clientUid); + virtual sp<IProCameraUser> connect(const sp<IProCameraCallbacks>& cameraCb, + int cameraId); // Extra permissions checks virtual status_t onTransact(uint32_t code, const Parcel& data, @@ -100,9 +104,11 @@ public: protected: BasicClient(const sp<CameraService>& cameraService, const sp<IBinder>& remoteCallback, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid); virtual ~BasicClient(); @@ -117,12 +123,41 @@ public: sp<CameraService> mCameraService; // immutable after constructor int mCameraId; // immutable after constructor int mCameraFacing; // immutable after constructor + const String16 mClientPackageName; pid_t mClientPid; + uid_t mClientUid; // immutable after constructor pid_t mServicePid; // immutable after constructor // - The app-side Binder interface to receive callbacks from us wp<IBinder> mRemoteCallback; // immutable after constructor - }; + + // permissions management + status_t startCameraOps(); + status_t finishCameraOps(); + + // Notify client about a fatal error + virtual void notifyError() = 0; + private: + AppOpsManager mAppOpsManager; + + class OpsCallback : public BnAppOpsCallback { + public: + OpsCallback(wp<BasicClient> client); + virtual void opChanged(int32_t op, const String16& packageName); + + private: + wp<BasicClient> mClient; + + }; // class OpsCallback + + sp<OpsCallback> mOpsCallback; + // Track whether startCameraOps was called successfully, to avoid + // finishing what we didn't start. + bool mOpsActive; + + // IAppOpsCallback interface, indirected through opListener + virtual void opChanged(int32_t op, const String16& packageName); + }; // class BasicClient class Client : public BnCamera, public BasicClient { @@ -153,9 +188,11 @@ public: // Interface used by CameraService Client(const sp<CameraService>& cameraService, const sp<ICameraClient>& cameraClient, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid); ~Client(); @@ -169,19 +206,24 @@ public: // convert client from cookie. Client lock should be acquired before getting Client. static Client* getClientFromCookie(void* user); + virtual void notifyError(); + // Initialized in constructor // - The app-side Binder interface to receive callbacks from us sp<ICameraClient> mCameraClient; - }; + + }; // class Client class ProClient : public BnProCameraUser, public BasicClient { public: ProClient(const sp<CameraService>& cameraService, const sp<IProCameraCallbacks>& remoteCallback, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid); virtual ~ProClient(); @@ -217,9 +259,10 @@ public: virtual status_t cancelStream(int streamId); protected: - sp<IProCameraCallbacks> mRemoteCallback; + virtual void notifyError(); - }; + sp<IProCameraCallbacks> mRemoteCallback; + }; // class ProClient private: diff --git a/services/camera/libcameraservice/ProCamera2Client.cpp b/services/camera/libcameraservice/ProCamera2Client.cpp index c264e2a..eda3012 100644 --- a/services/camera/libcameraservice/ProCamera2Client.cpp +++ b/services/camera/libcameraservice/ProCamera2Client.cpp @@ -43,12 +43,14 @@ static int getCallingUid() { ProCamera2Client::ProCamera2Client(const sp<CameraService>& cameraService, const sp<IProCameraCallbacks>& remoteCallback, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid): - ProClient(cameraService, remoteCallback, - cameraId, cameraFacing, clientPid, servicePid), + ProClient(cameraService, remoteCallback, clientPackageName, + cameraId, cameraFacing, clientPid, clientUid, servicePid), mSharedCameraCallbacks(remoteCallback) { ATRACE_CALL(); diff --git a/services/camera/libcameraservice/ProCamera2Client.h b/services/camera/libcameraservice/ProCamera2Client.h index cd0a2ae..9f514f4 100644 --- a/services/camera/libcameraservice/ProCamera2Client.h +++ b/services/camera/libcameraservice/ProCamera2Client.h @@ -77,9 +77,11 @@ public: ProCamera2Client(const sp<CameraService>& cameraService, const sp<IProCameraCallbacks>& remoteCallback, + const String16& clientPackageName, int cameraId, int cameraFacing, int clientPid, + uid_t clientUid, int servicePid); virtual ~ProCamera2Client(); |