[Lldb-commits] [lldb] fabd16c - [lldb][Android] Add platform.plugin.remote-android.package-name

Kazuki Sakamoto via lldb-commits lldb-commits at lists.llvm.org
Tue Jun 20 16:39:06 PDT 2023


Author: Kazuki Sakamoto
Date: 2023-06-20T16:17:21-07:00
New Revision: fabd16c7460e6cfae3106155ec79142bfa54db2e

URL: https://github.com/llvm/llvm-project/commit/fabd16c7460e6cfae3106155ec79142bfa54db2e
DIFF: https://github.com/llvm/llvm-project/commit/fabd16c7460e6cfae3106155ec79142bfa54db2e.diff

LOG: [lldb][Android] Add platform.plugin.remote-android.package-name

When LLDB fails to pull file from a package directory due to security
constraint, user needs to set the package name to
'platform.plugin.remote-android.package-name' property to run shell commands
as the package user. (e.g. to get file with 'cat' and 'dd').

https://cs.android.com/android/platform/superproject/+/master:
system/core/run-as/run-as.cpp;l=39-61;
drc=4a77a84a55522a3b122f9c63ef0d0b8a6a131627

Differential Revision: https://reviews.llvm.org/D152933

Added: 
    lldb/source/Plugins/Platform/Android/PlatformAndroidProperties.td

Modified: 
    lldb/source/Plugins/Platform/Android/CMakeLists.txt
    lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
    lldb/source/Plugins/Platform/Android/PlatformAndroid.h
    lldb/unittests/Platform/Android/PlatformAndroidTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Platform/Android/CMakeLists.txt b/lldb/source/Plugins/Platform/Android/CMakeLists.txt
index 5abb51a0b94ac..518041b6cb316 100644
--- a/lldb/source/Plugins/Platform/Android/CMakeLists.txt
+++ b/lldb/source/Plugins/Platform/Android/CMakeLists.txt
@@ -1,3 +1,11 @@
+lldb_tablegen(PlatformAndroidProperties.inc -gen-lldb-property-defs
+  SOURCE PlatformAndroidProperties.td
+  TARGET LLDBPluginPlatformAndroidPropertiesGen)
+
+lldb_tablegen(PlatformAndroidPropertiesEnum.inc -gen-lldb-property-enum-defs
+  SOURCE PlatformAndroidProperties.td
+  TARGET LLDBPluginPlatformAndroidPropertiesEnumGen)
+
 add_lldb_library(lldbPluginPlatformAndroid PLUGIN
   AdbClient.cpp
   PlatformAndroid.cpp
@@ -11,3 +19,7 @@ add_lldb_library(lldbPluginPlatformAndroid PLUGIN
   LINK_COMPONENTS
     Support
   )
+
+add_dependencies(lldbPluginPlatformAndroid
+  LLDBPluginPlatformAndroidPropertiesGen
+  LLDBPluginPlatformAndroidPropertiesEnumGen)

diff  --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
index 36ca784d5ebf1..a1d2924203f13 100644
--- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp
@@ -29,10 +29,36 @@ using namespace std::chrono;
 
 LLDB_PLUGIN_DEFINE(PlatformAndroid)
 
-static uint32_t g_initialize_count = 0;
-static const unsigned int g_android_default_cache_size =
+namespace {
+
+#define LLDB_PROPERTIES_android
+#include "PlatformAndroidProperties.inc"
+
+enum {
+#define LLDB_PROPERTIES_android
+#include "PlatformAndroidPropertiesEnum.inc"
+};
+
+class PluginProperties : public Properties {
+public:
+  PluginProperties() {
+    m_collection_sp = std::make_shared<OptionValueProperties>(
+        ConstString(PlatformAndroid::GetPluginNameStatic(false)));
+    m_collection_sp->Initialize(g_android_properties);
+  }
+};
+
+static PluginProperties &GetGlobalProperties() {
+  static PluginProperties g_settings;
+  return g_settings;
+}
+
+uint32_t g_initialize_count = 0;
+const unsigned int g_android_default_cache_size =
     2048; // Fits inside 4k adb packet.
 
+} // end of anonymous namespace
+
 void PlatformAndroid::Initialize() {
   PlatformLinux::Initialize();
 
@@ -45,7 +71,7 @@ void PlatformAndroid::Initialize() {
     PluginManager::RegisterPlugin(
         PlatformAndroid::GetPluginNameStatic(false),
         PlatformAndroid::GetPluginDescriptionStatic(false),
-        PlatformAndroid::CreateInstance);
+        PlatformAndroid::CreateInstance, PlatformAndroid::DebuggerInitialize);
   }
 }
 
@@ -128,6 +154,16 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
   return PlatformSP();
 }
 
+void PlatformAndroid::DebuggerInitialize(Debugger &debugger) {
+  if (!PluginManager::GetSettingForPlatformPlugin(
+          debugger, ConstString(GetPluginNameStatic(false)))) {
+    PluginManager::CreateSettingForPlatformPlugin(
+        debugger, GetGlobalProperties().GetValueProperties(),
+        "Properties for the Android platform plugin.",
+        /*is_global_property=*/true);
+  }
+}
+
 PlatformAndroid::PlatformAndroid(bool is_host)
     : PlatformLinux(is_host), m_sdk_version(0) {}
 
@@ -206,7 +242,8 @@ Status PlatformAndroid::GetFile(const FileSpec &source,
     return error;
 
   char cmd[PATH_MAX];
-  snprintf(cmd, sizeof(cmd), "cat '%s'", source_file.c_str());
+  snprintf(cmd, sizeof(cmd), "%scat '%s'", GetRunAs().c_str(),
+           source_file.c_str());
 
   return adb->ShellToFile(cmd, minutes(1), destination);
 }
@@ -260,9 +297,9 @@ Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec,
   // Use 'shell dd' to download the file slice with the offset and size.
   char cmd[PATH_MAX];
   snprintf(cmd, sizeof(cmd),
-           "dd if='%s' iflag=skip_bytes,count_bytes "
+           "%sdd if='%s' iflag=skip_bytes,count_bytes "
            "skip=%" PRIu64 " count=%" PRIu64 " status=none",
-           source_file.c_str(), src_offset, src_size);
+           GetRunAs().c_str(), source_file.c_str(), src_offset, src_size);
 
   return adb->ShellToFile(cmd, minutes(1), dst_file_spec);
 }
@@ -410,6 +447,27 @@ PlatformAndroid::AdbClientUP PlatformAndroid::GetAdbClient(Status &error) {
   return adb;
 }
 
+llvm::StringRef PlatformAndroid::GetPropertyPackageName() {
+  return GetGlobalProperties().GetPropertyAtIndexAs<llvm::StringRef>(
+      ePropertyPlatformPackageName, "");
+}
+
+std::string PlatformAndroid::GetRunAs() {
+  llvm::StringRef run_as = GetPropertyPackageName();
+  if (!run_as.empty()) {
+    // When LLDB fails to pull file from a package directory due to security
+    // constraint, user needs to set the package name to
+    // 'platform.plugin.remote-android.package-name' property in order to run
+    // shell commands as the package user using 'run-as' (e.g. to get file with
+    // 'cat' and 'dd').
+    // https://cs.android.com/android/platform/superproject/+/master:
+    // system/core/run-as/run-as.cpp;l=39-61;
+    // drc=4a77a84a55522a3b122f9c63ef0d0b8a6a131627
+    return std::string("run-as '") + run_as.str() + "' ";
+  }
+  return run_as.str();
+}
+
 AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) {
   if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
     return m_adb_sync_svc.get();

diff  --git a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h
index 2da3a985c70c3..5602edf73c1d3 100644
--- a/lldb/source/Plugins/Platform/Android/PlatformAndroid.h
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroid.h
@@ -30,6 +30,8 @@ class PlatformAndroid : public platform_linux::PlatformLinux {
   // lldb_private::PluginInterface functions
   static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
 
+  static void DebuggerInitialize(lldb_private::Debugger &debugger);
+
   static llvm::StringRef GetPluginNameStatic(bool is_host) {
     return is_host ? Platform::GetHostPlatformName() : "remote-android";
   }
@@ -73,6 +75,10 @@ class PlatformAndroid : public platform_linux::PlatformLinux {
   typedef std::unique_ptr<AdbClient> AdbClientUP;
   virtual AdbClientUP GetAdbClient(Status &error);
 
+  virtual llvm::StringRef GetPropertyPackageName();
+
+  std::string GetRunAs();
+
 private:
   AdbClient::SyncService *GetSyncService(Status &error);
 

diff  --git a/lldb/source/Plugins/Platform/Android/PlatformAndroidProperties.td b/lldb/source/Plugins/Platform/Android/PlatformAndroidProperties.td
new file mode 100644
index 0000000000000..bf1bc7b3cef02
--- /dev/null
+++ b/lldb/source/Plugins/Platform/Android/PlatformAndroidProperties.td
@@ -0,0 +1,9 @@
+include "../../../../include/lldb/Core/PropertiesBase.td"
+
+let Definition = "android" in {
+  def PlatformPackageName: Property<"package-name", "String">,
+    Global,
+    DefaultStringValue<"">,
+    Desc<"Specify package name to run adb shell command with 'run-as' as the "
+         "package user when necessary (e.g. to get file with 'cat' and 'dd').">;
+}

diff  --git a/lldb/unittests/Platform/Android/PlatformAndroidTest.cpp b/lldb/unittests/Platform/Android/PlatformAndroidTest.cpp
index 1d548c5e59c0e..a878da773714d 100644
--- a/lldb/unittests/Platform/Android/PlatformAndroidTest.cpp
+++ b/lldb/unittests/Platform/Android/PlatformAndroidTest.cpp
@@ -49,6 +49,7 @@ class PlatformAndroidTest : public PlatformAndroid, public ::testing::Test {
   }
 
   MOCK_METHOD1(GetAdbClient, AdbClientUP(Status &error));
+  MOCK_METHOD0(GetPropertyPackageName, llvm::StringRef());
 };
 
 } // namespace
@@ -112,6 +113,32 @@ TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFile) {
           .Success());
 }
 
+TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFileAndRunAs) {
+  auto adb_client = new MockAdbClient();
+  EXPECT_CALL(*adb_client,
+              ShellToFile(StrEq("run-as 'com.example.test' "
+                                "dd if='/system/app/Test/Test.apk' "
+                                "iflag=skip_bytes,count_bytes "
+                                "skip=4096 count=3600 status=none"),
+                          _, _))
+      .Times(1)
+      .WillOnce(Return(Status()));
+
+  EXPECT_CALL(*this, GetPropertyPackageName())
+      .Times(1)
+      .WillOnce(Return(llvm::StringRef("com.example.test")));
+
+  EXPECT_CALL(*this, GetAdbClient(_))
+      .Times(1)
+      .WillOnce(Return(ByMove(AdbClientUP(adb_client))));
+
+  EXPECT_TRUE(
+      DownloadModuleSlice(
+          FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
+          3600, FileSpec())
+          .Success());
+}
+
 TEST_F(PlatformAndroidTest, GetFileWithNormalFile) {
   auto sync_service = new MockSyncService();
   EXPECT_CALL(*sync_service, Stat(FileSpec("/data/local/tmp/test"), _, _, _))
@@ -164,3 +191,40 @@ TEST_F(PlatformAndroidTest, GetFileWithCatFallback) {
               FileSpec())
           .Success());
 }
+
+TEST_F(PlatformAndroidTest, GetFileWithCatFallbackAndRunAs) {
+  auto sync_service = new MockSyncService();
+  EXPECT_CALL(
+      *sync_service,
+      Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
+      .Times(1)
+      .WillOnce(DoAll(SetArgReferee<1>(0), Return(Status())));
+
+  auto adb_client0 = new MockAdbClient();
+  EXPECT_CALL(*adb_client0, GetSyncService(_))
+      .Times(1)
+      .WillOnce(Return(ByMove(SyncServiceUP(sync_service))));
+
+  auto adb_client1 = new MockAdbClient();
+  EXPECT_CALL(
+      *adb_client1,
+      ShellToFile(StrEq("run-as 'com.example.app' "
+                        "cat '/data/data/com.example.app/lib-main/libtest.so'"),
+                  _, _))
+      .Times(1)
+      .WillOnce(Return(Status()));
+
+  EXPECT_CALL(*this, GetPropertyPackageName())
+      .Times(1)
+      .WillOnce(Return(llvm::StringRef("com.example.app")));
+
+  EXPECT_CALL(*this, GetAdbClient(_))
+      .Times(2)
+      .WillOnce(Return(ByMove(AdbClientUP(adb_client0))))
+      .WillOnce(Return(ByMove(AdbClientUP(adb_client1))));
+
+  EXPECT_TRUE(
+      GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
+              FileSpec())
+          .Success());
+}


        


More information about the lldb-commits mailing list