diff --git a/Android.mk b/Android.mk index f1804b6..8cbc1d4 100644 --- a/Android.mk +++ b/Android.mk @@ -20,9 +20,9 @@ common_src_files := \ model/EmulatedVolume.cpp \ model/ObbVolume.cpp \ Utils.cpp \ - MoveTask.cpp \ - BenchmarkTask.cpp \ - TrimTask.cpp \ + MoveStorage.cpp \ + Benchmark.cpp \ + IdleMaint.cpp \ KeyBuffer.cpp \ Keymaster.cpp \ KeyStorage.cpp \ diff --git a/BenchmarkTask.cpp b/Benchmark.cpp similarity index 82% rename from BenchmarkTask.cpp rename to Benchmark.cpp index d10d792..63b4dd3 100644 --- a/BenchmarkTask.cpp +++ b/Benchmark.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "BenchmarkTask.h" +#include "Benchmark.h" #include "BenchmarkGen.h" #include "VolumeManager.h" @@ -24,6 +24,8 @@ #include #include +#include + #include #include #include @@ -36,21 +38,10 @@ using android::base::WriteStringToFile; namespace android { namespace vold { -static const char* kWakeLock = "BenchmarkTask"; +static const char* kWakeLock = "Benchmark"; -BenchmarkTask::BenchmarkTask(const std::string& path, - const android::sp& listener) : - mPath(path), mListener(listener) { -} - -BenchmarkTask::~BenchmarkTask() { -} - -void BenchmarkTask::start() { - mThread = std::thread(&BenchmarkTask::run, this); -} - -static status_t runInternal(const std::string& rootPath, android::os::PersistableBundle& extras) { +static status_t benchmarkInternal(const std::string& rootPath, + android::os::PersistableBundle* extras) { auto path = rootPath; path += "/misc"; if (android::vold::PrepareDir(path, 01771, AID_SYSTEM, AID_MISC)) { @@ -143,23 +134,24 @@ static status_t runInternal(const std::string& rootPath, android::os::Persistabl LOG(INFO) << "run took " << nanoseconds_to_milliseconds(run_d) << "ms"; LOG(INFO) << "destroy took " << nanoseconds_to_milliseconds(destroy_d) << "ms"; - extras.putString(String16("path"), String16(path.c_str())); - extras.putString(String16("ident"), String16(BenchmarkIdent().c_str())); - extras.putLong(String16("create"), create_d); - extras.putLong(String16("drop"), drop_d); - extras.putLong(String16("run"), run_d); - extras.putLong(String16("destroy"), destroy_d); + extras->putString(String16("path"), String16(path.c_str())); + extras->putString(String16("ident"), String16(BenchmarkIdent().c_str())); + extras->putLong(String16("create"), create_d); + extras->putLong(String16("drop"), drop_d); + extras->putLong(String16("run"), run_d); + extras->putLong(String16("destroy"), destroy_d); return 0; } -void BenchmarkTask::run() { +void Benchmark(const std::string& path, + const android::sp& listener) { acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); android::os::PersistableBundle extras; - status_t res = runInternal(mPath, extras); - if (mListener) { - mListener->onFinished(res, extras); + status_t res = benchmarkInternal(path, &extras); + if (listener) { + listener->onFinished(res, extras); } release_wake_lock(kWakeLock); diff --git a/BenchmarkTask.h b/Benchmark.h similarity index 61% rename from BenchmarkTask.h rename to Benchmark.h index dfa3922..4f19b01 100644 --- a/BenchmarkTask.h +++ b/Benchmark.h @@ -14,35 +14,18 @@ * limitations under the License. */ -#ifndef ANDROID_VOLD_BENCHMARK_TASK_H -#define ANDROID_VOLD_BENCHMARK_TASK_H +#ifndef ANDROID_VOLD_BENCHMARK_H +#define ANDROID_VOLD_BENCHMARK_H #include "android/os/IVoldTaskListener.h" -#include "Utils.h" #include -#include namespace android { namespace vold { -class BenchmarkTask { -public: - BenchmarkTask(const std::string& path, - const android::sp& listener); - virtual ~BenchmarkTask(); - - void start(); - -private: - std::string mPath; - android::sp mListener; - std::thread mThread; - - void run(); - - DISALLOW_COPY_AND_ASSIGN(BenchmarkTask); -}; +void Benchmark(const std::string& path, + const android::sp& listener); } // namespace vold } // namespace android diff --git a/TrimTask.cpp b/IdleMaint.cpp similarity index 78% rename from TrimTask.cpp rename to IdleMaint.cpp index 2718095..ed6374f 100644 --- a/TrimTask.cpp +++ b/IdleMaint.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "TrimTask.h" +#include "IdleMaint.h" #include "Utils.h" #include "VolumeManager.h" @@ -31,36 +31,26 @@ #include #include -/* From a would-be kernel header */ -#define FIDTRIM _IOWR('f', 128, struct fstrim_range) /* Deep discard trim */ - using android::base::StringPrintf; namespace android { namespace vold { -static const char* kWakeLock = "TrimTask"; - -TrimTask::TrimTask(int flags, const android::sp& listener) : - mFlags(flags), mListener(listener) { - // Collect both fstab and vold volumes - addFromFstab(); +static const char* kWakeLock = "IdleMaint"; +static void addFromVolumeManager(std::list* paths) { VolumeManager* vm = VolumeManager::Instance(); std::list privateIds; vm->listVolumes(VolumeBase::Type::kPrivate, privateIds); for (const auto& id : privateIds) { auto vol = vm->findVolume(id); if (vol != nullptr && vol->getState() == VolumeBase::State::kMounted) { - mPaths.push_back(vol->getPath()); + paths->push_back(vol->getPath()); } } } -TrimTask::~TrimTask() { -} - -void TrimTask::addFromFstab() { +static void addFromFstab(std::list* paths) { std::unique_ptr fstab(fs_mgr_read_fstab_default(), fs_mgr_free_fstab); struct fstab_rec *prev_rec = NULL; @@ -89,19 +79,20 @@ void TrimTask::addFromFstab() { continue; } - mPaths.push_back(fstab->recs[i].mount_point); + paths->push_back(fstab->recs[i].mount_point); prev_rec = &fstab->recs[i]; } } -void TrimTask::start() { - mThread = std::thread(&TrimTask::run, this); -} - -void TrimTask::run() { +void Trim(const android::sp& listener) { acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); - for (const auto& path : mPaths) { + // Collect both fstab and vold volumes + std::list paths; + addFromFstab(&paths); + addFromVolumeManager(&paths); + + for (const auto& path : paths) { LOG(DEBUG) << "Starting trim of " << path; android::os::PersistableBundle extras; @@ -110,8 +101,8 @@ void TrimTask::run() { int fd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW); if (fd < 0) { PLOG(WARNING) << "Failed to open " << path; - if (mListener) { - mListener->onStatus(-1, extras); + if (listener) { + listener->onStatus(-1, extras); } continue; } @@ -121,10 +112,10 @@ void TrimTask::run() { range.len = ULLONG_MAX; nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME); - if (ioctl(fd, (mFlags & Flags::kDeepTrim) ? FIDTRIM : FITRIM, &range)) { + if (ioctl(fd, FITRIM, &range)) { PLOG(WARNING) << "Trim failed on " << path; - if (mListener) { - mListener->onStatus(-1, extras); + if (listener) { + listener->onStatus(-1, extras); } } else { nsecs_t time = systemTime(SYSTEM_TIME_BOOTTIME) - start; @@ -132,16 +123,16 @@ void TrimTask::run() { << " in " << nanoseconds_to_milliseconds(time) << "ms"; extras.putLong(String16("bytes"), range.len); extras.putLong(String16("time"), time); - if (mListener) { - mListener->onStatus(0, extras); + if (listener) { + listener->onStatus(0, extras); } } close(fd); } - if (mListener) { + if (listener) { android::os::PersistableBundle extras; - mListener->onFinished(0, extras); + listener->onFinished(0, extras); } release_wake_lock(kWakeLock); diff --git a/TrimTask.h b/IdleMaint.h similarity index 57% rename from TrimTask.h rename to IdleMaint.h index a87728b..38dadfb 100644 --- a/TrimTask.h +++ b/IdleMaint.h @@ -14,40 +14,15 @@ * limitations under the License. */ -#ifndef ANDROID_VOLD_TRIM_TASK_H -#define ANDROID_VOLD_TRIM_TASK_H +#ifndef ANDROID_VOLD_IDLE_MAINT_H +#define ANDROID_VOLD_IDLE_MAINT_H #include "android/os/IVoldTaskListener.h" -#include "Utils.h" - -#include -#include namespace android { namespace vold { -class TrimTask { -public: - explicit TrimTask(int flags, const android::sp& listener); - virtual ~TrimTask(); - - enum Flags { - kDeepTrim = 1 << 0, - }; - - void start(); - -private: - int mFlags; - android::sp mListener; - std::list mPaths; - std::thread mThread; - - void addFromFstab(); - void run(); - - DISALLOW_COPY_AND_ASSIGN(TrimTask); -}; +void Trim(const android::sp& listener); } // namespace vold } // namespace android diff --git a/MoveTask.cpp b/MoveStorage.cpp similarity index 76% rename from MoveTask.cpp rename to MoveStorage.cpp index 4268ed4..4f5ebe8 100644 --- a/MoveTask.cpp +++ b/MoveStorage.cpp @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "MoveTask.h" +#include "MoveStorage.h" #include "Utils.h" #include "VolumeManager.h" @@ -23,6 +23,8 @@ #include #include +#include + #include #include @@ -44,22 +46,11 @@ static const char* kRmPath = "/system/bin/rm"; static const char* kWakeLock = "MoveTask"; -MoveTask::MoveTask(const std::shared_ptr& from, const std::shared_ptr& to, - const android::sp& listener) : - mFrom(from), mTo(to), mListener(listener) { -} - -MoveTask::~MoveTask() { -} - -void MoveTask::start() { - mThread = std::thread(&MoveTask::run, this); -} - -void MoveTask::notifyProgress(int progress) { - if (mListener) { +static void notifyProgress(int progress, + const android::sp& listener) { + if (listener) { android::os::PersistableBundle extras; - mListener->onStatus(progress, extras); + listener->onStatus(progress, extras); } } @@ -86,8 +77,9 @@ static status_t pushBackContents(const std::string& path, std::vector& listener) { + notifyProgress(startProgress, listener); uint64_t expectedBytes = GetTreeBytes(path); uint64_t startFreeBytes = GetFreeBytes(path); @@ -121,15 +113,15 @@ status_t MoveTask::execRm(const std::string& path, int startProgress, int stepPr sleep(1); uint64_t deltaFreeBytes = GetFreeBytes(path) - startFreeBytes; notifyProgress(startProgress + CONSTRAIN((int) - ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress)); + ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener); } return -1; #endif } -status_t MoveTask::execCp(const std::string& fromPath, const std::string& toPath, - int startProgress, int stepProgress) { - notifyProgress(startProgress); +static status_t execCp(const std::string& fromPath, const std::string& toPath, int startProgress, + int stepProgress, const android::sp& listener) { + notifyProgress(startProgress, listener); uint64_t expectedBytes = GetTreeBytes(fromPath); uint64_t startFreeBytes = GetFreeBytes(toPath); @@ -172,7 +164,7 @@ status_t MoveTask::execCp(const std::string& fromPath, const std::string& toPath sleep(1); uint64_t deltaFreeBytes = startFreeBytes - GetFreeBytes(toPath); notifyProgress(startProgress + CONSTRAIN((int) - ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress)); + ((deltaFreeBytes * stepProgress) / expectedBytes), 0, stepProgress), listener); } return -1; #endif @@ -192,69 +184,80 @@ static void bringOnline(const std::shared_ptr& vol) { vol->create(); } -void MoveTask::run() { - acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); - +static status_t moveStorageInternal(const std::shared_ptr& from, + const std::shared_ptr& to, + const android::sp& listener) { std::string fromPath; std::string toPath; // TODO: add support for public volumes - if (mFrom->getType() != VolumeBase::Type::kEmulated) goto fail; - if (mTo->getType() != VolumeBase::Type::kEmulated) goto fail; + if (from->getType() != VolumeBase::Type::kEmulated) goto fail; + if (to->getType() != VolumeBase::Type::kEmulated) goto fail; // Step 1: tear down volumes and mount silently without making // visible to userspace apps { std::lock_guard lock(VolumeManager::Instance()->getLock()); - bringOffline(mFrom); - bringOffline(mTo); + bringOffline(from); + bringOffline(to); } - fromPath = mFrom->getInternalPath(); - toPath = mTo->getInternalPath(); + fromPath = from->getInternalPath(); + toPath = to->getInternalPath(); // Step 2: clean up any stale data - if (execRm(toPath, 10, 10) != OK) { + if (execRm(toPath, 10, 10, listener) != OK) { goto fail; } // Step 3: perform actual copy - if (execCp(fromPath, toPath, 20, 60) != OK) { + if (execCp(fromPath, toPath, 20, 60, listener) != OK) { goto copy_fail; } // NOTE: MountService watches for this magic value to know // that move was successful - notifyProgress(82); + notifyProgress(82, listener); { std::lock_guard lock(VolumeManager::Instance()->getLock()); - bringOnline(mFrom); - bringOnline(mTo); + bringOnline(from); + bringOnline(to); } // Step 4: clean up old data - if (execRm(fromPath, 85, 15) != OK) { + if (execRm(fromPath, 85, 15, listener) != OK) { goto fail; } - notifyProgress(kMoveSucceeded); - release_wake_lock(kWakeLock); - return; + notifyProgress(kMoveSucceeded, listener); + return OK; copy_fail: // if we failed to copy the data we should not leave it laying around // in target location. Do not check return value, we can not do any // useful anyway. - execRm(toPath, 80, 1); + execRm(toPath, 80, 1, listener); fail: { std::lock_guard lock(VolumeManager::Instance()->getLock()); - bringOnline(mFrom); - bringOnline(mTo); + bringOnline(from); + bringOnline(to); } - notifyProgress(kMoveFailedInternalError); + notifyProgress(kMoveFailedInternalError, listener); + return -1; +} + +void MoveStorage(const std::shared_ptr& from, const std::shared_ptr& to, + const android::sp& listener) { + acquire_wake_lock(PARTIAL_WAKE_LOCK, kWakeLock); + + android::os::PersistableBundle extras; + status_t res = moveStorageInternal(from, to, listener); + if (listener) { + listener->onFinished(res, extras); + } + release_wake_lock(kWakeLock); - return; } } // namespace vold diff --git a/MoveStorage.h b/MoveStorage.h new file mode 100644 index 0000000..d271704 --- /dev/null +++ b/MoveStorage.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 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. + */ + +#ifndef ANDROID_VOLD_MOVE_STORAGE_H +#define ANDROID_VOLD_MOVE_STORAGE_H + +#include "android/os/IVoldTaskListener.h" +#include "model/VolumeBase.h" + +namespace android { +namespace vold { + +void MoveStorage(const std::shared_ptr& from, const std::shared_ptr& to, + const android::sp& listener); + +} // namespace vold +} // namespace android + +#endif diff --git a/MoveTask.h b/MoveTask.h deleted file mode 100644 index 246a24d..0000000 --- a/MoveTask.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2015 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. - */ - -#ifndef ANDROID_VOLD_MOVE_TASK_H -#define ANDROID_VOLD_MOVE_TASK_H - -#include "android/os/IVoldTaskListener.h" -#include "Utils.h" -#include "model/VolumeBase.h" - -#include - -namespace android { -namespace vold { - -class MoveTask { -public: - MoveTask(const std::shared_ptr& from, const std::shared_ptr& to, - const android::sp& listener); - virtual ~MoveTask(); - - void start(); - -private: - std::shared_ptr mFrom; - std::shared_ptr mTo; - android::sp mListener; - std::thread mThread; - - void run(); - - void notifyProgress(int progress); - - status_t execRm(const std::string& path, int startProgress, int stepProgress); - status_t execCp(const std::string& fromPath, const std::string& toPath, - int startProgress, int stepProgress); - - DISALLOW_COPY_AND_ASSIGN(MoveTask); -}; - -} // namespace vold -} // namespace android - -#endif diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index c82eb92..d8832d3 100644 --- a/VoldNativeService.cpp +++ b/VoldNativeService.cpp @@ -18,16 +18,17 @@ #include "VoldNativeService.h" #include "VolumeManager.h" -#include "BenchmarkTask.h" -#include "MoveTask.h" +#include "Benchmark.h" +#include "MoveStorage.h" #include "Process.h" -#include "TrimTask.h" +#include "IdleMaint.h" #include "cryptfs.h" #include "Ext4Crypt.h" #include "MetadataCrypt.h" #include +#include #include #include @@ -120,6 +121,10 @@ binder::Status checkArgumentPath(const std::string& path) { return exception(binder::Status::EX_ILLEGAL_ARGUMENT, StringPrintf("Path %s is relative", path.c_str())); } + if ((path + '/').find("/../") != std::string::npos) { + return exception(binder::Status::EX_ILLEGAL_ARGUMENT, + StringPrintf("Path %s is shady", path.c_str())); + } for (const char& c : path) { if (c == '\0' || c == '\n') { return exception(binder::Status::EX_ILLEGAL_ARGUMENT, @@ -377,7 +382,9 @@ binder::Status VoldNativeService::benchmark(const std::string& volId, return error("Volume " + volId + " missing path"); } - (new android::vold::BenchmarkTask(path, listener))->start(); + std::thread([=]() { + android::vold::Benchmark(path, listener); + }).detach(); return ok(); } @@ -395,7 +402,10 @@ binder::Status VoldNativeService::moveStorage(const std::string& fromVolId, } else if (toVol == nullptr) { return error("Failed to find volume " + toVolId); } - (new android::vold::MoveTask(fromVol, toVol, listener))->start(); + + std::thread([=]() { + android::vold::MoveStorage(fromVol, toVol, listener); + }).detach(); return ok(); } @@ -446,7 +456,9 @@ binder::Status VoldNativeService::fstrim(int32_t fstrimFlags, ENFORCE_UID(AID_SYSTEM); ACQUIRE_LOCK; - (new android::vold::TrimTask(fstrimFlags, listener))->start(); + std::thread([=]() { + android::vold::Trim(listener); + }).detach(); return ok(); } @@ -712,6 +724,7 @@ binder::Status VoldNativeService::destroyUserStorage(const std::unique_ptr