From 011ee12b1def041d71621da7740bf5784a5e6488 Mon Sep 17 00:00:00 2001
From: Jiyong Park <jiyong@google.com>
Date: Tue, 29 May 2018 16:41:30 +0900
Subject: [PATCH] Shared libs are supported in recovery mode

adbd has been built as a static executable since the same binary was
copied to the recovery partition where shared library is not supported.
However, since we now support shared library in the recovery partition,
adbd is built as a dynamic executable.

In addition, the dependency from adbd to libdebuggerd_handler is removed
as debuggerd is handled by the dynamic linker.

A few more modules in /system/core are marked as recovery_available:
true as they are transitive dependencies of the dynamic linker.

This change also includes ld.config.recovery.txt which is the linker
config file for the recovery mode. It is installed to /etc/ld.config.txt
and contains linker namespace config for the dynamic binaries under
/sbin.

Bug: 63673171
Test: `adb reboot recovery; adb devices` shows the device ID
Test: Select 'mount /system' in the recovery mode, then `adb shell`.
$ lsof -p `pidof adbd` shows that libm.so, libc.so, etc. are loaded from
the /lib directory.

Change-Id: I363d5a787863f1677ee40afb5d5841321ddaae77
---
 CleanSpec.mk                       |  1 +
 adb/Android.bp                     |  4 +---
 adb/daemon/main.cpp                |  2 --
 adb/daemon/shell_service.cpp       | 19 +++++++++++++++++++
 debuggerd/Android.bp               |  9 ++++++++-
 libutils/Android.bp                |  5 +++++
 libutils/misc.cpp                  |  6 +++---
 libziparchive/Android.bp           |  1 +
 rootdir/Android.mk                 | 10 ++++++++++
 rootdir/etc/ld.config.recovery.txt |  9 +++++++++
 shell_and_utilities/Android.bp     |  3 +++
 toolbox/Android.bp                 |  1 +
 12 files changed, 61 insertions(+), 9 deletions(-)
 create mode 100644 rootdir/etc/ld.config.recovery.txt

diff --git a/CleanSpec.mk b/CleanSpec.mk
index e6f8716523..0e43dae31d 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -77,3 +77,4 @@ $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vndksp.libraries.txt)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/ld.config.txt)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/llndk.libraries.txt)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/vndksp.libraries.txt)
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/recovery/root/)
diff --git a/adb/Android.bp b/adb/Android.bp
index 553473f19f..53bf7e34a0 100644
--- a/adb/Android.bp
+++ b/adb/Android.bp
@@ -302,8 +302,6 @@ cc_binary {
     name: "adbd",
     defaults: ["adb_defaults"],
 
-    // adbd must be static, as it is copied into the recovery image.
-    static_executable: true,
     recovery_available: true,
 
     srcs: [
@@ -344,7 +342,6 @@ cc_binary {
         "libselinux",
         "libsquashfs_utils",
         "libqemu_pipe",
-        "libdebuggerd_handler",
 
         "libbase",
         "libcutils",
@@ -371,6 +368,7 @@ cc_test {
         "liblog",
         "libusb",
         "libmdnssd",
+        "libselinux",
     ],
     test_suites: ["device-tests"],
 }
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 232d9c5fd2..c02cafab7f 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -38,7 +38,6 @@
 #include <scoped_minijail.h>
 
 #include <private/android_filesystem_config.h>
-#include "debuggerd/handler.h"
 #include "selinux/android.h"
 
 #include "adb.h"
@@ -274,7 +273,6 @@ int main(int argc, char** argv) {
 
     close_stdin();
 
-    debuggerd_init(nullptr);
     adb_trace_init(argv);
 
     D("Handling main()");
diff --git a/adb/daemon/shell_service.cpp b/adb/daemon/shell_service.cpp
index 401c99c543..56d647a7b5 100644
--- a/adb/daemon/shell_service.cpp
+++ b/adb/daemon/shell_service.cpp
@@ -98,6 +98,7 @@
 #include <android-base/properties.h>
 #include <android-base/stringprintf.h>
 #include <private/android_logger.h>
+#include <selinux/android.h>
 
 #include "adb.h"
 #include "adb_io.h"
@@ -343,6 +344,24 @@ bool Subprocess::ForkAndExec(std::string* error) {
                 adb_write(oom_score_adj_fd, oom_score_adj_value, strlen(oom_score_adj_value)));
         }
 
+#ifdef __ANDROID_RECOVERY__
+        // Special routine for recovery. Switch to shell domain when adbd is
+        // is running with dropped privileged (i.e. not running as root) and
+        // is built for the recovery mode. This is required because recovery
+        // rootfs is not labeled and everything is labeled just as rootfs.
+        char* con = nullptr;
+        if (getcon(&con) == 0) {
+            if (!strcmp(con, "u:r:adbd:s0")) {
+                if (selinux_android_setcon("u:r:shell:s0") < 0) {
+                    LOG(FATAL) << "Could not set SELinux context for subprocess";
+                }
+            }
+            freecon(con);
+        } else {
+            LOG(FATAL) << "Failed to get SELinux context";
+        }
+#endif
+
         if (command_.empty()) {
             // Spawn a login shell if we don't have a command.
             execle(_PATH_BSHELL, "-" _PATH_BSHELL, nullptr, cenv.data());
diff --git a/debuggerd/Android.bp b/debuggerd/Android.bp
index 0b13662097..1b20157b32 100644
--- a/debuggerd/Android.bp
+++ b/debuggerd/Android.bp
@@ -47,6 +47,7 @@ cc_library_shared {
 cc_library_static {
     name: "libtombstoned_client_static",
     defaults: ["debuggerd_defaults"],
+    recovery_available: true,
     srcs: [
         "tombstoned/tombstoned_client.cpp",
         "util.cpp",
@@ -90,7 +91,6 @@ cc_library_static {
 cc_library_static {
     name: "libdebuggerd_handler",
     defaults: ["debuggerd_defaults"],
-    recovery_available: true,
     srcs: ["handler/debuggerd_fallback_nop.cpp"],
 
     whole_static_libs: [
@@ -104,6 +104,7 @@ cc_library_static {
 cc_library_static {
     name: "libdebuggerd_handler_fallback",
     defaults: ["debuggerd_defaults"],
+    recovery_available: true,
     srcs: [
         "handler/debuggerd_fallback.cpp",
     ],
@@ -120,6 +121,12 @@ cc_library_static {
         "liblzma",
         "libcutils",
     ],
+    target: {
+        recovery: {
+            cflags: ["-DNO_LIBDEXFILE_SUPPORT"],
+            exclude_static_libs: ["libdexfile"],
+        },
+    },
 
     export_include_dirs: ["include"],
 }
diff --git a/libutils/Android.bp b/libutils/Android.bp
index 9395ef807e..bbfa9d8570 100644
--- a/libutils/Android.bp
+++ b/libutils/Android.bp
@@ -47,6 +47,7 @@ cc_library_headers {
 cc_defaults {
     name: "libutils_defaults",
     vendor_available: true,
+    recovery_available: true,
     vndk: {
         enabled: true,
         support_system_process: true,
@@ -90,6 +91,10 @@ cc_defaults {
             },
         },
 
+        recovery: {
+            exclude_shared_libs: ["libvndksupport"],
+        },
+
         host: {
             cflags: ["-DLIBUTILS_NATIVE=1"],
 
diff --git a/libutils/misc.cpp b/libutils/misc.cpp
index da28dfae64..f07434187f 100644
--- a/libutils/misc.cpp
+++ b/libutils/misc.cpp
@@ -23,7 +23,7 @@
 #include <utils/Log.h>
 #include <utils/Vector.h>
 
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
 #include <dlfcn.h>
 #include <vndksupport/linker.h>
 #endif
@@ -70,7 +70,7 @@ void add_sysprop_change_callback(sysprop_change_callback cb, int priority) {
 void add_sysprop_change_callback(sysprop_change_callback, int) {}
 #endif
 
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
 void (*get_report_sysprop_change_func())() {
     void (*func)() = nullptr;
     void* handle = android_load_sphal_library("libutils.so", RTLD_NOW);
@@ -85,7 +85,7 @@ void (*get_report_sysprop_change_func())() {
 void report_sysprop_change() {
     do_report_sysprop_change();
 
-#if defined(__ANDROID__)
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
     // libutils.so is double loaded; from the default namespace and from the
     // 'sphal' namespace. Redirect the sysprop change event to the other instance
     // of libutils.so loaded in the 'sphal' namespace so that listeners attached
diff --git a/libziparchive/Android.bp b/libziparchive/Android.bp
index 6c0661822c..2606aa9e38 100644
--- a/libziparchive/Android.bp
+++ b/libziparchive/Android.bp
@@ -58,6 +58,7 @@ cc_library {
     name: "libziparchive",
     host_supported: true,
     vendor_available: true,
+    recovery_available: true,
     vndk: {
         enabled: true,
     },
diff --git a/rootdir/Android.mk b/rootdir/Android.mk
index 3c9e5f3c57..70b6a3e2c7 100644
--- a/rootdir/Android.mk
+++ b/rootdir/Android.mk
@@ -305,6 +305,16 @@ endif  # ifeq ($(_enforce_vndk_lite_at_runtime),false)
 _enforce_vndk_at_runtime :=
 _enforce_vndk_lite_at_runtime :=
 
+#######################################
+# ld.config.txt for recovery
+include $(CLEAR_VARS)
+LOCAL_MODULE := ld.config.recovery.txt
+LOCAL_MODULE_CLASS := ETC
+LOCAL_SRC_FILES := etc/ld.config.recovery.txt
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)/etc
+LOCAL_MODULE_STEM := ld.config.txt
+include $(BUILD_PREBUILT)
+
 #######################################
 # llndk.libraries.txt
 include $(CLEAR_VARS)
diff --git a/rootdir/etc/ld.config.recovery.txt b/rootdir/etc/ld.config.recovery.txt
new file mode 100644
index 0000000000..5d6c01a857
--- /dev/null
+++ b/rootdir/etc/ld.config.recovery.txt
@@ -0,0 +1,9 @@
+# Copyright (C) 2018 The Android Open Source Project
+#
+# Bionic loader config file for recovery mode
+#
+
+dir.recovery = /system/bin
+
+[recovery]
+namespace.default.search.paths = /system/${LIB}
diff --git a/shell_and_utilities/Android.bp b/shell_and_utilities/Android.bp
index 2e42b70993..6438e3d5e1 100644
--- a/shell_and_utilities/Android.bp
+++ b/shell_and_utilities/Android.bp
@@ -12,10 +12,13 @@ phony {
         "mkshrc_vendor",
         "reboot",
         "sh",
+        "sh.recovery",
         "sh_vendor",
         "toolbox",
+        "toolbox.recovery",
         "toolbox_vendor",
         "toybox",
+        "toybox.recovery",
         "toybox_vendor",
     ],
 }
diff --git a/toolbox/Android.bp b/toolbox/Android.bp
index 077f5423d6..f12c810cd6 100644
--- a/toolbox/Android.bp
+++ b/toolbox/Android.bp
@@ -46,6 +46,7 @@ cc_defaults {
 cc_binary {
     name: "toolbox",
     defaults: ["toolbox_binary_defaults"],
+    recovery_available: true,
 }
 
 cc_binary {
-- 
GitLab