diff options
Diffstat (limited to 'services/camera')
| -rw-r--r-- | services/camera/libcameraservice/CameraService.cpp | 83 | ||||
| -rw-r--r-- | services/camera/libcameraservice/CameraService.h | 34 | 
2 files changed, 78 insertions, 39 deletions
diff --git a/services/camera/libcameraservice/CameraService.cpp b/services/camera/libcameraservice/CameraService.cpp index 59e1c37..fc9a332 100644 --- a/services/camera/libcameraservice/CameraService.cpp +++ b/services/camera/libcameraservice/CameraService.cpp @@ -122,8 +122,8 @@ static void torch_mode_status_change(  // should be ok for now.  static CameraService *gCameraService; -CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), -        mLastUserId(DEFAULT_LAST_USER_ID), mSoundRef(0), mModule(0), mFlashlight(0) { +CameraService::CameraService() : mEventLog(DEFAULT_EVENT_LOG_LENGTH), mAllowedUsers(), +        mSoundRef(0), mModule(0), mFlashlight(0) {      ALOGI("CameraService started (pid=%d)", getpid());      gCameraService = this; @@ -676,6 +676,20 @@ status_t CameraService::makeClient(const sp<CameraService>& cameraService,      return NO_ERROR;  } +String8 CameraService::toString(std::set<userid_t> intSet) { +    String8 s(""); +    bool first = true; +    for (userid_t i : intSet) { +        if (first) { +            s.appendFormat("%d", i); +            first = false; +        } else { +            s.appendFormat(", %d", i); +        } +    } +    return s; +} +  status_t CameraService::initializeShimMetadata(int cameraId) {      int uid = getCallingUid(); @@ -783,7 +797,7 @@ status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/      // Check device policy for this camera      char value[PROPERTY_VALUE_MAX];      char key[PROPERTY_KEY_MAX]; -    int clientUserId = multiuser_get_user_id(clientUid); +    userid_t clientUserId = multiuser_get_user_id(clientUid);      snprintf(key, PROPERTY_KEY_MAX, "sys.secpolicy.camera.off_%d", clientUserId);      property_get(key, value, "0");      if (strcmp(value, "1") == 0) { @@ -795,10 +809,10 @@ status_t CameraService::validateConnectLocked(const String8& cameraId, /*inout*/      // Only allow clients who are being used by the current foreground device user, unless calling      // from our own process. -    if (callingPid != getpid() && -            (mLastUserId != clientUserId && mLastUserId != DEFAULT_LAST_USER_ID)) { -        ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from previous " -                "device user %d, current device user %d)", callingPid, clientUserId, mLastUserId); +    if (callingPid != getpid() && (mAllowedUsers.find(clientUserId) == mAllowedUsers.end())) { +        ALOGE("CameraService::connect X (PID %d) rejected (cannot connect from " +                "device user %d, currently allowed device users: %s)", callingPid, clientUserId, +                toString(mAllowedUsers).string());          return PERMISSION_DENIED;      } @@ -1197,10 +1211,10 @@ status_t CameraService::setTorchMode(const String16& cameraId, bool enabled,      return OK;  } -void CameraService::notifySystemEvent(int eventId, int arg0) { +void CameraService::notifySystemEvent(int32_t eventId, const int32_t* args, size_t length) {      switch(eventId) {          case ICameraService::USER_SWITCHED: { -            doUserSwitch(/*newUserId*/arg0); +            doUserSwitch(/*newUserIds*/args, /*length*/length);              break;          }          case ICameraService::NO_EVENT: @@ -1443,20 +1457,30 @@ sp<CameraService::BasicClient> CameraService::removeClientLocked(const String8&      return clientDescriptorPtr->getValue();  } -void CameraService::doUserSwitch(int newUserId) { +void CameraService::doUserSwitch(const int32_t* newUserId, size_t length) {      // Acquire mServiceLock and prevent other clients from connecting      std::unique_ptr<AutoConditionLock> lock =              AutoConditionLock::waitAndAcquire(mServiceLockWrapper); -    if (newUserId <= 0) { -        ALOGW("%s: Bad user ID %d given during user switch, resetting to default.", __FUNCTION__, -                newUserId); -        newUserId = DEFAULT_LAST_USER_ID; +    std::set<userid_t> newAllowedUsers; +    for (size_t i = 0; i < length; i++) { +        if (newUserId[i] < 0) { +            ALOGE("%s: Bad user ID %d given during user switch, ignoring.", +                    __FUNCTION__, newUserId[i]); +            return; +        } +        newAllowedUsers.insert(static_cast<userid_t>(newUserId[i])); +    } + + +    if (newAllowedUsers == mAllowedUsers) { +        ALOGW("%s: Received notification of user switch with no updated user IDs.", __FUNCTION__); +        return;      } -    logUserSwitch(mLastUserId, newUserId); +    logUserSwitch(mAllowedUsers, newAllowedUsers); -    mLastUserId = newUserId; +    mAllowedUsers = std::move(newAllowedUsers);      // Current user has switched, evict all current clients.      std::vector<sp<BasicClient>> evicted; @@ -1468,6 +1492,13 @@ void CameraService::doUserSwitch(int newUserId) {              continue;          } +        // Don't evict clients that are still allowed. +        uid_t clientUid = clientSp->getClientUid(); +        userid_t clientUserId = multiuser_get_user_id(clientUid); +        if (mAllowedUsers.find(clientUserId) != mAllowedUsers.end()) { +            continue; +        } +          evicted.push_back(clientSp);          String8 curTime = getFormattedCurrentTime(); @@ -1527,10 +1558,13 @@ void CameraService::logRejected(const char* cameraId, int clientPid,              cameraId, clientPackage, clientPid, reason));  } -void CameraService::logUserSwitch(int oldUserId, int newUserId) { +void CameraService::logUserSwitch(const std::set<userid_t>& oldUserIds, +        const std::set<userid_t>& newUserIds) { +    String8 newUsers = toString(newUserIds); +    String8 oldUsers = toString(oldUserIds);      // Log the new and old users -    logEvent(String8::format("USER_SWITCH from old user: %d , to new user: %d", oldUserId, -            newUserId)); +    logEvent(String8::format("USER_SWITCH previous allowed users: %s , current allowed users: %s", +            oldUsers.string(), newUsers.string()));  }  void CameraService::logDeviceRemoved(const char* cameraId, const char* reason) { @@ -1735,6 +1769,10 @@ int CameraService::BasicClient::getClientPid() const {      return mClientPid;  } +uid_t CameraService::BasicClient::getClientUid() const { +    return mClientUid; +} +  bool CameraService::BasicClient::canCastToApiClient(apiLevel level) const {      // Defaults to API2.      return level == API_2; @@ -1937,12 +1975,18 @@ String8 CameraService::CameraClientManager::toString() const {          auto conflicting = i->getConflicting();          auto clientSp = i->getValue();          String8 packageName; +        userid_t clientUserId;          if (clientSp.get() != nullptr) {              packageName = String8{clientSp->getPackageName()}; +            uid_t clientUid = clientSp->getClientUid(); +            clientUserId = multiuser_get_user_id(clientUid);          }          ret.appendFormat("\n(Camera ID: %s, Cost: %" PRId32 ", PID: %" PRId32 ", Priority: %"                  PRId32 ", ", key.string(), cost, pid, priority); +        if (clientSp.get() != nullptr) { +            ret.appendFormat("User Id: %d, ", clientUserId); +        }          if (packageName.size() != 0) {              ret.appendFormat("Client Package Name: %s", packageName.string());          } @@ -2025,6 +2069,7 @@ status_t CameraService::dump(int fd, const Vector<String16>& args) {          result.appendFormat("Number of camera devices: %d\n", mNumberOfCameras);          String8 activeClientString = mActiveClientManager.toString();          result.appendFormat("Active Camera Clients:\n%s", activeClientString.string()); +        result.appendFormat("Allowed users:\n%s\n", toString(mAllowedUsers).string());          sp<VendorTagDescriptor> desc = VendorTagDescriptor::getGlobalVendorTagDescriptor();          if (desc == NULL) { diff --git a/services/camera/libcameraservice/CameraService.h b/services/camera/libcameraservice/CameraService.h index 1041550..9b7163a 100644 --- a/services/camera/libcameraservice/CameraService.h +++ b/services/camera/libcameraservice/CameraService.h @@ -83,11 +83,6 @@ public:      // Default number of messages to store in eviction log      static const size_t DEFAULT_EVENT_LOG_LENGTH = 100; -    enum { -        // Default last user id -        DEFAULT_LAST_USER_ID = 0, -    }; -      // Implementation of BinderService<T>      static char const* getServiceName() { return "media.camera"; } @@ -141,7 +136,7 @@ public:      virtual status_t    setTorchMode(const String16& cameraId, bool enabled,              const sp<IBinder>& clientBinder); -    virtual void notifySystemEvent(int eventId, int arg0); +    virtual void notifySystemEvent(int32_t eventId, const int32_t* args, size_t length);      // OK = supports api of that version, -EOPNOTSUPP = does not support      virtual status_t    supportsCameraApi( @@ -200,6 +195,9 @@ public:          virtual void notifyError(ICameraDeviceCallbacks::CameraErrorCode errorCode,                  const CaptureResultExtras& resultExtras) = 0; +        // Get the UID of the application client using this +        virtual uid_t getClientUid() const; +          // Get the PID of the application client using this          virtual int getClientPid() const; @@ -469,7 +467,6 @@ private:              const String16& clientPackageName, int clientUid, apiLevel effectiveApiLevel,              bool legacyMode, bool shimUpdateOnly, /*out*/sp<CLIENT>& device); -      // Lock guarding camera service state      Mutex               mServiceLock; @@ -492,8 +489,8 @@ private:      RingBuffer<String8> mEventLog;      Mutex mLogLock; -    // UID of last user. -    int mLastUserId; +    // Currently allowed user IDs +    std::set<userid_t> mAllowedUsers;      /**       * Get the camera state for a given camera id. @@ -542,7 +539,7 @@ private:      /**       * Handle a notification that the current device user has changed.       */ -    void doUserSwitch(int newUserId); +    void doUserSwitch(const int32_t* newUserId, size_t length);      /**       * Add an event log message. @@ -568,7 +565,8 @@ private:      /**       * Add an event log message that the current device user has been switched.       */ -    void logUserSwitch(int oldUserId, int newUserId); +    void logUserSwitch(const std::set<userid_t>& oldUserIds, +        const std::set<userid_t>& newUserIds);      /**       * Add an event log message that a device has been removed by the HAL @@ -699,6 +697,11 @@ private:              int facing, int clientPid, uid_t clientUid, int servicePid, bool legacyMode,              int halVersion, int deviceVersion, apiLevel effectiveApiLevel,              /*out*/sp<BasicClient>* client); + +    status_t checkCameraAccess(const String16& opPackageName); + +    static String8 toString(std::set<userid_t> intSet); +  };  template<class Func> @@ -775,15 +778,6 @@ status_t CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const String          if((ret = validateConnectLocked(cameraId, /*inout*/clientUid)) != NO_ERROR) {              return ret;          } -        int userId = multiuser_get_user_id(clientUid); - -        if (userId != mLastUserId && clientPid != getpid() ) { -            // If no previous user ID had been set, set to the user of the caller. -            logUserSwitch(mLastUserId, userId); -            LOG_ALWAYS_FATAL_IF(mLastUserId != DEFAULT_LAST_USER_ID, -                    "Invalid state: Should never update user ID here unless was default"); -            mLastUserId = userId; -        }          // Check the shim parameters after acquiring lock, if they have already been updated and          // we were doing a shim update, return immediately  | 
