Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b01a870e authored by Austin Borger's avatar Austin Borger
Browse files

Resolve uid / pid early during connection

This CL further clusters identity resolution in a single place in each
of connect / connectDevice / initializeShimMetadata. This will mean that
checking the validity of the provided AttributionSource can occur in
the same place as legacy caller identity resolution, and one flag check
will be needed in each caller to connectHelper.

Flag: EXEMPT Strict mechanical refactor
Bug: 190657833
Test: atest CtsCameraTestCases, Camera1 + Camera2 apps
Change-Id: I2ba8e78e7419e956151ed54d6a2a88f7946774ce
parent 06cc325f
Loading
Loading
Loading
Loading
+55 −37
Original line number Original line Diff line number Diff line
@@ -1612,11 +1612,12 @@ Status CameraService::initializeShimMetadata(int cameraId) {
    Status ret = Status::ok();
    Status ret = Status::ok();
    sp<Client> tmp = nullptr;
    sp<Client> tmp = nullptr;


    logConnectionAttempt(getCallingPid(), kServiceName, cameraIdStr, API_1);
    int callingPid = getCallingPid();
    logConnectionAttempt(callingPid, kServiceName, cameraIdStr, API_1);


    if (!(ret = connectHelper<ICameraClient,Client>(
    if (!(ret = connectHelper<ICameraClient,Client>(
            sp<ICameraClient>{nullptr}, cameraIdStr, cameraId,
            sp<ICameraClient>{nullptr}, cameraIdStr, cameraId,
            kServiceName, /*systemNativeClient*/ false, {}, uid, USE_CALLING_PID,
            kServiceName, /*systemNativeClient*/ false, {}, uid, callingPid,
            API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
            API_1, /*shimUpdateOnly*/ true, /*oomScoreOffset*/ 0,
            /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
            /*targetSdkVersion*/ __ANDROID_API_FUTURE__,
            /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
            /*rotationOverride*/hardware::ICameraService::ROTATION_OVERRIDE_OVERRIDE_TO_PORTRAIT,
@@ -1690,7 +1691,7 @@ Status CameraService::getLegacyParametersLazy(int cameraId,
}
}


Status CameraService::validateConnectLocked(const std::string& cameraId,
Status CameraService::validateConnectLocked(const std::string& cameraId,
        const std::string& clientName8, /*inout*/int& clientUid, /*inout*/int& clientPid) const {
        const std::string& clientName8, int clientUid, int clientPid) const {


#ifdef __BRILLO__
#ifdef __BRILLO__
    UNUSED(clientName8);
    UNUSED(clientName8);
@@ -1734,36 +1735,24 @@ Status CameraService::validateConnectLocked(const std::string& cameraId,
    return Status::ok();
    return Status::ok();
}
}


Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
Status CameraService::errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId,
        const std::string& clientName, int& clientUid, int& clientPid) const {
        const std::string& clientName, bool isPid) const {
    int callingPid = getCallingPid();
    int callingPid = getCallingPid();
    int callingUid = getCallingUid();
    int callingUid = getCallingUid();

    // Check if we can trust clientUid
    if (clientUid == USE_CALLING_UID) {
        clientUid = callingUid;
    } else if (!isTrustedCallingUid(callingUid)) {
    ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
    ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
                "(don't trust clientUid %d)", callingPid, callingUid, clientUid);
            "(don't trust %s %d)", callingPid, callingUid, isPid ? "clientPid" : "clientUid",
            isPid ? clientPid : clientUid);
    return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
    return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
            "Untrusted caller (calling PID %d, UID %d) trying to "
            "Untrusted caller (calling PID %d, UID %d) trying to "
            "forward camera access to camera %s for client %s (PID %d, UID %d)",
            "forward camera access to camera %s for client %s (PID %d, UID %d)",
                callingPid, callingUid, cameraId.c_str(),
            getCallingPid(), getCallingUid(), cameraId.c_str(),
            clientName.c_str(), clientPid, clientUid);
            clientName.c_str(), clientPid, clientUid);
}
}


    // Check if we can trust clientPid
Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
    if (clientPid == USE_CALLING_PID) {
        const std::string& clientName, int clientUid, int clientPid) const {
        clientPid = callingPid;
    int callingPid = getCallingPid();
    } else if (!isTrustedCallingUid(callingUid)) {
    int callingUid = getCallingUid();
        ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
                "(don't trust clientPid %d)", callingPid, callingUid, clientPid);
        return STATUS_ERROR_FMT(ERROR_PERMISSION_DENIED,
                "Untrusted caller (calling PID %d, UID %d) trying to "
                "forward camera access to camera %s for client %s (PID %d, UID %d)",
                callingPid, callingUid, cameraId.c_str(),
                clientName.c_str(), clientPid, clientUid);
    }


    if (shouldRejectSystemCameraConnection(cameraId)) {
    if (shouldRejectSystemCameraConnection(cameraId)) {
        ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
        ALOGW("Attempting to connect to system-only camera id %s, connection rejected",
@@ -2156,10 +2145,28 @@ Status CameraService::connect(
            clientPackageNameMaybe);
            clientPackageNameMaybe);
    logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraIdStr, API_1);
    logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraIdStr, API_1);


    int clientUid = clientAttribution.uid;
    int clientPid = clientAttribution.pid;

    // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and
    // need a way to guarantee the caller identity early.

    // Check if we can trust clientUid
    if (!resolveClientUid(clientUid)) {
        return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName,
                /* isPid=*/ false);
    }

    // Check if we can trust clientUid
    if (!resolveClientPid(clientPid)) {
        return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName,
                /* isPid= */ true);
    }

    sp<Client> client = nullptr;
    sp<Client> client = nullptr;
    ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
    ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
            clientPackageName, /*systemNativeClient*/ false, {},
            clientPackageName, /*systemNativeClient*/ false, {},
            clientAttribution.uid, clientAttribution.pid, API_1,
            clientUid, clientPid, API_1,
            /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
            /*shimUpdateOnly*/ false, /*oomScoreOffset*/ 0, targetSdkVersion,
            rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);
            rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);


@@ -2275,6 +2282,22 @@ Status CameraService::connectDevice(
            clientPackageNameMaybe);
            clientPackageNameMaybe);
    logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraId, API_2);
    logConnectionAttempt(clientAttribution.pid, clientPackageName, cameraId, API_2);


    userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid);
    if (clientAttribution.uid == USE_CALLING_UID) {
        clientUserId = multiuser_get_user_id(callingUid);
    }

    // Resolve the client identity. In the near future, we will no longer rely on USE_CALLING_*, and
    // need a way to guarantee the caller identity early.

    int clientUid = clientAttribution.uid;
    int clientPid = callingPid;
    // Check if we can trust clientUid
    if (!resolveClientUid(clientUid)) {
        return errorNotTrusted(clientPid, clientUid, cameraId, clientPackageName,
                /* isPid= */ false);
    }

    if (oomScoreOffset < 0) {
    if (oomScoreOffset < 0) {
        std::string msg =
        std::string msg =
                fmt::sprintf("Cannot increase the priority of a client %s pid %d for "
                fmt::sprintf("Cannot increase the priority of a client %s pid %d for "
@@ -2284,11 +2307,6 @@ Status CameraService::connectDevice(
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
    }
    }


    userid_t clientUserId = multiuser_get_user_id(clientAttribution.uid);
    if (clientAttribution.uid == USE_CALLING_UID) {
        clientUserId = multiuser_get_user_id(callingUid);
    }

    // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
    // Automotive privileged client AID_AUTOMOTIVE_EVS using exterior system camera for use cases
    // such as rear view and surround view cannot be disabled.
    // such as rear view and surround view cannot be disabled.
    if ((!isAutomotivePrivilegedClient(callingUid) || !isAutomotiveExteriorSystemCamera(cameraId))
    if ((!isAutomotivePrivilegedClient(callingUid) || !isAutomotiveExteriorSystemCamera(cameraId))
@@ -2312,7 +2330,7 @@ Status CameraService::connectDevice(


    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb,
    ret = connectHelper<hardware::camera2::ICameraDeviceCallbacks,CameraDeviceClient>(cameraCb,
            cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient,
            cameraId, /*api1CameraId*/-1, clientPackageName, systemNativeClient,
            clientAttribution.attributionTag, clientAttribution.uid, USE_CALLING_PID, API_2,
            clientAttribution.attributionTag, clientUid, clientPid, API_2,
            /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
            /*shimUpdateOnly*/ false, oomScoreOffset, targetSdkVersion, rotationOverride,
            /*forceSlowJpegMode*/false, unresolvedCameraId, isNonSystemNdk, /*out*/client);
            /*forceSlowJpegMode*/false, unresolvedCameraId, isNonSystemNdk, /*out*/client);


+4 −2
Original line number Original line Diff line number Diff line
@@ -950,14 +950,16 @@ private:
    // If clientPid/clientUid are USE_CALLING_PID/USE_CALLING_UID, they will be overwritten with
    // If clientPid/clientUid are USE_CALLING_PID/USE_CALLING_UID, they will be overwritten with
    // the calling pid/uid.
    // the calling pid/uid.
    binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
    binder::Status validateConnectLocked(const std::string& cameraId, const std::string& clientName,
            /*inout*/int& clientUid, /*inout*/int& clientPid) const;
            int clientUid, int clientPid) const;
    binder::Status validateClientPermissionsLocked(const std::string& cameraId,
    binder::Status validateClientPermissionsLocked(const std::string& cameraId,
            const std::string& clientName, /*inout*/int& clientUid, /*inout*/int& clientPid) const;
            const std::string& clientName, int clientUid, int clientPid) const;


    // If clientPackageNameMaybe is empty, attempts to resolve the package name.
    // If clientPackageNameMaybe is empty, attempts to resolve the package name.
    std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const;
    std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const;
    void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
    void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
        const std::string& cameraId, apiLevel effectiveApiLevel) const;
        const std::string& cameraId, apiLevel effectiveApiLevel) const;
    binder::Status errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId,
            const std::string& clientName, bool isPid) const;


    bool isCameraPrivacyEnabled(const String16& packageName,const std::string& cameraId,
    bool isCameraPrivacyEnabled(const String16& packageName,const std::string& cameraId,
           int clientPid, int ClientUid);
           int clientPid, int ClientUid);
+27 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,33 @@ void AttributionAndPermissionUtils::restoreCallingIdentity(int64_t token) {
    return;
    return;
}
}


// TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum.
bool AttributionAndPermissionUtils::resolveClientUid(/*inout*/ int& clientUid) {
    int callingUid = getCallingUid();

    if (clientUid == hardware::ICameraService::USE_CALLING_UID) {
        clientUid = callingUid;
    } else if (!isTrustedCallingUid(callingUid)) {
        return false;
    }

    return true;
}

// TODO(362551824): Make USE_CALLING_UID more explicit with a scoped enum.
bool AttributionAndPermissionUtils::resolveClientPid(/*inout*/ int& clientPid) {
    int callingUid = getCallingUid();
    int callingPid = getCallingPid();

    if (clientPid == hardware::ICameraService::USE_CALLING_PID) {
        clientPid = callingPid;
    } else if (!isTrustedCallingUid(callingUid)) {
        return false;
    }

    return true;
}

bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId,
bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId,
        const AttributionSourceState &attributionSource) {
        const AttributionSourceState &attributionSource) {
    if (isAutomotivePrivilegedClient(attributionSource.uid)) {
    if (isAutomotivePrivilegedClient(attributionSource.uid)) {
+11 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,9 @@ class AttributionAndPermissionUtils {
    virtual int64_t clearCallingIdentity();
    virtual int64_t clearCallingIdentity();
    virtual void restoreCallingIdentity(int64_t token);
    virtual void restoreCallingIdentity(int64_t token);


    virtual bool resolveClientUid(/*inout*/ int& clientUid);
    virtual bool resolveClientPid(/*inout*/ int& clientPid);

    /**
    /**
     * Pre-grants the permission if the attribution source uid is for an automotive
     * Pre-grants the permission if the attribution source uid is for an automotive
     * privileged client. Otherwise uses system service permission checker to check
     * privileged client. Otherwise uses system service permission checker to check
@@ -170,6 +173,14 @@ public:
        mAttributionAndPermissionUtils->restoreCallingIdentity(token);
        mAttributionAndPermissionUtils->restoreCallingIdentity(token);
    }
    }


    bool resolveClientUid(/*inout*/ int& clientUid) const {
        return mAttributionAndPermissionUtils->resolveClientUid(clientUid);
    }

    bool resolveClientPid(/*inout*/ int& clientPid) const {
        return mAttributionAndPermissionUtils->resolveClientPid(clientPid);
    }

    // The word 'System' here does not refer to callers only on the system
    // The word 'System' here does not refer to callers only on the system
    // partition. They just need to have an android system uid.
    // partition. They just need to have an android system uid.
    bool callerHasSystemUid() const {
    bool callerHasSystemUid() const {