Loading libs/binder/Parcel.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -1439,7 +1439,8 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) { case RpcSession::FileDescriptorTransportMode::NONE: { return FDS_NOT_ALLOWED; } case RpcSession::FileDescriptorTransportMode::UNIX: { case RpcSession::FileDescriptorTransportMode::UNIX: case RpcSession::FileDescriptorTransportMode::TRUSTY: { if (rpcFields->mFds == nullptr) { rpcFields->mFds = std::make_unique<decltype(rpcFields->mFds)::element_type>(); } Loading libs/binder/RpcState.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ static bool enableAncillaryFds(RpcSession::FileDescriptorTransportMode mode) { case RpcSession::FileDescriptorTransportMode::NONE: return false; case RpcSession::FileDescriptorTransportMode::UNIX: case RpcSession::FileDescriptorTransportMode::TRUSTY: return true; } } Loading Loading @@ -1207,6 +1208,20 @@ status_t RpcState::validateParcel(const sp<RpcSession>& session, const Parcel& p rpcFields->mFds->size(), kMaxFdsPerMsg); return BAD_VALUE; } break; } case RpcSession::FileDescriptorTransportMode::TRUSTY: { // Keep this in sync with trusty_ipc.h!!! // We could import that file here on Trusty, but it's not // available on Android constexpr size_t kMaxFdsPerMsg = 8; if (rpcFields->mFds->size() > kMaxFdsPerMsg) { *errorMsg = StringPrintf("Too many file descriptors in Parcel for Trusty " "IPC connection: %zu (max is %zu)", rpcFields->mFds->size(), kMaxFdsPerMsg); return BAD_VALUE; } break; } } } Loading libs/binder/include/binder/RpcSession.h +2 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,8 @@ public: NONE = 0, // Send file descriptors via unix domain socket ancillary data. UNIX = 1, // Send file descriptors as Trusty IPC handles. TRUSTY = 2, }; /** Loading libs/binder/trusty/OS.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #if defined(TRUSTY_USERSPACE) #include <openssl/rand.h> #include <trusty_ipc.h> #else #include <lib/rand/rand.h> #endif Loading @@ -23,6 +24,7 @@ #include <binder/RpcTransportTipcTrusty.h> #include "../OS.h" #include "TrustyStatus.h" using android::base::Result; Loading @@ -43,9 +45,14 @@ status_t getRandomBytes(uint8_t* data, size_t size) { #endif // TRUSTY_USERSPACE } status_t dupFileDescriptor(int /*oldFd*/, int* /*newFd*/) { // TODO: implement separately return INVALID_OPERATION; status_t dupFileDescriptor(int oldFd, int* newFd) { int res = dup(oldFd); if (res < 0) { return statusFromTrusty(res); } *newFd = res; return OK; } std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() { Loading libs/binder/trusty/RpcTransportTipcTrusty.cpp +53 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #define LOG_TAG "RpcTransportTipcTrusty" #include <inttypes.h> #include <trusty_ipc.h> #include <binder/RpcSession.h> Loading Loading @@ -47,7 +48,7 @@ public: status_t interruptableWriteFully( FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { if (niovs < 0) { return BAD_VALUE; Loading @@ -58,12 +59,32 @@ public: size += iovs[i].iov_len; } handle_t msgHandles[IPC_MAX_MSG_HANDLES]; ipc_msg_t msg{ .num_iov = static_cast<uint32_t>(niovs), .iov = iovs, .num_handles = 0, // TODO: add ancillaryFds .num_handles = 0, .handles = nullptr, }; if (ancillaryFds != nullptr && !ancillaryFds->empty()) { if (ancillaryFds->size() > IPC_MAX_MSG_HANDLES) { // This shouldn't happen because we check the FD count in RpcState. ALOGE("Saw too many file descriptors in RpcTransportCtxTipcTrusty: " "%zu (max is %u). Aborting session.", ancillaryFds->size(), IPC_MAX_MSG_HANDLES); return BAD_VALUE; } for (size_t i = 0; i < ancillaryFds->size(); i++) { msgHandles[i] = std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i)); } msg.num_handles = ancillaryFds->size(); msg.handles = msgHandles; } ssize_t rc = send_msg(mSocket.fd.get(), &msg); if (rc == ERR_NOT_ENOUGH_BUFFER) { // Peer is blocked, wait until it unblocks. Loading Loading @@ -97,8 +118,7 @@ public: status_t interruptableReadFully( FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) override { std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { if (niovs < 0) { return BAD_VALUE; } Loading @@ -124,11 +144,16 @@ public: return status; } LOG_ALWAYS_FATAL_IF(mMessageInfo.num_handles > IPC_MAX_MSG_HANDLES, "Received too many handles %" PRIu32, mMessageInfo.num_handles); bool haveHandles = mMessageInfo.num_handles != 0; handle_t msgHandles[IPC_MAX_MSG_HANDLES]; ipc_msg_t msg{ .num_iov = static_cast<uint32_t>(niovs), .iov = iovs, .num_handles = 0, // TODO: support ancillaryFds .handles = nullptr, .num_handles = mMessageInfo.num_handles, .handles = haveHandles ? msgHandles : 0, }; ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg); if (rc < 0) { Loading @@ -141,6 +166,28 @@ public: "Message offset exceeds length %zu/%zu", mMessageOffset, mMessageInfo.len); if (haveHandles) { if (ancillaryFds != nullptr) { ancillaryFds->reserve(ancillaryFds->size() + mMessageInfo.num_handles); for (size_t i = 0; i < mMessageInfo.num_handles; i++) { ancillaryFds->emplace_back(base::unique_fd(msgHandles[i])); } // Clear the saved number of handles so we don't accidentally // read them multiple times mMessageInfo.num_handles = 0; haveHandles = false; } else { ALOGE("Received unexpected handles %" PRIu32, mMessageInfo.num_handles); // It should be safe to continue here. We could abort, but then // peers could DoS us by sending messages with handles in them. // Close the handles since we are ignoring them. for (size_t i = 0; i < mMessageInfo.num_handles; i++) { ::close(msgHandles[i]); } } } // Release the message if all of it has been read if (mMessageOffset == mMessageInfo.len) { releaseMessage(); Loading Loading
libs/binder/Parcel.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -1439,7 +1439,8 @@ status_t Parcel::writeFileDescriptor(int fd, bool takeOwnership) { case RpcSession::FileDescriptorTransportMode::NONE: { return FDS_NOT_ALLOWED; } case RpcSession::FileDescriptorTransportMode::UNIX: { case RpcSession::FileDescriptorTransportMode::UNIX: case RpcSession::FileDescriptorTransportMode::TRUSTY: { if (rpcFields->mFds == nullptr) { rpcFields->mFds = std::make_unique<decltype(rpcFields->mFds)::element_type>(); } Loading
libs/binder/RpcState.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ static bool enableAncillaryFds(RpcSession::FileDescriptorTransportMode mode) { case RpcSession::FileDescriptorTransportMode::NONE: return false; case RpcSession::FileDescriptorTransportMode::UNIX: case RpcSession::FileDescriptorTransportMode::TRUSTY: return true; } } Loading Loading @@ -1207,6 +1208,20 @@ status_t RpcState::validateParcel(const sp<RpcSession>& session, const Parcel& p rpcFields->mFds->size(), kMaxFdsPerMsg); return BAD_VALUE; } break; } case RpcSession::FileDescriptorTransportMode::TRUSTY: { // Keep this in sync with trusty_ipc.h!!! // We could import that file here on Trusty, but it's not // available on Android constexpr size_t kMaxFdsPerMsg = 8; if (rpcFields->mFds->size() > kMaxFdsPerMsg) { *errorMsg = StringPrintf("Too many file descriptors in Parcel for Trusty " "IPC connection: %zu (max is %zu)", rpcFields->mFds->size(), kMaxFdsPerMsg); return BAD_VALUE; } break; } } } Loading
libs/binder/include/binder/RpcSession.h +2 −0 Original line number Diff line number Diff line Loading @@ -100,6 +100,8 @@ public: NONE = 0, // Send file descriptors via unix domain socket ancillary data. UNIX = 1, // Send file descriptors as Trusty IPC handles. TRUSTY = 2, }; /** Loading
libs/binder/trusty/OS.cpp +10 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #if defined(TRUSTY_USERSPACE) #include <openssl/rand.h> #include <trusty_ipc.h> #else #include <lib/rand/rand.h> #endif Loading @@ -23,6 +24,7 @@ #include <binder/RpcTransportTipcTrusty.h> #include "../OS.h" #include "TrustyStatus.h" using android::base::Result; Loading @@ -43,9 +45,14 @@ status_t getRandomBytes(uint8_t* data, size_t size) { #endif // TRUSTY_USERSPACE } status_t dupFileDescriptor(int /*oldFd*/, int* /*newFd*/) { // TODO: implement separately return INVALID_OPERATION; status_t dupFileDescriptor(int oldFd, int* newFd) { int res = dup(oldFd); if (res < 0) { return statusFromTrusty(res); } *newFd = res; return OK; } std::unique_ptr<RpcTransportCtxFactory> makeDefaultRpcTransportCtxFactory() { Loading
libs/binder/trusty/RpcTransportTipcTrusty.cpp +53 −6 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #define LOG_TAG "RpcTransportTipcTrusty" #include <inttypes.h> #include <trusty_ipc.h> #include <binder/RpcSession.h> Loading Loading @@ -47,7 +48,7 @@ public: status_t interruptableWriteFully( FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) const std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { if (niovs < 0) { return BAD_VALUE; Loading @@ -58,12 +59,32 @@ public: size += iovs[i].iov_len; } handle_t msgHandles[IPC_MAX_MSG_HANDLES]; ipc_msg_t msg{ .num_iov = static_cast<uint32_t>(niovs), .iov = iovs, .num_handles = 0, // TODO: add ancillaryFds .num_handles = 0, .handles = nullptr, }; if (ancillaryFds != nullptr && !ancillaryFds->empty()) { if (ancillaryFds->size() > IPC_MAX_MSG_HANDLES) { // This shouldn't happen because we check the FD count in RpcState. ALOGE("Saw too many file descriptors in RpcTransportCtxTipcTrusty: " "%zu (max is %u). Aborting session.", ancillaryFds->size(), IPC_MAX_MSG_HANDLES); return BAD_VALUE; } for (size_t i = 0; i < ancillaryFds->size(); i++) { msgHandles[i] = std::visit([](const auto& fd) { return fd.get(); }, ancillaryFds->at(i)); } msg.num_handles = ancillaryFds->size(); msg.handles = msgHandles; } ssize_t rc = send_msg(mSocket.fd.get(), &msg); if (rc == ERR_NOT_ENOUGH_BUFFER) { // Peer is blocked, wait until it unblocks. Loading Loading @@ -97,8 +118,7 @@ public: status_t interruptableReadFully( FdTrigger* /*fdTrigger*/, iovec* iovs, int niovs, const std::optional<android::base::function_ref<status_t()>>& /*altPoll*/, std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* /*ancillaryFds*/) override { std::vector<std::variant<base::unique_fd, base::borrowed_fd>>* ancillaryFds) override { if (niovs < 0) { return BAD_VALUE; } Loading @@ -124,11 +144,16 @@ public: return status; } LOG_ALWAYS_FATAL_IF(mMessageInfo.num_handles > IPC_MAX_MSG_HANDLES, "Received too many handles %" PRIu32, mMessageInfo.num_handles); bool haveHandles = mMessageInfo.num_handles != 0; handle_t msgHandles[IPC_MAX_MSG_HANDLES]; ipc_msg_t msg{ .num_iov = static_cast<uint32_t>(niovs), .iov = iovs, .num_handles = 0, // TODO: support ancillaryFds .handles = nullptr, .num_handles = mMessageInfo.num_handles, .handles = haveHandles ? msgHandles : 0, }; ssize_t rc = read_msg(mSocket.fd.get(), mMessageInfo.id, mMessageOffset, &msg); if (rc < 0) { Loading @@ -141,6 +166,28 @@ public: "Message offset exceeds length %zu/%zu", mMessageOffset, mMessageInfo.len); if (haveHandles) { if (ancillaryFds != nullptr) { ancillaryFds->reserve(ancillaryFds->size() + mMessageInfo.num_handles); for (size_t i = 0; i < mMessageInfo.num_handles; i++) { ancillaryFds->emplace_back(base::unique_fd(msgHandles[i])); } // Clear the saved number of handles so we don't accidentally // read them multiple times mMessageInfo.num_handles = 0; haveHandles = false; } else { ALOGE("Received unexpected handles %" PRIu32, mMessageInfo.num_handles); // It should be safe to continue here. We could abort, but then // peers could DoS us by sending messages with handles in them. // Close the handles since we are ignoring them. for (size_t i = 0; i < mMessageInfo.num_handles; i++) { ::close(msgHandles[i]); } } } // Release the message if all of it has been read if (mMessageOffset == mMessageInfo.len) { releaseMessage(); Loading