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

Commit 4ef19fa4 authored by Andy Hung's avatar Andy Hung
Browse files

Update audio permission checking

Change captureAudioOutputAllowed to check client pid.

Check calling uid with AID_AUDIOSERVER instead of calling pid with
own pid. This is consistent, and works if AudioFlinger and
AudioPolicyManager exist as different processes.

Remove getpid_cached since getpid() is very fast. This removes
any initialization issues.

Replace getuid() with AID_AUDIOSERVER to remove ambiguity of
multiple native audio services for multiple users. Only
one exists regardless of users.

Do not use multiuser UID checks for certain native services
that do not spawn for multiple users to prevent accidently exposure.

Move permission checks to use ServiceUtilities for control and
consistency.

Rename isTrustedCallingUid to isAudioServerOrMediaServerUid
so that permission check is explicitly known to caller.

Update MediaLogService to use ServiceUtilities.

Test: Basic sanity
Test: AudioTrackTest, AudioRecordTest, SoundPool, SoundTrigger
Bug: 79485140
Change-Id: Ib8ccb36929a9b4806c01626f32fa023a046d6020
parent ab7ef300
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -49,6 +49,7 @@ cc_library_shared {
        "libaudiomanager",
        "libaudiomanager",
        "libmedia_helper",
        "libmedia_helper",
        "libmediametrics",
        "libmediametrics",
        "libmediautils",
    ],
    ],
    export_shared_lib_headers: ["libbinder"],
    export_shared_lib_headers: ["libbinder"],


+2 −4
Original line number Original line Diff line number Diff line
@@ -24,10 +24,8 @@


#include <binder/IPCThreadState.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include <cutils/multiuser.h>
#include <media/TimeCheck.h>
#include <media/TimeCheck.h>
#include <private/android_filesystem_config.h>
#include <mediautils/ServiceUtilities.h>

#include "IAudioFlinger.h"
#include "IAudioFlinger.h"


namespace android {
namespace android {
@@ -912,7 +910,7 @@ status_t BnAudioFlinger::onTransact(
        case SET_MIC_MUTE:
        case SET_MIC_MUTE:
        case SET_LOW_RAM_DEVICE:
        case SET_LOW_RAM_DEVICE:
        case SYSTEM_READY: {
        case SYSTEM_READY: {
            if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) {
            if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                      __func__, code, IPCThreadState::self()->getCallingPid(),
                      __func__, code, IPCThreadState::self()->getCallingPid(),
                      IPCThreadState::self()->getCallingUid());
                      IPCThreadState::self()->getCallingUid());
+2 −3
Original line number Original line Diff line number Diff line
@@ -24,11 +24,10 @@


#include <binder/IPCThreadState.h>
#include <binder/IPCThreadState.h>
#include <binder/Parcel.h>
#include <binder/Parcel.h>
#include <cutils/multiuser.h>
#include <media/AudioEffect.h>
#include <media/AudioEffect.h>
#include <media/IAudioPolicyService.h>
#include <media/IAudioPolicyService.h>
#include <media/TimeCheck.h>
#include <media/TimeCheck.h>
#include <private/android_filesystem_config.h>
#include <mediautils/ServiceUtilities.h>
#include <system/audio.h>
#include <system/audio.h>


namespace android {
namespace android {
@@ -936,7 +935,7 @@ status_t BnAudioPolicyService::onTransact(
        case STOP_AUDIO_SOURCE:
        case STOP_AUDIO_SOURCE:
        case GET_SURROUND_FORMATS:
        case GET_SURROUND_FORMATS:
        case SET_SURROUND_FORMAT_ENABLED: {
        case SET_SURROUND_FORMAT_ENABLED: {
            if (multiuser_get_app_id(IPCThreadState::self()->getCallingUid()) >= AID_APP_START) {
            if (!isServiceUid(IPCThreadState::self()->getCallingUid())) {
                ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                ALOGW("%s: transaction %d received from PID %d unauthorized UID %d",
                      __func__, code, IPCThreadState::self()->getCallingPid(),
                      __func__, code, IPCThreadState::self()->getCallingPid(),
                      IPCThreadState::self()->getCallingUid());
                      IPCThreadState::self()->getCallingUid());
+1 −0
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ cc_library {
    ],
    ],
    shared_libs: [
    shared_libs: [
        "libbinder",
        "libbinder",
        "libcutils",
        "liblog",
        "liblog",
        "libutils",
        "libutils",
        "libmemunreachable",
        "libmemunreachable",
+5 −29
Original line number Original line Diff line number Diff line
@@ -18,7 +18,6 @@
#include <binder/IPCThreadState.h>
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <binder/PermissionCache.h>
#include <binder/PermissionCache.h>
#include <private/android_filesystem_config.h>
#include "mediautils/ServiceUtilities.h"
#include "mediautils/ServiceUtilities.h"


/* When performing permission checks we do not use permission cache for
/* When performing permission checks we do not use permission cache for
@@ -32,24 +31,6 @@ namespace android {


static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_AUDIO");
static const String16 sAndroidPermissionRecordAudio("android.permission.RECORD_AUDIO");


// Not valid until initialized by AudioFlinger constructor.  It would have to be
// re-initialized if the process containing AudioFlinger service forks (which it doesn't).
// This is often used to validate binder interface calls within audioserver
// (e.g. AudioPolicyManager to AudioFlinger).
pid_t getpid_cached;

// A trusted calling UID may specify the client UID as part of a binder interface call.
// otherwise the calling UID must be equal to the client UID.
bool isTrustedCallingUid(uid_t uid) {
    switch (uid) {
    case AID_MEDIA:
    case AID_AUDIOSERVER:
        return true;
    default:
        return false;
    }
}

static String16 resolveCallingPackage(PermissionController& permissionController,
static String16 resolveCallingPackage(PermissionController& permissionController,
        const String16& opPackageName, uid_t uid) {
        const String16& opPackageName, uid_t uid) {
    if (opPackageName.size() > 0) {
    if (opPackageName.size() > 0) {
@@ -71,16 +52,11 @@ static String16 resolveCallingPackage(PermissionController& permissionController
    return packages[0];
    return packages[0];
}
}


static inline bool isAudioServerOrRoot(uid_t uid) {
    // AID_ROOT is OK for command-line tests.  Native unforked audioserver always OK.
    return uid == AID_ROOT || uid == AID_AUDIOSERVER ;
}

static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
static bool checkRecordingInternal(const String16& opPackageName, pid_t pid,
        uid_t uid, bool start) {
        uid_t uid, bool start) {
    // Okay to not track in app ops as audio server is us and if
    // Okay to not track in app ops as audio server is us and if
    // device is rooted security model is considered compromised.
    // device is rooted security model is considered compromised.
    if (isAudioServerOrRoot(uid)) return true;
    if (isAudioServerOrRootUid(uid)) return true;


    // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
    // We specify a pid and uid here as mediaserver (aka MediaRecorder or StageFrightRecorder)
    // may open a record track on behalf of a client.  Note that pid may be a tid.
    // may open a record track on behalf of a client.  Note that pid may be a tid.
@@ -127,7 +103,7 @@ bool startRecording(const String16& opPackageName, pid_t pid, uid_t uid) {
void finishRecording(const String16& opPackageName, uid_t uid) {
void finishRecording(const String16& opPackageName, uid_t uid) {
    // Okay to not track in app ops as audio server is us and if
    // Okay to not track in app ops as audio server is us and if
    // device is rooted security model is considered compromised.
    // device is rooted security model is considered compromised.
    if (isAudioServerOrRoot(uid)) return;
    if (isAudioServerOrRootUid(uid)) return;


    PermissionController permissionController;
    PermissionController permissionController;
    String16 resolvedOpPackageName = resolveCallingPackage(
    String16 resolvedOpPackageName = resolveCallingPackage(
@@ -142,7 +118,7 @@ void finishRecording(const String16& opPackageName, uid_t uid) {
}
}


bool captureAudioOutputAllowed(pid_t pid, uid_t uid) {
bool captureAudioOutputAllowed(pid_t pid, uid_t uid) {
    if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
    if (isAudioServerOrRootUid(uid)) return true;
    static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
    static const String16 sCaptureAudioOutput("android.permission.CAPTURE_AUDIO_OUTPUT");
    bool ok = PermissionCache::checkPermission(sCaptureAudioOutput, pid, uid);
    bool ok = PermissionCache::checkPermission(sCaptureAudioOutput, pid, uid);
    if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
    if (!ok) ALOGE("Request requires android.permission.CAPTURE_AUDIO_OUTPUT");
@@ -163,7 +139,8 @@ bool captureHotwordAllowed(pid_t pid, uid_t uid) {
}
}


bool settingsAllowed() {
bool settingsAllowed() {
    if (getpid_cached == IPCThreadState::self()->getCallingPid()) return true;
    // given this is a permission check, could this be isAudioServerOrRootUid()?
    if (isAudioServerUid(IPCThreadState::self()->getCallingUid())) return true;
    static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
    static const String16 sAudioSettings("android.permission.MODIFY_AUDIO_SETTINGS");
    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
    bool ok = PermissionCache::checkCallingPermission(sAudioSettings);
@@ -180,7 +157,6 @@ bool modifyAudioRoutingAllowed() {
}
}


bool dumpAllowed() {
bool dumpAllowed() {
    // don't optimize for same pid, since mediaserver never dumps itself
    static const String16 sDump("android.permission.DUMP");
    static const String16 sDump("android.permission.DUMP");
    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    // IMPORTANT: Use PermissionCache - not a runtime permission and may not change.
    bool ok = PermissionCache::checkCallingPermission(sDump);
    bool ok = PermissionCache::checkCallingPermission(sDump);
Loading