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

Commit 7d65012d authored by Austin Borger's avatar Austin Borger Committed by Android (Google) Code Review
Browse files

Merge "Use context AttributionSource as the identity source-of-truth for connection" into main

parents 3d088071 95a0015e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -164,3 +164,10 @@ flag {
    description: "Enable stream reconfiguration for unchanged streams"
    bug: "341740105"
}

flag {
    namespace: "camera_platform"
    name: "use_context_attribution_source"
    description: "Use the context-provided AttributionSource when checking for client permissions"
    bug: "190657833"
}
+50 −92
Original line number Diff line number Diff line
@@ -1725,20 +1725,6 @@ Status CameraService::validateConnectLocked(const std::string& cameraId,
    return Status::ok();
}

Status CameraService::errorNotTrusted(int clientPid, int clientUid, const std::string& cameraId,
        const std::string& clientName, bool isPid) const {
    int callingPid = getCallingPid();
    int callingUid = getCallingUid();
    ALOGE("CameraService::connect X (calling PID %d, calling UID %d) rejected "
            "(don't trust %s %d)", callingPid, callingUid, isPid ? "clientPid" : "clientUid",
            isPid ? clientPid : clientUid);
    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)",
            getCallingPid(), getCallingUid(), cameraId.c_str(),
            clientName.c_str(), clientPid, clientUid);
}

Status CameraService::validateClientPermissionsLocked(const std::string& cameraId,
        const std::string& clientName, int clientUid, int clientPid) const {
    int callingPid = getCallingPid();
@@ -2131,27 +2117,21 @@ Status CameraService::connect(

    std::string clientPackageNameMaybe = clientAttribution.packageName.value_or("");
    bool isNonSystemNdk = clientPackageNameMaybe.size() == 0;
    std::string clientPackageName = resolvePackageName(clientAttribution.uid,
            clientPackageNameMaybe);
    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);
    AttributionSourceState resolvedClientAttribution(clientAttribution);
    ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraIdStr);
    if (!ret.isOk()) {
        logRejected(cameraIdStr, getCallingPid(),
                    clientAttribution.packageName.value_or("<unknown>"),
                    toStdString(ret.toString8()));
        return ret;
    }

    // Check if we can trust clientUid
    if (!resolveClientPid(clientPid)) {
        return errorNotTrusted(clientPid, clientUid, cameraIdStr, clientPackageName,
                /* isPid= */ true);
    }
    const int clientPid = resolvedClientAttribution.pid;
    const int clientUid = resolvedClientAttribution.uid;
    const std::string& clientPackageName = *resolvedClientAttribution.packageName;

    logConnectionAttempt(clientPid, clientPackageName, cameraIdStr, API_1);

    sp<Client> client = nullptr;
    ret = connectHelper<ICameraClient,Client>(cameraClient, cameraIdStr, api1CameraId,
@@ -2161,7 +2141,8 @@ Status CameraService::connect(
            rotationOverride, forceSlowJpegMode, cameraIdStr, isNonSystemNdk, /*out*/client);

    if (!ret.isOk()) {
        logRejected(cameraIdStr, getCallingPid(), clientAttribution.packageName.value_or(""),
        logRejected(cameraIdStr, getCallingPid(),
                    clientAttribution.packageName.value_or("<unknown>"),
                    toStdString(ret.toString8()));
        return ret;
    }
@@ -2268,31 +2249,30 @@ Status CameraService::connectDevice(
    std::string cameraId = cameraIdOptional.value();

    bool isNonSystemNdk = clientPackageNameMaybe.size() == 0;
    std::string clientPackageName = resolvePackageName(clientAttribution.uid,
            clientPackageNameMaybe);
    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);
    AttributionSourceState resolvedClientAttribution(clientAttribution);
    if (!flags::use_context_attribution_source()) {
        resolvedClientAttribution.pid = USE_CALLING_PID;
    }
    ret = resolveAttributionSource(resolvedClientAttribution, __FUNCTION__, cameraId);
    if (!ret.isOk()) {
        logRejected(cameraId, getCallingPid(), clientAttribution.packageName.value_or(""),
                    toStdString(ret.toString8()));
        return ret;
    }

    // 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.
    const int clientPid = resolvedClientAttribution.pid;
    const int clientUid = resolvedClientAttribution.uid;
    const std::string& clientPackageName = *resolvedClientAttribution.packageName;
    userid_t clientUserId = multiuser_get_user_id(resolvedClientAttribution.uid);

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

    if (oomScoreOffset < 0) {
        std::string msg =
                fmt::sprintf("Cannot increase the priority of a client %s pid %d for "
                        "camera id %s", clientPackageName.c_str(), callingPid,
                        cameraId.c_str());
        std::string msg = fmt::sprintf(
                "Cannot increase the priority of a client %s pid %d for "
                "camera id %s",
                clientPackageName.c_str(), clientPid, cameraId.c_str());
        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
        return STATUS_ERROR(ERROR_ILLEGAL_ARGUMENT, msg.c_str());
    }
@@ -2307,25 +2287,24 @@ Status CameraService::connectDevice(
    }

    // enforce system camera permissions
    if (oomScoreOffset > 0
            && !hasPermissionsForSystemCamera(cameraId, callingPid,
                    callingUid)
            && !isTrustedCallingUid(callingUid)) {
        std::string msg = fmt::sprintf("Cannot change the priority of a client %s pid %d for "
    if (oomScoreOffset > 0 && !hasPermissionsForSystemCamera(cameraId, clientPid, callingUid) &&
        !isTrustedCallingUid(callingUid)) {
        std::string msg = fmt::sprintf(
                "Cannot change the priority of a client %s pid %d for "
                "camera id %s without SYSTEM_CAMERA permissions",
                        clientPackageName.c_str(), callingPid, cameraId.c_str());
                clientPackageName.c_str(), clientPid, cameraId.c_str());
        ALOGE("%s: %s", __FUNCTION__, msg.c_str());
        return STATUS_ERROR(ERROR_PERMISSION_DENIED, msg.c_str());
    }

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

    if (!ret.isOk()) {
        logRejected(cameraId, callingPid, clientPackageName, toStdString(ret.toString8()));
        logRejected(cameraId, clientPid, clientPackageName, toStdString(ret.toString8()));
        return ret;
    }

@@ -2386,30 +2365,14 @@ bool CameraService::isCameraPrivacyEnabled(const String16& packageName, const st
}

void CameraService::logConnectionAttempt(int clientPid, const std::string& clientPackageName,
        const std::string& cameraId, apiLevel effectiveApiLevel) const {
    int packagePid = (clientPid == USE_CALLING_PID) ?
        getCallingPid() : clientPid;
                                         const std::string& cameraId,
                                         apiLevel effectiveApiLevel) const {
    ALOGI("CameraService::connect call (PID %d \"%s\", camera ID %s) and "
            "Camera API version %d", packagePid, clientPackageName.c_str(), cameraId.c_str(),
          "Camera API version %d",
          clientPid, clientPackageName.c_str(), cameraId.c_str(),
          static_cast<int>(effectiveApiLevel));
}

std::string CameraService::resolvePackageName(int clientUid,
        const std::string& clientPackageNameMaybe) const {
    if (clientPackageNameMaybe.size() <= 0) {
        int packageUid = (clientUid == USE_CALLING_UID) ?
                getCallingUid() : clientUid;
        // NDK calls don't come with package names, but we need one for various cases.
        // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
        // do exist. For all authentication cases, all packages under the same UID get the
        // same permissions, so picking any associated package name is sufficient. For some
        // other cases, this may give inaccurate names for clients in logs.
        return getPackageNameFromUid(packageUid);
    } else {
        return clientPackageNameMaybe;
    }
}

template<class CALLBACK, class CLIENT>
Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::string& cameraId,
        int api1CameraId, const std::string& clientPackageName, bool systemNativeClient,
@@ -2419,11 +2382,6 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str
        const std::string& originalCameraId, bool isNonSystemNdk, /*out*/sp<CLIENT>& device) {
    binder::Status ret = binder::Status::ok();

    int packageUid = (clientUid == USE_CALLING_UID) ?
            getCallingUid() : clientUid;
    int packagePid = (clientPid == USE_CALLING_PID) ?
            getCallingPid() : clientPid;

    nsecs_t openTimeNs = systemTime();

    sp<CLIENT> client = nullptr;
@@ -2643,7 +2601,7 @@ Status CameraService::connectHelper(const sp<CALLBACK>& cameraCb, const std::str
        if (flags::camera_privacy_allowlist()) {
            // Set camera muting behavior.
            isCameraPrivacyEnabled = this->isCameraPrivacyEnabled(
                    toString16(client->getPackageName()), cameraId, packagePid, packageUid);
                    toString16(client->getPackageName()), cameraId, clientPid, clientUid);
        } else {
            isCameraPrivacyEnabled =
                    mSensorPrivacyPolicy->isCameraPrivacyEnabled();
+0 −4
Original line number Diff line number Diff line
@@ -934,12 +934,8 @@ private:
    binder::Status validateClientPermissionsLocked(const std::string& cameraId,
            const std::string& clientName, int clientUid, int clientPid) const;

    // If clientPackageNameMaybe is empty, attempts to resolve the package name.
    std::string resolvePackageName(int clientUid, const std::string& clientPackageNameMaybe) const;
    void logConnectionAttempt(int clientPid, const std::string& clientPackageName,
        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,
           int clientPid, int ClientUid);
+138 −74
Original line number Diff line number Diff line
@@ -14,6 +14,9 @@
 * limitations under the License.
 */

#define LOG_TAG "AttributionAndPermissionUtils"
#define ATRACE_TAG ATRACE_TAG_CAMERA

#include "AttributionAndPermissionUtils.h"

#include <binder/AppOpsManager.h>
@@ -25,12 +28,12 @@
#include "CameraService.h"

#include <binder/IPCThreadState.h>
#include <hwbinder/IPCThreadState.h>
#include <binderthreadstate/CallerUtils.h>
#include <hwbinder/IPCThreadState.h>

namespace {
static const std::string kPermissionServiceName = "permission";
} // namespace anonymous
} // namespace

namespace android {

@@ -39,8 +42,7 @@ namespace flags = com::android::internal::camera::flags;
const std::string AttributionAndPermissionUtils::sDumpPermission("android.permission.DUMP");
const std::string AttributionAndPermissionUtils::sManageCameraPermission(
        "android.permission.MANAGE_CAMERA");
const std::string AttributionAndPermissionUtils::sCameraPermission(
        "android.permission.CAMERA");
const std::string AttributionAndPermissionUtils::sCameraPermission("android.permission.CAMERA");
const std::string AttributionAndPermissionUtils::sSystemCameraPermission(
        "android.permission.SYSTEM_CAMERA");
const std::string AttributionAndPermissionUtils::sCameraHeadlessSystemUserPermission(
@@ -54,14 +56,14 @@ const std::string AttributionAndPermissionUtils::sCameraOpenCloseListenerPermiss
const std::string AttributionAndPermissionUtils::sCameraInjectExternalCameraPermission(
        "android.permission.CAMERA_INJECT_EXTERNAL_CAMERA");

int AttributionAndPermissionUtils::getCallingUid() {
int AttributionAndPermissionUtils::getCallingUid() const {
    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
        return hardware::IPCThreadState::self()->getCallingUid();
    }
    return IPCThreadState::self()->getCallingUid();
}

int AttributionAndPermissionUtils::getCallingPid() {
int AttributionAndPermissionUtils::getCallingPid() const {
    if (getCurrentServingCall() == BinderCallType::HWBINDER) {
        return hardware::IPCThreadState::self()->getCallingPid();
    }
@@ -84,60 +86,31 @@ void AttributionAndPermissionUtils::restoreCallingIdentity(int64_t token) {
    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;
binder::Status AttributionAndPermissionUtils::resolveAttributionSource(
        /*inout*/ AttributionSourceState& resolvedAttributionSource, const std::string& methodName,
        const std::optional<std::string>& cameraIdMaybe) {
    // Check if we can trust clientUid
    if (!resolveClientUid(resolvedAttributionSource.uid)) {
        return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid,
                               methodName, cameraIdMaybe, *resolvedAttributionSource.packageName,
                               /* isPid= */ false);
    }

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

    if (clientPid == hardware::ICameraService::USE_CALLING_PID) {
        clientPid = callingPid;
    } else if (!isTrustedCallingUid(callingUid)) {
        return false;
    if (!resolveClientPid(resolvedAttributionSource.pid)) {
        return errorNotTrusted(resolvedAttributionSource.pid, resolvedAttributionSource.uid,
                               methodName, cameraIdMaybe, *resolvedAttributionSource.packageName,
                               /* isPid= */ true);
    }

    return true;
    return binder::Status::ok();
}

bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(const std::string &cameraId,
        const AttributionSourceState &attributionSource) {
    if (isAutomotivePrivilegedClient(attributionSource.uid)) {
        // If cameraId is empty, then it means that this check is not used for the
        // purpose of accessing a specific camera, hence grant permission just
        // based on uid to the automotive privileged client.
        if (cameraId.empty())
            return true;

        auto cameraService = mCameraService.promote();
        if (cameraService == nullptr) {
            ALOGE("%s: CameraService unavailable.", __FUNCTION__);
            return false;
        }

        // If this call is used for accessing a specific camera then cam_id must be provided.
        // In that case, only pre-grants the permission for accessing the exterior system only
        // camera.
        return cameraService->isAutomotiveExteriorSystemCamera(cameraId);
    }

    return false;
}

bool AttributionAndPermissionUtils::checkPermissionForPreflight(const std::string &cameraId,
        const std::string &permission, const AttributionSourceState &attributionSource,
        const std::string& message, int32_t attributedOpCode) {
bool AttributionAndPermissionUtils::checkPermissionForPreflight(
        const std::string& cameraId, const std::string& permission,
        const AttributionSourceState& attributionSource, const std::string& message,
        int32_t attributedOpCode) {
    if (checkAutomotivePrivilegedClient(cameraId, attributionSource)) {
        return true;
    }
@@ -177,8 +150,7 @@ bool AttributionAndPermissionUtils::isHeadlessSystemUserMode() {

bool AttributionAndPermissionUtils::isAutomotivePrivilegedClient(int32_t uid) {
    // Returns false if this is not an automotive device type.
    if (!isAutomotiveDevice())
        return false;
    if (!isAutomotiveDevice()) return false;

    // Returns true if the uid is AID_AUTOMOTIVE_EVS which is a
    // privileged client uid used for safety critical use cases such as
@@ -213,8 +185,8 @@ std::string AttributionAndPermissionUtils::getPackageNameFromUid(int clientUid)
    return packageName;
}

status_t AttributionAndPermissionUtils::getUidForPackage(const std::string &packageName,
        int userId, /*inout*/uid_t& uid, int err) {
status_t AttributionAndPermissionUtils::getUidForPackage(const std::string& packageName, int userId,
                                                         /*inout*/ uid_t& uid, int err) {
    PermissionController pc;
    uid = pc.getPackageUid(toString16(packageName), 0);
    if (uid <= 0) {
@@ -237,18 +209,20 @@ bool AttributionAndPermissionUtils::isCallerCameraServerNotDelegating() {
    return (getCallingPid() == getpid());
}

bool AttributionAndPermissionUtils::hasPermissionsForCamera(const std::string& cameraId,
        const AttributionSourceState& attributionSource) {
    return checkPermissionForPreflight(cameraId, sCameraPermission,
            attributionSource, std::string(), AppOpsManager::OP_NONE);
bool AttributionAndPermissionUtils::hasPermissionsForCamera(
        const std::string& cameraId, const AttributionSourceState& attributionSource) {
    return checkPermissionForPreflight(cameraId, sCameraPermission, attributionSource,
                                       std::string(), AppOpsManager::OP_NONE);
}

bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera(const std::string& cameraId,
        const AttributionSourceState& attributionSource, bool checkCameraPermissions) {
    bool systemCameraPermission = checkPermissionForPreflight(cameraId,
            sSystemCameraPermission, attributionSource, std::string(), AppOpsManager::OP_NONE);
    return systemCameraPermission && (!checkCameraPermissions
            || hasPermissionsForCamera(cameraId, attributionSource));
bool AttributionAndPermissionUtils::hasPermissionsForSystemCamera(
        const std::string& cameraId, const AttributionSourceState& attributionSource,
        bool checkCameraPermissions) {
    bool systemCameraPermission =
            checkPermissionForPreflight(cameraId, sSystemCameraPermission, attributionSource,
                                        std::string(), AppOpsManager::OP_NONE);
    return systemCameraPermission &&
           (!checkCameraPermissions || hasPermissionsForCamera(cameraId, attributionSource));
}

bool AttributionAndPermissionUtils::hasPermissionsForCameraHeadlessSystemUser(
@@ -269,6 +243,96 @@ bool AttributionAndPermissionUtils::hasPermissionsForOpenCloseListener(
                                       attributionSource, std::string(), AppOpsManager::OP_NONE);
}

bool AttributionAndPermissionUtils::checkAutomotivePrivilegedClient(
        const std::string& cameraId, const AttributionSourceState& attributionSource) {
    if (isAutomotivePrivilegedClient(attributionSource.uid)) {
        // If cameraId is empty, then it means that this check is not used for the
        // purpose of accessing a specific camera, hence grant permission just
        // based on uid to the automotive privileged client.
        if (cameraId.empty()) return true;

        auto cameraService = mCameraService.promote();
        if (cameraService == nullptr) {
            ALOGE("%s: CameraService unavailable.", __FUNCTION__);
            return false;
        }

        // If this call is used for accessing a specific camera then cam_id must be provided.
        // In that case, only pre-grants the permission for accessing the exterior system only
        // camera.
        return cameraService->isAutomotiveExteriorSystemCamera(cameraId);
    }

    return false;
}

void AttributionAndPermissionUtils::resolveAttributionPackage(
        AttributionSourceState& resolvedAttributionSource) {
    if (resolvedAttributionSource.packageName.has_value() &&
        resolvedAttributionSource.packageName->size() > 0) {
        return;
    }

    // NDK calls don't come with package names, but we need one for various cases.
    // Generally, there's a 1:1 mapping between UID and package name, but shared UIDs
    // do exist. For all authentication cases, all packages under the same UID get the
    // same permissions, so picking any associated package name is sufficient. For some
    // other cases, this may give inaccurate names for clients in logs.
    resolvedAttributionSource.packageName = getPackageNameFromUid(resolvedAttributionSource.uid);
}

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

    bool validUid = true;
    if (clientUid == hardware::ICameraService::USE_CALLING_UID) {
        clientUid = callingUid;
    } else {
        validUid = isTrustedCallingUid(callingUid);
        if (flags::use_context_attribution_source()) {
            validUid = validUid || (clientUid == callingUid);
        }
    }

    return validUid;
}

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

    bool validPid = true;
    if (clientPid == hardware::ICameraService::USE_CALLING_PID) {
        clientPid = callingPid;
    } else {
        validPid = isTrustedCallingUid(callingUid);
        if (flags::use_context_attribution_source()) {
            validPid = validPid || (clientPid == callingPid);
        }
    }

    return validPid;
}

binder::Status AttributionAndPermissionUtils::errorNotTrusted(
        int clientPid, int clientUid, const std::string& methodName,
        const std::optional<std::string>& cameraIdMaybe, const std::string& clientName,
        bool isPid) const {
    int callingPid = getCallingPid();
    int callingUid = getCallingUid();
    ALOGE("CameraService::%s X (calling PID %d, calling UID %d) rejected "
          "(don't trust %s %d)",
          methodName.c_str(), callingPid, callingUid, isPid ? "clientPid" : "clientUid",
          isPid ? clientPid : clientUid);
    return STATUS_ERROR_FMT(hardware::ICameraService::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)",
                            getCallingPid(), getCallingUid(), cameraIdMaybe.value_or("N/A").c_str(),
                            clientName.c_str(), clientPid, clientUid);
}

const sp<IPermissionController>& AttributionAndPermissionUtils::getPermissionController() const {
    static const char* kPermissionControllerService = "permission";
    static thread_local sp<IPermissionController> sPermissionController = nullptr;
+79 −65

File changed.

Preview size limit exceeded, changes collapsed.