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

Commit f785f497 authored by Riley Spahn's avatar Riley Spahn
Browse files

Add SELinux MAC to DrmManagerService.

Add SELinux checks on all interfaces exposed by the
DrmManagerService.

Change-Id: Ib170d3229d88781b76e5fc1c557c8fed233df5d1
parent 2e25819f
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -26,7 +26,8 @@ LOCAL_SHARED_LIBRARIES := \
    libutils \
    liblog \
    libbinder \
    libdl
    libdl \
    libselinux

LOCAL_STATIC_LIBRARIES := libdrmframeworkcommon

+70 −12
Original line number Diff line number Diff line
@@ -29,20 +29,68 @@
#include "DrmManagerService.h"
#include "DrmManager.h"

#include <selinux/android.h>

using namespace android;

static int selinux_enabled;
static char *drmserver_context;
static Vector<uid_t> trustedUids;

static bool isProtectedCallAllowed() {
const char *const DrmManagerService::drm_perm_labels[] = {
    "consumeRights",
    "setPlaybackStatus",
    "openDecryptSession",
    "closeDecryptSession",
    "initializeDecryptUnit",
    "decrypt",
    "finalizeDecryptUnit",
    "pread"
};

const char *DrmManagerService::get_perm_label(drm_perm_t perm) {
    unsigned int index = perm;

    if (index < 0 ||
            index >= (sizeof(drm_perm_labels) / sizeof(drm_perm_labels[0]))) {
        ALOGE("SELinux: Failed to retrieve permission label(perm=%d).\n", perm);
        abort();
    }
    return drm_perm_labels[index];
}

bool DrmManagerService::selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm) {
    if (selinux_enabled <= 0) {
        return true;
    }

    char *sctx;
    const char *selinux_class = "drmservice";
    const char *str_perm = get_perm_label(perm);

    if (getpidcon(spid, &sctx) != 0) {
        ALOGE("SELinux: getpidcon(pid=%d) failed.\n", spid);
        return false;
    }

    bool allowed = (selinux_check_access(sctx, drmserver_context, selinux_class,
            str_perm, NULL) == 0);
    freecon(sctx);

    return allowed;
}

bool DrmManagerService::isProtectedCallAllowed(drm_perm_t perm) {
    // TODO
    // Following implementation is just for reference.
    // Each OEM manufacturer should implement/replace with their own solutions.
    IPCThreadState* ipcState = IPCThreadState::self();
    uid_t uid = ipcState->getCallingUid();
    pid_t spid = ipcState->getCallingPid();

    for (unsigned int i = 0; i < trustedUids.size(); ++i) {
        if (trustedUids[i] == uid) {
            return true;
            return selinuxIsProtectedCallAllowed(spid, perm);
        }
    }
    return false;
@@ -60,6 +108,16 @@ void DrmManagerService::instantiate() {
        // Add trusted uids here
        trustedUids.push(AID_MEDIA);
    }

    selinux_enabled = is_selinux_enabled();
    if (selinux_enabled > 0 && getcon(&drmserver_context) != 0) {
        ALOGE("SELinux: DrmManagerService failed to get context for DrmManagerService. Aborting.\n");
        abort();
    }

    union selinux_callback cb;
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);
}

DrmManagerService::DrmManagerService() :
@@ -151,7 +209,7 @@ int DrmManagerService::checkRightsStatus(
status_t DrmManagerService::consumeRights(
            int uniqueId, DecryptHandle* decryptHandle, int action, bool reserve) {
    ALOGV("Entering consumeRights");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(CONSUME_RIGHTS)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->consumeRights(uniqueId, decryptHandle, action, reserve);
@@ -160,7 +218,7 @@ status_t DrmManagerService::consumeRights(
status_t DrmManagerService::setPlaybackStatus(
            int uniqueId, DecryptHandle* decryptHandle, int playbackStatus, int64_t position) {
    ALOGV("Entering setPlaybackStatus");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(SET_PLAYBACK_STATUS)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->setPlaybackStatus(uniqueId, decryptHandle, playbackStatus, position);
@@ -208,7 +266,7 @@ status_t DrmManagerService::getAllSupportInfo(
DecryptHandle* DrmManagerService::openDecryptSession(
            int uniqueId, int fd, off64_t offset, off64_t length, const char* mime) {
    ALOGV("Entering DrmManagerService::openDecryptSession");
    if (isProtectedCallAllowed()) {
    if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) {
        return mDrmManager->openDecryptSession(uniqueId, fd, offset, length, mime);
    }

@@ -218,7 +276,7 @@ DecryptHandle* DrmManagerService::openDecryptSession(
DecryptHandle* DrmManagerService::openDecryptSession(
            int uniqueId, const char* uri, const char* mime) {
    ALOGV("Entering DrmManagerService::openDecryptSession with uri");
    if (isProtectedCallAllowed()) {
    if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) {
        return mDrmManager->openDecryptSession(uniqueId, uri, mime);
    }

@@ -228,7 +286,7 @@ DecryptHandle* DrmManagerService::openDecryptSession(
DecryptHandle* DrmManagerService::openDecryptSession(
            int uniqueId, const DrmBuffer& buf, const String8& mimeType) {
    ALOGV("Entering DrmManagerService::openDecryptSession for streaming");
    if (isProtectedCallAllowed()) {
    if (isProtectedCallAllowed(OPEN_DECRYPT_SESSION)) {
        return mDrmManager->openDecryptSession(uniqueId, buf, mimeType);
    }

@@ -237,7 +295,7 @@ DecryptHandle* DrmManagerService::openDecryptSession(

status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* decryptHandle) {
    ALOGV("Entering closeDecryptSession");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(CLOSE_DECRYPT_SESSION)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->closeDecryptSession(uniqueId, decryptHandle);
@@ -246,7 +304,7 @@ status_t DrmManagerService::closeDecryptSession(int uniqueId, DecryptHandle* dec
status_t DrmManagerService::initializeDecryptUnit(int uniqueId, DecryptHandle* decryptHandle,
            int decryptUnitId, const DrmBuffer* headerInfo) {
    ALOGV("Entering initializeDecryptUnit");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(INITIALIZE_DECRYPT_UNIT)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->initializeDecryptUnit(uniqueId,decryptHandle, decryptUnitId, headerInfo);
@@ -256,7 +314,7 @@ status_t DrmManagerService::decrypt(
            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId,
            const DrmBuffer* encBuffer, DrmBuffer** decBuffer, DrmBuffer* IV) {
    ALOGV("Entering decrypt");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(DECRYPT)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->decrypt(uniqueId, decryptHandle, decryptUnitId, encBuffer, decBuffer, IV);
@@ -265,7 +323,7 @@ status_t DrmManagerService::decrypt(
status_t DrmManagerService::finalizeDecryptUnit(
            int uniqueId, DecryptHandle* decryptHandle, int decryptUnitId) {
    ALOGV("Entering finalizeDecryptUnit");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(FINALIZE_DECRYPT_UNIT)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->finalizeDecryptUnit(uniqueId, decryptHandle, decryptUnitId);
@@ -274,7 +332,7 @@ status_t DrmManagerService::finalizeDecryptUnit(
ssize_t DrmManagerService::pread(int uniqueId, DecryptHandle* decryptHandle,
            void* buffer, ssize_t numBytes, off64_t offset) {
    ALOGV("Entering pread");
    if (!isProtectedCallAllowed()) {
    if (!isProtectedCallAllowed(PREAD)) {
        return DRM_ERROR_NO_PERMISSION;
    }
    return mDrmManager->pread(uniqueId, decryptHandle, buffer, numBytes, offset);
+19 −0
Original line number Diff line number Diff line
@@ -42,9 +42,28 @@ public:
    static void instantiate();

private:
    enum drm_perm_t {
        CONSUME_RIGHTS          = 0,
        SET_PLAYBACK_STATUS     = 1,
        OPEN_DECRYPT_SESSION    = 2,
        CLOSE_DECRYPT_SESSION   = 3,
        INITIALIZE_DECRYPT_UNIT = 4,
        DECRYPT                 = 5,
        FINALIZE_DECRYPT_UNIT   = 6,
        PREAD                   = 7,
    };

    static const char *const drm_perm_labels[];

    DrmManagerService();
    virtual ~DrmManagerService();

    static const char *get_perm_label(drm_perm_t perm);

    static bool selinuxIsProtectedCallAllowed(pid_t spid, drm_perm_t perm);

    static bool isProtectedCallAllowed(drm_perm_t perm);

public:
    int addUniqueId(bool isNative);