Skip to content

Commit

Permalink
add device operations in IPC
Browse files Browse the repository at this point in the history
  • Loading branch information
cinit committed Dec 17, 2021
1 parent 9751e22 commit 9782261
Show file tree
Hide file tree
Showing 21 changed files with 348 additions and 5 deletions.
2 changes: 1 addition & 1 deletion app/src/main/cpp/libbasehalpatch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ set_target_properties(basehalpatch PROPERTIES
POSITION_INDEPENDENT_CODE ON
)

target_link_libraries(basehalpatch)
target_link_libraries(basehalpatch dl)
4 changes: 2 additions & 2 deletions app/src/main/cpp/libbasehalpatch/hook/hook_proc_symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ EXPORT int hook_proc_ioctl(int fd, unsigned long int request, unsigned long arg)
}
int result = pf_orig_ioctl(fd, request, arg);
int err = errno;
invokeIoctlResultCallback(result < 0 ? -err : result, fd, request, arg);
invokeIoctlResultCallback(result == -1 ? -err : result, fd, request, arg);
errno = err;
return result;
}
Expand All @@ -225,7 +225,7 @@ EXPORT int hook_proc_select(int nfds, void *readfds, void *writefds, void *excep
}
int result = pf_orig_select(nfds, readfds, writefds, exceptfds, timeout);
int err = errno;
invokeSelectResultCallback(result < 0 ? -err : result);
invokeSelectResultCallback(result < 0 ? -err : result, nfds, readfds, writefds, exceptfds, timeout);
errno = err;
return result;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ void invokeCloseResultCallback(int result, int fd);

void invokeIoctlResultCallback(int result, int fd, unsigned long int request, uint64_t arg);

void invokeSelectResultCallback(int result);
void invokeSelectResultCallback(int result, int nfds, void *readfds, void *writefds, void *exceptfds, void *timeout);

#ifdef __cplusplus
};
Expand Down
8 changes: 7 additions & 1 deletion app/src/main/cpp/libbasehalpatch/ipc/ipc_io_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static void postIoEvent(const IoSyscallInfo &opInfo, const void *ioBuffer, size_
void invokeReadResultCallback(ssize_t result, int fd, const void *buffer, size_t size) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_READ),
fd, result, (uint64_t) buffer, uint64_t(size), 0};
halpatchhook::callback::afterHook_read(result, fd, buffer, size);
if (result < 0) {
postIoEvent(info, nullptr, 0);
} else {
Expand All @@ -62,6 +63,7 @@ void invokeReadResultCallback(ssize_t result, int fd, const void *buffer, size_t
void invokeWriteResultCallback(ssize_t result, int fd, const void *buffer, size_t size) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_WRITE),
fd, result, (uint64_t) buffer, uint64_t(size), 0};
halpatchhook::callback::afterHook_write(result, fd, buffer, size);
if (result < 0) {
postIoEvent(info, nullptr, 0);
} else {
Expand All @@ -72,6 +74,7 @@ void invokeWriteResultCallback(ssize_t result, int fd, const void *buffer, size_
void invokeOpenResultCallback(int result, const char *name, int flags, uint32_t mode) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_OPEN),
result < 0 ? -1 : result, result, static_cast<uint64_t>(flags), mode, 0};
halpatchhook::callback::afterHook_open(result, name, flags, mode);
if (name != nullptr) {
postIoEvent(info, name, strlen(name));
} else {
Expand All @@ -82,17 +85,20 @@ void invokeOpenResultCallback(int result, const char *name, int flags, uint32_t
void invokeCloseResultCallback(int result, int fd) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_CLOSE),
fd, result, 0, 0, 0};
halpatchhook::callback::afterHook_close(result, fd);
postIoEvent(info, nullptr, 0);
}

void invokeIoctlResultCallback(int result, int fd, unsigned long int request, uint64_t arg) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_IOCTL),
fd, result, request, arg, 0};
halpatchhook::callback::afterHook_ioctl(result, fd, request, arg);
postIoEvent(info, nullptr, 0);
}

void invokeSelectResultCallback(int result) {
void invokeSelectResultCallback(int result, int nfds, void *readfds, void *writefds, void *exceptfds, void *timeout) {
IoSyscallInfo info = {static_cast<int32_t>(OpType::OP_TYPE_IO_SELECT),
0, result, 0, 0, 0};
halpatchhook::callback::afterHook_select(result, nfds, readfds, writefds, exceptfds, timeout);
postIoEvent(info, nullptr, 0);
}
16 changes: 16 additions & 0 deletions app/src/main/cpp/libbasehalpatch/ipc/ipc_io_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,20 @@
#include "daemon_ipc_struct.h"
#include "../hook/intercept_callbacks.h"

namespace halpatchhook::callback {

void afterHook_read(ssize_t result, int fd, const void *buffer, size_t size);

void afterHook_write(ssize_t result, int fd, const void *buffer, size_t size);

void afterHook_open(int result, const char *name, int flags, uint32_t mode);

void afterHook_close(int result, int fd);

void afterHook_ioctl(int result, int fd, unsigned long int request, uint64_t arg);

void afterHook_select(int result, int nfds, void *readfds, void *writefds, void *exceptfds, void *timeout);

}

#endif //NCI_HOST_NATIVES_IPC_IO_EVENT_H
2 changes: 2 additions & 0 deletions app/src/main/cpp/libnciclient/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CLANG_CXX_EXTRA_OPT} -fPIC -Werror=delete-non-virtual-dtor -Werror=return-type -Werror=non-virtual-dtor -Wno-invalid-offsetof")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CLANG_C_EXTRA_OPT} -fPIC -Werror=return-type")

set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-allow-shlib-undefined,--no-undefined")

set_target_properties(nciclient PROPERTIES
CXX_EXTENSIONS OFF
POSITION_INDEPENDENT_CODE ON
Expand Down
8 changes: 8 additions & 0 deletions app/src/main/cpp/libnciclient/NciHostDaemonProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,11 @@ TypedLpcResult<bool> NciHostDaemonProxy::clearHistoryIoEvents() {
TypedLpcResult<INciHostDaemon::DaemonStatus> NciHostDaemonProxy::getDaemonStatus() {
return invokeRemoteProcedure<INciHostDaemon::DaemonStatus>(Ids::getDaemonStatus);
}

TypedLpcResult<int> NciHostDaemonProxy::deviceDriverWriteRawBuffer(const std::vector<uint8_t> &buffer) {
return invokeRemoteProcedure<int, const std::vector<uint8_t> &>(Ids::deviceDriverWriteRawBuffer, buffer);
}

TypedLpcResult<int> NciHostDaemonProxy::deviceDriverIoctl0(uint64_t request, uint64_t arg) {
return invokeRemoteProcedure<int, const uint64_t &, const uint64_t &>(Ids::deviceDriverIoctl0, request, arg);
}
4 changes: 4 additions & 0 deletions app/src/main/cpp/libnciclient/NciHostDaemonProxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class NciHostDaemonProxy : public INciHostDaemon, public BaseIpcProxy {
TypedLpcResult<bool> clearHistoryIoEvents() override;

TypedLpcResult<DaemonStatus> getDaemonStatus() override;

TypedLpcResult<int> deviceDriverWriteRawBuffer(const std::vector<uint8_t> &buffer) override;

TypedLpcResult<int> deviceDriverIoctl0(uint64_t request, uint64_t arg) override;
};

}
Expand Down
68 changes: 68 additions & 0 deletions app/src/main/cpp/libnciclient/ipc_handle_jni.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -716,3 +716,71 @@ Java_cc_ioctl_nfcdevicehost_daemon_internal_NciHostDaemonProxy_getDaemonStatus
return nullptr;
}
}

/*
* Class: cc_ioctl_nfcdevicehost_daemon_internal_NciHostDaemonProxy
* Method: deviceDriverWriteRaw
* Signature: ([B)I
*/
extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL
Java_cc_ioctl_nfcdevicehost_daemon_internal_NciHostDaemonProxy_deviceDriverWriteRaw
(JNIEnv *env, jobject, jbyteArray jdata) {
if (jdata == nullptr) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "data is null");
return 0;
}
std::vector<uint8_t> data;
jsize len = env->GetArrayLength(jdata);
data.resize(len);
env->GetByteArrayRegion(jdata, 0, len, reinterpret_cast<jbyte *>(data.data()));
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 0;
} else {
if (auto lpcResult = proxy->deviceDriverWriteRawBuffer(data);
!jniThrowLpcResultErrorOrException(env, lpcResult)) {
int r;
if (lpcResult.getResult(&r)) {
return r;
} else {
env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
"error while read data from LpcResult");
return 0;
}
}
return 0;
}
}

/*
* Class: cc_ioctl_nfcdevicehost_daemon_internal_NciHostDaemonProxy
* Method: deviceDriverIoctl0
* Signature: (JJ)I
*/
extern "C" [[maybe_unused]] JNIEXPORT jint JNICALL
Java_cc_ioctl_nfcdevicehost_daemon_internal_NciHostDaemonProxy_deviceDriverIoctl0
(JNIEnv *env, jobject, jlong request, jlong arg) {
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 0;
} else {
if (auto lpcResult = proxy->deviceDriverIoctl0(uint64_t(request), uint64_t(arg));
!jniThrowLpcResultErrorOrException(env, lpcResult)) {
int r;
if (lpcResult.getResult(&r)) {
return r;
} else {
env->ThrowNew(env->FindClass("java/lang/RuntimeException"),
"error while read data from LpcResult");
return 0;
}
}
return 0;
}
}
16 changes: 16 additions & 0 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.

1 change: 1 addition & 0 deletions app/src/main/cpp/libnxphalpatch/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CLANG_C_EXTRA_OPT} -fPIC -Werror=return-ty

set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "")
set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-allow-shlib-undefined,--no-undefined")

set_target_properties(nxphalpatch PROPERTIES
LINKER_LANGUAGE C
Expand Down
97 changes: 97 additions & 0 deletions app/src/main/cpp/libnxphalpatch/ipc/ipc_request_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,45 @@
// Created by kinit on 2021-11-18.
//
#include <cstring>
#include <unistd.h>
#include <cerrno>
#include <sys/ioctl.h>

#include "ipc_requests.h"
#include "../../libbasehalpatch/hook/intercept_callbacks.h"
#include "../../libbasehalpatch/ipc/request_handler.h"
#include "../../libbasehalpatch/hook/hook_proc_symbols.h"

using namespace halpatch;

static volatile bool sInitialized = false;
static volatile int sNciDeviceFd = -1;

const char *const NCI_DEVICE_NAME = "/dev/nq-nci";

namespace halpatchhook::callback {

void afterHook_read(ssize_t result, int fd, const void *buffer, size_t size) {}

void afterHook_write(ssize_t result, int fd, const void *buffer, size_t size) {}

void afterHook_open(int result, const char *name, int flags, uint32_t mode) {
if (result > 0 && name != nullptr && strncmp(NCI_DEVICE_NAME, name, strlen(NCI_DEVICE_NAME)) == 0) {
sNciDeviceFd = result;
}
}

void afterHook_close(int result, int fd) {
if (fd == sNciDeviceFd) {
sNciDeviceFd = -1;
}
}

void afterHook_ioctl(int result, int fd, unsigned long int request, uint64_t arg) {}

void afterHook_select(int result, int nfds, void *readfds, void *writefds, void *exceptfds, void *timeout) {}

}

void handleGetVersionRequest(uint32_t requestId, const void *, uint32_t) {
const char *version = NCI_HOST_VERSION;
Expand Down Expand Up @@ -39,6 +70,61 @@ void handleInitPltHookRequest(uint32_t requestId, const void *payload, uint32_t
}
}

void handleGetDeviceStatusRequest(uint32_t requestId, const void *payload, uint32_t payloadSize) {
NxpNciDeviceStatus deviceStatus = {};
deviceStatus.esePowerStatus = NxpNciDeviceStatus::STATUS_UNKNOWN;
deviceStatus.nfccPowerStatus = NxpNciDeviceStatus::STATUS_UNKNOWN;
deviceStatus.deviceFileDescriptor = sNciDeviceFd;
HalResponse response = {requestId, 0, 0, sizeof(NxpNciDeviceStatus)};
sendResponsePacket(response, &deviceStatus);
}

void handleDeviceWriteRequest(uint32_t requestId, const void *payload, uint32_t payloadSize) {
const auto *requestBody = static_cast<const DeviceWriteRequest *>(payload);
if (payloadSize < 4 || payload == nullptr || payloadSize != 4 + requestBody->length) {
sendResponseError(requestId, HalRequestErrorCode::ERR_INVALID_ARGUMENT,
"invalid payload DeviceWriteRequest");
} else {
const auto *data = requestBody->data;
int fd = sNciDeviceFd;
auto size = size_t(requestBody->length);
if (sNciDeviceFd > 0) {
ssize_t result = write(fd, data, size);
if (result == -1) {
result = -errno;
}
HalResponse response = {requestId, uint32_t(result), 0, 0};
sendResponsePacket(response, nullptr);
invokeWriteResultCallback(result, fd, data, size);
} else {
HalResponse response = {requestId, uint32_t(-ENODEV), 0, 0};
sendResponsePacket(response, nullptr);
}
}
}

void handleDeviceIoctl0Request(uint32_t requestId, const void *payload, uint32_t payloadSize) {
if (payloadSize != sizeof(DeviceIoctl0Request) || payload == nullptr) {
sendResponseError(requestId, HalRequestErrorCode::ERR_INVALID_ARGUMENT,
"invalid payload DeviceIoctl0Request");
} else {
const auto *requestBody = static_cast<const DeviceIoctl0Request *>(payload);
int fd = sNciDeviceFd;
if (sNciDeviceFd > 0) {
int result = ioctl(fd, requestBody->request, requestBody->arg);
if (result == -1) {
result = -errno;
}
HalResponse response = {requestId, uint32_t(result), 0, 0};
sendResponsePacket(response, nullptr);
invokeIoctlResultCallback(result, fd, requestBody->request, requestBody->arg);
} else {
HalResponse response = {requestId, uint32_t(-ENODEV), 0, 0};
sendResponsePacket(response, nullptr);
}
}
}

int handleRequestPacket(const HalRequest &request, const void *payload) {
uint32_t requestId = request.id;
auto requestCode = static_cast<RequestId>(request.requestCode);
Expand All @@ -53,6 +139,17 @@ int handleRequestPacket(const HalRequest &request, const void *payload) {
case RequestId::INIT_PLT_HOOK:
handleInitPltHookRequest(requestId, payload, payloadSize);
return 0;
case RequestId::GET_DEVICE_STATUS:
handleGetDeviceStatusRequest(requestId, payload, payloadSize);
return 0;
case RequestId::DEVICE_OPERATION_WRITE: {
handleDeviceWriteRequest(requestId, payload, payloadSize);
return 0;
}
case RequestId::DEVICE_OPERATION_IOCTL0: {
handleDeviceIoctl0Request(requestId, payload, payloadSize);
return 0;
}
default:
return -1;
}
Expand Down
29 changes: 29 additions & 0 deletions app/src/main/cpp/libnxphalpatch/ipc/ipc_requests.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,36 @@ enum class RequestId : uint32_t {
GET_VERSION = 0x1,
GET_HOOK_STATUS = 0x40,
INIT_PLT_HOOK = 0x41,
GET_DEVICE_STATUS = 0x50,
DEVICE_OPERATION_WRITE = 0x51,
DEVICE_OPERATION_IOCTL0 = 0x52,
};

struct NxpNciDeviceStatus {
static constexpr uint8_t STATUS_UNKNOWN = 0;
static constexpr uint8_t STATUS_ENABLED = 1;
static constexpr uint8_t STATUS_DISABLED = 2;

uint8_t nfccPowerStatus;
uint8_t esePowerStatus;
uint8_t unused1_0;
uint8_t unused1_1;
uint32_t deviceFileDescriptor;
uint32_t unused4_2;
uint32_t unused4_3;
};
static_assert(sizeof(NxpNciDeviceStatus) == 16, "NxpNciDeviceStatus size error");

struct DeviceIoctl0Request {
uint64_t request;
uint64_t arg;
};
static_assert(sizeof(DeviceIoctl0Request) == 16, "DeviceIoctl0Request size error");

struct DeviceWriteRequest {
uint32_t length;
uint8_t data[];
};
// no size static assert...

#endif //NCI_HOST_NATIVES_IPC_REQUESTS_H
Loading

0 comments on commit 9782261

Please sign in to comment.