From 975e303ad2e6fcd2184cbca9eb44d192fe7ea416 Mon Sep 17 00:00:00 2001
From: Dan Albert <danalbert@google.com>
Date: Tue, 19 Dec 2017 11:26:05 -0800
Subject: [PATCH] Restrict NDK link type to matching STLs.

Test: make native
Bug: None
Change-Id: Ie9d9107fe0eeb425843ae2db197e1c60d14a59ca
---
 core/allowed_ndk_types.mk         | 62 +++++++++++++++++++++++++++++++
 core/binary.mk                    | 12 +++---
 core/install_jni_libs_internal.mk |  9 +++--
 core/prebuilt_internal.mk         |  4 +-
 4 files changed, 77 insertions(+), 10 deletions(-)
 create mode 100644 core/allowed_ndk_types.mk

diff --git a/core/allowed_ndk_types.mk b/core/allowed_ndk_types.mk
new file mode 100644
index 000000000..fb6d43c20
--- /dev/null
+++ b/core/allowed_ndk_types.mk
@@ -0,0 +1,62 @@
+# Determines the types of NDK modules the current module is allowed to link to.
+# Input variables:
+#   LOCAL_MODULE
+#   LOCAL_MODULE_CLASS
+#   LOCAL_NDK_STL_VARIANT
+#   LOCAL_SDK_VERSION
+# Output variables:
+#   my_ndk_stl_family: Family of the NDK STL.
+#   my_allowed_ndk_types: Types of NDK modules that may be linked.
+#   my_warn_ndk_types: Types of NDK modules that shouldn't be linked, but are.
+
+my_allowed_ndk_types :=
+my_warn_ndk_types :=
+my_ndk_stl_family :=
+
+ifdef LOCAL_SDK_VERSION
+    ifeq ($(LOCAL_NDK_STL_VARIANT),)
+        my_ndk_stl_family := system
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),system)
+        my_ndk_stl_family := system
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),c++_shared)
+        my_ndk_stl_family := libc++
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),c++_static)
+        my_ndk_stl_family := libc++
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),gnustl_static)
+        my_ndk_stl_family := gnustl
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),stlport_shared)
+        my_ndk_stl_family := stlport
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),stlport_static)
+        my_ndk_stl_family := stlport
+    else ifeq ($(LOCAL_NDK_STL_VARIANT),none)
+        my_ndk_stl_family := none
+    else
+        $(call pretty-error,invalid LOCAL_NDK_STL_VARIANT: $(LOCAL_NDK_STL_VARIANT))
+    endif
+
+    # The system STL is only the C++ ABI layer, so it's compatible with any STL.
+    my_allowed_ndk_types += native:ndk:system
+
+    # Libaries that don't use the STL can be linked to anything.
+    my_allowed_ndk_types += native:ndk:none
+
+    # And it's okay to link your own STL type. Strictly speaking there are more
+    # restrictions depending on static vs shared STL, but that will be a follow
+    # up patch.
+    my_allowed_ndk_types += native:ndk:$(my_ndk_stl_family)
+
+    ifeq ($(LOCAL_MODULE_CLASS),APPS)
+        # For an app package, it's actually okay to depend on any set of STLs.
+        # If any of the individual libraries depend on each other they've
+        # already been checked for consistency, and if they don't they'll be
+        # kept isolated by RTLD_LOCAL anyway.
+        my_allowed_ndk_types += \
+            native:ndk:gnustl native:ndk:libc++ native:ndk:stlport
+    endif
+else
+    my_allowed_ndk_types := native:ndk:none native:ndk:system
+    ifeq ($(LOCAL_MODULE_CLASS),APPS)
+        # CTS is bad and it should feel bad: http://b/13249737
+        my_warn_ndk_types += native:ndk:libc++
+    endif
+endif
diff --git a/core/binary.mk b/core/binary.mk
index 92f995964..9e0697b69 100644
--- a/core/binary.mk
+++ b/core/binary.mk
@@ -1404,10 +1404,12 @@ endif
 ## other NDK-built libraries
 ####################################################
 
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
+
 ifdef LOCAL_SDK_VERSION
-my_link_type := native:ndk
-my_warn_types :=
-my_allowed_types := native:ndk
+my_link_type := native:ndk:$(my_ndk_stl_family)
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types)
 else ifdef LOCAL_USE_VNDK
     _name := $(patsubst %.vendor,%,$(LOCAL_MODULE))
     ifneq ($(filter $(_name),$(VNDK_CORE_LIBRARIES) $(VNDK_SAMEPROCESS_LIBRARIES) $(LLNDK_LIBRARIES)),)
@@ -1427,8 +1429,8 @@ else ifdef LOCAL_USE_VNDK
     endif
 else
 my_link_type := native:platform
-my_warn_types :=
-my_allowed_types := native:ndk native:platform
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types) native:platform
 endif
 
 my_link_deps := $(addprefix STATIC_LIBRARIES:,$(my_whole_static_libraries) $(my_static_libraries))
diff --git a/core/install_jni_libs_internal.mk b/core/install_jni_libs_internal.mk
index 265d48241..80e0c24d8 100644
--- a/core/install_jni_libs_internal.mk
+++ b/core/install_jni_libs_internal.mk
@@ -108,15 +108,16 @@ endif  # inner my_prebuilt_jni_libs
 endif  # outer my_prebuilt_jni_libs
 
 # Verify that all included libraries are built against the NDK
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
 ifneq ($(strip $(LOCAL_JNI_SHARED_LIBRARIES)),)
 ifneq ($(LOCAL_SDK_VERSION),)
 my_link_type := app:sdk
-my_warn_types := native:platform
-my_allowed_types := native:ndk
+my_warn_types := native:platform $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types)
 else
 my_link_type := app:platform
-my_warn_types :=
-my_allowed_types := native:ndk native:platform native:vendor native:vndk native:vndk_private
+my_warn_types := $(my_warn_ndk_types)
+my_allowed_types := $(my_allowed_ndk_types) native:platform native:vendor native:vndk native:vndk_private
 endif
 
 my_link_deps := $(addprefix SHARED_LIBRARIES:,$(LOCAL_JNI_SHARED_LIBRARIES))
diff --git a/core/prebuilt_internal.mk b/core/prebuilt_internal.mk
index 2a9ad1f0e..dbfa64a82 100644
--- a/core/prebuilt_internal.mk
+++ b/core/prebuilt_internal.mk
@@ -173,8 +173,10 @@ else
 endif
 export_cflags :=
 
+include $(BUILD_SYSTEM)/allowed_ndk_types.mk
+
 ifdef LOCAL_SDK_VERSION
-my_link_type := native:ndk
+my_link_type := native:ndk:$(my_ndk_stl_family)
 else ifdef LOCAL_USE_VNDK
     _name := $(patsubst %.vendor,%,$(LOCAL_MODULE))
     ifneq ($(filter $(_name),$(VNDK_CORE_LIBRARIES) $(VNDK_SAMEPROCESS_LIBRARIES) $(LLNDK_LIBRARIES)),)