Add ADB root service changes

Co-authored-by: Alessandro Astone <ales.astone@gmail.com>
Co-authored-by: Bruno Martins <bgcngm@gmail.com>
Co-authored-by: dianlujitao <dianlujitao@lineageos.org>
Co-authored-by: Luca Stefani <luca.stefani.ge1@gmail.com>
Co-authored-by: LuK1337 <priv.luk@gmail.com>
Co-authored-by: nift4 <nift4@protonmail.com>
Change-Id: Ie8db34705d36f3e9f2c53617ec59a26087cbcc87
diff --git a/Android.bp b/Android.bp
index 7a7e491..c099e71 100644
--- a/Android.bp
+++ b/Android.bp
@@ -43,7 +43,6 @@
         "-Wall",
         "-Wextra",
         "-Werror",
-        "-Wexit-time-destructors",
         "-Wno-non-virtual-dtor",
         "-Wno-unused-parameter",
         "-Wno-missing-field-initializers",
@@ -696,11 +695,13 @@
                 "daemon/restart_service.cpp",
             ],
             shared_libs: [
+                "libbinder_ndk",
                 "libmdnssd",
                 "libselinux",
             ],
             static_libs: [
                 "android_trade_in_mode_flags_cc_lib",
+                "adbroot_aidl_interface-ndk",
             ],
         },
         recovery: {
@@ -708,11 +709,13 @@
                 "daemon/abb_service.cpp",
             ],
             exclude_shared_libs: [
+                "libbinder_ndk",
                 "libadb_pairing_auth",
                 "libadb_pairing_connection",
             ],
             exclude_static_libs: [
                 "android_trade_in_mode_flags_cc_lib",
+                "adbroot_aidl_interface-ndk",
             ],
         },
     },
@@ -835,8 +838,26 @@
     ],
     target: {
         android: {
+            shared_libs: [
+                "libbinder_ndk",
+            ],
+
             static_libs: [
                 "android_trade_in_mode_flags_cc_lib",
+                "adbroot_aidl_interface-ndk",
+            ],
+        },
+
+        recovery: {
+            exclude_shared_libs: [
+                "libadb_pairing_auth",
+                "libadb_pairing_connection",
+                "libbinder_ndk",
+            ],
+
+            exclude_static_libs: [
+                "android_trade_in_mode_flags_cc_lib",
+                "adbroot_aidl_interface-ndk",
             ],
         },
     },
@@ -879,6 +900,30 @@
 }
 
 cc_binary {
+    name: "adb_root",
+    srcs: [
+        "root/adbroot_service.cpp",
+        "root/main.cpp",
+    ],
+    init_rc: [
+        "root/adb_root.rc",
+    ],
+    shared_libs: [
+        "libbase",
+        "libbinder",
+        "libbinder_ndk",
+        "libcutils",
+        "liblog",
+        "libutils",
+        "packagemanager_aidl-cpp",
+    ],
+    static_libs: [
+        "adbroot_aidl_interface-ndk",
+    ],
+    system_ext_specific: true,
+}
+
+cc_binary {
     name: "abb",
 
     defaults: ["adbd_defaults"],
@@ -1117,3 +1162,34 @@
         "fastdeploy/testdata/sample.cd",
     ],
 }
+
+aidl_interface {
+    name: "adbroot_aidl_interface",
+    unstable: true,
+    local_include_dir: "aidl",
+    srcs: [
+        "aidl/android/adbroot/IADBRootService.aidl",
+    ],
+    backend: {
+        cpp: {
+            enabled: false,
+        },
+        java: {
+            enabled: false,
+        },
+        ndk: {
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.adbd",
+            ],
+            min_sdk_version: "30",
+        },
+    },
+}
+
+filegroup {
+    name: "adbrootservice_aidl",
+    srcs: [
+        "aidl/android/adbroot/IADBRootService.aidl",
+    ],
+}
diff --git a/aidl/android/adbroot/IADBRootService.aidl b/aidl/android/adbroot/IADBRootService.aidl
new file mode 100644
index 0000000..ada5ce8
--- /dev/null
+++ b/aidl/android/adbroot/IADBRootService.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+package android.adbroot;
+
+/** {@hide} */
+@PermissionManuallyEnforced
+interface IADBRootService {
+    boolean isSupported();
+    void setEnabled(boolean enabled);
+    boolean getEnabled();
+}
diff --git a/daemon/restart_service.cpp b/daemon/restart_service.cpp
index 16d2627..c942c1f 100644
--- a/daemon/restart_service.cpp
+++ b/daemon/restart_service.cpp
@@ -16,6 +16,11 @@
 
 #define TRACE_TAG SERVICES
 
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
+#include <aidl/android/adbroot/IADBRootService.h>
+#include <android/binder_manager.h>
+#endif
+
 #include "sysdeps.h"
 
 #include <unistd.h>
@@ -33,10 +38,33 @@
         WriteFdExactly(fd.get(), "adbd is already running as root\n");
         return;
     }
+
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
+    ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_getService("adbroot_service"));
+    std::shared_ptr<aidl::android::adbroot::IADBRootService> service =
+            aidl::android::adbroot::IADBRootService::fromBinder(binder);
+    if (!service) {
+        LOG(ERROR) << "Failed to get adbroot_service interface";
+        return;
+    }
+#endif
+
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
+    bool enabled = false;
+    if (auto status = service->getEnabled(&enabled); !status.isOk()) {
+#endif
     if (!__android_log_is_debuggable()) {
         WriteFdExactly(fd.get(), "adbd cannot run as root in production builds\n");
         return;
     }
+#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
+    }
+    if (!enabled) {
+        WriteFdExactly(fd, "ADB Root access is disabled by system setting - "
+                "enable in Settings -> System -> Developer options\n");
+        return;
+    }
+#endif
 
     LOG(INFO) << "adbd restarting as root";
     android::base::SetProperty("service.adb.root", "1");
diff --git a/root/adb_root.rc b/root/adb_root.rc
new file mode 100644
index 0000000..8c65c0b
--- /dev/null
+++ b/root/adb_root.rc
@@ -0,0 +1,7 @@
+service adb_root /system_ext/bin/adb_root
+    class main
+    user root
+    group root
+
+on post-fs-data
+    mkdir /data/adbroot 0700 root root
diff --git a/root/adbroot_service.cpp b/root/adbroot_service.cpp
new file mode 100644
index 0000000..ff30f4b
--- /dev/null
+++ b/root/adbroot_service.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 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.
+ */
+
+#include <android/binder_manager.h>
+#include <android/content/pm/IPackageManagerNative.h>
+#include <android-base/file.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/strings.h>
+#include <binder/IBinder.h>
+#include <binder/IServiceManager.h>
+#include <cutils/multiuser.h>
+#include <private/android_filesystem_config.h>
+
+#include "adbroot_service.h"
+
+namespace {
+const std::string kStoragePath = "/data/adbroot/";
+const std::string kEnabled = "enabled";
+
+static ndk::ScopedAStatus SecurityException(const std::string& msg) {
+    LOG(ERROR) << msg;
+    return ndk::ScopedAStatus(AStatus_fromExceptionCodeWithMessage(EX_SECURITY, msg.c_str()));
+}
+}  // anonymous namespace
+
+namespace android {
+static bool isAutomotive() {
+    sp<IServiceManager> serviceManager = defaultServiceManager();
+    if (serviceManager.get() == nullptr) {
+        LOG(ERROR) << "Unable to access native ServiceManager";
+        return false;
+    }
+
+    sp<content::pm::IPackageManagerNative> packageManager;
+    sp<IBinder> binder = serviceManager->waitForService(String16("package_native"));
+    packageManager = interface_cast<content::pm::IPackageManagerNative>(binder);
+    if (packageManager == nullptr) {
+        LOG(ERROR) << "Unable to access native PackageManager";
+        return false;
+    }
+
+    bool isAutomotive = false;
+    binder::Status status =
+        packageManager->hasSystemFeature(String16("android.hardware.type.automotive"), 0,
+                                         &isAutomotive);
+    if (!status.isOk()) {
+        LOG(ERROR) << "Calling hasSystemFeature failed: " << status.exceptionMessage().c_str();
+        return false;
+    }
+
+    return isAutomotive;
+}
+}  // namespace android
+
+namespace aidl {
+namespace android {
+namespace adbroot {
+
+using ::android::AutoMutex;
+using ::android::base::ReadFileToString;
+using ::android::base::SetProperty;
+using ::android::base::Trim;
+using ::android::base::WriteStringToFile;
+
+static inline bool isAutomotive(uid_t uid) {
+    appid_t appid = multiuser_get_app_id(uid);
+
+    return appid == AID_SYSTEM && ::android::isAutomotive();
+}
+
+ADBRootService::ADBRootService() : enabled_(false) {
+    std::string buf;
+    if (ReadFileToString(kStoragePath + kEnabled, &buf)) {
+        enabled_ = Trim(buf) == "1";
+    }
+}
+
+void ADBRootService::Register() {
+    auto service = ndk::SharedRefBase::make<ADBRootService>();
+    binder_status_t status = AServiceManager_addService(
+            service->asBinder().get(), getServiceName());
+
+    if (status != STATUS_OK) {
+        LOG(FATAL) << "Could not register adbroot service: " << status;
+    }
+}
+
+ndk::ScopedAStatus ADBRootService::isSupported(bool* _aidl_return) {
+    uid_t uid = AIBinder_getCallingUid();
+    if (uid != AID_SYSTEM && uid != AID_SHELL && !isAutomotive(uid)) {
+        return SecurityException("Caller must be system or shell");
+    }
+
+    AutoMutex _l(lock_);
+    *_aidl_return = __android_log_is_debuggable();
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ADBRootService::setEnabled(bool enabled) {
+    uid_t uid = AIBinder_getCallingUid();
+    if (uid != AID_SYSTEM && !isAutomotive(uid)) {
+        return SecurityException("Caller must be system");
+    }
+
+    AutoMutex _l(lock_);
+
+    if (enabled_ != enabled) {
+        enabled_ = enabled;
+        WriteStringToFile(std::to_string(enabled), kStoragePath + kEnabled);
+
+        // Turning off adb root, restart adbd.
+        if (!enabled) {
+            SetProperty("service.adb.root", "0");
+            SetProperty("ctl.restart", "adbd");
+        }
+    }
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus ADBRootService::getEnabled(bool* _aidl_return) {
+    uid_t uid = AIBinder_getCallingUid();
+    if (uid != AID_SYSTEM && uid != AID_SHELL && !isAutomotive(uid)) {
+        return SecurityException("Caller must be system or shell");
+    }
+
+    AutoMutex _l(lock_);
+    *_aidl_return = enabled_;
+    return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace adbroot
+}  // namespace android
+}  // namespace aidl
diff --git a/root/adbroot_service.h b/root/adbroot_service.h
new file mode 100644
index 0000000..9881542
--- /dev/null
+++ b/root/adbroot_service.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2019 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 <aidl/android/adbroot/BnADBRootService.h>
+#include <android/binder_status.h>
+#include <log/log_properties.h>
+#include <utils/Mutex.h>
+
+namespace aidl {
+namespace android {
+namespace adbroot {
+
+using ::android::Mutex;
+
+class ADBRootService : public BnADBRootService {
+  public:
+    ADBRootService();
+
+    static void Register();
+
+    ndk::ScopedAStatus isSupported(bool* _aidl_return) override;
+    ndk::ScopedAStatus setEnabled(bool enabled) override;
+    ndk::ScopedAStatus getEnabled(bool* _aidl_return) override;
+
+    static char const* getServiceName() { return "adbroot_service"; }
+  private:
+    bool enabled_;
+    Mutex lock_;
+};
+
+}  // namespace adbroot
+}  // namespace android
+}  // namespace aidl
diff --git a/root/main.cpp b/root/main.cpp
new file mode 100644
index 0000000..7de0945
--- /dev/null
+++ b/root/main.cpp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2019 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.
+//
+
+#include <android/binder_process.h>
+#include <android-base/logging.h>
+
+#include "adbroot_service.h"
+
+int main(int /* argc */, char** argv) {
+    android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
+
+    aidl::android::adbroot::ADBRootService::Register();
+
+    ABinderProcess_startThreadPool();
+    ABinderProcess_joinThreadPool();
+
+    return 0;
+}