Merge "Increase core count in atrace.rc"
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 805e576..181f405 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -548,21 +548,17 @@
     return mHasFds;
 }
 
-status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool& result) const {
+status_t Parcel::hasFileDescriptorsInRange(size_t offset, size_t len, bool* result) const {
     if (len > INT32_MAX || offset > INT32_MAX) {
         // Don't accept size_t values which may have come from an inadvertent conversion from a
         // negative int.
         return BAD_VALUE;
     }
-    size_t limit = offset + len;
-    if (offset > mDataSize || len > mDataSize || limit > mDataSize || offset > limit) {
+    size_t limit;
+    if (__builtin_add_overflow(offset, len, &limit) || limit > mDataSize) {
         return BAD_VALUE;
     }
-    result = hasFileDescriptorsInRangeUnchecked(offset, len);
-    return NO_ERROR;
-}
-
-bool Parcel::hasFileDescriptorsInRangeUnchecked(size_t offset, size_t len) const {
+    *result = false;
     for (size_t i = 0; i < mObjectsSize; i++) {
         size_t pos = mObjects[i];
         if (pos < offset) continue;
@@ -572,10 +568,11 @@
         }
         const flat_binder_object* flat = reinterpret_cast<const flat_binder_object*>(mData + pos);
         if (flat->hdr.type == BINDER_TYPE_FD) {
-            return true;
+            *result = true;
+            break;
         }
     }
-    return false;
+    return NO_ERROR;
 }
 
 void Parcel::markSensitive() const
@@ -2568,9 +2565,9 @@
     }
 }
 
-void Parcel::scanForFds() const
-{
-    mHasFds = hasFileDescriptorsInRangeUnchecked(0, dataSize());
+void Parcel::scanForFds() const {
+    status_t status = hasFileDescriptorsInRange(0, dataSize(), &mHasFds);
+    ALOGE_IF(status != NO_ERROR, "Error %d calling hasFileDescriptorsInRange()", status);
     mFdsKnown = true;
 }
 
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index 967b8e3..4edc202 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -127,14 +127,23 @@
 
 void RpcServer::setRootObject(const sp<IBinder>& binder) {
     std::lock_guard<std::mutex> _l(mLock);
+    mRootObjectFactory = nullptr;
     mRootObjectWeak = mRootObject = binder;
 }
 
 void RpcServer::setRootObjectWeak(const wp<IBinder>& binder) {
     std::lock_guard<std::mutex> _l(mLock);
     mRootObject.clear();
+    mRootObjectFactory = nullptr;
     mRootObjectWeak = binder;
 }
+void RpcServer::setPerSessionRootObject(
+        std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& makeObject) {
+    std::lock_guard<std::mutex> _l(mLock);
+    mRootObject.clear();
+    mRootObjectWeak.clear();
+    mRootObjectFactory = std::move(makeObject);
+}
 
 sp<IBinder> RpcServer::getRootObject() {
     std::lock_guard<std::mutex> _l(mLock);
@@ -174,8 +183,14 @@
 
     status_t status;
     while ((status = mShutdownTrigger->triggerablePoll(mServer, POLLIN)) == OK) {
-        unique_fd clientFd(TEMP_FAILURE_RETRY(
-                accept4(mServer.get(), nullptr, nullptr /*length*/, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+        sockaddr_storage addr;
+        socklen_t addrLen = sizeof(addr);
+
+        unique_fd clientFd(
+                TEMP_FAILURE_RETRY(accept4(mServer.get(), reinterpret_cast<sockaddr*>(&addr),
+                                           &addrLen, SOCK_CLOEXEC | SOCK_NONBLOCK)));
+
+        LOG_ALWAYS_FATAL_IF(addrLen > static_cast<socklen_t>(sizeof(addr)), "Truncated address");
 
         if (clientFd < 0) {
             ALOGE("Could not accept4 socket: %s", strerror(errno));
@@ -187,7 +202,7 @@
             std::lock_guard<std::mutex> _l(mLock);
             std::thread thread =
                     std::thread(&RpcServer::establishConnection, sp<RpcServer>::fromExisting(this),
-                                std::move(clientFd));
+                                std::move(clientFd), addr, addrLen);
             mConnectingThreads[thread.get_id()] = std::move(thread);
         }
     }
@@ -257,7 +272,8 @@
     return mConnectingThreads.size();
 }
 
-void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd) {
+void RpcServer::establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
+                                    const sockaddr_storage addr, socklen_t addrLen) {
     // TODO(b/183988761): cannot trust this simple ID
     LOG_ALWAYS_FATAL_IF(!server->mAgreedExperimental, "no!");
 
@@ -383,11 +399,23 @@
             session = RpcSession::make();
             session->setMaxIncomingThreads(server->mMaxThreads);
             if (!session->setProtocolVersion(protocolVersion)) return;
+
+            // if null, falls back to server root
+            sp<IBinder> sessionSpecificRoot;
+            if (server->mRootObjectFactory != nullptr) {
+                sessionSpecificRoot =
+                        server->mRootObjectFactory(reinterpret_cast<const sockaddr*>(&addr),
+                                                   addrLen);
+                if (sessionSpecificRoot == nullptr) {
+                    ALOGE("Warning: server returned null from root object factory");
+                }
+            }
+
             if (!session->setForServer(server,
                                        sp<RpcServer::EventListener>::fromExisting(
                                                static_cast<RpcServer::EventListener*>(
                                                        server.get())),
-                                       sessionId)) {
+                                       sessionId, sessionSpecificRoot)) {
                 ALOGE("Failed to attach server to session");
                 return;
             }
diff --git a/libs/binder/RpcSession.cpp b/libs/binder/RpcSession.cpp
index 9eef3e8..137411b 100644
--- a/libs/binder/RpcSession.cpp
+++ b/libs/binder/RpcSession.cpp
@@ -700,7 +700,8 @@
 }
 
 bool RpcSession::setForServer(const wp<RpcServer>& server, const wp<EventListener>& eventListener,
-                              const std::vector<uint8_t>& sessionId) {
+                              const std::vector<uint8_t>& sessionId,
+                              const sp<IBinder>& sessionSpecificRoot) {
     LOG_ALWAYS_FATAL_IF(mForServer != nullptr);
     LOG_ALWAYS_FATAL_IF(server == nullptr);
     LOG_ALWAYS_FATAL_IF(mEventListener != nullptr);
@@ -713,6 +714,7 @@
     mId = sessionId;
     mForServer = server;
     mEventListener = eventListener;
+    mSessionSpecificRootObject = sessionSpecificRoot;
     return true;
 }
 
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 9ba64f3..09b3d68 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -870,7 +870,9 @@
                     if (server) {
                         switch (transaction->code) {
                             case RPC_SPECIAL_TRANSACT_GET_ROOT: {
-                                replyStatus = reply.writeStrongBinder(server->getRootObject());
+                                sp<IBinder> root = session->mSessionSpecificRootObject
+                                        ?: server->getRootObject();
+                                replyStatus = reply.writeStrongBinder(root);
                                 break;
                             }
                             default: {
diff --git a/libs/binder/include/binder/Parcel.h b/libs/binder/include/binder/Parcel.h
index 32056d9..d90e803 100644
--- a/libs/binder/include/binder/Parcel.h
+++ b/libs/binder/include/binder/Parcel.h
@@ -87,7 +87,7 @@
     void                restoreAllowFds(bool lastValue);
 
     bool                hasFileDescriptors() const;
-    status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool& result) const;
+    status_t hasFileDescriptorsInRange(size_t offset, size_t length, bool* result) const;
 
     // Zeros data when reallocating. Other mitigations may be added
     // in the future.
@@ -576,7 +576,6 @@
 
     status_t            writeRawNullableParcelable(const Parcelable*
                                                    parcelable);
-    bool hasFileDescriptorsInRangeUnchecked(size_t offset, size_t length) const;
 
     //-----------------------------------------------------------------------------
     // Generic type read and write methods for Parcel:
diff --git a/libs/binder/include/binder/RpcServer.h b/libs/binder/include/binder/RpcServer.h
index fb2cf23..04c6b59 100644
--- a/libs/binder/include/binder/RpcServer.h
+++ b/libs/binder/include/binder/RpcServer.h
@@ -130,6 +130,10 @@
      * Holds a weak reference to the root object.
      */
     void setRootObjectWeak(const wp<IBinder>& binder);
+    /**
+     * Allows a root object to be created for each session
+     */
+    void setPerSessionRootObject(std::function<sp<IBinder>(const sockaddr*, socklen_t)>&& object);
     sp<IBinder> getRootObject();
 
     /**
@@ -179,7 +183,8 @@
     void onSessionAllIncomingThreadsEnded(const sp<RpcSession>& session) override;
     void onSessionIncomingThreadEnded() override;
 
-    static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd);
+    static void establishConnection(sp<RpcServer>&& server, base::unique_fd clientFd,
+                                    const sockaddr_storage addr, socklen_t addrLen);
     status_t setupSocketServer(const RpcSocketAddress& address);
 
     const std::unique_ptr<RpcTransportCtx> mCtx;
@@ -194,6 +199,7 @@
     std::map<std::thread::id, std::thread> mConnectingThreads;
     sp<IBinder> mRootObject;
     wp<IBinder> mRootObjectWeak;
+    std::function<sp<IBinder>(const sockaddr*, socklen_t)> mRootObjectFactory;
     std::map<std::vector<uint8_t>, sp<RpcSession>> mSessions;
     std::unique_ptr<FdTrigger> mShutdownTrigger;
     std::condition_variable mShutdownCv;
diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h
index f5505da..f9b733d 100644
--- a/libs/binder/include/binder/RpcSession.h
+++ b/libs/binder/include/binder/RpcSession.h
@@ -256,7 +256,8 @@
                                                  bool init);
     [[nodiscard]] bool setForServer(const wp<RpcServer>& server,
                                     const wp<RpcSession::EventListener>& eventListener,
-                                    const std::vector<uint8_t>& sessionId);
+                                    const std::vector<uint8_t>& sessionId,
+                                    const sp<IBinder>& sessionSpecificRoot);
     sp<RpcConnection> assignIncomingConnectionToThisThread(
             std::unique_ptr<RpcTransport> rpcTransport);
     [[nodiscard]] bool removeIncomingConnection(const sp<RpcConnection>& connection);
@@ -313,6 +314,10 @@
     sp<WaitForShutdownListener> mShutdownListener; // used for client sessions
     wp<EventListener> mEventListener; // mForServer if server, mShutdownListener if client
 
+    // session-specific root object (if a different root is used for each
+    // session)
+    sp<IBinder> mSessionSpecificRootObject;
+
     std::vector<uint8_t> mId;
 
     std::unique_ptr<FdTrigger> mShutdownTrigger;
diff --git a/libs/binder/tests/IBinderRpcTest.aidl b/libs/binder/tests/IBinderRpcTest.aidl
index 9e10788..fdd02a4 100644
--- a/libs/binder/tests/IBinderRpcTest.aidl
+++ b/libs/binder/tests/IBinderRpcTest.aidl
@@ -18,6 +18,9 @@
     oneway void sendString(@utf8InCpp String str);
     @utf8InCpp String doubleString(@utf8InCpp String str);
 
+    // get the port that a client used to connect to this object
+    int getClientPort();
+
     // number of known RPC binders to process, RpcState::countBinders by session
     int[] countBinders();
 
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index f132ff7..62215bb 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -174,6 +174,7 @@
 class MyBinderRpcTest : public BnBinderRpcTest {
 public:
     wp<RpcServer> server;
+    int port = 0;
 
     Status sendString(const std::string& str) override {
         (void)str;
@@ -183,6 +184,10 @@
         *strstr = str + str;
         return Status::ok();
     }
+    Status getClientPort(int* out) override {
+        *out = port;
+        return Status::ok();
+    }
     Status countBinders(std::vector<int32_t>* out) override {
         sp<RpcServer> spServer = server.promote();
         if (spServer == nullptr) {
@@ -643,13 +648,39 @@
 
     BinderRpcTestProcessSession createRpcTestSocketServerProcess(const Options& options) {
         BinderRpcTestProcessSession ret{
-                .proc = createRpcTestSocketServerProcess(options,
-                                                         [&](const sp<RpcServer>& server) {
-                                                             sp<MyBinderRpcTest> service =
-                                                                     new MyBinderRpcTest;
-                                                             server->setRootObject(service);
-                                                             service->server = server;
-                                                         }),
+                .proc = createRpcTestSocketServerProcess(
+                        options,
+                        [&](const sp<RpcServer>& server) {
+                            server->setPerSessionRootObject([&](const sockaddr* addr,
+                                                                socklen_t len) {
+                                sp<MyBinderRpcTest> service = sp<MyBinderRpcTest>::make();
+                                switch (addr->sa_family) {
+                                    case AF_UNIX:
+                                        // nothing to save
+                                        break;
+                                    case AF_VSOCK:
+                                        CHECK_EQ(len, sizeof(sockaddr_vm));
+                                        service->port = reinterpret_cast<const sockaddr_vm*>(addr)
+                                                                ->svm_port;
+                                        break;
+                                    case AF_INET:
+                                        CHECK_EQ(len, sizeof(sockaddr_in));
+                                        service->port = reinterpret_cast<const sockaddr_in*>(addr)
+                                                                ->sin_port;
+                                        break;
+                                    case AF_INET6:
+                                        CHECK_EQ(len, sizeof(sockaddr_in));
+                                        service->port = reinterpret_cast<const sockaddr_in6*>(addr)
+                                                                ->sin6_port;
+                                        break;
+                                    default:
+                                        LOG_ALWAYS_FATAL("Unrecognized address family %d",
+                                                         addr->sa_family);
+                                }
+                                service->server = server;
+                                return service;
+                            });
+                        }),
         };
 
         ret.rootBinder = ret.proc.sessions.at(0).root;
@@ -682,6 +713,27 @@
     }
 }
 
+TEST_P(BinderRpc, SeparateRootObject) {
+    SocketType type = std::get<0>(GetParam());
+    if (type == SocketType::PRECONNECTED || type == SocketType::UNIX) {
+        // we can't get port numbers for unix sockets
+        return;
+    }
+
+    auto proc = createRpcTestSocketServerProcess({.numSessions = 2});
+
+    int port1 = 0;
+    EXPECT_OK(proc.rootIface->getClientPort(&port1));
+
+    sp<IBinderRpcTest> rootIface2 = interface_cast<IBinderRpcTest>(proc.proc.sessions.at(1).root);
+    int port2;
+    EXPECT_OK(rootIface2->getClientPort(&port2));
+
+    // we should have a different IBinderRpcTest object created for each
+    // session, because we use setPerSessionRootObject
+    EXPECT_NE(port1, port2);
+}
+
 TEST_P(BinderRpc, TransactionsMustBeMarkedRpc) {
     auto proc = createRpcTestSocketServerProcess({});
     Parcel data;
diff --git a/libs/binder/tests/parcel_fuzzer/binder.cpp b/libs/binder/tests/parcel_fuzzer/binder.cpp
index 8e8994b..e4f57b0 100644
--- a/libs/binder/tests/parcel_fuzzer/binder.cpp
+++ b/libs/binder/tests/parcel_fuzzer/binder.cpp
@@ -305,7 +305,7 @@
         size_t offset = p.readUint32();
         size_t length = p.readUint32();
         bool result;
-        status_t status = p.hasFileDescriptorsInRange(offset, length, result);
+        status_t status = p.hasFileDescriptorsInRange(offset, length, &result);
         FUZZ_LOG() << " status: " << status  << " result: " << result;
     },
 };