Skip to content

Commit fabd16c

Browse files
committed
[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
1 parent 49f55b0 commit fabd16c

File tree

5 files changed

+155
-6
lines changed

5 files changed

+155
-6
lines changed

lldb/source/Plugins/Platform/Android/CMakeLists.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
lldb_tablegen(PlatformAndroidProperties.inc -gen-lldb-property-defs
2+
SOURCE PlatformAndroidProperties.td
3+
TARGET LLDBPluginPlatformAndroidPropertiesGen)
4+
5+
lldb_tablegen(PlatformAndroidPropertiesEnum.inc -gen-lldb-property-enum-defs
6+
SOURCE PlatformAndroidProperties.td
7+
TARGET LLDBPluginPlatformAndroidPropertiesEnumGen)
8+
19
add_lldb_library(lldbPluginPlatformAndroid PLUGIN
210
AdbClient.cpp
311
PlatformAndroid.cpp
@@ -11,3 +19,7 @@ add_lldb_library(lldbPluginPlatformAndroid PLUGIN
1119
LINK_COMPONENTS
1220
Support
1321
)
22+
23+
add_dependencies(lldbPluginPlatformAndroid
24+
LLDBPluginPlatformAndroidPropertiesGen
25+
LLDBPluginPlatformAndroidPropertiesEnumGen)

lldb/source/Plugins/Platform/Android/PlatformAndroid.cpp

Lines changed: 64 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,36 @@ using namespace std::chrono;
2929

3030
LLDB_PLUGIN_DEFINE(PlatformAndroid)
3131

32-
static uint32_t g_initialize_count = 0;
33-
static const unsigned int g_android_default_cache_size =
32+
namespace {
33+
34+
#define LLDB_PROPERTIES_android
35+
#include "PlatformAndroidProperties.inc"
36+
37+
enum {
38+
#define LLDB_PROPERTIES_android
39+
#include "PlatformAndroidPropertiesEnum.inc"
40+
};
41+
42+
class PluginProperties : public Properties {
43+
public:
44+
PluginProperties() {
45+
m_collection_sp = std::make_shared<OptionValueProperties>(
46+
ConstString(PlatformAndroid::GetPluginNameStatic(false)));
47+
m_collection_sp->Initialize(g_android_properties);
48+
}
49+
};
50+
51+
static PluginProperties &GetGlobalProperties() {
52+
static PluginProperties g_settings;
53+
return g_settings;
54+
}
55+
56+
uint32_t g_initialize_count = 0;
57+
const unsigned int g_android_default_cache_size =
3458
2048; // Fits inside 4k adb packet.
3559

60+
} // end of anonymous namespace
61+
3662
void PlatformAndroid::Initialize() {
3763
PlatformLinux::Initialize();
3864

@@ -45,7 +71,7 @@ void PlatformAndroid::Initialize() {
4571
PluginManager::RegisterPlugin(
4672
PlatformAndroid::GetPluginNameStatic(false),
4773
PlatformAndroid::GetPluginDescriptionStatic(false),
48-
PlatformAndroid::CreateInstance);
74+
PlatformAndroid::CreateInstance, PlatformAndroid::DebuggerInitialize);
4975
}
5076
}
5177

@@ -128,6 +154,16 @@ PlatformSP PlatformAndroid::CreateInstance(bool force, const ArchSpec *arch) {
128154
return PlatformSP();
129155
}
130156

157+
void PlatformAndroid::DebuggerInitialize(Debugger &debugger) {
158+
if (!PluginManager::GetSettingForPlatformPlugin(
159+
debugger, ConstString(GetPluginNameStatic(false)))) {
160+
PluginManager::CreateSettingForPlatformPlugin(
161+
debugger, GetGlobalProperties().GetValueProperties(),
162+
"Properties for the Android platform plugin.",
163+
/*is_global_property=*/true);
164+
}
165+
}
166+
131167
PlatformAndroid::PlatformAndroid(bool is_host)
132168
: PlatformLinux(is_host), m_sdk_version(0) {}
133169

@@ -206,7 +242,8 @@ Status PlatformAndroid::GetFile(const FileSpec &source,
206242
return error;
207243

208244
char cmd[PATH_MAX];
209-
snprintf(cmd, sizeof(cmd), "cat '%s'", source_file.c_str());
245+
snprintf(cmd, sizeof(cmd), "%scat '%s'", GetRunAs().c_str(),
246+
source_file.c_str());
210247

211248
return adb->ShellToFile(cmd, minutes(1), destination);
212249
}
@@ -260,9 +297,9 @@ Status PlatformAndroid::DownloadModuleSlice(const FileSpec &src_file_spec,
260297
// Use 'shell dd' to download the file slice with the offset and size.
261298
char cmd[PATH_MAX];
262299
snprintf(cmd, sizeof(cmd),
263-
"dd if='%s' iflag=skip_bytes,count_bytes "
300+
"%sdd if='%s' iflag=skip_bytes,count_bytes "
264301
"skip=%" PRIu64 " count=%" PRIu64 " status=none",
265-
source_file.c_str(), src_offset, src_size);
302+
GetRunAs().c_str(), source_file.c_str(), src_offset, src_size);
266303

267304
return adb->ShellToFile(cmd, minutes(1), dst_file_spec);
268305
}
@@ -410,6 +447,27 @@ PlatformAndroid::AdbClientUP PlatformAndroid::GetAdbClient(Status &error) {
410447
return adb;
411448
}
412449

450+
llvm::StringRef PlatformAndroid::GetPropertyPackageName() {
451+
return GetGlobalProperties().GetPropertyAtIndexAs<llvm::StringRef>(
452+
ePropertyPlatformPackageName, "");
453+
}
454+
455+
std::string PlatformAndroid::GetRunAs() {
456+
llvm::StringRef run_as = GetPropertyPackageName();
457+
if (!run_as.empty()) {
458+
// When LLDB fails to pull file from a package directory due to security
459+
// constraint, user needs to set the package name to
460+
// 'platform.plugin.remote-android.package-name' property in order to run
461+
// shell commands as the package user using 'run-as' (e.g. to get file with
462+
// 'cat' and 'dd').
463+
// https://cs.android.com/android/platform/superproject/+/master:
464+
// system/core/run-as/run-as.cpp;l=39-61;
465+
// drc=4a77a84a55522a3b122f9c63ef0d0b8a6a131627
466+
return std::string("run-as '") + run_as.str() + "' ";
467+
}
468+
return run_as.str();
469+
}
470+
413471
AdbClient::SyncService *PlatformAndroid::GetSyncService(Status &error) {
414472
if (m_adb_sync_svc && m_adb_sync_svc->IsConnected())
415473
return m_adb_sync_svc.get();

lldb/source/Plugins/Platform/Android/PlatformAndroid.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ class PlatformAndroid : public platform_linux::PlatformLinux {
3030
// lldb_private::PluginInterface functions
3131
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);
3232

33+
static void DebuggerInitialize(lldb_private::Debugger &debugger);
34+
3335
static llvm::StringRef GetPluginNameStatic(bool is_host) {
3436
return is_host ? Platform::GetHostPlatformName() : "remote-android";
3537
}
@@ -73,6 +75,10 @@ class PlatformAndroid : public platform_linux::PlatformLinux {
7375
typedef std::unique_ptr<AdbClient> AdbClientUP;
7476
virtual AdbClientUP GetAdbClient(Status &error);
7577

78+
virtual llvm::StringRef GetPropertyPackageName();
79+
80+
std::string GetRunAs();
81+
7682
private:
7783
AdbClient::SyncService *GetSyncService(Status &error);
7884

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
include "../../../../include/lldb/Core/PropertiesBase.td"
2+
3+
let Definition = "android" in {
4+
def PlatformPackageName: Property<"package-name", "String">,
5+
Global,
6+
DefaultStringValue<"">,
7+
Desc<"Specify package name to run adb shell command with 'run-as' as the "
8+
"package user when necessary (e.g. to get file with 'cat' and 'dd').">;
9+
}

lldb/unittests/Platform/Android/PlatformAndroidTest.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class PlatformAndroidTest : public PlatformAndroid, public ::testing::Test {
4949
}
5050

5151
MOCK_METHOD1(GetAdbClient, AdbClientUP(Status &error));
52+
MOCK_METHOD0(GetPropertyPackageName, llvm::StringRef());
5253
};
5354

5455
} // namespace
@@ -112,6 +113,32 @@ TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFile) {
112113
.Success());
113114
}
114115

116+
TEST_F(PlatformAndroidTest, DownloadModuleSliceWithZipFileAndRunAs) {
117+
auto adb_client = new MockAdbClient();
118+
EXPECT_CALL(*adb_client,
119+
ShellToFile(StrEq("run-as 'com.example.test' "
120+
"dd if='/system/app/Test/Test.apk' "
121+
"iflag=skip_bytes,count_bytes "
122+
"skip=4096 count=3600 status=none"),
123+
_, _))
124+
.Times(1)
125+
.WillOnce(Return(Status()));
126+
127+
EXPECT_CALL(*this, GetPropertyPackageName())
128+
.Times(1)
129+
.WillOnce(Return(llvm::StringRef("com.example.test")));
130+
131+
EXPECT_CALL(*this, GetAdbClient(_))
132+
.Times(1)
133+
.WillOnce(Return(ByMove(AdbClientUP(adb_client))));
134+
135+
EXPECT_TRUE(
136+
DownloadModuleSlice(
137+
FileSpec("/system/app/Test/Test.apk!/lib/arm64-v8a/libtest.so"), 4096,
138+
3600, FileSpec())
139+
.Success());
140+
}
141+
115142
TEST_F(PlatformAndroidTest, GetFileWithNormalFile) {
116143
auto sync_service = new MockSyncService();
117144
EXPECT_CALL(*sync_service, Stat(FileSpec("/data/local/tmp/test"), _, _, _))
@@ -164,3 +191,40 @@ TEST_F(PlatformAndroidTest, GetFileWithCatFallback) {
164191
FileSpec())
165192
.Success());
166193
}
194+
195+
TEST_F(PlatformAndroidTest, GetFileWithCatFallbackAndRunAs) {
196+
auto sync_service = new MockSyncService();
197+
EXPECT_CALL(
198+
*sync_service,
199+
Stat(FileSpec("/data/data/com.example.app/lib-main/libtest.so"), _, _, _))
200+
.Times(1)
201+
.WillOnce(DoAll(SetArgReferee<1>(0), Return(Status())));
202+
203+
auto adb_client0 = new MockAdbClient();
204+
EXPECT_CALL(*adb_client0, GetSyncService(_))
205+
.Times(1)
206+
.WillOnce(Return(ByMove(SyncServiceUP(sync_service))));
207+
208+
auto adb_client1 = new MockAdbClient();
209+
EXPECT_CALL(
210+
*adb_client1,
211+
ShellToFile(StrEq("run-as 'com.example.app' "
212+
"cat '/data/data/com.example.app/lib-main/libtest.so'"),
213+
_, _))
214+
.Times(1)
215+
.WillOnce(Return(Status()));
216+
217+
EXPECT_CALL(*this, GetPropertyPackageName())
218+
.Times(1)
219+
.WillOnce(Return(llvm::StringRef("com.example.app")));
220+
221+
EXPECT_CALL(*this, GetAdbClient(_))
222+
.Times(2)
223+
.WillOnce(Return(ByMove(AdbClientUP(adb_client0))))
224+
.WillOnce(Return(ByMove(AdbClientUP(adb_client1))));
225+
226+
EXPECT_TRUE(
227+
GetFile(FileSpec("/data/data/com.example.app/lib-main/libtest.so"),
228+
FileSpec())
229+
.Success());
230+
}

0 commit comments

Comments
 (0)