Skip to content

Commit

Permalink
add eSE PM injection
Browse files Browse the repository at this point in the history
  • Loading branch information
cinit committed Dec 29, 2021
1 parent 44a86d6 commit 9cc111f
Show file tree
Hide file tree
Showing 29 changed files with 785 additions and 310 deletions.
15 changes: 12 additions & 3 deletions app/src/main/cpp/libbasehalpatch/ipc/daemon_ipc_struct.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ enum class OpType : uint32_t {
OP_TYPE_IO_SELECT = 6,
};

class SourceType {
public:
static constexpr uint32_t UNKNOWN = 0;
static constexpr uint32_t NFC_CONTROLLER = 0x100;
static constexpr uint32_t SECURE_ELEMENT_EMBEDDED = 0x200;
};

struct IoSyscallInfo {
int32_t opType;
int32_t fd;
Expand All @@ -70,14 +77,16 @@ struct IoSyscallInfo {
int64_t bufferLength;
};

struct IoOperationEvent {
uint32_t sequence;
struct IoSyscallEvent {
uint32_t uniqueSequence;
uint32_t sourceType;
uint32_t sourceSequence;
uint32_t rfu;
uint64_t timestamp;
IoSyscallInfo info;
};
static_assert(sizeof(IoSyscallInfo) == 40);
static_assert(sizeof(IoOperationEvent) == sizeof(IoSyscallInfo) + 16);
static_assert(sizeof(IoSyscallEvent) == sizeof(IoSyscallInfo) + 24);
static_assert(sizeof(OriginHookProcedure) == 56);

struct SharedObjectInfo {
Expand Down
11 changes: 7 additions & 4 deletions app/src/main/cpp/libbasehalpatch/ipc/ipc_io_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,23 @@ static uint64_t getCurrentTimeMillis() {

static void postIoEvent(const IoSyscallInfo &opInfo, const void *ioBuffer, size_t ioBufSize) {
if (int fd = getDaemonIpcSocket(); fd > 0) {
size_t pkLen = sizeof(HalTrxnPacketHeader) + sizeof(IoOperationEvent) + (ioBuffer == nullptr ? 0 : ioBufSize);
size_t pkLen = sizeof(HalTrxnPacketHeader) + sizeof(IoSyscallEvent) + (ioBuffer == nullptr ? 0 : ioBufSize);
void *buf = malloc(pkLen);
if (buf == nullptr) {
return;
}
if (ioBuffer != nullptr && ioBufSize > 0) {
memcpy(((char *) buf) + sizeof(HalTrxnPacketHeader) + sizeof(IoOperationEvent), ioBuffer, ioBufSize);
memcpy(((char *) buf) + sizeof(HalTrxnPacketHeader) + sizeof(IoSyscallEvent), ioBuffer, ioBufSize);
}
auto *pHeader = static_cast<HalTrxnPacketHeader *>(buf);
pHeader->type = TrxnType::IO_EVENT;
pHeader->length = int(pkLen);
auto *pEvent = reinterpret_cast<IoOperationEvent *>(((char *) buf) + sizeof(HalTrxnPacketHeader));
auto *pEvent = reinterpret_cast<IoSyscallEvent *>(((char *) buf) + sizeof(HalTrxnPacketHeader));
pEvent->rfu = 0;
pEvent->sequence = g_IoEventSequence++;
// we don't know the uniqueSequence and sourceType, leave them as 0, they will be filled in by the daemon
pEvent->uniqueSequence = 0;
pEvent->sourceType = 0;
pEvent->sourceSequence = g_IoEventSequence++;
pEvent->timestamp = getCurrentTimeMillis();
pEvent->info = opInfo;
pEvent->info.bufferLength = int64_t(ioBufSize);
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/libnciclient/NciClientImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ bool NciClientImpl::dispatchEvent(const IpcTransactor::LpcEnv &env, uint32_t eve
switch (eventId) {
case Ids::IO_EVENT : {
R::invoke(this, args, R::is(
+[](T *p, const IoOperationEvent &event, const std::vector<uint8_t> &payload) {
+[](T *p, const IoSyscallEvent &event, const std::vector<uint8_t> &payload) {
p->onIoEvent(event, payload);
}));
return true;
Expand All @@ -43,7 +43,7 @@ bool NciClientImpl::dispatchEvent(const IpcTransactor::LpcEnv &env, uint32_t eve
}
}

void NciClientImpl::onIoEvent(const IoOperationEvent &event, const std::vector<uint8_t> &payload) {
void NciClientImpl::onIoEvent(const IoSyscallEvent &event, const std::vector<uint8_t> &payload) {
NciClientImpl_forwardRemoteIoEvent(event, payload);
}

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/libnciclient/NciClientImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ class NciClientImpl : public INciClient, public BaseIpcObject {

bool dispatchEvent(const IpcTransactor::LpcEnv &env, uint32_t eventId, const ArgList &args) override;

void onIoEvent(const halpatch::IoOperationEvent &event, const std::vector<uint8_t> &payload) override;
void onIoEvent(const halpatch::IoSyscallEvent &event, const std::vector<uint8_t> &payload) override;

void onRemoteDeath(int pid) override;
};

}

void NciClientImpl_forwardRemoteIoEvent(const halpatch::IoOperationEvent &event, const std::vector<uint8_t> &payload);
void NciClientImpl_forwardRemoteIoEvent(const halpatch::IoSyscallEvent &event, const std::vector<uint8_t> &payload);

void NciClientImpl_forwardRemoteDeathEvent(int pid);

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/libnciclient/NciHostDaemonProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ TypedLpcResult<bool> NciHostDaemonProxy::isHwServiceConnected() {
return invokeRemoteProcedure<bool>(Ids::isHwServiceConnected);
}

TypedLpcResult<bool> NciHostDaemonProxy::initHwServiceConnection(const std::string &soPath) {
return invokeRemoteProcedure<bool, const std::string &>(Ids::initHwServiceConnection, soPath);
TypedLpcResult<bool> NciHostDaemonProxy::initHwServiceConnection(const std::vector<std::string> &soPath) {
return invokeRemoteProcedure<bool, const std::vector<std::string> &>(Ids::initHwServiceConnection, soPath);
}

TypedLpcResult<INciHostDaemon::HistoryIoOperationEventList>
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/libnciclient/NciHostDaemonProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class NciHostDaemonProxy : public INciHostDaemon, public BaseIpcProxy {

TypedLpcResult<bool> isHwServiceConnected() override;

TypedLpcResult<bool> initHwServiceConnection(const std::string &soPath) override;
TypedLpcResult<bool> initHwServiceConnection(const std::vector<std::string> &soPath) override;

TypedLpcResult<HistoryIoOperationEventList> getHistoryIoOperations(uint32_t start, uint32_t length) override;

Expand Down
100 changes: 70 additions & 30 deletions app/src/main/cpp/libnciclient/ipc_handle_jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ using namespace ipcprotocol;

static std::mutex g_EventMutex;
static std::condition_variable g_EventWaitCondition;
static std::vector<std::tuple<halpatch::IoOperationEvent, std::vector<uint8_t>>> g_IoEventVec;
static std::vector<std::tuple<halpatch::IoSyscallEvent, std::vector<uint8_t>>> g_IoEventVec;
static std::vector<int> g_RemoteDeathVec;
static bool g_isNciHostDaemonConnectedPrevious = false;

Expand Down Expand Up @@ -131,6 +131,31 @@ bool jniThrowLpcResultErrorOrCorruption(JNIEnv *env, const TypedLpcResult<T> &re
return false;
}

jobject createHalServiceStatusObject(JNIEnv *env, const INciHostDaemon::DaemonStatus::HalServiceStatus &status) {
jclass clazz = env->FindClass("cc/ioctl/nfcdevicehost/ipc/daemon/INciHostDaemon$DaemonStatus$HalServiceStatus");
jmethodID constructor = env->GetMethodID(clazz, "<init>",
"(ZIILjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V");
jobject jexecPath = getJStringOrNull(env, status.halServiceExePath);
jobject jcontext = getJStringOrNull(env, status.halServiceProcessSecurityContext);
jobject jlabel = getJStringOrNull(env, status.halServiceExecutableSecurityLabel);
jobject jstatus = env->NewObject(clazz, constructor, status.isHalServiceAttached, status.halServicePid,
status.halServiceUid, jexecPath, status.halServiceArch, jcontext, jlabel);
return jstatus;
}

jobject createDaemonStatusObject(JNIEnv *env, const INciHostDaemon::DaemonStatus &status) {
jclass clazz = env->FindClass("cc/ioctl/nfcdevicehost/ipc/daemon/INciHostDaemon$DaemonStatus");
jmethodID constructor = env->GetMethodID(clazz, "<init>",
"(ILjava/lang/String;ILjava/lang/String;Lcc/ioctl/nfcdevicehost/ipc/daemon/INciHostDaemon$DaemonStatus$HalServiceStatus;Lcc/ioctl/nfcdevicehost/ipc/daemon/INciHostDaemon$DaemonStatus$HalServiceStatus;)V");
jobject jexecPath = getJStringOrNull(env, status.versionName);
jobject jcontext = getJStringOrNull(env, status.daemonProcessSecurityContext);
jobject jnfc = createHalServiceStatusObject(env, status.nfcHalServiceStatus);
jobject jese = createHalServiceStatusObject(env, status.esePmServiceStatus);
jobject jstatus = env->NewObject(clazz, constructor, status.processId, jexecPath, status.abiArch,
jcontext, jnfc, jese);
return jstatus;
}

void IpcNativeCallback_IpcStatusChangeListener(IpcConnector::IpcStatusEvent event, IpcTransactor *obj);

extern "C" [[maybe_unused]] JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
Expand Down Expand Up @@ -433,32 +458,59 @@ Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_isHwServiceCo
/*
* Class: cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy
* Method: initHwServiceConnection
* Signature: (Ljava/lang/String;)Z
* Signature: ([Ljava/lang/String;)Z
*/
extern "C" [[maybe_unused]] JNIEXPORT jboolean JNICALL
Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_initHwServiceConnection
(JNIEnv *env, jobject, jstring jstrSoPath) {
if (jstrSoPath == nullptr) {
(JNIEnv *env, jobject, jobjectArray jstrSoPathArray) {
if (jstrSoPathArray == nullptr) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"),
"null so path array");
return 0;
}
std::string path1, path2;
// length of the array should be 2
if (env->GetArrayLength(jstrSoPathArray) != 2) {
env->ThrowNew(env->FindClass("java/lang/IllegalArgumentException"),
"invalid so path array length, expected 2");
return 0;
}
auto jstr1 = static_cast<jstring>(env->GetObjectArrayElement(jstrSoPathArray, 0));
if (jstr1 == nullptr) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"),
"null jstrSoPathArray[0]");
return 0;
}
auto jstr2 = static_cast<jstring>(env->GetObjectArrayElement(jstrSoPathArray, 1));
if (jstr2 == nullptr) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"),
"null so path");
"null jstrSoPathArray[1]");
return 0;
}
const char *strSoPath1 = env->GetStringUTFChars(jstr1, nullptr);
if (strSoPath1 == nullptr) {
env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
"out of memory");
return 0;
}
const char *strSoPath = env->GetStringUTFChars(jstrSoPath, nullptr);
if (strSoPath == nullptr) {
path1 = strSoPath1;
env->ReleaseStringUTFChars(jstr1, strSoPath1);
const char *strSoPath2 = env->GetStringUTFChars(jstr2, nullptr);
if (strSoPath2 == nullptr) {
env->ThrowNew(env->FindClass("java/lang/OutOfMemoryError"),
"out of memory");
return 0;
}
std::string soPath(strSoPath);
env->ReleaseStringUTFChars(jstrSoPath, strSoPath);
path2 = strSoPath2;
env->ReleaseStringUTFChars(jstr2, strSoPath2);
IpcConnector &connector = IpcConnector::getInstance();
INciHostDaemon *proxy = connector.getNciDaemon();
if (proxy == nullptr) {
env->ThrowNew(env->FindClass("java/lang/IllegalStateException"),
"attempt to transact while proxy object not available");
return false;
} else {
if (auto lpcResult = proxy->initHwServiceConnection(soPath);
if (auto lpcResult = proxy->initHwServiceConnection({path1, path2});
!jniThrowLpcResultErrorOrCorruption(env, lpcResult)) {
bool r;
if (lpcResult.hasException()) {
Expand All @@ -480,7 +532,7 @@ Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_initHwService
}


void NciClientImpl_forwardRemoteIoEvent(const halpatch::IoOperationEvent &event, const std::vector<uint8_t> &payload) {
void NciClientImpl_forwardRemoteIoEvent(const halpatch::IoSyscallEvent &event, const std::vector<uint8_t> &payload) {
std::scoped_lock<std::mutex> lock(g_EventMutex);
g_IoEventVec.emplace_back(event, payload);
g_EventWaitCondition.notify_all();
Expand Down Expand Up @@ -538,14 +590,14 @@ Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_waitForEvent
}
// check for io event
if (!g_IoEventVec.empty()) {
halpatch::IoOperationEvent event = std::get<0>(g_IoEventVec.back());
halpatch::IoSyscallEvent event = std::get<0>(g_IoEventVec.back());
std::vector<uint8_t> payload = std::get<1>(g_IoEventVec.back());
g_IoEventVec.pop_back();
jmethodID ctor = env->GetMethodID(
env->FindClass("cc/ioctl/nfcdevicehost/ipc/daemon/internal/NciHostDaemonProxy$RawIoEventPacket"),
"<init>", "([B[B)V");
jbyteArray buffer1 = env->NewByteArray(sizeof(halpatch::IoOperationEvent));
env->SetByteArrayRegion(buffer1, 0, sizeof(halpatch::IoOperationEvent), (jbyte *) &event);
jbyteArray buffer1 = env->NewByteArray(sizeof(halpatch::IoSyscallEvent));
env->SetByteArrayRegion(buffer1, 0, sizeof(halpatch::IoSyscallEvent), (jbyte *) &event);
jbyteArray buffer2 = nullptr;
if (!payload.empty()) {
buffer2 = env->NewByteArray(payload.size());
Expand Down Expand Up @@ -621,8 +673,8 @@ Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_ntGetHistoryI
size_t resultSize = r.events.size();
jobjectArray array = env->NewObjectArray(resultSize, clRawEvent, nullptr);
for (size_t i = 0; i < resultSize; ++i) {
jbyteArray buffer1 = env->NewByteArray(sizeof(halpatch::IoOperationEvent));
env->SetByteArrayRegion(buffer1, 0, sizeof(halpatch::IoOperationEvent),
jbyteArray buffer1 = env->NewByteArray(sizeof(halpatch::IoSyscallEvent));
env->SetByteArrayRegion(buffer1, 0, sizeof(halpatch::IoSyscallEvent),
(jbyte *) &r.events[i]);
jbyteArray buffer2 = nullptr;
if (!r.payloads[i].empty()) {
Expand Down Expand Up @@ -693,20 +745,8 @@ Java_cc_ioctl_nfcdevicehost_ipc_daemon_internal_NciHostDaemonProxy_getDaemonStat
!jniThrowLpcResultErrorOrException(env, lpcResult)) {
INciHostDaemon::DaemonStatus r;
if (lpcResult.getResult(&r)) {
jclass klass = env->FindClass("cc/ioctl/nfcdevicehost/ipc/daemon/INciHostDaemon$DaemonStatus");
jmethodID ctor = env->GetMethodID(klass, "<init>",
"(ILjava/lang/String;ILjava/lang/String;ZIILjava/lang/String;ILjava/lang/String;Ljava/lang/String;)V");
jstring jversionName = env->NewStringUTF(r.versionName.c_str());
jstring jdaemonProcessSecurityContext = getJStringOrNull(env, r.daemonProcessSecurityContext);
jstring jhalServiceExePath = getJStringOrNull(env, r.halServiceExePath);
jstring jhalServiceProcessSecurityContext = getJStringOrNull(env, r.halServiceProcessSecurityContext);
jstring jhalServiceExecutableSecurityLabel = getJStringOrNull(env, r.halServiceExecutableSecurityLabel);
jobject status = env->NewObject(klass, ctor, jint(r.processId), jversionName, jint(r.abiArch),
jdaemonProcessSecurityContext, jboolean(r.isHalServiceAttached),
jint(r.halServicePid), jint(r.halServiceUid), jhalServiceExePath,
jint(r.halServiceArch), jhalServiceProcessSecurityContext,
jhalServiceExecutableSecurityLabel);
return status;
jobject jstatus = createDaemonStatusObject(env, r);
return jstatus;
} else {
env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
"error while read data from LpcResult");
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/cpp/libnciclient/ipc_handle_jni.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion app/src/main/cpp/ncihostd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ add_executable(ncihostd startup/startup.c startup/daemon.cpp ipc/IpcStateControl
service/front/NciHostDaemonImpl.cpp service/front/NciClientProxy.cpp service/HwServiceStatus.cpp
elfsym/ElfView.cpp elfsym/ProcessView.cpp inject/Injector.cpp inject/arch/ptrace_inject_utils.cpp
inject/arch/ptrace_inject_arm_impl.cpp inject/arch/ptrace_inject_x86_impl.cpp inject/SysServicePatch.cpp
service/ServiceManager.cpp service/hw/BaseHwHalHandler.cpp service/hw/nxpnci/NxpHalHandler.cpp
service/ServiceManager.cpp service/hw/BaseHwHalHandler.cpp
service/hw/nxpnci/NxpHalHandler.cpp service/hw/qtiesepm/QtiEsePmHandler.cpp
service/xposed/BaseRemoteAndroidService.cpp service/xposed/AndroidNfcService.cpp)

if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
Expand Down
19 changes: 16 additions & 3 deletions app/src/main/cpp/ncihostd/inject/SysServicePatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,8 @@ int SysServicePatch::connectToService(int &localSocket, int &remoteSocket) {
return 0;
}

int SysServicePatch::getPltHookEntries(OriginHookProcedure &hookProc, std::string_view targetSoname) const {
int SysServicePatch::getPltHookEntries(OriginHookProcedure &hookProc, std::string_view targetSoname,
uint32_t targetHookEntries) const {
uintptr_t targetBase = mInjector.getModuleBaseAddress(targetSoname);
if (targetBase == 0) {
LOGE("Failed to get base address of %s", targetSoname.data());
Expand Down Expand Up @@ -288,10 +289,22 @@ int SysServicePatch::getPltHookEntries(OriginHookProcedure &hookProc, std::strin
hookProc.off_plt_close = uint32_t(addr);
}
}
if ((hookProc.off_plt_read_chk || hookProc.off_plt_read)
&& (hookProc.off_plt_write_chk || hookProc.off_plt_write)) {
if ((((targetHookEntries & PltHookTarget::OPEN) == 0) ||
(hookProc.off_plt_open != 0 || hookProc.off_plt_open_2 != 0))
&& (((targetHookEntries & PltHookTarget::CLOSE) == 0) || (hookProc.off_plt_close != 0))
&& (((targetHookEntries & PltHookTarget::WRITE) == 0) ||
(hookProc.off_plt_write_chk != 0 || hookProc.off_plt_write != 0))
&& (((targetHookEntries & PltHookTarget::READ) == 0) ||
(hookProc.off_plt_read_chk != 0 || hookProc.off_plt_read != 0))
&& (((targetHookEntries & PltHookTarget::IOCTL) == 0) || (hookProc.off_plt_ioctl != 0))) {
return 0;
} else {
LOGE("Failed to get plt hook entries of %s", targetSoname.data());
LOGE("targetHookEntries: %x", targetHookEntries);
LOGE("open: %x, open_2: %x, close: %x, write: %x, write_chk: %x, read: %x, read_chk: %x, ioctl: %x",
hookProc.off_plt_open, hookProc.off_plt_open_2, hookProc.off_plt_close,
hookProc.off_plt_write, hookProc.off_plt_write_chk, hookProc.off_plt_read,
hookProc.off_plt_read_chk, hookProc.off_plt_ioctl);
return -EFAULT;
}
}
Expand Down
14 changes: 13 additions & 1 deletion app/src/main/cpp/ncihostd/inject/SysServicePatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef NCI_HOST_NATIVES_SYSSERVICEPATCH_H
#define NCI_HOST_NATIVES_SYSSERVICEPATCH_H

#include <cstdint>
#include <string_view>
#include <string>

Expand All @@ -15,6 +16,16 @@
namespace halpatch {

class SysServicePatch {
public:
class PltHookTarget {
public:
static constexpr uint32_t OPEN = 1u << 1u;
static constexpr uint32_t CLOSE = 1u << 2u;
static constexpr uint32_t READ = 1u << 3u;
static constexpr uint32_t WRITE = 1u << 4u;
static constexpr uint32_t IOCTL = 1u << 5u;
};

private:
int mTargetPid = -1;
int mSharedObjectFd = -1;
Expand Down Expand Up @@ -107,7 +118,8 @@ class SysServicePatch {
* @param targetSoname the target shared object name
* @return 0 on success, -errno on failure.
*/
[[nodiscard]] int getPltHookEntries(OriginHookProcedure &hookProc, std::string_view targetSoname) const;
[[nodiscard]] int getPltHookEntries(OriginHookProcedure &hookProc, std::string_view targetSoname,
uint32_t targetHookEntries) const;
};

}
Expand Down
Loading

0 comments on commit 9cc111f

Please sign in to comment.