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

Commit 94fdd187 authored by Automerger Merge Worker's avatar Automerger Merge Worker
Browse files

Merge "libbinder_ndk: support handleShellCommand" am: ef464b38

Change-Id: I68f451481f618ab57316fa973d67a831a63eee8c
parents a645ce2a ef464b38
Loading
Loading
Loading
Loading
+49 −0
Original line number Diff line number Diff line
@@ -24,10 +24,13 @@

#include <android-base/logging.h>
#include <binder/IPCThreadState.h>
#include <binder/IResultReceiver.h>
#include <private/android_filesystem_config.h>

using DeathRecipient = ::android::IBinder::DeathRecipient;

using ::android::IBinder;
using ::android::IResultReceiver;
using ::android::Parcel;
using ::android::sp;
using ::android::status_t;
@@ -158,6 +161,45 @@ status_t ABBinder::onTransact(transaction_code_t code, const Parcel& data, Parce

        binder_status_t status = getClass()->onTransact(this, code, &in, &out);
        return PruneStatusT(status);
    } else if (code == SHELL_COMMAND_TRANSACTION) {
        int in = data.readFileDescriptor();
        int out = data.readFileDescriptor();
        int err = data.readFileDescriptor();

        int argc = data.readInt32();
        std::vector<String8> utf8Args;          // owns memory of utf8s
        std::vector<const char*> utf8Pointers;  // what can be passed over NDK API
        for (int i = 0; i < argc && data.dataAvail() > 0; i++) {
            utf8Args.push_back(String8(data.readString16()));
            utf8Pointers.push_back(utf8Args[i].c_str());
        }

        data.readStrongBinder();  // skip over the IShellCallback
        sp<IResultReceiver> resultReceiver = IResultReceiver::asInterface(data.readStrongBinder());

        // Shell commands should only be callable by ADB.
        uid_t uid = AIBinder_getCallingUid();
        if (uid != AID_ROOT && uid != AID_SHELL) {
            if (resultReceiver != nullptr) {
                resultReceiver->send(-1);
            }
            return STATUS_PERMISSION_DENIED;
        }

        // Check that the file descriptors are valid.
        if (in == STATUS_BAD_TYPE || out == STATUS_BAD_TYPE || err == STATUS_BAD_TYPE) {
            if (resultReceiver != nullptr) {
                resultReceiver->send(-1);
            }
            return STATUS_BAD_VALUE;
        }

        binder_status_t status = getClass()->handleShellCommand(
                this, in, out, err, utf8Pointers.data(), utf8Pointers.size());
        if (resultReceiver != nullptr) {
            resultReceiver->send(status);
        }
        return status;
    } else {
        return BBinder::onTransact(code, data, reply, flags);
    }
@@ -266,6 +308,13 @@ void AIBinder_Class_setOnDump(AIBinder_Class* clazz, AIBinder_onDump onDump) {
    clazz->onDump = onDump;
}

void AIBinder_Class_setHandleShellCommand(AIBinder_Class* clazz,
                                          AIBinder_handleShellCommand handleShellCommand) {
    CHECK(clazz != nullptr) << "setHandleShellCommand requires non-null clazz";

    clazz->handleShellCommand = handleShellCommand;
}

void AIBinder_DeathRecipient::TransferDeathRecipient::binderDied(const wp<IBinder>& who) {
    CHECK(who == mWho);

+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <android/binder_ibinder.h>
#include <android/binder_shell.h>
#include "ibinder_internal.h"

#include <atomic>
@@ -115,6 +116,7 @@ struct AIBinder_Class {

    // optional methods for a class
    AIBinder_onDump onDump;
    AIBinder_handleShellCommand handleShellCommand;

   private:
    // This must be a String16 since BBinder virtual getInterfaceDescriptor returns a reference to
+40 −3
Original line number Diff line number Diff line
@@ -30,6 +30,11 @@
#include <android/binder_auto_utils.h>
#include <android/binder_ibinder.h>

#if __has_include(<android/binder_shell.h>)
#include <android/binder_shell.h>
#define HAS_BINDER_SHELL_COMMAND
#endif  //_has_include

#include <assert.h>

#include <memory>
@@ -108,7 +113,15 @@ class ICInterface : public SharedRefBase {
    /**
     * Dumps information about the interface. By default, dumps nothing.
     */
    virtual inline binder_status_t dump(int /*fd*/, const char** /*args*/, uint32_t /*numArgs*/);
    virtual inline binder_status_t dump(int fd, const char** args, uint32_t numArgs);

#ifdef HAS_BINDER_SHELL_COMMAND
    /**
     * Process shell commands. By default, does nothing.
     */
    virtual inline binder_status_t handleShellCommand(int in, int out, int err, const char** argv,
                                                      uint32_t argc);
#endif

    /**
     * Interprets this binder as this underlying interface if this has stored an ICInterface in the
@@ -136,6 +149,11 @@ class ICInterface : public SharedRefBase {
        static inline void onDestroy(void* userData);
        static inline binder_status_t onDump(AIBinder* binder, int fd, const char** args,
                                             uint32_t numArgs);

#ifdef HAS_BINDER_SHELL_COMMAND
        static inline binder_status_t handleShellCommand(AIBinder* binder, int in, int out, int err,
                                                         const char** argv, uint32_t argc);
#endif
    };
};

@@ -191,6 +209,13 @@ binder_status_t ICInterface::dump(int /*fd*/, const char** /*args*/, uint32_t /*
    return STATUS_OK;
}

#ifdef HAS_BINDER_SHELL_COMMAND
binder_status_t ICInterface::handleShellCommand(int /*in*/, int /*out*/, int /*err*/,
                                                const char** /*argv*/, uint32_t /*argc*/) {
    return STATUS_OK;
}
#endif

std::shared_ptr<ICInterface> ICInterface::asInterface(AIBinder* binder) {
    return ICInterfaceData::getInterface(binder);
}
@@ -203,9 +228,12 @@ AIBinder_Class* ICInterface::defineClass(const char* interfaceDescriptor,
        return nullptr;
    }

    // We can't know if this method is overriden by a subclass interface, so we must register
    // ourselves. The default (nothing to dump) is harmless.
    // We can't know if these methods are overridden by a subclass interface, so we must register
    // ourselves. The defaults are harmless.
    AIBinder_Class_setOnDump(clazz, ICInterfaceData::onDump);
#ifdef HAS_BINDER_SHELL_COMMAND
    AIBinder_Class_setHandleShellCommand(clazz, ICInterfaceData::handleShellCommand);
#endif
    return clazz;
}

@@ -234,6 +262,15 @@ binder_status_t ICInterface::ICInterfaceData::onDump(AIBinder* binder, int fd, c
    return interface->dump(fd, args, numArgs);
}

#ifdef HAS_BINDER_SHELL_COMMAND
binder_status_t ICInterface::ICInterfaceData::handleShellCommand(AIBinder* binder, int in, int out,
                                                                 int err, const char** argv,
                                                                 uint32_t argc) {
    std::shared_ptr<ICInterface> interface = getInterface(binder);
    return interface->handleShellCommand(in, out, err, argv, argc);
}
#endif

template <typename INTERFACE>
SpAIBinder BnCInterface<INTERFACE>::asBinder() {
    std::lock_guard<std::mutex> l(mMutex);
+55 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source 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.
 */

#pragma once

#include <android/binder_ibinder.h>

__BEGIN_DECLS

/**
 * Function to execute a shell command.
 *
 * Available since API level 30.
 *
 * \param binder the binder executing the command
 * \param in input file descriptor, should be flushed, ownership is not passed
 * \param out output file descriptor, should be flushed, ownership is not passed
 * \param err error file descriptor, should be flushed, ownership is not passed
 * \param argv array of null-terminated strings for command (may be null if argc
 * is 0)
 * \param argc length of argv array
 *
 * \return binder_status_t result of transaction
 */
typedef binder_status_t (*AIBinder_handleShellCommand)(AIBinder* binder, int in, int out, int err,
                                                       const char** argv, uint32_t argc);

/**
 * This sets the implementation of handleShellCommand for a class.
 *
 * If this isn't set, nothing will be executed when handleShellCommand is called.
 *
 * Available since API level 30.
 *
 * \param handleShellCommand function to call when a shell transaction is
 * received
 */
void AIBinder_Class_setHandleShellCommand(AIBinder_Class* clazz,
                                          AIBinder_handleShellCommand handleShellCommand)
        __INTRODUCED_IN(30);

__END_DECLS
+1 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ LIBBINDER_NDK30 { # introduced=30
    AIBinder_markSystemStability; # apex
    AIBinder_markVendorStability; # llndk
    AIBinder_markVintfStability; # apex llndk
    AIBinder_Class_setHandleShellCommand; # apex llndk
  local:
    *;
};
Loading