aaudio: prevent apps from affecting a stream they do not own

Bug: 62951648
Test: need test that hacks a stream handle from another user ID
Change-Id: I342f2a4cf9350c949f346b3c867d7f9e035c76b4
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.cpp b/media/libaaudio/src/binding/AAudioBinderClient.cpp
index 435b30f..c45bd71 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.cpp
+++ b/media/libaaudio/src/binding/AAudioBinderClient.cpp
@@ -159,23 +159,19 @@
 * Manage the specified thread as a low latency audio thread.
 */
 aaudio_result_t AAudioBinderClient::registerAudioThread(aaudio_handle_t streamHandle,
-                                                        pid_t clientProcessId,
                                                         pid_t clientThreadId,
                                                         int64_t periodNanoseconds) {
     const sp<IAAudioService> &service = getAAudioService();
     if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
     return service->registerAudioThread(streamHandle,
-                                        clientProcessId,
                                         clientThreadId,
                                         periodNanoseconds);
 }
 
 aaudio_result_t AAudioBinderClient::unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                          pid_t clientProcessId,
                                                           pid_t clientThreadId) {
     const sp<IAAudioService> &service = getAAudioService();
     if (service == 0) return AAUDIO_ERROR_NO_SERVICE;
     return service->unregisterAudioThread(streamHandle,
-                                          clientProcessId,
                                           clientThreadId);
 }
diff --git a/media/libaaudio/src/binding/AAudioBinderClient.h b/media/libaaudio/src/binding/AAudioBinderClient.h
index e223376..7cf7bf8 100644
--- a/media/libaaudio/src/binding/AAudioBinderClient.h
+++ b/media/libaaudio/src/binding/AAudioBinderClient.h
@@ -82,12 +82,10 @@
      * TODO Consider passing this information as part of the startStream() call.
      */
     aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
-                                                pid_t clientProcessId,
                                                 pid_t clientThreadId,
                                                 int64_t periodNanoseconds) override;
 
     aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                  pid_t clientProcessId,
                                                   pid_t clientThreadId) override;
 };
 
diff --git a/media/libaaudio/src/binding/AAudioServiceInterface.h b/media/libaaudio/src/binding/AAudioServiceInterface.h
index 824e5bc..d6a130f 100644
--- a/media/libaaudio/src/binding/AAudioServiceInterface.h
+++ b/media/libaaudio/src/binding/AAudioServiceInterface.h
@@ -76,12 +76,10 @@
      * Manage the specified thread as a low latency audio thread.
      */
     virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
-                                                pid_t clientProcessId,
                                                 pid_t clientThreadId,
                                                 int64_t periodNanoseconds) = 0;
 
     virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                  pid_t clientProcessId,
                                                   pid_t clientThreadId) = 0;
 };
 
diff --git a/media/libaaudio/src/binding/AAudioStreamRequest.cpp b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
index a5c27b9..8a765ad 100644
--- a/media/libaaudio/src/binding/AAudioStreamRequest.cpp
+++ b/media/libaaudio/src/binding/AAudioStreamRequest.cpp
@@ -45,8 +45,7 @@
 status_t AAudioStreamRequest::writeToParcel(Parcel* parcel) const {
     status_t status = parcel->writeInt32((int32_t) mUserId);
     if (status != NO_ERROR) goto error;
-    status = parcel->writeInt32((int32_t) mProcessId);
-    if (status != NO_ERROR) goto error;
+
     status = parcel->writeInt32((int32_t) mDirection);
     if (status != NO_ERROR) goto error;
 
@@ -70,10 +69,6 @@
 
     status = parcel->readInt32(&temp);
     if (status != NO_ERROR) goto error;
-    mProcessId = (pid_t) temp;
-
-    status = parcel->readInt32(&temp);
-    if (status != NO_ERROR) goto error;
     mDirection = (aaudio_direction_t) temp;
 
     status = parcel->readBool(&mSharingModeMatchRequired);
diff --git a/media/libaaudio/src/binding/IAAudioService.cpp b/media/libaaudio/src/binding/IAAudioService.cpp
index 247d1d2..e4bf82a 100644
--- a/media/libaaudio/src/binding/IAAudioService.cpp
+++ b/media/libaaudio/src/binding/IAAudioService.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <aaudio/AAudio.h>
+#include <binder/IPCThreadState.h>
 
 #include "binding/AudioEndpointParcelable.h"
 #include "binding/AAudioStreamRequest.h"
@@ -185,15 +186,13 @@
     }
 
     virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
-                                              pid_t clientProcessId,
-                                              pid_t clientThreadId,
-                                              int64_t periodNanoseconds)
+                                                pid_t clientThreadId,
+                                                int64_t periodNanoseconds)
     override {
         Parcel data, reply;
         // send command
         data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
         data.writeInt32(streamHandle);
-        data.writeInt32((int32_t) clientProcessId);
         data.writeInt32((int32_t) clientThreadId);
         data.writeInt64(periodNanoseconds);
         status_t err = remote()->transact(REGISTER_AUDIO_THREAD, data, &reply);
@@ -207,14 +206,12 @@
     }
 
     virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                  pid_t clientProcessId,
                                                   pid_t clientThreadId)
     override {
         Parcel data, reply;
         // send command
         data.writeInterfaceToken(IAAudioService::getInterfaceDescriptor());
         data.writeInt32(streamHandle);
-        data.writeInt32((int32_t) clientProcessId);
         data.writeInt32((int32_t) clientThreadId);
         status_t err = remote()->transact(UNREGISTER_AUDIO_THREAD, data, &reply);
         if (err != NO_ERROR) {
@@ -239,7 +236,6 @@
     aaudio_handle_t stream;
     aaudio::AAudioStreamRequest request;
     aaudio::AAudioStreamConfiguration configuration;
-    pid_t pid;
     pid_t tid;
     int64_t nanoseconds;
     aaudio_result_t result;
@@ -249,12 +245,13 @@
         case OPEN_STREAM: {
             CHECK_INTERFACE(IAAudioService, data, reply);
             request.readFromParcel(&data);
-
             //ALOGD("BnAAudioService::client openStream request dump --------------------");
             //request.dump();
-
+            // Override the uid and pid from the client in case they are incorrect.
+            request.setUserId(IPCThreadState::self()->getCallingUid());
+            request.setProcessId(IPCThreadState::self()->getCallingPid());
             stream = openStream(request, configuration);
-            //ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X", stream);
+            //ALOGD("BnAAudioService::onTransact OPEN_STREAM server handle = 0x%08X ----", stream);
             reply->writeInt32(stream);
             configuration.writeToParcel(reply);
             return NO_ERROR;
@@ -332,10 +329,9 @@
         case REGISTER_AUDIO_THREAD: {
             CHECK_INTERFACE(IAAudioService, data, reply);
             data.readInt32(&stream);
-            data.readInt32(&pid);
             data.readInt32(&tid);
             data.readInt64(&nanoseconds);
-            result = registerAudioThread(stream, pid, tid, nanoseconds);
+            result = registerAudioThread(stream, tid, nanoseconds);
             ALOGV("BnAAudioService::onTransact REGISTER_AUDIO_THREAD 0x%08X, result = %d",
                     stream, result);
             reply->writeInt32(result);
@@ -345,9 +341,8 @@
         case UNREGISTER_AUDIO_THREAD: {
             CHECK_INTERFACE(IAAudioService, data, reply);
             data.readInt32(&stream);
-            data.readInt32(&pid);
             data.readInt32(&tid);
-            result = unregisterAudioThread(stream, pid, tid);
+            result = unregisterAudioThread(stream, tid);
             ALOGV("BnAAudioService::onTransact UNREGISTER_AUDIO_THREAD 0x%08X, result = %d",
                     stream, result);
             reply->writeInt32(result);
diff --git a/media/libaaudio/src/binding/IAAudioService.h b/media/libaaudio/src/binding/IAAudioService.h
index 44a5e12..071c5b8 100644
--- a/media/libaaudio/src/binding/IAAudioService.h
+++ b/media/libaaudio/src/binding/IAAudioService.h
@@ -82,15 +82,12 @@
 
     /**
      * Manage the specified thread as a low latency audio thread.
-     * TODO Consider passing this information as part of the startStream() call.
      */
     virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
-                                              pid_t clientProcessId,
                                               pid_t clientThreadId,
                                               int64_t periodNanoseconds) = 0;
 
     virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                pid_t clientProcessId,
                                                 pid_t clientThreadId) = 0;
 };
 
diff --git a/media/libaaudio/src/client/AudioStreamInternal.cpp b/media/libaaudio/src/client/AudioStreamInternal.cpp
index b59c445..e40f4f9 100644
--- a/media/libaaudio/src/client/AudioStreamInternal.cpp
+++ b/media/libaaudio/src/client/AudioStreamInternal.cpp
@@ -364,7 +364,6 @@
         return AAUDIO_ERROR_INVALID_STATE;
     }
     return mServiceInterface.registerAudioThread(mServiceStreamHandle,
-                                              getpid(),
                                               gettid(),
                                               getPeriodNanoseconds());
 }
@@ -373,7 +372,7 @@
     if (mServiceStreamHandle == AAUDIO_HANDLE_INVALID) {
         return AAUDIO_ERROR_INVALID_STATE;
     }
-    return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, getpid(), gettid());
+    return mServiceInterface.unregisterAudioThread(mServiceStreamHandle, gettid());
 }
 
 aaudio_result_t AudioStreamInternal::getTimestamp(clockid_t clockId,
diff --git a/media/libaaudio/src/core/AudioStream.h b/media/libaaudio/src/core/AudioStream.h
index 7c7fcc5..15c85f9 100644
--- a/media/libaaudio/src/core/AudioStream.h
+++ b/media/libaaudio/src/core/AudioStream.h
@@ -84,9 +84,7 @@
         return AAUDIO_OK;
     }
 
-    virtual aaudio_result_t setBufferSize(int32_t requestedFrames) {
-        return AAUDIO_ERROR_UNIMPLEMENTED;
-    }
+    virtual aaudio_result_t setBufferSize(int32_t requestedFrames) = 0;
 
     virtual aaudio_result_t createThread(int64_t periodNanoseconds,
                                        aaudio_audio_thread_proc_t threadProc,
@@ -214,15 +212,15 @@
 
     // ============== I/O ===========================
     // A Stream will only implement read() or write() depending on its direction.
-    virtual aaudio_result_t write(const void *buffer,
-                             int32_t numFrames,
-                             int64_t timeoutNanoseconds) {
+    virtual aaudio_result_t write(const void *buffer __unused,
+                             int32_t numFrames __unused,
+                             int64_t timeoutNanoseconds __unused) {
         return AAUDIO_ERROR_UNIMPLEMENTED;
     }
 
-    virtual aaudio_result_t read(void *buffer,
-                            int32_t numFrames,
-                            int64_t timeoutNanoseconds) {
+    virtual aaudio_result_t read(void *buffer __unused,
+                            int32_t numFrames __unused,
+                            int64_t timeoutNanoseconds __unused) {
         return AAUDIO_ERROR_UNIMPLEMENTED;
     }
 
diff --git a/services/oboeservice/AAudioService.cpp b/services/oboeservice/AAudioService.cpp
index 0841127..443f40d 100644
--- a/services/oboeservice/AAudioService.cpp
+++ b/services/oboeservice/AAudioService.cpp
@@ -47,6 +47,8 @@
 
 android::AAudioService::AAudioService()
     : BnAAudioService() {
+    mCachedProcessId = getpid();
+    mCachedUserId = getuid();   // TODO consider using geteuid()
 }
 
 AAudioService::~AAudioService() {
@@ -108,8 +110,10 @@
         ALOGE("AAudioService::openStream(): failed, return %d", result);
         return result;
     } else {
+        const uid_t ownerUserId = request.getUserId(); // only set by service, not by client
+        serviceStream->setOwnerUserId(ownerUserId);
         aaudio_handle_t handle = mHandleTracker.put(AAUDIO_HANDLE_TYPE_STREAM, serviceStream);
-        ALOGD("AAudioService::openStream(): handle = 0x%08X", handle);
+        ALOGD("AAudioService::openStream(): handle = 0x%08X owned by %d", handle, ownerUserId);
         if (handle < 0) {
             ALOGE("AAudioService::openStream(): handle table full");
             delete serviceStream;
@@ -133,8 +137,23 @@
 
 AAudioServiceStreamBase *AAudioService::convertHandleToServiceStream(
         aaudio_handle_t streamHandle) const {
-    return (AAudioServiceStreamBase *) mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM,
-                              (aaudio_handle_t)streamHandle);
+    AAudioServiceStreamBase *serviceStream = (AAudioServiceStreamBase *)
+            mHandleTracker.get(AAUDIO_HANDLE_TYPE_STREAM, (aaudio_handle_t)streamHandle);
+    if (serviceStream != nullptr) {
+        // Only allow owner or the aaudio service to access the stream.
+        const uid_t callingUserId = IPCThreadState::self()->getCallingUid();
+        const uid_t ownerUserId = serviceStream->getOwnerUserId();
+        bool callerOwnsIt = callingUserId == ownerUserId;
+        bool serverCalling = callingUserId == mCachedUserId;
+        bool serverOwnsIt = ownerUserId == mCachedUserId;
+        bool allowed = callerOwnsIt || serverCalling || serverOwnsIt;
+        if (!allowed) {
+            ALOGE("AAudioService: calling uid %d cannot access stream 0x%08X owned by %d",
+                  callingUserId, streamHandle, ownerUserId);
+            serviceStream = nullptr;
+        }
+    }
+    return serviceStream;
 }
 
 aaudio_result_t AAudioService::getStreamDescription(
@@ -190,7 +209,6 @@
 }
 
 aaudio_result_t AAudioService::registerAudioThread(aaudio_handle_t streamHandle,
-                                                         pid_t clientProcessId,
                                                          pid_t clientThreadId,
                                                          int64_t periodNanoseconds) {
     AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
@@ -202,12 +220,14 @@
         ALOGE("AAudioService::registerAudioThread(), thread already registered");
         return AAUDIO_ERROR_INVALID_STATE;
     }
+
+    const pid_t ownerPid = IPCThreadState::self()->getCallingPid(); // TODO review
     serviceStream->setRegisteredThread(clientThreadId);
-    int err = android::requestPriority(clientProcessId, clientThreadId,
+    int err = android::requestPriority(ownerPid, clientThreadId,
                                        DEFAULT_AUDIO_PRIORITY, true /* isForApp */);
     if (err != 0){
-        ALOGE("AAudioService::registerAudioThread() failed, errno = %d, priority = %d",
-              errno, DEFAULT_AUDIO_PRIORITY);
+        ALOGE("AAudioService::registerAudioThread(%d) failed, errno = %d, priority = %d",
+              clientThreadId, errno, DEFAULT_AUDIO_PRIORITY);
         return AAUDIO_ERROR_INTERNAL;
     } else {
         return AAUDIO_OK;
@@ -215,7 +235,6 @@
 }
 
 aaudio_result_t AAudioService::unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                     pid_t clientProcessId,
                                                      pid_t clientThreadId) {
     AAudioServiceStreamBase *serviceStream = convertHandleToServiceStream(streamHandle);
     if (serviceStream == nullptr) {
diff --git a/services/oboeservice/AAudioService.h b/services/oboeservice/AAudioService.h
index c622f5d..9b6b342 100644
--- a/services/oboeservice/AAudioService.h
+++ b/services/oboeservice/AAudioService.h
@@ -64,11 +64,11 @@
     virtual aaudio_result_t flushStream(aaudio_handle_t streamHandle);
 
     virtual aaudio_result_t registerAudioThread(aaudio_handle_t streamHandle,
-                                              pid_t pid, pid_t tid,
-                                              int64_t periodNanoseconds) ;
+                                                pid_t tid,
+                                                int64_t periodNanoseconds) ;
 
     virtual aaudio_result_t unregisterAudioThread(aaudio_handle_t streamHandle,
-                                                  pid_t pid, pid_t tid);
+                                                  pid_t tid);
 
 private:
 
@@ -76,6 +76,9 @@
 
     HandleTracker mHandleTracker;
 
+    uid_t   mCachedUserId = -1;
+    pid_t   mCachedProcessId = -1;
+
     enum constants {
         DEFAULT_AUDIO_PRIORITY = 2
     };
diff --git a/services/oboeservice/AAudioServiceStreamBase.h b/services/oboeservice/AAudioServiceStreamBase.h
index 46ceeae..da0b537 100644
--- a/services/oboeservice/AAudioServiceStreamBase.h
+++ b/services/oboeservice/AAudioServiceStreamBase.h
@@ -113,6 +113,13 @@
 
     void processFatalError();
 
+    uid_t getOwnerUserId() const {
+        return mOwnerUserId;
+    }
+    void setOwnerUserId(uid_t uid) {
+        mOwnerUserId = uid;
+    }
+
 protected:
     aaudio_result_t writeUpMessageQueue(AAudioServiceMessage *command);
 
@@ -138,6 +145,7 @@
     int32_t            mSamplesPerFrame = AAUDIO_UNSPECIFIED;
     int32_t            mSampleRate = AAUDIO_UNSPECIFIED;
     int32_t            mCapacityInFrames = AAUDIO_UNSPECIFIED;
+    uid_t              mOwnerUserId = -1;
 };
 
 } /* namespace aaudio */