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

Commit 6b959ebe authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 12809477 from 06e3c3fa to 25Q2-release

Change-Id: I8471239078656ff72cfc68ce3f1207cc6e3e4ad8
parents 20f26af4 06e3c3fa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -775,6 +775,7 @@ void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(),
                   getpid());
    mProcess->checkExpectingThreadPoolStart();
    mProcess->mCurrentThreads++;
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

+84 −14
Original line number Diff line number Diff line
@@ -156,7 +156,7 @@ enum {

#ifdef BINDER_WITH_KERNEL_IPC
static void acquire_object(const sp<ProcessState>& proc, const flat_binder_object& obj,
                           const void* who) {
                           const void* who, bool tagFds) {
    switch (obj.hdr.type) {
        case BINDER_TYPE_BINDER:
            if (obj.binder) {
@@ -173,7 +173,7 @@ static void acquire_object(const sp<ProcessState>& proc, const flat_binder_objec
            return;
        }
        case BINDER_TYPE_FD: {
            if (obj.cookie != 0) { // owned
            if (tagFds && obj.cookie != 0) { // owned
                FdTag(obj.handle, nullptr, who);
            }
            return;
@@ -611,7 +611,7 @@ status_t Parcel::appendFrom(const Parcel* parcel, size_t offset, size_t len) {
                    }
                }

                acquire_object(proc, *flat, this);
                acquire_object(proc, *flat, this, true /*tagFds*/);
            }
        }
#else
@@ -1797,13 +1797,22 @@ restart_write:
        // Need to write meta-data?
        if (nullMetaData || val.binder != 0) {
            kernelFields->mObjects[kernelFields->mObjectsSize] = mDataPos;
            acquire_object(ProcessState::self(), val, this);
            acquire_object(ProcessState::self(), val, this, true /*tagFds*/);
            kernelFields->mObjectsSize++;
        }

        return finishWrite(sizeof(flat_binder_object));
    }

    if (mOwner) {
        // continueWrite does have the logic to convert this from an
        // owned to an unowned Parcel. However, this is pretty inefficient,
        // and it's really strange to need to do so, so prefer to avoid
        // these paths than try to support them.
        ALOGE("writing objects not supported on owned Parcels");
        return PERMISSION_DENIED;
    }

    if (!enoughData) {
        const status_t err = growData(sizeof(val));
        if (err != NO_ERROR) return err;
@@ -2719,6 +2728,65 @@ size_t Parcel::ipcObjectsCount() const
    return 0;
}

static void do_nothing_release_func(const uint8_t* data, size_t dataSize,
                                    const binder_size_t* objects, size_t objectsCount) {
    (void)data;
    (void)dataSize;
    (void)objects;
    (void)objectsCount;
}
static void delete_data_release_func(const uint8_t* data, size_t dataSize,
                                     const binder_size_t* objects, size_t objectsCount) {
    delete[] data;
    (void)dataSize;
    (void)objects;
    (void)objectsCount;
}

void Parcel::makeDangerousViewOf(Parcel* p) {
    if (p->isForRpc()) {
        // warning: this must match the logic in rpcSetDataReference
        auto* rf = p->maybeRpcFields();
        LOG_ALWAYS_FATAL_IF(rf == nullptr);
        std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>> fds;
        if (rf->mFds) {
            fds.reserve(rf->mFds->size());
            for (const auto& fd : *rf->mFds) {
                fds.push_back(binder::borrowed_fd(toRawFd(fd)));
            }
        }
        status_t result =
                rpcSetDataReference(rf->mSession, p->mData, p->mDataSize,
                                    rf->mObjectPositions.data(), rf->mObjectPositions.size(),
                                    std::move(fds), do_nothing_release_func);
        LOG_ALWAYS_FATAL_IF(result != OK, "Failed: %s", statusToString(result).c_str());
    } else {
#ifdef BINDER_WITH_KERNEL_IPC
        // warning: this must match the logic in ipcSetDataReference
        auto* kf = p->maybeKernelFields();
        LOG_ALWAYS_FATAL_IF(kf == nullptr);

        // Ownership of FDs is passed to the Parcel from kernel binder. This should be refactored
        // to move this ownership out of Parcel and into release_func. However, today, Parcel
        // always assums it can own and close FDs today. So, for purposes of testing consistency,
        // , create new FDs it can own.

        uint8_t* newData = new uint8_t[p->mDataSize]; // deleted by delete_data_release_func
        memcpy(newData, p->mData, p->mDataSize);
        for (size_t i = 0; i < kf->mObjectsSize; i++) {
            flat_binder_object* flat =
                    reinterpret_cast<flat_binder_object*>(newData + kf->mObjects[i]);
            if (flat->hdr.type == BINDER_TYPE_FD) {
                flat->handle = fcntl(flat->handle, F_DUPFD_CLOEXEC, 0);
            }
        }

        ipcSetDataReference(newData, p->mDataSize, kf->mObjects, kf->mObjectsSize,
                            delete_data_release_func);
#endif // BINDER_WITH_KERNEL_IPC
    }
}

void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
                                 size_t objectsCount, release_func relFunc) {
    // this code uses 'mOwner == nullptr' to understand whether it owns memory
@@ -2729,6 +2797,7 @@ void Parcel::ipcSetDataReference(const uint8_t* data, size_t dataSize, const bin
    auto* kernelFields = maybeKernelFields();
    LOG_ALWAYS_FATAL_IF(kernelFields == nullptr); // guaranteed by freeData.

    // must match makeDangerousViewOf
    mData = const_cast<uint8_t*>(data);
    mDataSize = mDataCapacity = dataSize;
    kernelFields->mObjects = const_cast<binder_size_t*>(objects);
@@ -2807,6 +2876,7 @@ status_t Parcel::rpcSetDataReference(
    auto* rpcFields = maybeRpcFields();
    LOG_ALWAYS_FATAL_IF(rpcFields == nullptr); // guaranteed by markForRpc.

    // must match makeDangerousViewOf
    mData = const_cast<uint8_t*>(data);
    mDataSize = mDataCapacity = dataSize;
    mOwner = relFunc;
@@ -2874,15 +2944,17 @@ void Parcel::releaseObjects()
#endif // BINDER_WITH_KERNEL_IPC
}

void Parcel::acquireObjects()
{
void Parcel::reacquireObjects(size_t objectsSize) {
    auto* kernelFields = maybeKernelFields();
    if (kernelFields == nullptr) {
        return;
    }

#ifdef BINDER_WITH_KERNEL_IPC
    size_t i = kernelFields->mObjectsSize;
    LOG_ALWAYS_FATAL_IF(objectsSize > kernelFields->mObjectsSize,
                        "Object size %zu out of range of %zu", objectsSize,
                        kernelFields->mObjectsSize);
    size_t i = objectsSize;
    if (i == 0) {
        return;
    }
@@ -2892,8 +2964,10 @@ void Parcel::acquireObjects()
    while (i > 0) {
        i--;
        const flat_binder_object* flat = reinterpret_cast<flat_binder_object*>(data + objects[i]);
        acquire_object(proc, *flat, this);
        acquire_object(proc, *flat, this, false /*tagFds*/); // they are already tagged
    }
#else
    (void) objectsSize;
#endif // BINDER_WITH_KERNEL_IPC
}

@@ -3110,12 +3184,8 @@ status_t Parcel::continueWrite(size_t desired)
                return NO_MEMORY;
            }

            // Little hack to only acquire references on objects
            // we will be keeping.
            size_t oldObjectsSize = kernelFields->mObjectsSize;
            kernelFields->mObjectsSize = objectsSize;
            acquireObjects();
            kernelFields->mObjectsSize = oldObjectsSize;
            // only acquire references on objects we are keeping
            reacquireObjects(objectsSize);
        }
        if (rpcFields) {
            if (status_t status = truncateRpcObjects(objectsSize); status != OK) {
+15 −0
Original line number Diff line number Diff line
@@ -501,6 +501,21 @@ bool ProcessState::isThreadPoolStarted() const {
    return mThreadPoolStarted;
}

void ProcessState::checkExpectingThreadPoolStart() const {
    if (mThreadPoolStarted) return;

    // this is also racey, but you should setup the threadpool in the main thread. If that is an
    // issue, we can check if we are the process leader, but haven't seen the issue in practice.
    size_t requestedThreads = mMaxThreads.load();

    // if it's manually set to the default, we do ignore it here...
    if (requestedThreads == DEFAULT_MAX_BINDER_THREADS) return;
    if (requestedThreads == 0) return;

    ALOGW("Thread pool configuration of size %zu requested, but startThreadPool was not called.",
          requestedThreads);
}

#define DRIVER_FEATURES_PATH "/dev/binderfs/features/"
bool ProcessState::isDriverFeatureEnabled(const DriverFeature feature) {
    // Use static variable to cache the results.
+7 −2
Original line number Diff line number Diff line
@@ -649,6 +649,11 @@ public:

    LIBBINDER_EXPORTED void print(std::ostream& to, uint32_t flags = 0) const;

    // This API is to quickly become a view of another Parcel, so that we can also
    // test 'owner' paths quickly. It's extremely dangerous to use this API in
    // practice, and you should never ever do it.
    LIBBINDER_EXPORTED void makeDangerousViewOf(Parcel* p);

private:
    // Close all file descriptors in the parcel at object positions >= newObjectsSize.
    void closeFileDescriptors(size_t newObjectsSize);
@@ -664,7 +669,7 @@ private:
    void ipcSetDataReference(const uint8_t* data, size_t dataSize, const binder_size_t* objects,
                             size_t objectsCount, release_func relFunc);
    // Takes ownership even when an error is returned.
    status_t rpcSetDataReference(
    [[nodiscard]] status_t rpcSetDataReference(
            const sp<RpcSession>& session, const uint8_t* data, size_t dataSize,
            const uint32_t* objectTable, size_t objectTableSize,
            std::vector<std::variant<binder::unique_fd, binder::borrowed_fd>>&& ancillaryFds,
@@ -672,7 +677,7 @@ private:

    status_t            finishWrite(size_t len);
    void                releaseObjects();
    void                acquireObjects();
    void reacquireObjects(size_t objectSize);
    status_t            growData(size_t len);
    // Clear the Parcel and set the capacity to `desired`.
    // Doesn't reset the RPC session association.
+2 −0
Original line number Diff line number Diff line
@@ -141,6 +141,8 @@ public:
private:
    static sp<ProcessState> init(const char* defaultDriver, bool requireDefault);

    void checkExpectingThreadPoolStart() const;

    static void onFork();
    static void parentPostFork();
    static void childPostFork();
Loading