OSDN Git Service

ProCamera: Add security permission checks for disabling transmit LED
authorIgor Murashkin <iam@google.com>
Tue, 23 Apr 2013 21:51:29 +0000 (14:51 -0700)
committerIgor Murashkin <iam@google.com>
Thu, 25 Apr 2013 21:05:25 +0000 (14:05 -0700)
Bug: 8554573
Change-Id: Ie909908a4cab3700bd622282e8342e8fa5b72376

services/camera/libcameraservice/ProCamera2Client.cpp
services/camera/libcameraservice/ProCamera2Client.h
services/camera/libcameraservice/camera2/Parameters.cpp

index 575b075..251fdab 100644 (file)
@@ -203,6 +203,10 @@ status_t ProCamera2Client::submitRequest(camera_metadata_t* request,
 
     CameraMetadata metadata(request);
 
+    if (!enforceRequestPermissions(metadata)) {
+        return PERMISSION_DENIED;
+    }
+
     if (streaming) {
         return mDevice->setStreamingRequest(metadata);
     } else {
@@ -388,4 +392,55 @@ void ProCamera2Client::onFrameAvailable(int32_t frameId,
 
 }
 
+bool ProCamera2Client::enforceRequestPermissions(CameraMetadata& metadata) {
+
+    const int pid = IPCThreadState::self()->getCallingPid();
+    const int selfPid = getpid();
+    camera_metadata_entry_t entry;
+
+    /**
+     * Mixin default important security values
+     * - android.led.transmit = defaulted ON
+     */
+    CameraMetadata staticInfo = mDevice->info();
+    entry = staticInfo.find(ANDROID_LED_AVAILABLE_LEDS);
+    for(size_t i = 0; i < entry.count; ++i) {
+        uint8_t led = entry.data.u8[i];
+
+        switch(led) {
+            case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
+                uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
+                if (!metadata.exists(ANDROID_LED_TRANSMIT)) {
+                    metadata.update(ANDROID_LED_TRANSMIT,
+                                    &transmitDefault, 1);
+                }
+                break;
+            }
+        }
+    }
+
+    // We can do anything!
+    if (pid == selfPid) {
+        return true;
+    }
+
+    /**
+     * Permission check special fields in the request
+     * - android.led.transmit = android.permission.CAMERA_DISABLE_TRANSMIT
+     */
+    entry = metadata.find(ANDROID_LED_TRANSMIT);
+    if (entry.count > 0 && entry.data.u8[0] != ANDROID_LED_TRANSMIT_ON) {
+        String16 permissionString =
+            String16("android.permission.CAMERA_DISABLE_TRANSMIT_LED");
+        if (!checkCallingPermission(permissionString)) {
+            const int uid = IPCThreadState::self()->getCallingUid();
+            ALOGE("Permission Denial: "
+                  "can't disable transmit LED pid=%d, uid=%d", pid, uid);
+            return false;
+        }
+    }
+
+    return true;
+}
+
 } // namespace android
index 1dec263..faee9f9 100644 (file)
@@ -110,6 +110,7 @@ private:
     static const int32_t FRAME_PROCESSOR_LISTENER_MAX_ID = 0x7fffffffL;
 
     /** Utility members */
+    bool enforceRequestPermissions(CameraMetadata& metadata);
 
     // Whether or not we have an exclusive lock on the device
     // - if no we can't modify the request queue.
index d13fe8b..a304b35 100644 (file)
@@ -1588,6 +1588,32 @@ status_t Parameters::updateRequest(CameraMetadata *request) const {
     ATRACE_CALL();
     status_t res;
 
+    /**
+     * Mixin default important security values
+     * - android.led.transmit = defaulted ON
+     */
+    camera_metadata_ro_entry_t entry = staticInfo(ANDROID_LED_AVAILABLE_LEDS,
+                                                  /*minimumCount*/0);
+    for(size_t i = 0; i < entry.count; ++i) {
+        uint8_t led = entry.data.u8[i];
+
+        switch(led) {
+            // Transmit LED is unconditionally on when using
+            // the android.hardware.Camera API
+            case ANDROID_LED_AVAILABLE_LEDS_TRANSMIT: {
+                uint8_t transmitDefault = ANDROID_LED_TRANSMIT_ON;
+                res = request->update(ANDROID_LED_TRANSMIT,
+                                      &transmitDefault, 1);
+                if (res != OK) return res;
+                break;
+            }
+        }
+    }
+
+    /**
+     * Construct metadata from parameters
+     */
+
     uint8_t metadataMode = ANDROID_REQUEST_METADATA_MODE_FULL;
     res = request->update(ANDROID_REQUEST_METADATA_MODE,
             &metadataMode, 1);