Merge "Add permissions to modify raw_syscall filters."
diff --git a/cmds/servicemanager/Android.bp b/cmds/servicemanager/Android.bp
index 25bd9a3..edeb2a4 100644
--- a/cmds/servicemanager/Android.bp
+++ b/cmds/servicemanager/Android.bp
@@ -113,6 +113,9 @@
},
srcs: ["ServiceManagerFuzzer.cpp"],
fuzz_config: {
+ libfuzzer_options: [
+ "max_len=50000",
+ ],
cc: [
"smoreland@google.com",
"waghpawan@google.com",
diff --git a/cmds/servicemanager/ServiceManagerFuzzer.cpp b/cmds/servicemanager/ServiceManagerFuzzer.cpp
index 9e2e53f..39f8522 100644
--- a/cmds/servicemanager/ServiceManagerFuzzer.cpp
+++ b/cmds/servicemanager/ServiceManagerFuzzer.cpp
@@ -26,13 +26,9 @@
using ::android::sp;
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- if (size > 50000) {
- return 0;
- }
-
auto accessPtr = std::make_unique<Access>();
auto serviceManager = sp<ServiceManager>::make(std::move(accessPtr));
fuzzService(serviceManager, FuzzedDataProvider(data, size));
return 0;
-}
\ No newline at end of file
+}
diff --git a/libs/binder/Android.bp b/libs/binder/Android.bp
index 441a4a8..fabf3eb 100644
--- a/libs/binder/Android.bp
+++ b/libs/binder/Android.bp
@@ -339,6 +339,34 @@
defaults: ["libbinder_tls_defaults"],
}
+cc_library_shared {
+ name: "libbinder_trusty",
+ vendor: true,
+ srcs: [
+ "RpcTransportTipcAndroid.cpp",
+ "RpcTrusty.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder",
+ "liblog",
+ "libtrusty",
+ "libutils",
+ ],
+ static_libs: [
+ "libbase",
+ ],
+ export_include_dirs: ["include_trusty"],
+
+ // Most of Android doesn't need this library and shouldn't use it,
+ // so we restrict its visibility to the Trusty-specific packages.
+ visibility: [
+ ":__subpackages__",
+ "//system/core/trusty:__subpackages__",
+ "//vendor:__subpackages__",
+ ],
+}
+
// For testing
cc_library_static {
name: "libbinder_tls_static",
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index b5ea60f..1dc6233 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -202,6 +202,17 @@
proxy->withLock(doWithLock);
}
+sp<IBinder> IBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ BBinder* local = localBinder();
+ if (local) {
+ return local->lookupOrCreateWeak(objectID, make, makeArgs);
+ }
+ BpBinder* proxy = this->remoteBinder();
+ LOG_ALWAYS_FATAL_IF(proxy == nullptr, "binder object must be either local or remote");
+ return proxy->lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
// ---------------------------------------------------------------------------
class BBinder::RpcServerLink : public IBinder::DeathRecipient {
@@ -378,6 +389,14 @@
doWithLock();
}
+sp<IBinder> BBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ Extras* e = getOrCreateExtras();
+ LOG_ALWAYS_FATAL_IF(!e, "no memory");
+ AutoMutex _l(e->mLock);
+ return e->mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BBinder* BBinder::localBinder()
{
return this;
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index b6d35ef..d9b7231 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -100,6 +100,36 @@
return value;
}
+namespace {
+struct Tag {
+ wp<IBinder> binder;
+};
+} // namespace
+
+static void cleanWeak(const void* /* id */, void* obj, void* /* cookie */) {
+ delete static_cast<Tag*>(obj);
+}
+
+sp<IBinder> BpBinder::ObjectManager::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ entry_t& e = mObjects[objectID];
+ if (e.object != nullptr) {
+ if (auto attached = static_cast<Tag*>(e.object)->binder.promote()) {
+ return attached;
+ }
+ } else {
+ e.object = new Tag;
+ LOG_ALWAYS_FATAL_IF(!e.object, "no more memory");
+ }
+ sp<IBinder> newObj = make(makeArgs);
+
+ static_cast<Tag*>(e.object)->binder = newObj;
+ e.cleanupCookie = nullptr;
+ e.func = cleanWeak;
+
+ return newObj;
+}
+
void BpBinder::ObjectManager::kill()
{
const size_t N = mObjects.size();
@@ -516,6 +546,12 @@
doWithLock();
}
+sp<IBinder> BpBinder::lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs) {
+ AutoMutex _l(mLock);
+ return mObjects.lookupOrCreateWeak(objectID, make, makeArgs);
+}
+
BpBinder* BpBinder::remoteBinder()
{
return this;
diff --git a/libs/binder/OS.cpp b/libs/binder/OS.cpp
index 6eb7272..cc4a03b 100644
--- a/libs/binder/OS.cpp
+++ b/libs/binder/OS.cpp
@@ -48,4 +48,14 @@
return OK;
}
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+ int ret = fcntl(oldFd, F_DUPFD_CLOEXEC, 0);
+ if (ret < 0) {
+ return -errno;
+ }
+
+ *newFd = ret;
+ return OK;
+}
+
} // namespace android
diff --git a/libs/binder/OS.h b/libs/binder/OS.h
index e802e9c..d6e1c78 100644
--- a/libs/binder/OS.h
+++ b/libs/binder/OS.h
@@ -28,4 +28,6 @@
status_t getRandomBytes(uint8_t* data, size_t size);
+status_t dupFileDescriptor(int oldFd, int* newFd);
+
} // namespace android
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index 8b5d118..8887572 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -48,6 +48,7 @@
#include <utils/String8.h>
#include <utils/misc.h>
+#include "OS.h"
#include "RpcState.h"
#include "Static.h"
#include "Utils.h"
@@ -1477,9 +1478,9 @@
status_t Parcel::writeDupFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -1496,9 +1497,9 @@
status_t Parcel::writeDupParcelFileDescriptor(int fd)
{
- int dupFd = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (dupFd < 0) {
- return -errno;
+ int dupFd;
+ if (status_t err = dupFileDescriptor(fd, &dupFd); err != OK) {
+ return err;
}
status_t err = writeParcelFileDescriptor(dupFd, true /*takeOwnership*/);
if (err != OK) {
@@ -2295,7 +2296,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
@@ -2312,7 +2318,12 @@
return BAD_TYPE;
}
- val->reset(fcntl(got, F_DUPFD_CLOEXEC, 0));
+ int dupFd;
+ if (status_t err = dupFileDescriptor(got, &dupFd); err != OK) {
+ return BAD_VALUE;
+ }
+
+ val->reset(dupFd);
if (val->get() < 0) {
return BAD_VALUE;
diff --git a/libs/binder/RpcTransportTipcAndroid.cpp b/libs/binder/RpcTransportTipcAndroid.cpp
new file mode 100644
index 0000000..79983f4
--- /dev/null
+++ b/libs/binder/RpcTransportTipcAndroid.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#define LOG_TAG "RpcTransportTipcAndroid"
+
+#include <binder/RpcSession.h>
+#include <binder/RpcTransportTipcAndroid.h>
+#include <log/log.h>
+#include <poll.h>
+#include <trusty/tipc.h>
+
+#include "FdTrigger.h"
+#include "RpcState.h"
+#include "RpcTransportUtils.h"
+
+using android::base::Error;
+using android::base::Result;
+
+namespace android {
+
+namespace {
+
+// RpcTransport for writing Trusty IPC clients in Android.
+class RpcTransportTipcAndroid : public RpcTransport {
+public:
+ explicit RpcTransportTipcAndroid(android::base::unique_fd socket)
+ : mSocket(std::move(socket)) {}
+
+ status_t pollRead() override {
+ if (mReadBufferPos < mReadBufferSize) {
+ // We have more data in the read buffer
+ return OK;
+ }
+
+ // Trusty IPC device is not a socket, so MSG_PEEK is not available
+ pollfd pfd{.fd = mSocket.get(), .events = static_cast<int16_t>(POLLIN), .revents = 0};
+ ssize_t ret = TEMP_FAILURE_RETRY(::poll(&pfd, 1, 0));
+ if (ret < 0) {
+ int savedErrno = errno;
+ if (savedErrno == EAGAIN || savedErrno == EWOULDBLOCK) {
+ return WOULD_BLOCK;
+ }
+
+ LOG_RPC_DETAIL("RpcTransport poll(): %s", strerror(savedErrno));
+ return -savedErrno;
+ }
+
+ if (pfd.revents & POLLNVAL) {
+ return BAD_VALUE;
+ }
+ if (pfd.revents & POLLERR) {
+ return DEAD_OBJECT;
+ }
+ if (pfd.revents & POLLHUP) {
+ return DEAD_OBJECT;
+ }
+ if (pfd.revents & POLLIN) {
+ return OK;
+ }
+
+ return WOULD_BLOCK;
+ }
+
+ 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)
+ override {
+ auto writeFn = [&](iovec* iovs, size_t niovs) -> ssize_t {
+ // TODO: send ancillaryFds. For now, we just abort if anyone tries
+ // to send any.
+ LOG_ALWAYS_FATAL_IF(ancillaryFds != nullptr && !ancillaryFds->empty(),
+ "File descriptors are not supported on Trusty yet");
+ return TEMP_FAILURE_RETRY(tipc_send(mSocket.get(), iovs, niovs, nullptr, 0));
+ };
+ return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, writeFn, "tipc_send",
+ POLLOUT, altPoll);
+ }
+
+ 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 {
+ auto readFn = [&](iovec* iovs, size_t niovs) -> ssize_t {
+ // Fill the read buffer at most once per readFn call, then try to
+ // return as much of it as possible. If the input iovecs are spread
+ // across multiple messages that require multiple fillReadBuffer
+ // calls, we expect the caller to advance the iovecs past the first
+ // read and call readFn as many times as needed to get all the data
+ status_t ret = fillReadBuffer();
+ if (ret != OK) {
+ return ret;
+ }
+
+ ssize_t processSize = 0;
+ for (size_t i = 0; i < niovs && mReadBufferPos < mReadBufferSize; i++) {
+ auto& iov = iovs[i];
+ size_t numBytes = std::min(iov.iov_len, mReadBufferSize - mReadBufferPos);
+ memcpy(iov.iov_base, mReadBuffer.get() + mReadBufferPos, numBytes);
+ mReadBufferPos += numBytes;
+ processSize += numBytes;
+ }
+
+ return processSize;
+ };
+ return interruptableReadOrWrite(mSocket.get(), fdTrigger, iovs, niovs, readFn, "read",
+ POLLIN, altPoll);
+ }
+
+private:
+ status_t fillReadBuffer() {
+ if (mReadBufferPos < mReadBufferSize) {
+ return OK;
+ }
+
+ if (!mReadBuffer) {
+ // Guarantee at least kDefaultBufferSize bytes
+ mReadBufferCapacity = std::max(mReadBufferCapacity, kDefaultBufferSize);
+ mReadBuffer.reset(new (std::nothrow) uint8_t[mReadBufferCapacity]);
+ if (!mReadBuffer) {
+ return NO_MEMORY;
+ }
+ }
+
+ // Reset the size and position in case we have to exit with an error.
+ // After we read a message into the buffer, we update the size
+ // with the actual value.
+ mReadBufferPos = 0;
+ mReadBufferSize = 0;
+
+ while (true) {
+ ssize_t processSize =
+ TEMP_FAILURE_RETRY(read(mSocket.get(), mReadBuffer.get(), mReadBufferCapacity));
+ if (processSize == 0) {
+ return DEAD_OBJECT;
+ } else if (processSize < 0) {
+ int savedErrno = errno;
+ if (savedErrno == EMSGSIZE) {
+ // Buffer was too small, double it and retry
+ if (__builtin_mul_overflow(mReadBufferCapacity, 2, &mReadBufferCapacity)) {
+ return NO_MEMORY;
+ }
+ mReadBuffer.reset(new (std::nothrow) uint8_t[mReadBufferCapacity]);
+ if (!mReadBuffer) {
+ return NO_MEMORY;
+ }
+ continue;
+ } else {
+ LOG_RPC_DETAIL("RpcTransport fillBuffer(): %s", strerror(savedErrno));
+ return -savedErrno;
+ }
+ } else {
+ mReadBufferSize = static_cast<size_t>(processSize);
+ return OK;
+ }
+ }
+ }
+
+ base::unique_fd mSocket;
+
+ // For now, we copy all the input data into a temporary buffer because
+ // we might get multiple interruptableReadFully calls per message, but
+ // the tipc device only allows one read call. We read every message into
+ // this temporary buffer, then return pieces of it from our method.
+ //
+ // The special transaction GET_MAX_THREADS takes 40 bytes, so the default
+ // size should start pretty high.
+ static constexpr size_t kDefaultBufferSize = 64;
+ std::unique_ptr<uint8_t[]> mReadBuffer;
+ size_t mReadBufferPos = 0;
+ size_t mReadBufferSize = 0;
+ size_t mReadBufferCapacity = 0;
+};
+
+// RpcTransportCtx for Trusty.
+class RpcTransportCtxTipcAndroid : public RpcTransportCtx {
+public:
+ std::unique_ptr<RpcTransport> newTransport(android::base::unique_fd fd,
+ FdTrigger*) const override {
+ return std::make_unique<RpcTransportTipcAndroid>(std::move(fd));
+ }
+ std::vector<uint8_t> getCertificate(RpcCertificateFormat) const override { return {}; }
+};
+
+} // namespace
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcAndroid::newServerCtx() const {
+ return std::make_unique<RpcTransportCtxTipcAndroid>();
+}
+
+std::unique_ptr<RpcTransportCtx> RpcTransportCtxFactoryTipcAndroid::newClientCtx() const {
+ return std::make_unique<RpcTransportCtxTipcAndroid>();
+}
+
+const char* RpcTransportCtxFactoryTipcAndroid::toCString() const {
+ return "trusty";
+}
+
+std::unique_ptr<RpcTransportCtxFactory> RpcTransportCtxFactoryTipcAndroid::make() {
+ return std::unique_ptr<RpcTransportCtxFactoryTipcAndroid>(
+ new RpcTransportCtxFactoryTipcAndroid());
+}
+
+} // namespace android
diff --git a/libs/binder/RpcTrusty.cpp b/libs/binder/RpcTrusty.cpp
new file mode 100644
index 0000000..ea49eef
--- /dev/null
+++ b/libs/binder/RpcTrusty.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#define LOG_TAG "RpcTrusty"
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <binder/RpcSession.h>
+#include <binder/RpcTransportTipcAndroid.h>
+#include <trusty/tipc.h>
+
+namespace android {
+
+using android::base::unique_fd;
+
+sp<IBinder> RpcTrustyConnect(const char* device, const char* port) {
+ auto session = RpcSession::make(RpcTransportCtxFactoryTipcAndroid::make());
+ auto request = [=] {
+ int tipcFd = tipc_connect(device, port);
+ if (tipcFd < 0) {
+ LOG(ERROR) << "Failed to connect to Trusty service. Error code: " << tipcFd;
+ return unique_fd();
+ }
+ return unique_fd(tipcFd);
+ };
+ if (status_t status = session->setupPreconnectedClient(unique_fd{}, request); status != OK) {
+ LOG(ERROR) << "Failed to set up Trusty client. Error: " << statusToString(status).c_str();
+ return nullptr;
+ }
+ return session->getRootObject();
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 46223bb..88d9ca1 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -59,6 +59,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BBinder* localBinder();
diff --git a/libs/binder/include/binder/BpBinder.h b/libs/binder/include/binder/BpBinder.h
index 19ad5e6..4172cc5 100644
--- a/libs/binder/include/binder/BpBinder.h
+++ b/libs/binder/include/binder/BpBinder.h
@@ -72,6 +72,8 @@
virtual void* findObject(const void* objectID) const final;
virtual void* detachObject(const void* objectID) final;
void withLock(const std::function<void()>& doWithLock);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
virtual BpBinder* remoteBinder();
@@ -96,6 +98,8 @@
IBinder::object_cleanup_func func);
void* find(const void* objectID) const;
void* detach(const void* objectID);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, IBinder::object_make_func make,
+ const void* makeArgs);
void kill();
@@ -104,9 +108,9 @@
ObjectManager& operator=(const ObjectManager&);
struct entry_t {
- void* object;
- void* cleanupCookie;
- IBinder::object_cleanup_func func;
+ void* object = nullptr;
+ void* cleanupCookie = nullptr;
+ IBinder::object_cleanup_func func = nullptr;
};
std::map<const void*, entry_t> mObjects;
diff --git a/libs/binder/include/binder/Delegate.h b/libs/binder/include/binder/Delegate.h
new file mode 100644
index 0000000..8b3fc1c
--- /dev/null
+++ b/libs/binder/include/binder/Delegate.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2022 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 <binder/IBinder.h>
+
+#ifndef __BIONIC__
+#ifndef __assert
+
+// defined differently by liblog
+#pragma push_macro("LOG_PRI")
+#ifdef LOG_PRI
+#undef LOG_PRI
+#endif
+#include <syslog.h>
+#pragma pop_macro("LOG_PRI")
+
+#define __assert(a, b, c) \
+ do { \
+ syslog(LOG_ERR, a ": " c); \
+ abort(); \
+ } while (false)
+#endif // __assert
+#endif // __BIONIC__
+
+namespace android {
+
+/*
+ * Used to manage AIDL's *Delegator types.
+ * This is used to:
+ * - create a new *Delegator object that delegates to the binder argument.
+ * - or return an existing *Delegator object that already delegates to the
+ * binder argument.
+ * - or return the underlying delegate binder if the binder argument is a
+ * *Delegator itself.
+ *
+ * @param binder - the binder to delegate to or unwrap
+ *
+ * @return pointer to the *Delegator object or the unwrapped binder object
+ */
+template <typename T>
+sp<T> delegate(const sp<T>& binder) {
+ const void* isDelegatorId = &T::descriptor;
+ const void* hasDelegatorId = &T::descriptor + 1;
+ // is binder itself a delegator?
+ if (T::asBinder(binder)->findObject(isDelegatorId)) {
+ if (T::asBinder(binder)->findObject(hasDelegatorId)) {
+ __assert(__FILE__, __LINE__,
+ "This binder has a delegator and is also delegator itself! This is "
+ "likely an unintended mixing of binders.");
+ return nullptr;
+ }
+ // unwrap the delegator
+ return static_cast<typename T::DefaultDelegator*>(binder.get())->getImpl();
+ }
+
+ struct MakeArgs {
+ const sp<T>* binder;
+ const void* id;
+ } makeArgs;
+ makeArgs.binder = &binder;
+ makeArgs.id = isDelegatorId;
+
+ // the binder is not a delegator, so construct one
+ sp<IBinder> newDelegator = T::asBinder(binder)->lookupOrCreateWeak(
+ hasDelegatorId,
+ [](const void* args) -> sp<IBinder> {
+ auto delegator = sp<typename T::DefaultDelegator>::make(
+ *static_cast<const MakeArgs*>(args)->binder);
+ // make sure we know this binder is a delegator by attaching a unique ID
+ (void)delegator->attachObject(static_cast<const MakeArgs*>(args)->id,
+ reinterpret_cast<void*>(0x1), nullptr, nullptr);
+ return delegator;
+ },
+ static_cast<const void*>(&makeArgs));
+ return sp<typename T::DefaultDelegator>::cast(newDelegator);
+}
+
+} // namespace android
diff --git a/libs/binder/include/binder/IBinder.h b/libs/binder/include/binder/IBinder.h
index 43fc5ff..83aaca7 100644
--- a/libs/binder/include/binder/IBinder.h
+++ b/libs/binder/include/binder/IBinder.h
@@ -284,6 +284,9 @@
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
+ typedef sp<IBinder> (*object_make_func)(const void* makeArgs);
+ sp<IBinder> lookupOrCreateWeak(const void* objectID, object_make_func make,
+ const void* makeArgs);
protected:
virtual ~IBinder();
diff --git a/libs/binder/include_trusty/binder/RpcTransportTipcAndroid.h b/libs/binder/include_trusty/binder/RpcTransportTipcAndroid.h
new file mode 100644
index 0000000..4a4172a
--- /dev/null
+++ b/libs/binder/include_trusty/binder/RpcTransportTipcAndroid.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+// Wraps the transport layer of RPC. Implementation uses Trusty IPC.
+
+#pragma once
+
+#include <memory>
+
+#include <binder/RpcTransport.h>
+
+namespace android {
+
+// RpcTransportCtxFactory for writing Trusty IPC clients in Android.
+class RpcTransportCtxFactoryTipcAndroid : public RpcTransportCtxFactory {
+public:
+ static std::unique_ptr<RpcTransportCtxFactory> make();
+
+ std::unique_ptr<RpcTransportCtx> newServerCtx() const override;
+ std::unique_ptr<RpcTransportCtx> newClientCtx() const override;
+ const char* toCString() const override;
+
+private:
+ RpcTransportCtxFactoryTipcAndroid() = default;
+};
+
+} // namespace android
diff --git a/libs/binder/include_trusty/binder/RpcTrusty.h b/libs/binder/include_trusty/binder/RpcTrusty.h
new file mode 100644
index 0000000..f124e0c
--- /dev/null
+++ b/libs/binder/include_trusty/binder/RpcTrusty.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2022 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 <binder/IBinder.h>
+
+namespace android {
+
+sp<IBinder> RpcTrustyConnect(const char* device, const char* port);
+
+} // namespace android
diff --git a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
index f45aa76..c1f2620 100644
--- a/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
+++ b/libs/binder/ndk/include_cpp/android/binder_parcelable_utils.h
@@ -58,6 +58,9 @@
#endif
AParcel_appendFrom(other.mParcel.get(), this->mParcel.get(), 0,
AParcel_getDataSize(other.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
#endif
@@ -192,6 +195,9 @@
if (__ANDROID_API__ >= 31) {
#endif
AParcel_reset(mParcel.get());
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
}
}
@@ -201,6 +207,29 @@
inline bool operator==(const AParcelableHolder& rhs) const { return this == &rhs; }
inline bool operator>(const AParcelableHolder& rhs) const { return this > &rhs; }
inline bool operator>=(const AParcelableHolder& rhs) const { return this >= &rhs; }
+#if __ANDROID_API__ >= 31
+ inline AParcelableHolder& operator=(const AParcelableHolder& rhs) {
+ // AParcelableHolder has been introduced in 31.
+#ifdef __ANDROID_UNAVAILABLE_SYMBOLS_ARE_WEAK__
+ if (__builtin_available(android 31, *)) {
+#else
+ if (__ANDROID_API__ >= 31) {
+#endif
+ this->reset();
+ if (this->mStability != rhs.mStability) {
+ syslog(LOG_ERR, "AParcelableHolder stability mismatch: this %d rhs %d!",
+ this->mStability, rhs.mStability);
+ abort();
+ }
+ AParcel_appendFrom(rhs.mParcel.get(), this->mParcel.get(), 0,
+ AParcel_getDataSize(rhs.mParcel.get()));
+ } else {
+ syslog(LOG_ERR,
+ "sdk_version not compatible, AParcelableHolder need sdk_version >= 31!");
+ }
+ return *this;
+ }
+#endif
private:
mutable ndk::ScopedAParcel mParcel;
diff --git a/libs/binder/tests/binderBinderUnitTest.cpp b/libs/binder/tests/binderBinderUnitTest.cpp
index ce2770f..b6aed0d 100644
--- a/libs/binder/tests/binderBinderUnitTest.cpp
+++ b/libs/binder/tests/binderBinderUnitTest.cpp
@@ -15,10 +15,11 @@
*/
#include <binder/Binder.h>
-#include <binder/IBinder.h>
+#include <binder/IInterface.h>
#include <gtest/gtest.h>
using android::BBinder;
+using android::IBinder;
using android::OK;
using android::sp;
@@ -48,3 +49,49 @@
binder->setExtension(ext);
EXPECT_EQ(ext, binder->getExtension());
}
+
+struct MyCookie {
+ bool* deleted;
+};
+
+class UniqueBinder : public BBinder {
+public:
+ UniqueBinder(const void* c) : cookie(reinterpret_cast<const MyCookie*>(c)) {
+ *cookie->deleted = false;
+ }
+ ~UniqueBinder() { *cookie->deleted = true; }
+ const MyCookie* cookie;
+};
+
+static sp<IBinder> make(const void* arg) {
+ return sp<UniqueBinder>::make(arg);
+}
+
+TEST(Binder, LookupOrCreateWeak) {
+ auto binder = sp<BBinder>::make();
+ bool deleted;
+ MyCookie cookie = {&deleted};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_NE(binder, createdBinder);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie);
+ EXPECT_EQ(createdBinder, lookedUpBinder);
+ EXPECT_FALSE(deleted);
+}
+
+TEST(Binder, LookupOrCreateWeakDropSp) {
+ auto binder = sp<BBinder>::make();
+ bool deleted1 = false;
+ bool deleted2 = false;
+ MyCookie cookie1 = {&deleted1};
+ MyCookie cookie2 = {&deleted2};
+ sp<IBinder> createdBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie1);
+ EXPECT_NE(binder, createdBinder);
+
+ createdBinder.clear();
+ EXPECT_TRUE(deleted1);
+
+ sp<IBinder> lookedUpBinder = binder->lookupOrCreateWeak(kObjectId1, make, &cookie2);
+ EXPECT_EQ(&cookie2, sp<UniqueBinder>::cast(lookedUpBinder)->cookie);
+ EXPECT_FALSE(deleted2);
+}
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index e72f39c..5de08bd 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -1158,6 +1158,42 @@
EXPECT_EQ(readValue, testValue);
}
+// see ProcessState.cpp BINDER_VM_SIZE = 1MB.
+// This value is not exposed, but some code in the framework relies on being able to use
+// buffers near the cap size.
+// TODO(b/238777741): why do larger values, like 300K fail sometimes
+constexpr size_t kSizeBytesAlmostFull = 100'000;
+constexpr size_t kSizeBytesOverFull = 1'050'000;
+
+TEST_F(BinderLibTest, GargantuanVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+
+ for (size_t i = 0; i < 10; i++) {
+ // a slight variation in size is used to consider certain possible caching implementations
+ const std::vector<uint64_t> testValue((kSizeBytesAlmostFull + i) / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply), StatusEq(NO_ERROR))
+ << i;
+ std::vector<uint64_t> readValue;
+ EXPECT_THAT(reply.readUint64Vector(&readValue), StatusEq(OK));
+ EXPECT_EQ(readValue, testValue);
+ }
+}
+
+TEST_F(BinderLibTest, LimitExceededVectorSent) {
+ sp<IBinder> server = addServer();
+ ASSERT_TRUE(server != nullptr);
+ const std::vector<uint64_t> testValue(kSizeBytesOverFull / sizeof(uint64_t), 42);
+
+ Parcel data, reply;
+ data.writeUint64Vector(testValue);
+ EXPECT_THAT(server->transact(BINDER_LIB_TEST_ECHO_VECTOR, data, &reply),
+ StatusEq(FAILED_TRANSACTION));
+}
+
TEST_F(BinderLibTest, BufRejected) {
Parcel data, reply;
uint32_t buf;
diff --git a/libs/binder/trusty/OS.cpp b/libs/binder/trusty/OS.cpp
index 187add4..bbfa381 100644
--- a/libs/binder/trusty/OS.cpp
+++ b/libs/binder/trusty/OS.cpp
@@ -32,4 +32,9 @@
return res == 1 ? OK : UNKNOWN_ERROR;
}
+status_t dupFileDescriptor(int oldFd, int* newFd) {
+ // TODO: implement separately
+ return INVALID_OPERATION;
+}
+
} // namespace android
diff --git a/libs/binder/trusty/rules.mk b/libs/binder/trusty/rules.mk
index 83475f5..d0d0861 100644
--- a/libs/binder/trusty/rules.mk
+++ b/libs/binder/trusty/rules.mk
@@ -36,6 +36,7 @@
$(LIBBINDER_DIR)/IInterface.cpp \
$(LIBBINDER_DIR)/IResultReceiver.cpp \
$(LIBBINDER_DIR)/Parcel.cpp \
+ $(LIBBINDER_DIR)/ParcelFileDescriptor.cpp \
$(LIBBINDER_DIR)/RpcServer.cpp \
$(LIBBINDER_DIR)/RpcSession.cpp \
$(LIBBINDER_DIR)/RpcState.cpp \
diff --git a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
index 129f430..0e110b7 100644
--- a/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
+++ b/libs/sensor/fuzz/sensor_fuzzer/sensor_fuzzer.cpp
@@ -26,8 +26,10 @@
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
FuzzedDataProvider fdp(data, size);
struct sensor_t sensor_type;
- sensor_type.name = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
- sensor_type.vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN).c_str();
+ std::string name = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.name = name.c_str();
+ std::string vendor = fdp.ConsumeBytesAsString(MAX_STR_LEN);
+ sensor_type.vendor = vendor.c_str();
sensor_type.stringType = "";
sensor_type.requiredPermission = "";
sensor_type.version = fdp.ConsumeIntegral<int>();
diff --git a/services/vibratorservice/test/Android.bp b/services/vibratorservice/test/Android.bp
index 3294724..adba3db 100644
--- a/services/vibratorservice/test/Android.bp
+++ b/services/vibratorservice/test/Android.bp
@@ -57,4 +57,9 @@
static_libs: [
"libgmock",
],
+ // FIXME: Workaround LTO build breakage
+ // http://b/241699694
+ lto: {
+ never: true,
+ },
}