Switch media fw permissions checks to AttributionSource (av)
Attribution source is the abstraction to capture the data
flows for private data across apps. Checking permissions
for an attribution source does this for all apps in the
chain that would receive the data as well as the relevant
app ops are checked/noted/started as needed.
bug: 158792096
Test: atest CtsMediaTestCases
atest CtsPermissionTestCases
atest CtsPermission2TestCases
atest CtsPermission3TestCases
atest CtsPermission4TestCases
atest CtsPermission5TestCases
atest CtsAppOpsTestCases
atest CtsAppOps2TestCases
Merged-In: I1c5a4321dd3b2d458372058c99604a6ec208717c
Change-Id: I1c5a4321dd3b2d458372058c99604a6ec208717c
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index 09e5ec5..57ff0d7 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -65,7 +65,7 @@
using ::android::aidl_utils::binderStatusFromStatusT;
using binder::Status;
-using media::permission::Identity;
+using content::AttributionSourceState;
using media::VolumeShaper;
// ----------------------------------------------------------------------------
// TrackBase
@@ -238,12 +238,13 @@
}
}
-// TODO b/182392769: use identity util
-static Identity audioServerIdentity(pid_t pid) {
- Identity i{};
- i.uid = AID_AUDIOSERVER;
- i.pid = pid;
- return i;
+// TODO b/182392769: use attribution source util
+static AttributionSourceState audioServerAttributionSource(pid_t pid) {
+ AttributionSourceState attributionSource{};
+ attributionSource.uid = AID_AUDIOSERVER;
+ attributionSource.pid = pid;
+ attributionSource.token = sp<BBinder>::make();
+ return attributionSource;
}
status_t AudioFlinger::ThreadBase::TrackBase::initCheck() const
@@ -498,11 +499,11 @@
// static
sp<AudioFlinger::PlaybackThread::OpPlayAudioMonitor>
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::createIfNeeded(
- const Identity& identity, const audio_attributes_t& attr, int id,
+ const AttributionSourceState& attributionSource, const audio_attributes_t& attr, int id,
audio_stream_type_t streamType)
{
Vector <String16> packages;
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.uid));
+ uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
getPackagesForUid(uid, packages);
if (isServiceUid(uid)) {
if (packages.isEmpty()) {
@@ -525,13 +526,15 @@
return nullptr;
}
- Identity checkedIdentity = AudioFlinger::checkIdentityPackage(identity);
- return new OpPlayAudioMonitor(checkedIdentity, attr.usage, id);
+ AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ attributionSource);
+ return new OpPlayAudioMonitor(checkedAttributionSource, attr.usage, id);
}
AudioFlinger::PlaybackThread::OpPlayAudioMonitor::OpPlayAudioMonitor(
- const Identity& identity, audio_usage_t usage, int id)
- : mHasOpPlayAudio(true), mIdentity(identity), mUsage((int32_t) usage), mId(id)
+ const AttributionSourceState& attributionSource, audio_usage_t usage, int id)
+ : mHasOpPlayAudio(true), mAttributionSource(attributionSource), mUsage((int32_t) usage),
+ mId(id)
{
}
@@ -546,10 +549,11 @@
void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::onFirstRef()
{
checkPlayAudioForUsage();
- if (mIdentity.packageName.has_value()) {
+ if (mAttributionSource.packageName.has_value()) {
mOpCallback = new PlayAudioOpCallback(this);
mAppOpsManager.startWatchingMode(AppOpsManager::OP_PLAY_AUDIO,
- VALUE_OR_FATAL(aidl2legacy_string_view_String16(mIdentity.packageName.value_or("")))
+ VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+ mAttributionSource.packageName.value_or("")))
, mOpCallback);
}
}
@@ -563,12 +567,12 @@
// - not called from PlayAudioOpCallback because the callback is not installed in this case
void AudioFlinger::PlaybackThread::OpPlayAudioMonitor::checkPlayAudioForUsage()
{
- if (!mIdentity.packageName.has_value()) {
+ if (!mAttributionSource.packageName.has_value()) {
mHasOpPlayAudio.store(false);
} else {
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mIdentity.uid));
+ uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(mAttributionSource.uid));
String16 packageName = VALUE_OR_FATAL(
- aidl2legacy_string_view_String16(mIdentity.packageName.value_or("")));
+ aidl2legacy_string_view_String16(mAttributionSource.packageName.value_or("")));
bool hasIt = mAppOpsManager.checkAudioOpNoThrow(AppOpsManager::OP_PLAY_AUDIO,
mUsage, uid, packageName) == AppOpsManager::MODE_ALLOWED;
ALOGD("OpPlayAudio: track:%d usage:%d %smuted", mId, mUsage, hasIt ? "not " : "");
@@ -620,7 +624,7 @@
const sp<IMemory>& sharedBuffer,
audio_session_t sessionId,
pid_t creatorPid,
- const Identity& identity,
+ const AttributionSourceState& attributionSource,
audio_output_flags_t flags,
track_type type,
audio_port_handle_t portId,
@@ -634,7 +638,7 @@
(sharedBuffer != 0) ? sharedBuffer->unsecurePointer() : buffer,
(sharedBuffer != 0) ? sharedBuffer->size() : bufferSize,
sessionId, creatorPid,
- VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.uid)), true /*isOut*/,
+ VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)), true /*isOut*/,
(type == TYPE_PATCH) ? ( buffer == NULL ? ALLOC_LOCAL : ALLOC_NONE) : ALLOC_CBLK,
type,
portId,
@@ -649,7 +653,7 @@
mPresentationCompleteFrames(0),
mFrameMap(16 /* sink-frame-to-track-frame map memory */),
mVolumeHandler(new media::VolumeHandler(sampleRate)),
- mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(identity, attr, id(),
+ mOpPlayAudioMonitor(OpPlayAudioMonitor::createIfNeeded(attributionSource, attr, id(),
streamType)),
// mSinkTimestamp
mFastIndex(-1),
@@ -672,7 +676,7 @@
return;
}
- uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.uid));
+ uid_t uid = VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid));
if (!thread->isTrackAllowed_l(channelMask, format, sessionId, uid)) {
ALOGE("%s(%d): no more tracks available", __func__, mId);
releaseCblk(); // this makes the track invalid.
@@ -718,8 +722,8 @@
// HapticGenerator effect, which will generate haptic data, on the track. In that case,
// external vibration is always created for all tracks attached to haptic playback thread.
mAudioVibrationController = new AudioVibrationController(this);
- std::string packageName = identity.packageName.has_value() ?
- identity.packageName.value() : "";
+ std::string packageName = attributionSource.packageName.has_value() ?
+ attributionSource.packageName.value() : "";
mExternalVibration = new os::ExternalVibration(
mUid, packageName, mAttr, mAudioVibrationController);
}
@@ -1840,12 +1844,12 @@
audio_format_t format,
audio_channel_mask_t channelMask,
size_t frameCount,
- const Identity& identity)
+ const AttributionSourceState& attributionSource)
: Track(playbackThread, NULL, AUDIO_STREAM_PATCH,
audio_attributes_t{} /* currently unused for output track */,
sampleRate, format, channelMask, frameCount,
nullptr /* buffer */, (size_t)0 /* bufferSize */, nullptr /* sharedBuffer */,
- AUDIO_SESSION_NONE, getpid(), identity, AUDIO_OUTPUT_FLAG_NONE,
+ AUDIO_SESSION_NONE, getpid(), attributionSource, AUDIO_OUTPUT_FLAG_NONE,
TYPE_OUTPUT),
mActive(false), mSourceThread(sourceThread)
{
@@ -2075,7 +2079,7 @@
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, nullptr /* sharedBuffer */,
- AUDIO_SESSION_NONE, getpid(), audioServerIdentity(getpid()), flags,
+ AUDIO_SESSION_NONE, getpid(), audioServerAttributionSource(getpid()), flags,
TYPE_PATCH, AUDIO_PORT_HANDLE_NONE, frameCountToBeReady),
PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, true, true),
*playbackThread, timeout)
@@ -2213,32 +2217,33 @@
// static
sp<AudioFlinger::RecordThread::OpRecordAudioMonitor>
AudioFlinger::RecordThread::OpRecordAudioMonitor::createIfNeeded(
- const Identity& identity, const audio_attributes_t& attr)
+ const AttributionSourceState& attributionSource, const audio_attributes_t& attr)
{
- if (isServiceUid(identity.uid)) {
+ if (isServiceUid(attributionSource.uid)) {
ALOGV("not silencing record for service %s",
- identity.toString().c_str());
+ attributionSource.toString().c_str());
return nullptr;
}
// Capturing from FM TUNER output is not controlled by an app op
// because it does not affect users privacy as does capturing from an actual microphone.
if (attr.source == AUDIO_SOURCE_FM_TUNER) {
- ALOGV("not muting FM TUNER capture for uid %d", identity.uid);
+ ALOGV("not muting FM TUNER capture for uid %d", attributionSource.uid);
return nullptr;
}
- Identity checkedIdentity = AudioFlinger::checkIdentityPackage(identity);
- if (!checkedIdentity.packageName.has_value()
- || checkedIdentity.packageName.value().size() == 0) {
+ AttributionSourceState checkedAttributionSource = AudioFlinger::checkAttributionSourcePackage(
+ attributionSource);
+ if (!checkedAttributionSource.packageName.has_value()
+ || checkedAttributionSource.packageName.value().size() == 0) {
return nullptr;
}
- return new OpRecordAudioMonitor(checkedIdentity, getOpForSource(attr.source));
+ return new OpRecordAudioMonitor(checkedAttributionSource, getOpForSource(attr.source));
}
AudioFlinger::RecordThread::OpRecordAudioMonitor::OpRecordAudioMonitor(
- const Identity& identity, int32_t appOp)
- : mHasOp(true), mIdentity(identity), mAppOp(appOp)
+ const AttributionSourceState& attributionSource, int32_t appOp)
+ : mHasOp(true), mAttributionSource(attributionSource), mAppOp(appOp)
{
}
@@ -2254,9 +2259,11 @@
{
checkOp();
mOpCallback = new RecordAudioOpCallback(this);
- ALOGV("start watching op %d for %s", mAppOp, mIdentity.toString().c_str());
- mAppOpsManager.startWatchingMode(mAppOp,
- VALUE_OR_FATAL(aidl2legacy_string_view_String16(mIdentity.packageName.value_or(""))),
+ ALOGV("start watching op %d for %s", mAppOp, mAttributionSource.toString().c_str());
+ // TODO: We need to always watch AppOpsManager::OP_RECORD_AUDIO too
+ // since it controls the mic permission for legacy apps.
+ mAppOpsManager.startWatchingMode(mAppOp, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+ mAttributionSource.packageName.value_or(""))),
mOpCallback);
}
@@ -2272,17 +2279,17 @@
// - not called from RecordAudioOpCallback because the callback is not installed in this case
void AudioFlinger::RecordThread::OpRecordAudioMonitor::checkOp()
{
-
+ // TODO: We need to always check AppOpsManager::OP_RECORD_AUDIO too
+ // since it controls the mic permission for legacy apps.
const int32_t mode = mAppOpsManager.checkOp(mAppOp,
- mIdentity.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
- mIdentity.packageName.value_or(""))));
- const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
+ mAttributionSource.uid, VALUE_OR_FATAL(aidl2legacy_string_view_String16(
+ mAttributionSource.packageName.value_or(""))));
+ const bool hasIt = (mode == AppOpsManager::MODE_ALLOWED);
// verbose logging only log when appOp changed
ALOGI_IF(hasIt != mHasOp.load(),
"App op %d missing, %ssilencing record %s",
- mAppOp, hasIt ? "un" : "", mIdentity.toString().c_str());
+ mAppOp, hasIt ? "un" : "", mAttributionSource.toString().c_str());
mHasOp.store(hasIt);
-
}
AudioFlinger::RecordThread::OpRecordAudioMonitor::RecordAudioOpCallback::RecordAudioOpCallback(
@@ -2382,7 +2389,7 @@
size_t bufferSize,
audio_session_t sessionId,
pid_t creatorPid,
- const Identity& identity,
+ const AttributionSourceState& attributionSource,
audio_input_flags_t flags,
track_type type,
audio_port_handle_t portId,
@@ -2390,7 +2397,7 @@
: TrackBase(thread, client, attr, sampleRate, format,
channelMask, frameCount, buffer, bufferSize, sessionId,
creatorPid,
- VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.uid)),
+ VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
false /*isOut*/,
(type == TYPE_DEFAULT) ?
((flags & AUDIO_INPUT_FLAG_FAST) ? ALLOC_PIPE : ALLOC_CBLK) :
@@ -2403,7 +2410,7 @@
mRecordBufferConverter(NULL),
mFlags(flags),
mSilenced(false),
- mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(identity, attr)),
+ mOpRecordAudioMonitor(OpRecordAudioMonitor::createIfNeeded(attributionSource, attr)),
mStartFrames(startFrames)
{
if (mCblk == NULL) {
@@ -2712,10 +2719,11 @@
return PERMISSION_DENIED;
}
- Identity identity{};
- identity.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
- identity.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
- if (!captureHotwordAllowed(identity)) {
+ AttributionSourceState attributionSource{};
+ attributionSource.uid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingUid));
+ attributionSource.pid = VALUE_OR_RETURN_STATUS(legacy2aidl_uid_t_int32_t(callingPid));
+ attributionSource.token = sp<BBinder>::make();
+ if (!captureHotwordAllowed(attributionSource)) {
return PERMISSION_DENIED;
}
@@ -2751,7 +2759,7 @@
audio_attributes_t{} /* currently unused for patch track */,
sampleRate, format, channelMask, frameCount,
buffer, bufferSize, AUDIO_SESSION_NONE, getpid(),
- audioServerIdentity(getpid()), flags, TYPE_PATCH),
+ audioServerAttributionSource(getpid()), flags, TYPE_PATCH),
PatchTrackBase(new ClientProxy(mCblk, mBuffer, frameCount, mFrameSize, false, true),
*recordThread, timeout)
{
@@ -3028,19 +3036,19 @@
audio_channel_mask_t channelMask,
audio_session_t sessionId,
bool isOut,
- const Identity& identity,
+ const AttributionSourceState& attributionSource,
pid_t creatorPid,
audio_port_handle_t portId)
: TrackBase(thread, NULL, attr, sampleRate, format,
channelMask, (size_t)0 /* frameCount */,
nullptr /* buffer */, (size_t)0 /* bufferSize */,
sessionId, creatorPid,
- VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.uid)),
+ VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.uid)),
isOut,
ALLOC_NONE,
TYPE_DEFAULT, portId,
std::string(AMEDIAMETRICS_KEY_PREFIX_AUDIO_MMAP) + std::to_string(portId)),
- mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(identity.pid))),
+ mPid(VALUE_OR_FATAL(aidl2legacy_int32_t_uid_t(attributionSource.pid))),
mSilenced(false), mSilencedNotified(false)
{
// Once this item is logged by the server, the client can add properties.