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

Commit eb484051 authored by Jorge Ruesga's avatar Jorge Ruesga
Browse files

appop: reimplement OP_RECORD_AUDIO op check in mediaserver



Obtain the real package name for the calling app from the packagemanager binder and
link to client registry. Also block only openRecord and createEffect (which are the
methods used to record audio), and ignore the createTrack that is used also by
legacy audio apps and isn't related to audio recording.

Change-Id: Iedd6022fab1efab47a29da7bd07e922dcdeb294c
Signed-off-by: default avatarJorge Ruesga <jorge@ruesga.com>
parent a4125c86
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)

LOCAL_SRC_FILES:=               \
    PackageManager.cpp          \
    AudioFlinger.cpp            \
    Threads.cpp                 \
    Tracks.cpp                  \
+39 −6
Original line number Diff line number Diff line
@@ -65,6 +65,7 @@
#include "AudioMixer.h"
#include "AudioFlinger.h"
#include "ServiceUtilities.h"
#include "PackageManager.h"

#include <media/EffectsFactoryApi.h>
#include <audio_effects/effect_visualizer.h>
@@ -1341,11 +1342,14 @@ void AudioFlinger::registerClient(const sp<IAudioFlingerClient>& client)

    Mutex::Autolock _l(mLock);

    pid_t pid = IPCThreadState::self()->getCallingPid();
    IPCThreadState* ipcState = IPCThreadState::self();
    pid_t pid = ipcState->getCallingPid();
    uid_t uid = ipcState->getCallingUid();
    if (mNotificationClients.indexOfKey(pid) < 0) {
        sp<NotificationClient> notificationClient = new NotificationClient(this,
                                                                            client,
                                                                            pid);
                                                                            pid,
                                                                            getNameForUid(uid));
        ALOGV("registerClient() client %p, pid %d", notificationClient.get(), pid);

        mNotificationClients.add(pid, notificationClient);
@@ -1519,8 +1523,8 @@ void AudioFlinger::Client::releaseTimedTrack()

AudioFlinger::NotificationClient::NotificationClient(const sp<AudioFlinger>& audioFlinger,
                                                     const sp<IAudioFlingerClient>& client,
                                                     pid_t pid)
    : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client)
                                                     pid_t pid, const String16 clientName)
    : mAudioFlinger(audioFlinger), mPid(pid), mAudioFlingerClient(client), mClientName(clientName)
{
}

@@ -1565,7 +1569,7 @@ sp<IAudioRecord> AudioFlinger::openRecord(
#endif

    // check calling permissions
    if (!recordingAllowed()) {
    if (!recordingAllowed() || !checkAudioRecordOp()) {
        ALOGE("openRecord() permission denied: recording not allowed");
        lStatus = PERMISSION_DENIED;
        goto Exit;
@@ -2641,7 +2645,7 @@ sp<IEffect> AudioFlinger::createEffect(

        // check recording permission for visualizer
        if ((memcmp(&desc.type, SL_IID_VISUALIZATION, sizeof(effect_uuid_t)) == 0) &&
            !recordingAllowed()) {
            (!recordingAllowed() || !checkAudioRecordOp())) {
            lStatus = PERMISSION_DENIED;
            goto Exit;
        }
@@ -2994,4 +2998,33 @@ status_t AudioFlinger::onTransact(
    return BnAudioFlinger::onTransact(code, data, reply, flags);
}

bool AudioFlinger::checkAudioRecordOp()
{
    IPCThreadState* ipcState = IPCThreadState::self();
    pid_t pid = ipcState->getCallingPid();
    uid_t uid = ipcState->getCallingUid();

    if (uid < AID_APP) {
        return true;
    }

    Mutex::Autolock _l(mLock);

    {
        String16 clientName;
        int index = mNotificationClients.indexOfKey(pid);
        if (index >= 0) {
            clientName = mNotificationClients.valueAt(index)->clientName();
        }

        if (clientName.size() <= 0) {
            return true;
        }

        // check AppOp permission
        return (mAppOpsManager.noteOp(AppOpsManager::OP_RECORD_AUDIO, uid, clientName) ==
                AppOpsManager::MODE_ALLOWED);
    }
}

}; // namespace android
+8 −1
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@
#include <utils/TypeHelpers.h>
#include <utils/Vector.h>

#include <binder/AppOpsManager.h>
#include <binder/BinderService.h>
#include <binder/MemoryDealer.h>

@@ -388,10 +389,11 @@ private:
    public:
                            NotificationClient(const sp<AudioFlinger>& audioFlinger,
                                                const sp<IAudioFlingerClient>& client,
                                                pid_t pid);
                                                pid_t pid, const String16 clientName);
        virtual             ~NotificationClient();

                sp<IAudioFlingerClient> audioFlingerClient() const { return mAudioFlingerClient; }
                String16     clientName() const { return mClientName; }

                // IBinder::DeathRecipient
                virtual     void        binderDied(const wp<IBinder>& who);
@@ -403,6 +405,7 @@ private:
        const sp<AudioFlinger>  mAudioFlinger;
        const pid_t             mPid;
        const sp<IAudioFlingerClient> mAudioFlingerClient;
        const String16          mClientName;
    };

    class TrackHandle;
@@ -831,6 +834,10 @@ private:
    bool    mIsLowRamDevice;
    bool    mIsDeviceTypeKnown;
    nsecs_t mGlobalEffectEnableTime;  // when a global effect was last enabled

    // For checking audio record access
    AppOpsManager mAppOpsManager;
    bool    checkAudioRecordOp();
};

#undef INCLUDING_FROM_AUDIOFLINGER_H
+54 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The CyanogenMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <unistd.h>
#include <binder/IBinder.h>
#include <binder/IServiceManager.h>
#include <binder/Parcel.h>
#include <utils/String16.h>

#include "PackageManager.h"

namespace android {

// This need to be synced with IPackageManager.java
const uint32_t GET_NAME_FROM_UID_TRANSACTION = IBinder::FIRST_CALL_TRANSACTION + 25;

String16 getNameForUid(int uid)
{
    int fd = -1;

    sp<IServiceManager> sm = defaultServiceManager();
    sp<IBinder> pm = sm->getService(String16("package"));
    if (pm != NULL) {
        Parcel data, reply;
        data.writeInterfaceToken(String16("android.content.pm.IPackageManager"));
        data.writeInt32(uid);
        status_t ret = pm->transact(GET_NAME_FROM_UID_TRANSACTION, data, &reply);
        if (ret == NO_ERROR) {
            int32_t exceptionCode = reply.readExceptionCode();
            if (!exceptionCode) {
                return reply.readString16();
            } else {
                // An exception was thrown back; fall through to return failure
                ALOGD("getNameForUid(%d) caught exception %d\n", uid, exceptionCode);
            }
        }
    }
    return String16();
}

} /* namespace android */
+28 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2014 The CyanogenMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PackageManager_H
#define PackageManager_H

#include <utils/String16.h>

namespace android {

String16 getNameForUid(int uid);

}

#endif