diff options
author | Yifan Hong <elsk@google.com> | 2019-03-15 14:19:08 -0700 |
---|---|---|
committer | Yifan Hong <elsk@google.com> | 2019-03-20 16:28:06 -0700 |
commit | b84fb57317c99f56e77dd21d80d230a3d5aefe9b (patch) | |
tree | d762d8b9e8ae566079eca9fc71e9ab41014bc21c /partition_tools | |
parent | b48d79fa91f888fbd3fd63465f9d28b682cd74c3 (diff) | |
download | extras-b84fb57317c99f56e77dd21d80d230a3d5aefe9b.tar.gz |
Make lpdump possible without root.
Test: adb unroot && adb shell lpdump
Bug: 126233777
Change-Id: Ie559072fe53fee43d7c4a9e8f97a89d979e5b9bc
Diffstat (limited to 'partition_tools')
-rw-r--r-- | partition_tools/Android.bp | 57 | ||||
-rw-r--r-- | partition_tools/aidl/Android.bp | 30 | ||||
-rw-r--r-- | partition_tools/aidl/android/lpdump/ILpdump.aidl | 4 | ||||
-rw-r--r-- | partition_tools/lpdump.cc | 39 | ||||
-rw-r--r-- | partition_tools/lpdump_host.cc | 21 | ||||
-rw-r--r-- | partition_tools/lpdump_target.cc | 84 | ||||
-rw-r--r-- | partition_tools/lpdumpd.cc | 75 | ||||
-rw-r--r-- | partition_tools/lpdumpd.rc | 35 |
8 files changed, 336 insertions, 9 deletions
diff --git a/partition_tools/Android.bp b/partition_tools/Android.bp index 4a1bb272..2b9e37fd 100644 --- a/partition_tools/Android.bp +++ b/partition_tools/Android.bp @@ -27,8 +27,8 @@ cc_defaults { }, } -cc_binary { - name: "lpdump", +cc_library_shared { + name: "liblpdump", defaults: ["lp_defaults"], host_supported: true, shared_libs: [ @@ -42,6 +42,7 @@ cc_binary { target: { android: { shared_libs: [ + "libcutils", "libfs_mgr", ], }, @@ -49,6 +50,40 @@ cc_binary { } cc_binary { + name: "lpdump", + defaults: ["lp_defaults"], + host_supported: true, + shared_libs: [ + "libbase", + "liblog", + "liblp", + ], + target: { + android: { + srcs: [ + "lpdump_target.cc", + ], + shared_libs: [ + "liblpdump_interface-cpp", + "libbinder", + "libutils", + ], + required: [ + "lpdumpd", + ], + }, + host: { + srcs: [ + "lpdump_host.cc", + ], + shared_libs: [ + "liblpdump", + ], + }, + }, +} + +cc_binary { name: "lpmake", defaults: ["lp_defaults"], host_supported: true, @@ -75,3 +110,21 @@ cc_binary { "lpflash.cc", ], } + +cc_binary { + name: "lpdumpd", + defaults: ["lp_defaults"], + init_rc: ["lpdumpd.rc"], + shared_libs: [ + "libbase", + "libbinder", + "liblog", + "liblp", + "liblpdump", + "liblpdump_interface-cpp", + "libutils", + ], + srcs: [ + "lpdumpd.cc", + ], +} diff --git a/partition_tools/aidl/Android.bp b/partition_tools/aidl/Android.bp new file mode 100644 index 00000000..60be072f --- /dev/null +++ b/partition_tools/aidl/Android.bp @@ -0,0 +1,30 @@ +// +// 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. +// + +aidl_interface { + name: "liblpdump_interface", + srcs: [ + "android/lpdump/ILpdump.aidl", + ], + backend: { + cpp: { + gen_log: true, + }, + ndk: { + enabled: false, + }, + }, +} diff --git a/partition_tools/aidl/android/lpdump/ILpdump.aidl b/partition_tools/aidl/android/lpdump/ILpdump.aidl new file mode 100644 index 00000000..e1343608 --- /dev/null +++ b/partition_tools/aidl/android/lpdump/ILpdump.aidl @@ -0,0 +1,4 @@ +package android.lpdump; +interface ILpdump { + @utf8InCpp String run(in @utf8InCpp String[] args); +} diff --git a/partition_tools/lpdump.cc b/partition_tools/lpdump.cc index 365b86cc..e3c6d393 100644 --- a/partition_tools/lpdump.cc +++ b/partition_tools/lpdump.cc @@ -28,6 +28,7 @@ #include <android-base/strings.h> #include <android-base/parseint.h> #ifdef __ANDROID__ +#include <cutils/android_get_control_file.h> #include <fs_mgr.h> #endif #include <liblp/liblp.h> @@ -77,14 +78,35 @@ static bool IsBlockDevice(const char* file) { return !stat(file, &s) && S_ISBLK(s.st_mode); } +// Reimplementation of fs_mgr_get_slot_suffix() without reading +// kernel commandline. +static std::string GetSlotSuffix() { + return base::GetProperty("ro.boot.slot_suffix", ""); +} + +// Reimplementation of fs_mgr_get_super_partition_name() without reading +// kernel commandline. Always return the super partition at current slot. +static std::string GetSuperPartionName() { + std::string super_partition = base::GetProperty("ro.boot.super_partition", ""); + if (super_partition.empty()) { + return LP_METADATA_DEFAULT_PARTITION_NAME; + } + return super_partition + GetSlotSuffix(); +} + class FileOrBlockDeviceOpener final : public PartitionOpener { public: android::base::unique_fd Open(const std::string& path, int flags) const override { // Try a local file first. - android::base::unique_fd fd(open(path.c_str(), flags)); - if (fd >= 0) { - return fd; - } + android::base::unique_fd fd; + +#ifdef __ANDROID__ + fd.reset(android_get_control_file(path.c_str())); + if (fd >= 0) return fd; +#endif + fd.reset(open(path.c_str(), flags)); + if (fd >= 0) return fd; + return PartitionOpener::Open(path, flags); } }; @@ -96,6 +118,9 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) { { nullptr, 0, nullptr, 0 }, }; + // Allow this function to be invoked by lpdumpd multiple times. + optind = 1; + int rv; int index; uint32_t slot = 0; @@ -122,8 +147,8 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) { } } else { #ifdef __ANDROID__ - auto slot_number = SlotNumberForSlotSuffix(fs_mgr_get_slot_suffix()); - pt = ReadMetadata(fs_mgr_get_super_partition_name(), slot_number); + auto slot_number = SlotNumberForSlotSuffix(GetSlotSuffix()); + pt = ReadMetadata(GetSuperPartionName(), slot_number); #else return usage(argc, argv, cerr); #endif @@ -190,6 +215,6 @@ int LpdumpMain(int argc, char* argv[], std::ostream& cout, std::ostream& cerr) { return EX_OK; } -int main(int argc, char* argv[]) { +int LpdumpMain(int argc, char* argv[]) { return LpdumpMain(argc, argv, std::cout, std::cerr); } diff --git a/partition_tools/lpdump_host.cc b/partition_tools/lpdump_host.cc new file mode 100644 index 00000000..7011a234 --- /dev/null +++ b/partition_tools/lpdump_host.cc @@ -0,0 +1,21 @@ +/* + * 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. + */ + +int LpdumpMain(int argc, char* argv[]); + +int main(int argc, char* argv[]) { + return LpdumpMain(argc, argv); +} diff --git a/partition_tools/lpdump_target.cc b/partition_tools/lpdump_target.cc new file mode 100644 index 00000000..e777602a --- /dev/null +++ b/partition_tools/lpdump_target.cc @@ -0,0 +1,84 @@ +/* + * 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-base/logging.h> +#include <android-base/properties.h> +#include <android/lpdump/ILpdump.h> +#include <binder/IServiceManager.h> +#include <iostream> +#include <string> +#include <vector> + +using namespace android; +using namespace std::chrono_literals; +using ::android::lpdump::ILpdump; + +int Run(ILpdump* service, const std::vector<std::string>& args) { + std::string output; + binder::Status status = service->run(args, &output); + if (status.isOk()) { + std::cout << output; + return 0; + } + std::cerr << status.exceptionMessage(); + if (status.serviceSpecificErrorCode() != 0) { + return status.serviceSpecificErrorCode(); + } + return -status.exceptionCode(); +} + +std::vector<std::string> GetArgVector(int argc, char* argv[]) { + std::vector<std::string> args; + args.reserve(argc); + for (int i = 0; i < argc; ++i) { + args.push_back(argv[i]); + } + return args; +} + +class LpdumpService { +public: + LpdumpService() { + base::SetProperty("sys.lpdumpd", "start"); + status_t status = getService(String16("lpdump_service"), &service_); + int wait_counter = 0; + while (status != OK && wait_counter++ < 3) { + sleep(1); + status = getService(String16("lpdump"), &service_); + } + if (status != OK || service_ == nullptr) { + std::cerr << "Cannot get lpdump service: " << strerror(-status) << std::endl; + LOG(ERROR) << "Cannot get lpdump service: " << strerror(-status); + } + } + ~LpdumpService() { + base::SetProperty("sys.lpdumpd", "stop"); + } + sp<ILpdump> get() { return service_; } +private: + sp<ILpdump> service_; +}; + +int main(int argc, char* argv[]) { + LpdumpService wrapper; + sp<ILpdump> service = wrapper.get(); + if (service == nullptr) { + return 1; + } + int ret = Run(service.get(), GetArgVector(argc, argv)); + base::SetProperty("sys.lpdumpd", "stop"); + return ret; +} diff --git a/partition_tools/lpdumpd.cc b/partition_tools/lpdumpd.cc new file mode 100644 index 00000000..83ec60ed --- /dev/null +++ b/partition_tools/lpdumpd.cc @@ -0,0 +1,75 @@ +/* + * 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 <limits> +#include <sstream> +#include <string> +#include <vector> + +#include <android-base/logging.h> +#include <android-base/strings.h> +#include <android/lpdump/BnLpdump.h> +#include <android/lpdump/ILpdump.h> +#include <binder/IPCThreadState.h> +#include <binder/IServiceManager.h> +#include <binder/ProcessState.h> + +int LpdumpMain(int argc, char* argv[], std::ostream&, std::ostream&); + +namespace android { +namespace lpdump { + +using binder::Status; + +class Lpdump : public BnLpdump { + public: + Lpdump() = default; + virtual ~Lpdump() = default; + + Status run(const std::vector<std::string>& args, std::string* aidl_return) override { + if (args.size() > std::numeric_limits<int>::max()) { + return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT); + } + std::vector<std::string> m_args = args; + char* argv[m_args.size()]; + for (size_t i = 0; i < m_args.size(); ++i) { + argv[i] = m_args[i].data(); + } + LOG(DEBUG) << "Dumping with args: " << base::Join(args, " "); + std::stringstream output; + int ret = LpdumpMain((int)m_args.size(), argv, output, output); + if (ret == 0) { + *aidl_return = output.str(); + return Status::ok(); + } else { + return Status::fromServiceSpecificError(ret, output.str().c_str()); + } + } +}; + +} // namespace lpdump +} // namespace android + +int main(int, char**) { + using namespace android; + + sp<lpdump::Lpdump> service = new lpdump::Lpdump(); + defaultServiceManager()->addService(String16("lpdump_service"), service); + LOG(VERBOSE) << "lpdumpd starting"; + ProcessState::self()->startThreadPool(); + IPCThreadState::self()->joinThreadPool(); + return 0; +} diff --git a/partition_tools/lpdumpd.rc b/partition_tools/lpdumpd.rc new file mode 100644 index 00000000..46ef5b35 --- /dev/null +++ b/partition_tools/lpdumpd.rc @@ -0,0 +1,35 @@ +# +# 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. +# + +service lpdumpd /system/bin/lpdumpd + # TODO(b/129011369): make this killable by lmkd + oneshot + disabled + user system + group system + # On Launch devices, assume "super". On virtual devices, ${ro.boot.super_partition} + # might be something else. + file /dev/block/by-name/${ro.boot.super_partition:-super} r + # On retrofit devices, ${ro.boot.super_partition} is slot-suffixed. + # Use NO_SUCH_DEVICE_NO_SUCH_SUFFIX as default values so that host_init_verifier does + # not complain about missing sysprops + file /dev/block/by-name/${ro.boot.super_partition:-NO_SUCH_DEVICE}${ro.boot.slot_suffix:-_NO_SUCH_SUFFIX} r + +on property:sys.lpdumpd=start + start lpdumpd + +on property:sys.lpdumpd=stop + stop lpdumpd |