libhidlbase: work w/ cfi

In a couple of places, in order to reduce templated code, HIDL relies on
auto-generated classes being exactly the same.

- one of these places, this reliance is unnecessary, so it's removed
- one of these places, explicitly documenting assumptions and turning
  off cfi

Fixes: 151006394
Test: hidl_test (w/ libhidlbase cfi on)
Test: atest MediaDrmClearkeyTest (no more cfi error)
Change-Id: I4834d38bcdaa2bb94e014f4c749251ee2025af15
diff --git a/transport/HidlBinderSupport.cpp b/transport/HidlBinderSupport.cpp
index 89b3a24..b48b460 100644
--- a/transport/HidlBinderSupport.cpp
+++ b/transport/HidlBinderSupport.cpp
@@ -19,6 +19,9 @@
 #include <hidl/HidlBinderSupport.h>
 
 #include <android/hidl/base/1.0/BpHwBase.h>
+#include <android/hidl/manager/1.0/BpHwServiceManager.h>
+#include <android/hidl/manager/1.1/BpHwServiceManager.h>
+#include <android/hidl/manager/1.2/BpHwServiceManager.h>
 #include <hwbinder/IPCThreadState.h>
 #include "InternalStatic.h"  // TODO(b/69122224): remove this include, for getOrCreateCachedBinder
 
@@ -206,16 +209,34 @@
     return status;
 }
 
+// assume: iface != nullptr, iface isRemote
+// This function is to sandbox a cast through a BpHw* class into a function, so
+// that we can remove cfi sanitization from it. Do not add additional
+// functionality here.
+__attribute__((no_sanitize("cfi"))) static inline BpHwRefBase* forceGetRefBase(
+        ::android::hidl::base::V1_0::IBase* ifacePtr) {
+    using ::android::hidl::base::V1_0::BpHwBase;
+
+    // canary only
+    static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_0::BpHwServiceManager));
+    static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_1::BpHwServiceManager));
+    static_assert(sizeof(BpHwBase) == sizeof(hidl::manager::V1_2::BpHwServiceManager));
+
+    // All BpHw* are generated the same. This may be BpHwServiceManager,
+    // BpHwFoo, or any other class. For ABI compatibility, we can't modify the
+    // class hierarchy of these, so we have no way to get BpHwRefBase from a
+    // remote ifacePtr.
+    BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
+    return static_cast<BpHwRefBase*>(bpBase);
+}
+
 sp<IBinder> getOrCreateCachedBinder(::android::hidl::base::V1_0::IBase* ifacePtr) {
     if (ifacePtr == nullptr) {
         return nullptr;
     }
 
     if (ifacePtr->isRemote()) {
-        using ::android::hidl::base::V1_0::BpHwBase;
-
-        BpHwBase* bpBase = static_cast<BpHwBase*>(ifacePtr);
-        BpHwRefBase* bpRefBase = static_cast<BpHwRefBase*>(bpBase);
+        BpHwRefBase* bpRefBase = forceGetRefBase(ifacePtr);
         return sp<IBinder>(bpRefBase->remote());
     }