diff options
| author | 2022-10-07 05:04:36 +0000 | |
|---|---|---|
| committer | 2022-10-07 05:04:36 +0000 | |
| commit | e0358af0eb56fe7c240444b62ea0186071a079c3 (patch) | |
| tree | 576cd65685dc79cfc37981eb62c5db8941008fcd | |
| parent | dd97965819bc06246a2d6312a9916627ccbec78a (diff) | |
| parent | 67296dd1f52542644b85ab8e0f3b0ed0f1c04060 (diff) | |
Merge "libbinder: add ancillaryFd support in RpcTransportTipcTrusty" am: 8eb983cefa am: 67296dd1f5
Original change: https://android-review.googlesource.com/c/platform/frameworks/native/+/2189664
Change-Id: Ia6bcd4a2da668024fbf53d5d2891f00359473773
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
| -rw-r--r-- | libs/binder/Parcel.cpp | 3 | ||||
| -rw-r--r-- | libs/binder/RpcState.cpp | 15 | ||||
| -rw-r--r-- | libs/binder/include/binder/RpcSession.h | 2 | ||||
| -rw-r--r-- | libs/binder/trusty/OS.cpp | 13 | ||||
| -rw-r--r-- | libs/binder/trusty/RpcTransportTipcTrusty.cpp | 59 | ||||
| -rw-r--r-- | libs/binder/trusty/include/binder/RpcServerTrusty.h | 4 |
6 files changed, 86 insertions, 10 deletions
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp index 83332980b2..07d0a65ae0 100644 --- a/libs/binder/Parcel.cpp +++ b/libs/binder/Parcel.cpp @@ -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>(); } diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp index 7067328358..b27f1028d4 100644 --- a/libs/binder/RpcState.cpp +++ b/libs/binder/RpcState.cpp @@ -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; } } @@ -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; } } } diff --git a/libs/binder/include/binder/RpcSession.h b/libs/binder/include/binder/RpcSession.h index a25ba987c8..1bd49750a7 100644 --- a/libs/binder/include/binder/RpcSession.h +++ b/libs/binder/include/binder/RpcSession.h @@ -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, }; /** diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp index 46346bb3e9..6b3f17e70d 100644 --- a/libs/binder/trusty/OS.cpp +++ b/libs/binder/trusty/OS.cpp @@ -16,6 +16,7 @@ #if defined(TRUSTY_USERSPACE) #include <openssl/rand.h> +#include <trusty_ipc.h> #else #include <lib/rand/rand.h> #endif @@ -23,6 +24,7 @@ #include <binder/RpcTransportTipcTrusty.h> #include "../OS.h" +#include "TrustyStatus.h" using android::base::Result; @@ -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() { diff --git a/libs/binder/trusty/RpcTransportTipcTrusty.cpp b/libs/binder/trusty/RpcTransportTipcTrusty.cpp index 0b67b9fb12..58bfe71211 100644 --- a/libs/binder/trusty/RpcTransportTipcTrusty.cpp +++ b/libs/binder/trusty/RpcTransportTipcTrusty.cpp @@ -16,6 +16,7 @@ #define LOG_TAG "RpcTransportTipcTrusty" +#include <inttypes.h> #include <trusty_ipc.h> #include <binder/RpcSession.h> @@ -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; @@ -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. @@ -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; } @@ -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) { @@ -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(); diff --git a/libs/binder/trusty/include/binder/RpcServerTrusty.h b/libs/binder/trusty/include/binder/RpcServerTrusty.h index cc31c95da1..7d9dd8c648 100644 --- a/libs/binder/trusty/include/binder/RpcServerTrusty.h +++ b/libs/binder/trusty/include/binder/RpcServerTrusty.h @@ -60,6 +60,10 @@ public: std::unique_ptr<RpcTransportCtxFactory> rpcTransportCtxFactory = nullptr); void setProtocolVersion(uint32_t version) { mRpcServer->setProtocolVersion(version); } + void setSupportedFileDescriptorTransportModes( + const std::vector<RpcSession::FileDescriptorTransportMode>& modes) { + mRpcServer->setSupportedFileDescriptorTransportModes(modes); + } void setRootObject(const sp<IBinder>& binder) { mRpcServer->setRootObject(binder); } void setRootObjectWeak(const wp<IBinder>& binder) { mRpcServer->setRootObjectWeak(binder); } void setPerSessionRootObject(std::function<sp<IBinder>(const void*, size_t)>&& object) { |