Merge "libbinder: RPC delay bp refcounts"
diff --git a/libs/binder/BpBinder.cpp b/libs/binder/BpBinder.cpp
index 92df874..06542f0 100644
--- a/libs/binder/BpBinder.cpp
+++ b/libs/binder/BpBinder.cpp
@@ -48,10 +48,6 @@
// Another arbitrary value a binder count needs to drop below before another callback will be called
uint32_t BpBinder::sBinderProxyCountLowWatermark = 2000;
-// Once the limit has been exceeded, keep calling the limit callback for every this many new proxies
-// created over the limit.
-constexpr uint32_t REPEAT_LIMIT_CALLBACK_INTERVAL = 1000;
-
enum {
LIMIT_REACHED_MASK = 0x80000000, // A flag denoting that the limit has been reached
COUNTING_VALUE_MASK = 0x7FFFFFFF, // A mask of the remaining bits for the count value
@@ -129,7 +125,7 @@
uint32_t lastLimitCallbackAt = sLastLimitCallbackMap[trackedUid];
if (trackedValue > lastLimitCallbackAt &&
- (trackedValue - lastLimitCallbackAt > REPEAT_LIMIT_CALLBACK_INTERVAL)) {
+ (trackedValue - lastLimitCallbackAt > sBinderProxyCountHighWatermark)) {
ALOGE("Still too many binder proxy objects sent to uid %d from uid %d (%d proxies "
"held)",
getuid(), trackedUid, trackedValue);
diff --git a/libs/binder/FdTrigger.cpp b/libs/binder/FdTrigger.cpp
index 49f83ff..5e22593 100644
--- a/libs/binder/FdTrigger.cpp
+++ b/libs/binder/FdTrigger.cpp
@@ -17,11 +17,13 @@
#define LOG_TAG "FdTrigger"
#include <log/log.h>
+#include "FdTrigger.h"
+
#include <poll.h>
#include <android-base/macros.h>
-#include "FdTrigger.h"
+#include "RpcState.h"
namespace android {
std::unique_ptr<FdTrigger> FdTrigger::make() {
@@ -42,21 +44,53 @@
}
status_t FdTrigger::triggerablePoll(base::borrowed_fd fd, int16_t event) {
- while (true) {
- pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
- {.fd = mRead.get(), .events = 0, .revents = 0}};
- int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
- if (ret < 0) {
- return -errno;
- }
- if (ret == 0) {
- continue;
- }
- if (pfd[1].revents & POLLHUP) {
- return DEAD_OBJECT;
- }
- return pfd[0].revents & event ? OK : DEAD_OBJECT;
+ LOG_ALWAYS_FATAL_IF(event == 0, "triggerablePoll %d with event 0 is not allowed", fd.get());
+ pollfd pfd[]{{.fd = fd.get(), .events = static_cast<int16_t>(event), .revents = 0},
+ {.fd = mRead.get(), .events = 0, .revents = 0}};
+ int ret = TEMP_FAILURE_RETRY(poll(pfd, arraysize(pfd), -1));
+ if (ret < 0) {
+ return -errno;
}
+ LOG_ALWAYS_FATAL_IF(ret == 0, "poll(%d) returns 0 with infinite timeout", fd.get());
+
+ // At least one FD has events. Check them.
+
+ // Detect explicit trigger(): DEAD_OBJECT
+ if (pfd[1].revents & POLLHUP) {
+ return DEAD_OBJECT;
+ }
+ // See unknown flags in trigger FD's revents (POLLERR / POLLNVAL).
+ // Treat this error condition as UNKNOWN_ERROR.
+ if (pfd[1].revents != 0) {
+ ALOGE("Unknown revents on trigger FD %d: revents = %d", pfd[1].fd, pfd[1].revents);
+ return UNKNOWN_ERROR;
+ }
+
+ // pfd[1].revents is 0, hence pfd[0].revents must be set, and only possible values are
+ // a subset of event | POLLHUP | POLLERR | POLLNVAL.
+
+ // POLLNVAL: invalid FD number, e.g. not opened.
+ if (pfd[0].revents & POLLNVAL) {
+ return BAD_VALUE;
+ }
+
+ // Error condition. It wouldn't be possible to do I/O on |fd| afterwards.
+ // Note: If this is the write end of a pipe then POLLHUP may also be set simultaneously. We
+ // still want DEAD_OBJECT in this case.
+ if (pfd[0].revents & POLLERR) {
+ LOG_RPC_DETAIL("poll() incoming FD %d results in revents = %d", pfd[0].fd, pfd[0].revents);
+ return DEAD_OBJECT;
+ }
+
+ // Success condition; event flag(s) set. Even though POLLHUP may also be set,
+ // treat it as a success condition to ensure data is drained.
+ if (pfd[0].revents & event) {
+ return OK;
+ }
+
+ // POLLHUP: Peer closed connection. Treat as DEAD_OBJECT.
+ // This is a very common case, so don't log.
+ return DEAD_OBJECT;
}
} // namespace android
diff --git a/libs/binder/RpcServer.cpp b/libs/binder/RpcServer.cpp
index cf95fda..ba2920e 100644
--- a/libs/binder/RpcServer.cpp
+++ b/libs/binder/RpcServer.cpp
@@ -205,8 +205,11 @@
}
mShutdownTrigger->trigger();
+
for (auto& [id, session] : mSessions) {
(void)id;
+ // server lock is a more general lock
+ std::lock_guard<std::mutex> _lSession(session->mMutex);
session->mShutdownTrigger->trigger();
}
diff --git a/libs/binder/RpcState.cpp b/libs/binder/RpcState.cpp
index 82efe6d..b5c6cb0 100644
--- a/libs/binder/RpcState.cpp
+++ b/libs/binder/RpcState.cpp
@@ -454,12 +454,16 @@
const sp<IBinder>& binder, uint32_t code, const Parcel& data,
const sp<RpcSession>& session, Parcel* reply, uint32_t flags) {
if (!data.isForRpc()) {
- ALOGE("Refusing to send RPC with parcel not crafted for RPC");
+ ALOGE("Refusing to send RPC with parcel not crafted for RPC call on binder %p code "
+ "%" PRIu32,
+ binder.get(), code);
return BAD_TYPE;
}
if (data.objectsCount() != 0) {
- ALOGE("Parcel at %p has attached objects but is being used in an RPC call", &data);
+ ALOGE("Parcel at %p has attached objects but is being used in an RPC call on binder %p "
+ "code %" PRIu32,
+ &data, binder.get(), code);
return BAD_TYPE;
}
diff --git a/libs/binder/rust/src/native.rs b/libs/binder/rust/src/native.rs
index e7c3396..a91092e 100644
--- a/libs/binder/rust/src/native.rs
+++ b/libs/binder/rust/src/native.rs
@@ -441,6 +441,8 @@
///
/// Registers the given binder object with the given identifier. If successful,
/// this service can then be retrieved using that identifier.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
pub fn add_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
let instance = CString::new(identifier).unwrap();
let status = unsafe {
@@ -462,6 +464,8 @@
///
/// If any service in the process is registered as lazy, all should be, otherwise
/// the process may be shut down while a service is in use.
+///
+/// This function will panic if the identifier contains a 0 byte (NUL).
pub fn register_lazy_service(identifier: &str, mut binder: SpIBinder) -> Result<()> {
let instance = CString::new(identifier).unwrap();
let status = unsafe {
diff --git a/libs/binder/tests/Android.bp b/libs/binder/tests/Android.bp
index 71c0e86..680f0ed 100644
--- a/libs/binder/tests/Android.bp
+++ b/libs/binder/tests/Android.bp
@@ -134,6 +134,37 @@
},
}
+cc_library_static {
+ name: "libbinder_tls_test_utils",
+ host_supported: true,
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ defaults: [
+ "binder_test_defaults",
+ "libbinder_tls_shared_deps",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbase",
+ "liblog",
+ ],
+ static_libs: [
+ "libbinder_tls_static",
+ ],
+ srcs: [
+ "RpcTlsTestUtils.cpp",
+ ],
+ export_include_dirs: [
+ "include_tls_test_utils",
+ ],
+ visibility: [
+ ":__subpackages__",
+ ],
+}
+
cc_test {
name: "binderRpcTest",
host_supported: true,
@@ -153,8 +184,6 @@
srcs: [
"binderRpcTest.cpp",
- "RpcAuthTesting.cpp",
- "RpcCertificateVerifierSimple.cpp",
],
shared_libs: [
"libbinder",
@@ -166,6 +195,7 @@
],
static_libs: [
"libbinder_tls_static",
+ "libbinder_tls_test_utils",
"binderRpcTestIface-cpp",
"binderRpcTestIface-ndk",
],
@@ -189,7 +219,6 @@
"libbinder_tls_shared_deps",
],
srcs: [
- "RpcAuthTesting.cpp",
"RpcTlsUtilsTest.cpp",
],
shared_libs: [
@@ -199,6 +228,7 @@
"liblog",
],
static_libs: [
+ "libbinder_tls_test_utils",
"libbinder_tls_static",
],
test_suites: ["general-tests", "device-tests"],
@@ -219,7 +249,6 @@
srcs: [
"binderRpcBenchmark.cpp",
"IBinderRpcBenchmark.aidl",
- "RpcAuthTesting.cpp",
],
shared_libs: [
"libbase",
@@ -228,6 +257,7 @@
"libutils",
],
static_libs: [
+ "libbinder_tls_test_utils",
"libbinder_tls_static",
],
}
diff --git a/libs/binder/tests/RpcAuthTesting.h b/libs/binder/tests/RpcAuthTesting.h
deleted file mode 100644
index c3c2df4..0000000
--- a/libs/binder/tests/RpcAuthTesting.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2021 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/RpcAuth.h>
-
-namespace android {
-
-constexpr const uint32_t kCertValidSeconds = 30 * (60 * 60 * 24); // 30 days
-bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert();
-bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pKey, uint32_t validSeconds);
-
-// An implementation of RpcAuth that generates a key pair and a self-signed
-// certificate every time configure() is called.
-class RpcAuthSelfSigned : public RpcAuth {
-public:
- RpcAuthSelfSigned(uint32_t validSeconds = kCertValidSeconds) : mValidSeconds(validSeconds) {}
- status_t configure(SSL_CTX* ctx) override;
-
-private:
- const uint32_t mValidSeconds;
-};
-
-class RpcAuthPreSigned : public RpcAuth {
-public:
- RpcAuthPreSigned(bssl::UniquePtr<EVP_PKEY> pkey, bssl::UniquePtr<X509> cert)
- : mPkey(std::move(pkey)), mCert(std::move(cert)) {}
- status_t configure(SSL_CTX* ctx) override;
-
-private:
- bssl::UniquePtr<EVP_PKEY> mPkey;
- bssl::UniquePtr<X509> mCert;
-};
-
-} // namespace android
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.cpp b/libs/binder/tests/RpcCertificateVerifierSimple.cpp
deleted file mode 100644
index 1f74adc..0000000
--- a/libs/binder/tests/RpcCertificateVerifierSimple.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 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 "RpcCertificateVerifierSimple"
-#include <log/log.h>
-
-#include <binder/RpcTlsUtils.h>
-
-#include "RpcCertificateVerifierSimple.h"
-
-namespace android {
-
-status_t RpcCertificateVerifierSimple::verify(const SSL* ssl, uint8_t* outAlert) {
- const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
- bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
- LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
- "%s: libssl should not ask to verify non-existing cert", logPrefix);
-
- std::lock_guard<std::mutex> lock(mMutex);
- for (const auto& trustedCert : mTrustedPeerCertificates) {
- if (0 == X509_cmp(trustedCert.get(), peerCert.get())) {
- return OK;
- }
- }
- *outAlert = SSL_AD_CERTIFICATE_UNKNOWN;
- return PERMISSION_DENIED;
-}
-
-status_t RpcCertificateVerifierSimple::addTrustedPeerCertificate(RpcCertificateFormat format,
- const std::vector<uint8_t>& cert) {
- bssl::UniquePtr<X509> x509 = deserializeCertificate(cert, format);
- if (x509 == nullptr) {
- ALOGE("Certificate is not in the proper format %s", PrintToString(format).c_str());
- return BAD_VALUE;
- }
- std::lock_guard<std::mutex> lock(mMutex);
- mTrustedPeerCertificates.push_back(std::move(x509));
- return OK;
-}
-
-} // namespace android
diff --git a/libs/binder/tests/RpcCertificateVerifierSimple.h b/libs/binder/tests/RpcCertificateVerifierSimple.h
deleted file mode 100644
index bdb2426..0000000
--- a/libs/binder/tests/RpcCertificateVerifierSimple.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2021 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 <mutex>
-#include <string_view>
-#include <vector>
-
-#include <openssl/ssl.h>
-
-#include <binder/RpcCertificateFormat.h>
-#include <binder/RpcCertificateVerifier.h>
-
-namespace android {
-
-// A simple certificate verifier for testing.
-// Keep a list of leaf certificates as trusted. No certificate chain support.
-//
-// All APIs are thread-safe. However, if verify() and addTrustedPeerCertificate() are called
-// simultaneously in different threads, it is not deterministic whether verify() will use the
-// certificate being added.
-class RpcCertificateVerifierSimple : public RpcCertificateVerifier {
-public:
- status_t verify(const SSL*, uint8_t*) override;
-
- // Add a trusted peer certificate. Peers presenting this certificate are accepted.
- //
- // Caller must ensure that RpcTransportCtx::newTransport() are called after all trusted peer
- // certificates are added. Otherwise, RpcTransport-s created before may not trust peer
- // certificates added later.
- [[nodiscard]] status_t addTrustedPeerCertificate(RpcCertificateFormat format,
- const std::vector<uint8_t>& cert);
-
-private:
- std::mutex mMutex; // for below
- std::vector<bssl::UniquePtr<X509>> mTrustedPeerCertificates;
-};
-
-} // namespace android
diff --git a/libs/binder/tests/RpcAuthTesting.cpp b/libs/binder/tests/RpcTlsTestUtils.cpp
similarity index 72%
rename from libs/binder/tests/RpcAuthTesting.cpp
rename to libs/binder/tests/RpcTlsTestUtils.cpp
index c0587a2..6119313 100644
--- a/libs/binder/tests/RpcAuthTesting.cpp
+++ b/libs/binder/tests/RpcTlsTestUtils.cpp
@@ -13,7 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include "RpcAuthTesting.h"
+
+#define LOG_TAG "RpcTlsTestUtils"
+#include <log/log.h>
+
+#include <binder/RpcTlsTestUtils.h>
+
+#include <binder/RpcTlsUtils.h>
+
#include "../Utils.h" // for TEST_AND_RETURN
namespace android {
@@ -80,4 +87,32 @@
return OK;
}
+status_t RpcCertificateVerifierSimple::verify(const SSL* ssl, uint8_t* outAlert) {
+ const char* logPrefix = SSL_is_server(ssl) ? "Server" : "Client";
+ bssl::UniquePtr<X509> peerCert(SSL_get_peer_certificate(ssl)); // Does not set error queue
+ LOG_ALWAYS_FATAL_IF(peerCert == nullptr,
+ "%s: libssl should not ask to verify non-existing cert", logPrefix);
+
+ std::lock_guard<std::mutex> lock(mMutex);
+ for (const auto& trustedCert : mTrustedPeerCertificates) {
+ if (0 == X509_cmp(trustedCert.get(), peerCert.get())) {
+ return OK;
+ }
+ }
+ *outAlert = SSL_AD_CERTIFICATE_UNKNOWN;
+ return PERMISSION_DENIED;
+}
+
+status_t RpcCertificateVerifierSimple::addTrustedPeerCertificate(RpcCertificateFormat format,
+ const std::vector<uint8_t>& cert) {
+ bssl::UniquePtr<X509> x509 = deserializeCertificate(cert, format);
+ if (x509 == nullptr) {
+ ALOGE("Certificate is not in the proper format %s", PrintToString(format).c_str());
+ return BAD_VALUE;
+ }
+ std::lock_guard<std::mutex> lock(mMutex);
+ mTrustedPeerCertificates.push_back(std::move(x509));
+ return OK;
+}
+
} // namespace android
diff --git a/libs/binder/tests/RpcTlsUtilsTest.cpp b/libs/binder/tests/RpcTlsUtilsTest.cpp
index 9b3078d..530606c 100644
--- a/libs/binder/tests/RpcTlsUtilsTest.cpp
+++ b/libs/binder/tests/RpcTlsUtilsTest.cpp
@@ -14,11 +14,10 @@
* limitations under the License.
*/
+#include <binder/RpcTlsTestUtils.h>
#include <binder/RpcTlsUtils.h>
#include <gtest/gtest.h>
-#include "RpcAuthTesting.h"
-
namespace android {
std::string toDebugString(EVP_PKEY* pkey) {
diff --git a/libs/binder/tests/binderRpcBenchmark.cpp b/libs/binder/tests/binderRpcBenchmark.cpp
index 0477d50..f8718aa 100644
--- a/libs/binder/tests/binderRpcBenchmark.cpp
+++ b/libs/binder/tests/binderRpcBenchmark.cpp
@@ -25,6 +25,7 @@
#include <binder/RpcCertificateVerifier.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
#include <binder/RpcTlsUtils.h>
#include <binder/RpcTransportRaw.h>
#include <binder/RpcTransportTls.h>
@@ -37,8 +38,6 @@
#include <sys/types.h>
#include <unistd.h>
-#include "RpcAuthTesting.h"
-
using android::BBinder;
using android::defaultServiceManager;
using android::IBinder;
@@ -50,6 +49,7 @@
using android::RpcAuthPreSigned;
using android::RpcCertificateFormat;
using android::RpcCertificateVerifier;
+using android::RpcCertificateVerifierNoOp;
using android::RpcServer;
using android::RpcSession;
using android::RpcTransportCtxFactory;
@@ -90,25 +90,20 @@
Transport::RPC_TLS,
};
-// Certificate validation happens during handshake and does not affect the result of benchmarks.
-// Skip certificate validation to simplify the setup process.
-class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
-public:
- status_t verify(const SSL*, uint8_t*) override { return OK; }
-};
-
std::unique_ptr<RpcTransportCtxFactory> makeFactoryTls() {
auto pkey = android::makeKeyPairForSelfSignedCert();
CHECK_NE(pkey.get(), nullptr);
auto cert = android::makeSelfSignedCert(pkey.get(), android::kCertValidSeconds);
CHECK_NE(cert.get(), nullptr);
- auto verifier = std::make_shared<RpcCertificateVerifierNoOp>();
+ auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(OK);
auto auth = std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
return RpcTransportCtxFactoryTls::make(verifier, std::move(auth));
}
static sp<RpcSession> gSession = RpcSession::make();
+// Certificate validation happens during handshake and does not affect the result of benchmarks.
+// Skip certificate validation to simplify the setup process.
static sp<RpcSession> gSessionTls = RpcSession::make(makeFactoryTls());
#ifdef __BIONIC__
static const String16 kKernelBinderInstance = String16(u"binderRpcBenchmark-control");
diff --git a/libs/binder/tests/binderRpcTest.cpp b/libs/binder/tests/binderRpcTest.cpp
index ed477d6..a1058bc 100644
--- a/libs/binder/tests/binderRpcTest.cpp
+++ b/libs/binder/tests/binderRpcTest.cpp
@@ -31,6 +31,7 @@
#include <binder/ProcessState.h>
#include <binder/RpcServer.h>
#include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
#include <binder/RpcTlsUtils.h>
#include <binder/RpcTransport.h>
#include <binder/RpcTransportRaw.h>
@@ -51,8 +52,6 @@
#include "../RpcSocketAddress.h" // for testing preconnected clients
#include "../RpcState.h" // for debugging
#include "../vm_sockets.h" // for VMADDR_*
-#include "RpcAuthTesting.h"
-#include "RpcCertificateVerifierSimple.h"
using namespace std::chrono_literals;
using namespace std::placeholders;
diff --git a/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
new file mode 100644
index 0000000..094addd
--- /dev/null
+++ b/libs/binder/tests/include_tls_test_utils/binder/RpcTlsTestUtils.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 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 <memory>
+#include <mutex>
+
+#include <binder/RpcAuth.h>
+#include <binder/RpcCertificateFormat.h>
+#include <binder/RpcCertificateVerifier.h>
+#include <binder/RpcTransport.h>
+#include <openssl/ssl.h>
+#include <utils/Errors.h>
+
+namespace android {
+
+constexpr const uint32_t kCertValidSeconds = 30 * (60 * 60 * 24); // 30 days
+bssl::UniquePtr<EVP_PKEY> makeKeyPairForSelfSignedCert();
+bssl::UniquePtr<X509> makeSelfSignedCert(EVP_PKEY* pKey, uint32_t validSeconds);
+
+// An implementation of RpcAuth that generates a key pair and a self-signed
+// certificate every time configure() is called.
+class RpcAuthSelfSigned : public RpcAuth {
+public:
+ RpcAuthSelfSigned(uint32_t validSeconds = kCertValidSeconds) : mValidSeconds(validSeconds) {}
+ status_t configure(SSL_CTX* ctx) override;
+
+private:
+ const uint32_t mValidSeconds;
+};
+
+class RpcAuthPreSigned : public RpcAuth {
+public:
+ RpcAuthPreSigned(bssl::UniquePtr<EVP_PKEY> pkey, bssl::UniquePtr<X509> cert)
+ : mPkey(std::move(pkey)), mCert(std::move(cert)) {}
+ status_t configure(SSL_CTX* ctx) override;
+
+private:
+ bssl::UniquePtr<EVP_PKEY> mPkey;
+ bssl::UniquePtr<X509> mCert;
+};
+
+// A simple certificate verifier for testing.
+// Keep a list of leaf certificates as trusted. No certificate chain support.
+//
+// All APIs are thread-safe. However, if verify() and addTrustedPeerCertificate() are called
+// simultaneously in different threads, it is not deterministic whether verify() will use the
+// certificate being added.
+class RpcCertificateVerifierSimple : public RpcCertificateVerifier {
+public:
+ status_t verify(const SSL*, uint8_t*) override;
+
+ // Add a trusted peer certificate. Peers presenting this certificate are accepted.
+ //
+ // Caller must ensure that RpcTransportCtx::newTransport() are called after all trusted peer
+ // certificates are added. Otherwise, RpcTransport-s created before may not trust peer
+ // certificates added later.
+ [[nodiscard]] status_t addTrustedPeerCertificate(RpcCertificateFormat format,
+ const std::vector<uint8_t>& cert);
+
+private:
+ std::mutex mMutex; // for below
+ std::vector<bssl::UniquePtr<X509>> mTrustedPeerCertificates;
+};
+
+// A RpcCertificateVerifier that does not verify anything.
+class RpcCertificateVerifierNoOp : public RpcCertificateVerifier {
+public:
+ RpcCertificateVerifierNoOp(status_t status) : mStatus(status) {}
+ status_t verify(const SSL*, uint8_t*) override { return mStatus; }
+
+private:
+ status_t mStatus;
+};
+
+} // namespace android
diff --git a/libs/binder/tests/rpc_fuzzer/Android.bp b/libs/binder/tests/rpc_fuzzer/Android.bp
index be55eba..c0f0a12 100644
--- a/libs/binder/tests/rpc_fuzzer/Android.bp
+++ b/libs/binder/tests/rpc_fuzzer/Android.bp
@@ -19,12 +19,19 @@
srcs: [
"main.cpp",
],
+ // Not using libbinder_tls_shared_deps to use deterministic boringssl libraries.
static_libs: [
"libbase",
"libcutils",
"liblog",
+ "libbinder_tls_static",
+ "libbinder_tls_test_utils",
+ "libssl_fuzz_unsafe",
+ "libcrypto_fuzz_unsafe",
],
-
+ cflags: [
+ "-DBORINGSSL_UNSAFE_DETERMINISTIC_MODE" // for RAND_reset_for_fuzzing
+ ],
target: {
android: {
shared_libs: [
@@ -39,4 +46,8 @@
],
},
},
+ data: [
+ "server.crt",
+ "server.key",
+ ],
}
diff --git a/libs/binder/tests/rpc_fuzzer/create_certs.sh b/libs/binder/tests/rpc_fuzzer/create_certs.sh
new file mode 100755
index 0000000..4ae4cb1
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/create_certs.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+
+# As explained in
+# https://gist.github.com/darrenjs/4645f115d10aa4b5cebf57483ec82eca
+
+openssl genrsa -des3 -passout pass:xxxx -out server.pass.key 2048
+openssl rsa -passin pass:xxxx -in server.pass.key -out server.key
+rm -f server.pass.key
+
+openssl req \
+ -subj "/" \
+ -new -key server.key -out server.csr
+
+openssl x509 -req -sha256 -days 99999 -in server.csr -signkey server.key -out server.crt
+rm -f server.csr
diff --git a/libs/binder/tests/rpc_fuzzer/main.cpp b/libs/binder/tests/rpc_fuzzer/main.cpp
index c848798..518849a 100644
--- a/libs/binder/tests/rpc_fuzzer/main.cpp
+++ b/libs/binder/tests/rpc_fuzzer/main.cpp
@@ -13,13 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/unique_fd.h>
#include <binder/Binder.h>
#include <binder/Parcel.h>
#include <binder/RpcServer.h>
-#include <binder/RpcSession.h>
+#include <binder/RpcTlsTestUtils.h>
+#include <binder/RpcTransport.h>
+#include <binder/RpcTransportRaw.h>
+#include <binder/RpcTransportTls.h>
#include <fuzzer/FuzzedDataProvider.h>
+#include <openssl/rand.h>
+#include <openssl/ssl.h>
#include <sys/resource.h>
#include <sys/un.h>
@@ -51,13 +58,66 @@
}
};
+int passwordCallback(char* buf, int size, int /*rwflag*/, void* /*u*/) {
+ constexpr const char pass[] = "xxxx"; // See create_certs.sh
+ if (size <= 0) return 0;
+ int numCopy = std::min<int>(size, sizeof(pass));
+ (void)memcpy(buf, pass, numCopy);
+ return numCopy;
+}
+
+struct ServerAuth {
+ bssl::UniquePtr<EVP_PKEY> pkey;
+ bssl::UniquePtr<X509> cert;
+};
+
+// Use pre-configured keys because runtime generated keys / certificates are not
+// deterministic, and the algorithm is time consuming.
+ServerAuth readServerKeyAndCert() {
+ ServerAuth ret;
+
+ auto keyPath = android::base::GetExecutableDirectory() + "/data/server.key";
+ bssl::UniquePtr<BIO> keyBio(BIO_new_file(keyPath.c_str(), "r"));
+ ret.pkey.reset(PEM_read_bio_PrivateKey(keyBio.get(), nullptr, passwordCallback, nullptr));
+ CHECK_NE(ret.pkey.get(), nullptr);
+
+ auto certPath = android::base::GetExecutableDirectory() + "/data/server.crt";
+ bssl::UniquePtr<BIO> certBio(BIO_new_file(certPath.c_str(), "r"));
+ ret.cert.reset(PEM_read_bio_X509(certBio.get(), nullptr, nullptr, nullptr));
+ CHECK_NE(ret.cert.get(), nullptr);
+
+ return ret;
+}
+
+std::unique_ptr<RpcAuth> createServerRpcAuth() {
+ static auto sAuth = readServerKeyAndCert();
+
+ CHECK(EVP_PKEY_up_ref(sAuth.pkey.get()));
+ bssl::UniquePtr<EVP_PKEY> pkey(sAuth.pkey.get());
+ CHECK(X509_up_ref(sAuth.cert.get()));
+ bssl::UniquePtr<X509> cert(sAuth.cert.get());
+
+ return std::make_unique<RpcAuthPreSigned>(std::move(pkey), std::move(cert));
+}
+
+std::unique_ptr<RpcTransportCtxFactory> makeTransportCtxFactory(FuzzedDataProvider* provider) {
+ bool isTls = provider->ConsumeBool();
+ if (!isTls) {
+ return RpcTransportCtxFactoryRaw::make();
+ }
+ status_t verifyStatus = provider->ConsumeIntegral<status_t>();
+ auto verifier = std::make_shared<RpcCertificateVerifierNoOp>(verifyStatus);
+ return RpcTransportCtxFactoryTls::make(verifier, createServerRpcAuth());
+}
+
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
if (size > 50000) return 0;
FuzzedDataProvider provider(data, size);
+ RAND_reset_for_fuzzing();
unlink(kSock.c_str());
- sp<RpcServer> server = RpcServer::make();
+ sp<RpcServer> server = RpcServer::make(makeTransportCtxFactory(&provider));
server->setRootObject(sp<SomeBinder>::make());
server->iUnderstandThisCodeIsExperimentalAndIWillNotUseItInProduction();
CHECK_EQ(OK, server->setupUnixDomainServer(kSock.c_str()));
diff --git a/libs/binder/tests/rpc_fuzzer/server.crt b/libs/binder/tests/rpc_fuzzer/server.crt
new file mode 100644
index 0000000..9142474
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.crt
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICiTCCAXECFG1ggXE36l2WXeG6YTnaRVB7EmgQMA0GCSqGSIb3DQEBCwUAMAAw
+IBcNMjEwOTI5MDEzOTEzWhgPMjI5NTA3MTQwMTM5MTNaMAAwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDE3KnhPMwINpP5aIHIo/3GTlROZOK5AmkEsWmP
+w8smSWo2hJ7M0sOhruvOz82WORj48K8C0W72yFN+e9g32qoNMJFP/s6j1RWmaAKZ
+eSQUq6ixyaGhFLBOoukVykfTnY4qn4RbX5HzgpAPR1gv5ELvMXXPrxvtpIcVIrhm
+/dBQIa3iHZS6kypNbmRx/nhDVU8FK9s9WU5VLpbuNxv+m4X4Y1M/VZNatUMx5I0o
+ystV4JTqzjRZRPR4sxtMhu8/A11JsBVLeu8ZM/0IGCjmLOF4hy5a5YDv8MOJtdG2
+LI7ibZNtyrZiKwwhJc3tElzeIFit4T5Xjx69y/EMS4Hwhf3zAgMBAAEwDQYJKoZI
+hvcNAQELBQADggEBAD3gRbUybW7P2CihMyskTgS9HoIT9c02JWjtueWQIiQkyqTB
+6QdUQTHM5weil6TiW8NfpQQUIvrh66Pkph65shvFqxUsjdW25b4RbfUldFihfs1n
+kTa+e+hZONnVuzLvezIs2b8dygH9GA5y2OiLxwrMUcyaoCHGwKF7iOE0SJhfx0kY
+JDs4O+gAVjEsBSc24pm9aHBxgRCiEm1I4+RZf6PRBIz1ZadGBFsCZ+Gj6wyLP2Wq
+kjjMiV6o8pEjJjM+Oi4GfxvNewMCd2hMZYuJYpYC3cc7fPIpx8luidqKJdve8c6m
+KQ+dJ6ZQxEi0Zc9Jzre7NNoVcpIdc8SbkEM/DDo=
+-----END CERTIFICATE-----
diff --git a/libs/binder/tests/rpc_fuzzer/server.key b/libs/binder/tests/rpc_fuzzer/server.key
new file mode 100644
index 0000000..743470e
--- /dev/null
+++ b/libs/binder/tests/rpc_fuzzer/server.key
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEpQIBAAKCAQEAxNyp4TzMCDaT+WiByKP9xk5UTmTiuQJpBLFpj8PLJklqNoSe
+zNLDoa7rzs/NljkY+PCvAtFu9shTfnvYN9qqDTCRT/7Oo9UVpmgCmXkkFKuoscmh
+oRSwTqLpFcpH052OKp+EW1+R84KQD0dYL+RC7zF1z68b7aSHFSK4Zv3QUCGt4h2U
+upMqTW5kcf54Q1VPBSvbPVlOVS6W7jcb/puF+GNTP1WTWrVDMeSNKMrLVeCU6s40
+WUT0eLMbTIbvPwNdSbAVS3rvGTP9CBgo5izheIcuWuWA7/DDibXRtiyO4m2Tbcq2
+YisMISXN7RJc3iBYreE+V48evcvxDEuB8IX98wIDAQABAoIBACcI5jp+NqrOP6st
+uMZTFifzMi5VPMuYmcBPeXIDTc3qsr/ari5JAHeX2rQoakiGS9hYySsS4iDW+g9T
+eT0iA6QX5Ehrawf7YY6cgx9xcOEUZJ/ULlNlacw961/huzpPvHfhJ3qCycryMaSF
+7guZBFivgv/KZgxKGmrrdosdeufYXL3eHWZIrvcN4cDVgxslZg0o3Y5kCW3/KmDO
+QwvBlqgja93yImmkFA5BA/hQUsWuMBiR0xAd4b1NSBVCGTAYuCm6Up+6tIxeBSu5
+MVnNXbAIyVkbAS+gaR4uut6ObzFwUyGKDMaMpJ0LHLbusZy0svevu6Hjx+eH0ePC
+rj1xmDECgYEA4WR+1m3Tej0botG68+pZ8yLBgomSBAqpINCFkMEGQ2sQ1CqMMkHq
+8LAQNotU56W/0/H3eQemE3qBSKt1BUffpCvCHWkL9DRyDNhiq9U2PvV2Lx0Bv77e
+ET5MSDECUjlIsDqnv2qbq/m23BiP7AM8c9s6HjD0PqptyHjLlWHK86kCgYEA35hW
+AZEqMzsTNVQ8lXQtbqCyv8lls1SJbvIf3b5KItw9CwqpLr+UXssXh713j+yMW+WN
+3nv5+VaggkNBa9fHdqQEYT0L52OnLNjsfTlVhP5g2lOIa5VQYb/wqF1TaiZ27SGU
+lmLqiyArZgTnc3yo1wuIRPAbYbbm6CVnz7bm5jsCgYEAqfov7WZF5hnPjaq9YtWJ
+oGLFrLwy8flYMvcOw2vOXWmQ93Be6kfr9jfRAlFxZoEJeb0w9IVgKbBpb3Ree+0I
+K7cUXTmrWi9zE1zcjNnuXuyehElL2F8I+dgRjx/msDujJcQWXbT4UWmxDas4XrTS
+Ek1yNvKUP+4nfNgcMDvf4oECgYEAjgfYajpqEgzukKunqFAaI/HUWdt2zMlgW6dV
+8qdTtH0uEXt+KIHtn6FmmwURk8zxA9b3nWInUeljIBvUzMpOm+BoH9SFYUB+CxDo
+eEsZNdfYchcpyx0X6F/iYTCXMhCo7syr9DN1RVbz+mQXGdcP8ToUH6Zd3l4uozxP
+izRly80CgYEAqz7fCgQH74BwHoroSNdD3Cn6KNVx+oPuwRmzO4xMSOGyd/dNB2NA
+uzzuCTbrzC0jCXpqR0Bh9gYMjxyRZbifPX/YuFHyCIKK4+SQfeC4ZEwmSJVGWeh7
+3NksFJPCH4K3KbLNputByWJWOgKUdy70e/xOi83acBAVyRs+7H9LocE=
+-----END RSA PRIVATE KEY-----
diff --git a/libs/binder/tests/unit_fuzzers/Android.bp b/libs/binder/tests/unit_fuzzers/Android.bp
index 6f054d2..8ea948c 100644
--- a/libs/binder/tests/unit_fuzzers/Android.bp
+++ b/libs/binder/tests/unit_fuzzers/Android.bp
@@ -30,16 +30,28 @@
"-Wall",
"-Werror",
],
- shared_libs: [
- "libbinder",
- "libutils",
- "libbase",
- ],
target: {
+ android: {
+ shared_libs: [
+ "libcutils",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
+ host: {
+ static_libs: [
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libbase",
+ "libbinder",
+ ],
+ },
darwin: {
enabled: false,
- }
- }
+ },
+ },
}
cc_fuzz {