blob: 2caa445f709aec6fcc99cf65e67a61fce143540f [file] [log] [blame]
David Andersonc053b3b2019-01-08 18:22:07 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "gsi_service.h"
18
Yo Chiang721a0e42020-12-28 19:29:47 +080019#include <sys/statvfs.h>
David Andersone7a8ade2019-03-13 19:21:22 -070020#include <sys/vfs.h>
David Andersonc053b3b2019-01-08 18:22:07 -080021#include <unistd.h>
22
Yo Chiang53bed1c2020-01-01 16:25:19 +080023#include <array>
David Andersonc053b3b2019-01-08 18:22:07 -080024#include <chrono>
25#include <string>
26#include <vector>
27
Yifan Hongd66695b2019-12-23 16:07:45 -080028#include <android-base/errors.h>
David Andersonc053b3b2019-01-08 18:22:07 -080029#include <android-base/file.h>
30#include <android-base/logging.h>
Howard Chen7885d3c2020-02-26 12:48:41 +080031#include <android-base/properties.h>
David Andersonc053b3b2019-01-08 18:22:07 -080032#include <android-base/stringprintf.h>
David Anderson5f805912019-03-07 12:41:15 -080033#include <android-base/strings.h>
David Anderson551ae3a2019-08-01 12:53:06 -070034#include <android/gsi/BnImageService.h>
David Andersonc053b3b2019-01-08 18:22:07 -080035#include <android/gsi/IGsiService.h>
Yo Chiang1f080912020-10-07 17:29:57 +080036#include <android/os/IVold.h>
37#include <binder/IServiceManager.h>
Howard Chen67a27092020-02-15 17:32:02 +080038#include <binder/LazyServiceRegistrar.h>
David Anderson73274df2022-01-10 02:37:33 +000039#include <cutils/android_reboot.h>
David Anderson64b53fb2019-07-01 19:05:35 -070040#include <ext4_utils/ext4_utils.h>
David Andersone7a8ade2019-03-13 19:21:22 -070041#include <fs_mgr.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080042#include <libavb/libavb.h>
David Andersond614eca2019-09-09 17:57:06 -070043#include <libdm/dm.h>
David Anderson6f373b72019-06-05 15:04:00 -070044#include <libfiemap/image_manager.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080045#include <openssl/sha.h>
David Anderson3c819cb2019-02-08 17:50:50 -080046#include <private/android_filesystem_config.h>
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +080047#include <selinux/android.h>
Yo Chiang721a0e42020-12-28 19:29:47 +080048#include <storage_literals/storage_literals.h>
David Andersonb3aff182019-01-11 14:37:51 -080049
David Andersonc053b3b2019-01-08 18:22:07 -080050#include "file_paths.h"
David Andersonb3aff182019-01-11 14:37:51 -080051#include "libgsi_private.h"
David Andersonc053b3b2019-01-08 18:22:07 -080052
53namespace android {
54namespace gsi {
55
56using namespace std::literals;
57using namespace android::fs_mgr;
David Anderson9ca77282019-07-15 23:56:13 +000058using namespace android::fiemap;
Yo Chiang721a0e42020-12-28 19:29:47 +080059using namespace android::storage_literals;
Howard Chen4663de62019-11-05 20:46:20 +080060using android::base::ReadFileToString;
Yo Chiang53bed1c2020-01-01 16:25:19 +080061using android::base::ReadFullyAtOffset;
Howard Chen4663de62019-11-05 20:46:20 +080062using android::base::RemoveFileIfExists;
Howard Chen7885d3c2020-02-26 12:48:41 +080063using android::base::SetProperty;
David Anderson3c819cb2019-02-08 17:50:50 -080064using android::base::StringPrintf;
David Andersonc86531e2019-02-25 18:50:35 -080065using android::base::unique_fd;
Howard Chen4663de62019-11-05 20:46:20 +080066using android::base::WriteStringToFd;
67using android::base::WriteStringToFile;
Howard Chen67a27092020-02-15 17:32:02 +080068using android::binder::LazyServiceRegistrar;
David Andersond614eca2019-09-09 17:57:06 -070069using android::dm::DeviceMapper;
David Andersonc053b3b2019-01-08 18:22:07 -080070
Howard Chen4663de62019-11-05 20:46:20 +080071// Default userdata image size.
72static constexpr int64_t kDefaultUserdataSize = int64_t(2) * 1024 * 1024 * 1024;
73
Yo Chiang53bed1c2020-01-01 16:25:19 +080074static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst);
75
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +080076// Fix the file contexts of dsu metadata files.
77// By default, newly created files inherit the file contexts of their parent
78// directory. Since globally readable public metadata files are labeled with a
79// different context, gsi_public_metadata_file, we need to call this function to
80// fix their contexts after creating them.
81static void RestoreconMetadataFiles() {
82 auto flags = SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIP_SEHASH;
83 selinux_android_restorecon(DSU_METADATA_PREFIX, flags);
84}
85
Howard Chen67a27092020-02-15 17:32:02 +080086GsiService::GsiService() {
David Anderson6a5b8a72019-01-16 16:24:48 -080087 progress_ = {};
88}
89
Yi-Yo Chiang457b9c72022-08-09 20:09:19 +080090void GsiService::Register(const std::string& name) {
Howard Chen67a27092020-02-15 17:32:02 +080091 auto lazyRegistrar = LazyServiceRegistrar::getInstance();
92 android::sp<GsiService> service = new GsiService();
Yi-Yo Chiang457b9c72022-08-09 20:09:19 +080093 auto ret = lazyRegistrar.registerService(service, name);
David Anderson4c756732019-07-12 14:18:37 -070094
Howard Chen67a27092020-02-15 17:32:02 +080095 if (ret != android::OK) {
96 LOG(FATAL) << "Could not register gsi service: " << ret;
David Anderson4c756732019-07-12 14:18:37 -070097 }
98}
99
David Anderson5cc440c2019-04-16 14:34:27 -0700100#define ENFORCE_SYSTEM \
101 do { \
102 binder::Status status = CheckUid(); \
103 if (!status.isOk()) return status; \
David Anderson3c819cb2019-02-08 17:50:50 -0800104 } while (0)
105
David Anderson5cc440c2019-04-16 14:34:27 -0700106#define ENFORCE_SYSTEM_OR_SHELL \
107 do { \
108 binder::Status status = CheckUid(AccessLevel::SystemOrShell); \
109 if (!status.isOk()) return status; \
David Andersonb5f44b32019-02-20 18:04:37 -0800110 } while (0)
111
Howard Chen4663de62019-11-05 20:46:20 +0800112int GsiService::SaveInstallation(const std::string& installation) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800113 auto dsu_slot = GetDsuSlot(installation);
114 auto install_dir_file = DsuInstallDirFile(dsu_slot);
115 auto metadata_dir = android::base::Dirname(install_dir_file);
116 if (access(metadata_dir.c_str(), F_OK) != 0) {
117 if (mkdir(metadata_dir.c_str(), 0777) != 0) {
118 PLOG(ERROR) << "Failed to mkdir " << metadata_dir;
119 return INSTALL_ERROR_GENERIC;
120 }
121 }
Howard Chen4663de62019-11-05 20:46:20 +0800122 auto fd = android::base::unique_fd(
Howard Chenee5c2b12019-11-08 11:57:47 +0800123 open(install_dir_file.c_str(), O_RDWR | O_SYNC | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
Howard Chen4663de62019-11-05 20:46:20 +0800124 if (!WriteStringToFd(installation, fd)) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800125 PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800126 return INSTALL_ERROR_GENERIC;
127 }
128 return INSTALL_OK;
129}
130
Howard Chen3a5e19a2021-01-07 16:07:52 +0800131static bool IsExternalStoragePath(const std::string& path);
132
Howard Chen4663de62019-11-05 20:46:20 +0800133binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
134 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800135 std::lock_guard<std::mutex> guard(lock_);
Howard Chen4663de62019-11-05 20:46:20 +0800136 if (IsGsiRunning()) {
137 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
138 return binder::Status::ok();
139 }
140 install_dir_ = install_dir;
141 if (int status = ValidateInstallParams(install_dir_)) {
142 *_aidl_return = status;
143 return binder::Status::ok();
144 }
145 std::string message;
Howard Chenee5c2b12019-11-08 11:57:47 +0800146 auto dsu_slot = GetDsuSlot(install_dir_);
147 if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
Howard Chen4663de62019-11-05 20:46:20 +0800148 LOG(ERROR) << message;
149 }
150 // Remember the installation directory before allocate any resource
151 *_aidl_return = SaveInstallation(install_dir_);
152 return binder::Status::ok();
153}
154
155binder::Status GsiService::closeInstall(int* _aidl_return) {
156 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800157 std::lock_guard<std::mutex> guard(lock_);
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800158
159 installer_ = {};
160
Howard Chenee5c2b12019-11-08 11:57:47 +0800161 auto dsu_slot = GetDsuSlot(install_dir_);
162 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800163 if (!WriteStringToFile("OK", file)) {
164 PLOG(ERROR) << "write failed: " << file;
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800165 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
166 return binder::Status::ok();
Howard Chen4663de62019-11-05 20:46:20 +0800167 }
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800168
169 // Create installation complete marker files, but set disabled immediately.
170 if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
171 PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
172 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
173 return binder::Status::ok();
174 }
175 RestoreconMetadataFiles();
176
177 // DisableGsi() creates the DSU install status file and mark it as "disabled".
178 if (!DisableGsi()) {
179 PLOG(ERROR) << "cannot write DSU status file: " << kDsuInstallStatusFile;
180 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
181 return binder::Status::ok();
182 }
183
184 SetProperty(kGsiInstalledProp, "1");
185 *_aidl_return = IGsiService::INSTALL_OK;
Howard Chen4663de62019-11-05 20:46:20 +0800186 return binder::Status::ok();
187}
188
189binder::Status GsiService::createPartition(const ::std::string& name, int64_t size, bool readOnly,
190 int32_t* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800191 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800192 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800193
Howard Chen4663de62019-11-05 20:46:20 +0800194 if (install_dir_.empty()) {
195 PLOG(ERROR) << "open is required for createPartition";
196 *_aidl_return = INSTALL_ERROR_GENERIC;
197 return binder::Status::ok();
198 }
199
David Andersoneb30ac22019-03-12 15:24:53 -0700200 // Do some precursor validation on the arguments before diving into the
201 // install process.
Howard Chen4663de62019-11-05 20:46:20 +0800202 if (size % LP_SECTOR_SIZE) {
203 LOG(ERROR) << " size " << size << " is not a multiple of " << LP_SECTOR_SIZE;
204 *_aidl_return = INSTALL_ERROR_GENERIC;
David Andersoneb30ac22019-03-12 15:24:53 -0700205 return binder::Status::ok();
206 }
207
Howard Chen4663de62019-11-05 20:46:20 +0800208 if (size == 0 && name == "userdata") {
209 size = kDefaultUserdataSize;
210 }
Yo Chiang1f080912020-10-07 17:29:57 +0800211
212 if (name == "userdata") {
213 auto dsu_slot = GetDsuSlot(install_dir_);
214 auto key_dir = DefaultDsuMetadataKeyDir(dsu_slot);
215 auto key_dir_file = DsuMetadataKeyDirFile(dsu_slot);
216 if (!android::base::WriteStringToFile(key_dir, key_dir_file)) {
217 PLOG(ERROR) << "write failed: " << key_dir_file;
218 *_aidl_return = INSTALL_ERROR_GENERIC;
219 return binder::Status::ok();
220 }
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +0800221 RestoreconMetadataFiles();
Yo Chiang1f080912020-10-07 17:29:57 +0800222 }
223
Howard Chenee5c2b12019-11-08 11:57:47 +0800224 installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name,
225 GetDsuSlot(install_dir_), size, readOnly);
Howard Chen9f40baf2019-12-16 13:31:12 +0800226 progress_ = {};
Yi-Yo Chiangc4d64002021-02-12 02:17:03 +0800227 *_aidl_return = installer_->StartInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800228 return binder::Status::ok();
229}
230
Yo Chiang36fdbc62020-08-20 19:40:31 +0800231binder::Status GsiService::closePartition(int32_t* _aidl_return) {
232 ENFORCE_SYSTEM;
233 std::lock_guard<std::mutex> guard(lock_);
234
235 if (installer_ == nullptr) {
236 LOG(ERROR) << "createPartition() has to be called before closePartition()";
237 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
238 return binder::Status::ok();
239 }
240 // It is important to not reset |installer_| here because other methods such
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800241 // as isGsiInstallInProgress() relies on the state of |installer_|.
242 // TODO: Maybe don't do this, use a dedicated |in_progress_| flag?
Yo Chiang36fdbc62020-08-20 19:40:31 +0800243 *_aidl_return = installer_->FinishInstall();
244 return binder::Status::ok();
245}
246
David Anderson1d94d262019-01-11 20:39:51 -0800247binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
David Andersonc053b3b2019-01-08 18:22:07 -0800248 int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800249 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800250 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800251
David Andersonb2988ab2019-04-16 17:14:09 -0700252 if (!installer_) {
253 *_aidl_return = false;
254 return binder::Status::ok();
255 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800256
David Andersonb2988ab2019-04-16 17:14:09 -0700257 *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
David Anderson6a5b8a72019-01-16 16:24:48 -0800258 return binder::Status::ok();
259}
260
261void GsiService::StartAsyncOperation(const std::string& step, int64_t total_bytes) {
262 std::lock_guard<std::mutex> guard(progress_lock_);
263
264 progress_.step = step;
265 progress_.status = STATUS_WORKING;
266 progress_.bytes_processed = 0;
267 progress_.total_bytes = total_bytes;
268}
269
270void GsiService::UpdateProgress(int status, int64_t bytes_processed) {
271 std::lock_guard<std::mutex> guard(progress_lock_);
272
273 progress_.status = status;
David Andersona64e3922019-02-01 16:27:18 -0800274 if (status == STATUS_COMPLETE) {
275 progress_.bytes_processed = progress_.total_bytes;
276 } else {
277 progress_.bytes_processed = bytes_processed;
278 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800279}
280
281binder::Status GsiService::getInstallProgress(::android::gsi::GsiProgress* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800282 ENFORCE_SYSTEM;
David Anderson6a5b8a72019-01-16 16:24:48 -0800283 std::lock_guard<std::mutex> guard(progress_lock_);
284
Howard Chen9f40baf2019-12-16 13:31:12 +0800285 if (installer_ == nullptr) {
286 progress_ = {};
287 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800288 *_aidl_return = progress_;
David Andersonc053b3b2019-01-08 18:22:07 -0800289 return binder::Status::ok();
290}
291
Howard Chen5676d962019-08-05 16:21:00 +0800292binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800293 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800294 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800295
David Andersonb2988ab2019-04-16 17:14:09 -0700296 if (!installer_) {
297 *_aidl_return = false;
298 return binder::Status::ok();
299 }
Howard Chen5676d962019-08-05 16:21:00 +0800300 *_aidl_return = installer_->CommitGsiChunk(bytes);
301 return binder::Status::ok();
302}
David Andersonb2988ab2019-04-16 17:14:09 -0700303
Howard Chen5676d962019-08-05 16:21:00 +0800304binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem,
305 int64_t size, bool* _aidl_return) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800306 ENFORCE_SYSTEM;
Howard Chen5676d962019-08-05 16:21:00 +0800307 if (!installer_) {
308 *_aidl_return = false;
309 return binder::Status::ok();
310 }
311 *_aidl_return = installer_->MapAshmem(ashmem.get(), size);
David Andersonc053b3b2019-01-08 18:22:07 -0800312 return binder::Status::ok();
313}
314
Howard Chen7885d3c2020-02-26 12:48:41 +0800315binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
316 const sp<IGsiServiceCallback>& resultCallback) {
Yi-Yo Chiangd646d792022-04-04 21:38:57 +0800317 ENFORCE_SYSTEM_OR_SHELL;
318 std::lock_guard<std::mutex> guard(lock_);
319
320 const auto result = EnableGsi(one_shot, dsuSlot);
Howard Chen7885d3c2020-02-26 12:48:41 +0800321 resultCallback->onResult(result);
322 return binder::Status::ok();
323}
324
Howard Chenee5c2b12019-11-08 11:57:47 +0800325binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800326 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800327 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800328
Yi-Yo Chiangd646d792022-04-04 21:38:57 +0800329 *_aidl_return = EnableGsi(one_shot, dsuSlot);
David Andersonc053b3b2019-01-08 18:22:07 -0800330 return binder::Status::ok();
331}
332
Howard Chen670b3062019-02-26 18:14:47 +0800333binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
334 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800335 std::lock_guard<std::mutex> guard(lock_);
Howard Chen670b3062019-02-26 18:14:47 +0800336 std::string boot_key;
337 if (!GetInstallStatus(&boot_key)) {
338 *_aidl_return = false;
339 } else {
Howard Chenee5c2b12019-11-08 11:57:47 +0800340 *_aidl_return = (boot_key != kInstallStatusDisabled);
Howard Chen670b3062019-02-26 18:14:47 +0800341 }
342 return binder::Status::ok();
343}
344
Howard Chen7885d3c2020-02-26 12:48:41 +0800345binder::Status GsiService::removeGsiAsync(const sp<IGsiServiceCallback>& resultCallback) {
Chih-Hung Hsieh03478f22022-12-20 13:27:31 -0800346 bool result = false;
Howard Chen7885d3c2020-02-26 12:48:41 +0800347 auto status = removeGsi(&result);
348 if (!status.isOk()) {
349 LOG(ERROR) << "Could not removeGsi: " << status.exceptionMessage().string();
350 result = IGsiService::INSTALL_ERROR_GENERIC;
351 }
352 resultCallback->onResult(result);
353 return binder::Status::ok();
354}
355
Howard Chen25b18cc2019-08-02 11:21:58 +0800356binder::Status GsiService::removeGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800357 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800358 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800359
Howard Chen3f6d5a62019-08-22 15:26:33 +0800360 std::string install_dir = GetActiveInstalledImageDir();
David Andersona141ba82019-01-14 19:09:27 -0800361 if (IsGsiRunning()) {
362 // Can't remove gsi files while running.
363 *_aidl_return = UninstallGsi();
364 } else {
Howard Chendee5d302020-02-05 10:58:29 +0800365 installer_ = {};
Howard Chen4663de62019-11-05 20:46:20 +0800366 *_aidl_return = RemoveGsiFiles(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800367 }
368 return binder::Status::ok();
369}
370
Howard Chen25b18cc2019-08-02 11:21:58 +0800371binder::Status GsiService::disableGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800372 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800373 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800374
375 *_aidl_return = DisableGsiInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800376 return binder::Status::ok();
377}
378
379binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800380 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800381 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800382
David Andersonc053b3b2019-01-08 18:22:07 -0800383 *_aidl_return = IsGsiRunning();
384 return binder::Status::ok();
385}
386
David Andersona141ba82019-01-14 19:09:27 -0800387binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800388 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800389 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800390
391 *_aidl_return = IsGsiInstalled();
392 return binder::Status::ok();
393}
394
395binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800396 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800397 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800398
David Andersonb2988ab2019-04-16 17:14:09 -0700399 *_aidl_return = !!installer_;
David Andersona141ba82019-01-14 19:09:27 -0800400 return binder::Status::ok();
401}
402
403binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800404 ENFORCE_SYSTEM;
Howard Chenecbc0192019-02-25 18:51:26 +0800405 should_abort_ = true;
Howard Chen67a27092020-02-15 17:32:02 +0800406 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800407
Howard Chenecbc0192019-02-25 18:51:26 +0800408 should_abort_ = false;
David Andersonb2988ab2019-04-16 17:14:09 -0700409 installer_ = nullptr;
David Andersona141ba82019-01-14 19:09:27 -0800410
David Andersona141ba82019-01-14 19:09:27 -0800411 *_aidl_return = true;
412 return binder::Status::ok();
413}
414
David Anderson5f805912019-03-07 12:41:15 -0800415binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
416 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800417 std::lock_guard<std::mutex> guard(lock_);
David Anderson5f805912019-03-07 12:41:15 -0800418
Howard Chen3f6d5a62019-08-22 15:26:33 +0800419 *_aidl_return = GetActiveInstalledImageDir();
David Anderson5f805912019-03-07 12:41:15 -0800420 return binder::Status::ok();
421}
422
Howard Chenee5c2b12019-11-08 11:57:47 +0800423binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) {
424 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800425 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800426
427 *_aidl_return = GetActiveDsuSlot();
428 return binder::Status::ok();
429}
430
431binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) {
432 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800433 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800434 *_aidl_return = GetInstalledDsuSlots();
435 return binder::Status::ok();
436}
437
Howard Chen4663de62019-11-05 20:46:20 +0800438binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) {
David Anderson8bdf6252019-06-11 16:43:24 -0700439 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800440 std::lock_guard<std::mutex> guard(lock_);
David Anderson8bdf6252019-06-11 16:43:24 -0700441
442 if (IsGsiRunning() || !IsGsiInstalled()) {
443 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
444 return binder::Status::ok();
445 }
446
Howard Chen3f6d5a62019-08-22 15:26:33 +0800447 std::string install_dir = GetActiveInstalledImageDir();
Howard Chenee5c2b12019-11-08 11:57:47 +0800448 *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name);
David Anderson8bdf6252019-06-11 16:43:24 -0700449
450 return binder::Status::ok();
451}
452
Yifan Hongd66695b2019-12-23 16:07:45 -0800453static binder::Status BinderError(const std::string& message,
454 FiemapStatus::ErrorCode status = FiemapStatus::ErrorCode::ERROR) {
455 return binder::Status::fromServiceSpecificError(static_cast<int32_t>(status), message.c_str());
David Anderson6f373b72019-06-05 15:04:00 -0700456}
457
David Andersond614eca2019-09-09 17:57:06 -0700458binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) {
459 ENFORCE_SYSTEM_OR_SHELL;
460
461 auto& dm = DeviceMapper::Instance();
462
463 std::vector<DeviceMapper::DmBlockDevice> devices;
464 if (!dm.GetAvailableDevices(&devices)) {
465 return BinderError("Could not list devices");
466 }
467
468 std::stringstream text;
469 for (const auto& device : devices) {
470 text << "Device " << device.name() << " (" << device.Major() << ":" << device.Minor()
471 << ")\n";
472
473 std::vector<DeviceMapper::TargetInfo> table;
474 if (!dm.GetTableInfo(device.name(), &table)) {
475 continue;
476 }
477
478 for (const auto& target : table) {
479 const auto& spec = target.spec;
480 auto target_type = DeviceMapper::GetTargetType(spec);
481 text << " " << target_type << " " << spec.sector_start << " " << spec.length << " "
482 << target.data << "\n";
483 }
484 }
485
486 *_aidl_return = text.str();
487 return binder::Status::ok();
488}
489
Yo Chiang53bed1c2020-01-01 16:25:19 +0800490binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) {
491 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800492 std::lock_guard<std::mutex> guard(lock_);
Yo Chiang53bed1c2020-01-01 16:25:19 +0800493
494 if (!installer_) {
495 *_aidl_return = INSTALL_ERROR_GENERIC;
496 return binder::Status::ok();
497 }
498 int fd = installer_->GetPartitionFd();
499 if (!GetAvbPublicKeyFromFd(fd, dst)) {
500 LOG(ERROR) << "Failed to extract AVB public key";
501 *_aidl_return = INSTALL_ERROR_GENERIC;
502 return binder::Status::ok();
503 }
504 *_aidl_return = INSTALL_OK;
505 return binder::Status::ok();
506}
507
Yo Chiang721a0e42020-12-28 19:29:47 +0800508binder::Status GsiService::suggestScratchSize(int64_t* _aidl_return) {
509 ENFORCE_SYSTEM;
510
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800511 static constexpr uint64_t kMinScratchSize = 512_MiB;
512 static constexpr uint64_t kMaxScratchSize = 2_GiB;
Yo Chiang721a0e42020-12-28 19:29:47 +0800513
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800514 uint64_t size = 0;
Yo Chiang721a0e42020-12-28 19:29:47 +0800515 struct statvfs info;
516 if (statvfs(install_dir_.c_str(), &info)) {
517 PLOG(ERROR) << "Could not statvfs(" << install_dir_ << ")";
518 } else {
Yi-Yo Chiang81af6b22021-11-03 20:26:32 +0800519 uint64_t free_space = static_cast<uint64_t>(info.f_bavail) * info.f_frsize;
520 const auto free_space_threshold =
521 PartitionInstaller::GetMinimumFreeSpaceThreshold(install_dir_);
522 if (free_space_threshold.has_value() && free_space > *free_space_threshold) {
523 // Round down to multiples of filesystem block size.
524 size = (free_space - *free_space_threshold) / info.f_frsize * info.f_frsize;
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800525 }
Yo Chiang721a0e42020-12-28 19:29:47 +0800526 }
527
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800528 // We can safely downcast the result here, since we clamped the result within int64_t range.
Yo Chiang721a0e42020-12-28 19:29:47 +0800529 *_aidl_return = std::clamp(size, kMinScratchSize, kMaxScratchSize);
530 return binder::Status::ok();
531}
532
Yi-Yo Chiang1ecc3af2021-12-02 18:30:24 +0800533bool GsiService::ResetBootAttemptCounter() {
Howard Chen4663de62019-11-05 20:46:20 +0800534 if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
535 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
536 return false;
537 }
Howard Chen7885d3c2020-02-26 12:48:41 +0800538 SetProperty(kGsiInstalledProp, "1");
Howard Chen4663de62019-11-05 20:46:20 +0800539 return true;
540}
541
542bool GsiService::SetBootMode(bool one_shot) {
543 if (one_shot) {
544 if (!android::base::WriteStringToFile("1", kDsuOneShotBootFile)) {
545 PLOG(ERROR) << "write " << kDsuOneShotBootFile;
546 return false;
547 }
548 } else if (!access(kDsuOneShotBootFile, F_OK)) {
549 std::string error;
550 if (!android::base::RemoveFileIfExists(kDsuOneShotBootFile, &error)) {
551 LOG(ERROR) << error;
552 return false;
553 }
554 }
555 return true;
556}
557
David Anderson6f373b72019-06-05 15:04:00 -0700558static binder::Status UidSecurityError() {
559 uid_t uid = IPCThreadState::self()->getCallingUid();
560 auto message = StringPrintf("UID %d is not allowed", uid);
561 return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
562}
563
David Anderson551ae3a2019-08-01 12:53:06 -0700564class ImageService : public BinderService<ImageService>, public BnImageService {
David Anderson6f373b72019-06-05 15:04:00 -0700565 public:
David Anderson551ae3a2019-08-01 12:53:06 -0700566 ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
Howard Chen96c31fd2019-08-23 17:38:51 +0800567 binder::Status getAllBackingImages(std::vector<std::string>* _aidl_return);
Yifan Hongd66695b2019-12-23 16:07:45 -0800568 binder::Status createBackingImage(const std::string& name, int64_t size, int flags,
569 const sp<IProgressCallback>& on_progress) override;
David Anderson6f373b72019-06-05 15:04:00 -0700570 binder::Status deleteBackingImage(const std::string& name) override;
571 binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
572 MappedImage* mapping) override;
573 binder::Status unmapImageDevice(const std::string& name) override;
David Anderson394f1f22019-07-29 12:49:02 -0700574 binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override;
David Andersonbee55a02019-08-01 15:01:55 -0700575 binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override;
Yo Chiang53bed1c2020-01-01 16:25:19 +0800576 binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
577 int32_t* _aidl_return) override;
Alessio Balsini0829fb22019-08-27 17:50:18 +0100578 binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override;
David Anderson86846bd2019-11-26 16:30:40 -0800579 binder::Status removeAllImages() override;
Yi-Yo Chiang6c1043f2022-08-08 19:03:09 +0800580 binder::Status disableImage(const std::string& name) override;
David Anderson7016a0d2019-12-16 22:06:47 -0800581 binder::Status removeDisabledImages() override;
David Anderson14aa72a2019-12-17 21:27:59 -0800582 binder::Status getMappedImageDevice(const std::string& name, std::string* device) override;
David Andersonf116bec2022-02-10 23:35:03 -0800583 binder::Status isImageDisabled(const std::string& name, bool* _aidl_return) override;
David Anderson6f373b72019-06-05 15:04:00 -0700584
585 private:
586 bool CheckUid();
587
David Anderson4c756732019-07-12 14:18:37 -0700588 android::sp<GsiService> service_;
David Anderson6f373b72019-06-05 15:04:00 -0700589 std::unique_ptr<ImageManager> impl_;
590 uid_t uid_;
591};
592
David Anderson551ae3a2019-08-01 12:53:06 -0700593ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
Howard Chen67a27092020-02-15 17:32:02 +0800594 : service_(service), impl_(std::move(impl)), uid_(uid) {}
David Anderson6f373b72019-06-05 15:04:00 -0700595
Howard Chen96c31fd2019-08-23 17:38:51 +0800596binder::Status ImageService::getAllBackingImages(std::vector<std::string>* _aidl_return) {
597 *_aidl_return = impl_->GetAllBackingImages();
598 return binder::Status::ok();
599}
600
Yifan Hongd66695b2019-12-23 16:07:45 -0800601binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags,
602 const sp<IProgressCallback>& on_progress) {
David Anderson6f373b72019-06-05 15:04:00 -0700603 if (!CheckUid()) return UidSecurityError();
604
Howard Chen67a27092020-02-15 17:32:02 +0800605 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700606
Yifan Hongd66695b2019-12-23 16:07:45 -0800607 std::function<bool(uint64_t, uint64_t)> callback;
608 if (on_progress) {
609 callback = [on_progress](uint64_t current, uint64_t total) -> bool {
610 auto status = on_progress->onProgress(static_cast<int64_t>(current),
611 static_cast<int64_t>(total));
612 if (!status.isOk()) {
613 LOG(ERROR) << "progress callback returned: " << status.toString8().string();
614 return false;
615 }
616 return true;
617 };
618 }
619
620 auto res = impl_->CreateBackingImage(name, size, flags, std::move(callback));
621 if (!res.is_ok()) {
622 return BinderError("Failed to create: " + res.string(), res.error_code());
David Anderson6f373b72019-06-05 15:04:00 -0700623 }
624 return binder::Status::ok();
625}
626
David Anderson551ae3a2019-08-01 12:53:06 -0700627binder::Status ImageService::deleteBackingImage(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700628 if (!CheckUid()) return UidSecurityError();
629
Howard Chen67a27092020-02-15 17:32:02 +0800630 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700631
632 if (!impl_->DeleteBackingImage(name)) {
633 return BinderError("Failed to delete");
634 }
635 return binder::Status::ok();
636}
637
David Anderson551ae3a2019-08-01 12:53:06 -0700638binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
639 MappedImage* mapping) {
David Anderson6f373b72019-06-05 15:04:00 -0700640 if (!CheckUid()) return UidSecurityError();
641
Howard Chen67a27092020-02-15 17:32:02 +0800642 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700643
644 if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
645 return BinderError("Failed to map");
646 }
647 return binder::Status::ok();
648}
649
David Anderson551ae3a2019-08-01 12:53:06 -0700650binder::Status ImageService::unmapImageDevice(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700651 if (!CheckUid()) return UidSecurityError();
652
Howard Chen67a27092020-02-15 17:32:02 +0800653 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700654
655 if (!impl_->UnmapImageDevice(name)) {
656 return BinderError("Failed to unmap");
657 }
658 return binder::Status::ok();
659}
660
David Anderson551ae3a2019-08-01 12:53:06 -0700661binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
David Anderson394f1f22019-07-29 12:49:02 -0700662 if (!CheckUid()) return UidSecurityError();
663
Howard Chen67a27092020-02-15 17:32:02 +0800664 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson394f1f22019-07-29 12:49:02 -0700665
666 *_aidl_return = impl_->BackingImageExists(name);
667 return binder::Status::ok();
668}
669
David Andersonbee55a02019-08-01 15:01:55 -0700670binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_return) {
671 if (!CheckUid()) return UidSecurityError();
672
Howard Chen67a27092020-02-15 17:32:02 +0800673 std::lock_guard<std::mutex> guard(service_->lock());
David Andersonbee55a02019-08-01 15:01:55 -0700674
675 *_aidl_return = impl_->IsImageMapped(name);
676 return binder::Status::ok();
677}
678
Yo Chiang53bed1c2020-01-01 16:25:19 +0800679binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
680 int32_t* _aidl_return) {
681 if (!CheckUid()) return UidSecurityError();
682
Howard Chen67a27092020-02-15 17:32:02 +0800683 std::lock_guard<std::mutex> guard(service_->lock());
Yo Chiang53bed1c2020-01-01 16:25:19 +0800684
685 std::string device_path;
686 std::unique_ptr<MappedDevice> mapped_device;
687 if (!impl_->IsImageMapped(name)) {
688 mapped_device = MappedDevice::Open(impl_.get(), 10s, name);
689 if (!mapped_device) {
690 PLOG(ERROR) << "Fail to map image: " << name;
691 *_aidl_return = IMAGE_ERROR;
692 return binder::Status::ok();
693 }
694 device_path = mapped_device->path();
695 } else {
696 if (!impl_->GetMappedImageDevice(name, &device_path)) {
697 PLOG(ERROR) << "GetMappedImageDevice() failed";
698 *_aidl_return = IMAGE_ERROR;
699 return binder::Status::ok();
700 }
701 }
702 android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
703 if (!fd.ok()) {
704 PLOG(ERROR) << "Fail to open mapped device: " << device_path;
705 *_aidl_return = IMAGE_ERROR;
706 return binder::Status::ok();
707 }
708 bool ok = GetAvbPublicKeyFromFd(fd.get(), dst);
709 fd = {};
710 if (!ok) {
711 LOG(ERROR) << "Failed to extract AVB public key";
712 *_aidl_return = IMAGE_ERROR;
713 return binder::Status::ok();
714 }
715 *_aidl_return = IMAGE_OK;
716 return binder::Status::ok();
717}
718
Alessio Balsini0829fb22019-08-27 17:50:18 +0100719binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) {
720 if (!CheckUid()) return UidSecurityError();
721
Howard Chen67a27092020-02-15 17:32:02 +0800722 std::lock_guard<std::mutex> guard(service_->lock());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100723
724 if (bytes < 0) {
725 return BinderError("Cannot use negative values");
726 }
Yifan Hongd66695b2019-12-23 16:07:45 -0800727 auto res = impl_->ZeroFillNewImage(name, bytes);
728 if (!res.is_ok()) {
729 return BinderError("Failed to fill image with zeros: " + res.string(), res.error_code());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100730 }
731 return binder::Status::ok();
732}
733
David Anderson86846bd2019-11-26 16:30:40 -0800734binder::Status ImageService::removeAllImages() {
735 if (!CheckUid()) return UidSecurityError();
736
Howard Chen67a27092020-02-15 17:32:02 +0800737 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson86846bd2019-11-26 16:30:40 -0800738 if (!impl_->RemoveAllImages()) {
739 return BinderError("Failed to remove all images");
740 }
741 return binder::Status::ok();
742}
743
Yi-Yo Chiang6c1043f2022-08-08 19:03:09 +0800744binder::Status ImageService::disableImage(const std::string& name) {
745 if (!CheckUid()) return UidSecurityError();
746
747 std::lock_guard<std::mutex> guard(service_->lock());
748 if (!impl_->DisableImage(name)) {
749 return BinderError("Failed to disable image: " + name);
750 }
751 return binder::Status::ok();
752}
753
David Anderson7016a0d2019-12-16 22:06:47 -0800754binder::Status ImageService::removeDisabledImages() {
755 if (!CheckUid()) return UidSecurityError();
756
Howard Chen67a27092020-02-15 17:32:02 +0800757 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson7016a0d2019-12-16 22:06:47 -0800758 if (!impl_->RemoveDisabledImages()) {
759 return BinderError("Failed to remove disabled images");
760 }
761 return binder::Status::ok();
762}
763
David Andersonf116bec2022-02-10 23:35:03 -0800764binder::Status ImageService::isImageDisabled(const std::string& name, bool* _aidl_return) {
765 if (!CheckUid()) return UidSecurityError();
766
767 std::lock_guard<std::mutex> guard(service_->lock());
768 *_aidl_return = impl_->IsImageDisabled(name);
769 return binder::Status::ok();
770}
771
David Anderson14aa72a2019-12-17 21:27:59 -0800772binder::Status ImageService::getMappedImageDevice(const std::string& name, std::string* device) {
773 if (!CheckUid()) return UidSecurityError();
774
Howard Chen67a27092020-02-15 17:32:02 +0800775 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson14aa72a2019-12-17 21:27:59 -0800776 if (!impl_->GetMappedImageDevice(name, device)) {
777 *device = "";
778 }
779 return binder::Status::ok();
780}
781
David Andersonbee55a02019-08-01 15:01:55 -0700782bool ImageService::CheckUid() {
David Anderson6f373b72019-06-05 15:04:00 -0700783 return uid_ == IPCThreadState::self()->getCallingUid();
784}
785
David Anderson551ae3a2019-08-01 12:53:06 -0700786binder::Status GsiService::openImageService(const std::string& prefix,
787 android::sp<IImageService>* _aidl_return) {
Howard Chen3a5e19a2021-01-07 16:07:52 +0800788 using android::base::StartsWith;
789
David Anderson6f373b72019-06-05 15:04:00 -0700790 static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
791 static constexpr char kImageDataPrefix[] = "/data/gsi/";
792
David Anderson6ad45ba2019-07-29 12:51:23 -0700793 auto in_metadata_dir = kImageMetadataPrefix + prefix;
794 auto in_data_dir = kImageDataPrefix + prefix;
Howard Chenee5c2b12019-11-08 11:57:47 +0800795 auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix));
David Anderson6f373b72019-06-05 15:04:00 -0700796
Alessio Balsinibb774d02020-01-21 23:34:39 +0000797 std::string in_data_dir_tmp;
798 if (android::base::ReadFileToString(install_dir_file, &in_data_dir_tmp)) {
799 in_data_dir = in_data_dir_tmp;
Howard Chenee5c2b12019-11-08 11:57:47 +0800800 LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir;
801 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700802 std::string metadata_dir, data_dir;
803 if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000804 PLOG(ERROR) << "realpath failed for metadata: " << in_metadata_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700805 return BinderError("Invalid path");
806 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700807 if (!android::base::Realpath(in_data_dir, &data_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000808 PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700809 return BinderError("Invalid path");
810 }
Howard Chen3a5e19a2021-01-07 16:07:52 +0800811 if (!StartsWith(metadata_dir, kImageMetadataPrefix)) {
812 return BinderError("Invalid metadata path");
813 }
814 if (!StartsWith(data_dir, kImageDataPrefix) && !StartsWith(data_dir, kDsuSDPrefix)) {
815 return BinderError("Invalid data path");
David Anderson6f373b72019-06-05 15:04:00 -0700816 }
817
818 uid_t uid = IPCThreadState::self()->getCallingUid();
819 if (uid != AID_ROOT) {
820 return UidSecurityError();
821 }
822
823 auto impl = ImageManager::Open(metadata_dir, data_dir);
824 if (!impl) {
825 return BinderError("Unknown error");
826 }
827
David Anderson551ae3a2019-08-01 12:53:06 -0700828 *_aidl_return = new ImageService(this, std::move(impl), uid);
David Anderson6f373b72019-06-05 15:04:00 -0700829 return binder::Status::ok();
830}
831
David Andersonb5f44b32019-02-20 18:04:37 -0800832binder::Status GsiService::CheckUid(AccessLevel level) {
833 std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
834 if (level == AccessLevel::SystemOrShell) {
835 allowed_uids.push_back(AID_SHELL);
David Anderson3c819cb2019-02-08 17:50:50 -0800836 }
837
David Andersonb5f44b32019-02-20 18:04:37 -0800838 uid_t uid = IPCThreadState::self()->getCallingUid();
839 for (const auto& allowed_uid : allowed_uids) {
840 if (allowed_uid == uid) {
841 return binder::Status::ok();
842 }
843 }
David Anderson6f373b72019-06-05 15:04:00 -0700844 return UidSecurityError();
David Anderson3c819cb2019-02-08 17:50:50 -0800845}
846
David Andersone7a8ade2019-03-13 19:21:22 -0700847static bool IsExternalStoragePath(const std::string& path) {
Howard Chen3a5e19a2021-01-07 16:07:52 +0800848 if (!android::base::StartsWith(path, kDsuSDPrefix)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700849 return false;
850 }
851 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
852 if (fd < 0) {
853 PLOG(ERROR) << "open failed: " << path;
854 return false;
855 }
856 struct statfs info;
857 if (fstatfs(fd, &info)) {
858 PLOG(ERROR) << "statfs failed: " << path;
859 return false;
860 }
861 LOG(ERROR) << "fs type: " << info.f_type;
862 return info.f_type == MSDOS_SUPER_MAGIC;
863}
864
Howard Chen4663de62019-11-05 20:46:20 +0800865int GsiService::ValidateInstallParams(std::string& install_dir) {
David Anderson49eea5f2019-05-23 13:27:01 -0700866 // If no install path was specified, use the default path. We also allow
867 // specifying the top-level folder, and then we choose the correct location
868 // underneath.
Howard Chen4663de62019-11-05 20:46:20 +0800869 if (install_dir.empty() || install_dir == "/data/gsi") {
870 install_dir = kDefaultDsuImageFolder;
David Andersoneb30ac22019-03-12 15:24:53 -0700871 }
872
Howard Chene1870742021-02-18 18:32:20 +0800873 if (access(install_dir.c_str(), F_OK) != 0 && (errno == ENOENT)) {
874 if (android::base::StartsWith(install_dir, kDsuSDPrefix)) {
875 if (mkdir(install_dir.c_str(), 0755) != 0) {
876 PLOG(ERROR) << "Failed to create " << install_dir;
877 return INSTALL_ERROR_GENERIC;
878 }
879 }
880 }
David Andersoneb30ac22019-03-12 15:24:53 -0700881 // Normalize the path and add a trailing slash.
Howard Chen4663de62019-11-05 20:46:20 +0800882 std::string origInstallDir = install_dir;
883 if (!android::base::Realpath(origInstallDir, &install_dir)) {
David Andersoneb30ac22019-03-12 15:24:53 -0700884 PLOG(ERROR) << "realpath failed: " << origInstallDir;
885 return INSTALL_ERROR_GENERIC;
886 }
David Anderson64b53fb2019-07-01 19:05:35 -0700887 // Ensure the path ends in / for consistency.
Howard Chen4663de62019-11-05 20:46:20 +0800888 if (!android::base::EndsWith(install_dir, "/")) {
889 install_dir += "/";
David Andersoneb30ac22019-03-12 15:24:53 -0700890 }
891
David Andersone7a8ade2019-03-13 19:21:22 -0700892 // Currently, we can only install to /data/gsi/ or external storage.
Howard Chen4663de62019-11-05 20:46:20 +0800893 if (IsExternalStoragePath(install_dir)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700894 Fstab fstab;
895 if (!ReadDefaultFstab(&fstab)) {
896 LOG(ERROR) << "cannot read default fstab";
897 return INSTALL_ERROR_GENERIC;
898 }
899 FstabEntry* system = GetEntryForMountPoint(&fstab, "/system");
900 if (!system) {
901 LOG(ERROR) << "cannot find /system fstab entry";
902 return INSTALL_ERROR_GENERIC;
903 }
904 if (fs_mgr_verity_is_check_at_most_once(*system)) {
905 LOG(ERROR) << "cannot install GSIs to external media if verity uses check_at_most_once";
906 return INSTALL_ERROR_GENERIC;
907 }
Howard Chen4663de62019-11-05 20:46:20 +0800908 } else if (install_dir != kDefaultDsuImageFolder) {
909 LOG(ERROR) << "cannot install DSU to " << install_dir;
David Andersoneb30ac22019-03-12 15:24:53 -0700910 return INSTALL_ERROR_GENERIC;
911 }
912 return INSTALL_OK;
913}
914
Howard Chenee5c2b12019-11-08 11:57:47 +0800915std::string GsiService::GetActiveDsuSlot() {
916 if (!install_dir_.empty()) {
917 return GetDsuSlot(install_dir_);
918 } else {
919 std::string active_dsu;
920 return GetActiveDsu(&active_dsu) ? active_dsu : "";
921 }
922}
923
Howard Chen3f6d5a62019-08-22 15:26:33 +0800924std::string GsiService::GetActiveInstalledImageDir() {
925 // Just in case an install was left hanging.
926 if (installer_) {
927 return installer_->install_dir();
928 } else {
929 return GetInstalledImageDir();
930 }
931}
932
David Anderson5f805912019-03-07 12:41:15 -0800933std::string GsiService::GetInstalledImageDir() {
934 // If there's no install left, just return /data/gsi since that's where
935 // installs go by default.
Howard Chenee5c2b12019-11-08 11:57:47 +0800936 std::string active_dsu;
David Anderson5f805912019-03-07 12:41:15 -0800937 std::string dir;
Howard Chenee5c2b12019-11-08 11:57:47 +0800938 if (GetActiveDsu(&active_dsu) &&
939 android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) {
David Anderson5f805912019-03-07 12:41:15 -0800940 return dir;
941 }
David Anderson9bdf8632019-07-01 14:49:11 -0700942 return kDefaultDsuImageFolder;
David Anderson5f805912019-03-07 12:41:15 -0800943}
944
Yo Chiang1f080912020-10-07 17:29:57 +0800945static android::sp<android::os::IVold> GetVoldService() {
946 return android::waitForService<android::os::IVold>(android::String16("vold"));
947}
948
Howard Chen4663de62019-11-05 20:46:20 +0800949bool GsiService::RemoveGsiFiles(const std::string& install_dir) {
David Anderson563e29a2019-03-06 19:20:45 -0800950 bool ok = true;
Howard Chenee5c2b12019-11-08 11:57:47 +0800951 auto active_dsu = GetDsuSlot(install_dir);
952 if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) {
Howard Chen18109b12019-08-13 17:00:44 +0800953 std::vector<std::string> images = manager->GetAllBackingImages();
954 for (auto&& image : images) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800955 if (!android::base::EndsWith(image, kDsuPostfix)) {
Howard Chen18109b12019-08-13 17:00:44 +0800956 continue;
Howard Chen3f6d5a62019-08-22 15:26:33 +0800957 }
958 if (manager->IsImageMapped(image)) {
959 ok &= manager->UnmapImageDevice(image);
960 }
Howard Chen4663de62019-11-05 20:46:20 +0800961 ok &= manager->DeleteBackingImage(image);
David Anderson64b53fb2019-07-01 19:05:35 -0700962 }
David Anderson563e29a2019-03-06 19:20:45 -0800963 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800964 auto dsu_slot = GetDsuSlot(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800965 std::vector<std::string> files{
David Anderson9bdf8632019-07-01 14:49:11 -0700966 kDsuInstallStatusFile,
David Anderson9bdf8632019-07-01 14:49:11 -0700967 kDsuOneShotBootFile,
Howard Chenee5c2b12019-11-08 11:57:47 +0800968 DsuInstallDirFile(dsu_slot),
969 GetCompleteIndication(dsu_slot),
David Andersonc053b3b2019-01-08 18:22:07 -0800970 };
David Andersonc053b3b2019-01-08 18:22:07 -0800971 for (const auto& file : files) {
David Anderson64b53fb2019-07-01 19:05:35 -0700972 std::string message;
Howard Chen4663de62019-11-05 20:46:20 +0800973 if (!RemoveFileIfExists(file, &message)) {
David Andersonc053b3b2019-01-08 18:22:07 -0800974 LOG(ERROR) << message;
975 ok = false;
976 }
977 }
Yo Chiang1f080912020-10-07 17:29:57 +0800978 if (auto vold = GetVoldService()) {
979 auto status = vold->destroyDsuMetadataKey(dsu_slot);
980 if (status.isOk()) {
981 std::string message;
982 if (!RemoveFileIfExists(DsuMetadataKeyDirFile(dsu_slot), &message)) {
983 LOG(ERROR) << message;
984 ok = false;
985 }
986 } else {
987 LOG(ERROR) << "Failed to destroy DSU metadata encryption key.";
988 ok = false;
989 }
990 } else {
991 LOG(ERROR) << "Failed to retrieve vold service.";
992 ok = false;
993 }
Howard Chen7885d3c2020-02-26 12:48:41 +0800994 if (ok) {
995 SetProperty(kGsiInstalledProp, "0");
996 }
David Andersonb3aff182019-01-11 14:37:51 -0800997 return ok;
998}
999
Yi-Yo Chiangd646d792022-04-04 21:38:57 +08001000int GsiService::EnableGsi(bool one_shot, const std::string& dsu_slot) {
1001 if (!android::gsi::IsGsiInstalled()) {
1002 LOG(ERROR) << "no gsi installed - cannot enable";
1003 return IGsiService::INSTALL_ERROR_GENERIC;
1004 }
1005 if (installer_) {
1006 LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?";
1007 return IGsiService::INSTALL_ERROR_GENERIC;
1008 }
1009
1010 if (!DisableGsi()) {
1011 PLOG(ERROR) << "cannot write DSU status file";
1012 return IGsiService::INSTALL_ERROR_GENERIC;
1013 }
1014 if (!SetBootMode(one_shot)) {
1015 return IGsiService::INSTALL_ERROR_GENERIC;
1016 }
1017 if (!ResetBootAttemptCounter()) {
1018 return IGsiService::INSTALL_ERROR_GENERIC;
1019 }
1020
1021 if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
1022 PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
1023 return IGsiService::INSTALL_ERROR_GENERIC;
1024 }
1025 RestoreconMetadataFiles();
1026 return IGsiService::INSTALL_OK;
1027}
1028
David Andersona141ba82019-01-14 19:09:27 -08001029bool GsiService::DisableGsiInstall() {
1030 if (!android::gsi::IsGsiInstalled()) {
1031 LOG(ERROR) << "cannot disable gsi install - no install detected";
1032 return false;
David Andersonb3aff182019-01-11 14:37:51 -08001033 }
David Andersonb2988ab2019-04-16 17:14:09 -07001034 if (installer_) {
David Andersona141ba82019-01-14 19:09:27 -08001035 LOG(ERROR) << "cannot disable gsi during GSI installation";
1036 return false;
1037 }
1038 if (!DisableGsi()) {
1039 PLOG(ERROR) << "could not write gsi status";
1040 return false;
1041 }
1042 return true;
David Andersonc053b3b2019-01-08 18:22:07 -08001043}
1044
Howard Chenee5c2b12019-11-08 11:57:47 +08001045std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) {
1046 return DSU_METADATA_PREFIX + dsu_slot + "/complete";
Howard Chen4663de62019-11-05 20:46:20 +08001047}
1048
Howard Chenee5c2b12019-11-08 11:57:47 +08001049bool GsiService::IsInstallationComplete(const std::string& dsu_slot) {
1050 if (access(kDsuInstallStatusFile, F_OK) != 0) {
1051 return false;
1052 }
1053 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +08001054 std::string content;
1055 if (!ReadFileToString(file, &content)) {
1056 return false;
1057 }
1058 return content == "OK";
1059}
1060
Howard Chenee5c2b12019-11-08 11:57:47 +08001061std::vector<std::string> GsiService::GetInstalledDsuSlots() {
1062 std::vector<std::string> dsu_slots;
1063 auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir);
1064 if (d != nullptr) {
1065 struct dirent* de;
1066 while ((de = readdir(d.get())) != nullptr) {
1067 if (de->d_name[0] == '.') {
1068 continue;
1069 }
1070 auto dsu_slot = std::string(de->d_name);
1071 if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) {
1072 continue;
1073 }
1074 dsu_slots.push_back(dsu_slot);
1075 }
1076 }
1077 return dsu_slots;
1078}
1079
Howard Chen3f6d5a62019-08-22 15:26:33 +08001080void GsiService::CleanCorruptedInstallation() {
Howard Chenee5c2b12019-11-08 11:57:47 +08001081 for (auto&& slot : GetInstalledDsuSlots()) {
1082 bool is_complete = IsInstallationComplete(slot);
1083 if (!is_complete) {
1084 LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot;
1085 std::string install_dir;
1086 if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) ||
1087 !RemoveGsiFiles(install_dir)) {
1088 LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot;
1089 }
Howard Chen4663de62019-11-05 20:46:20 +08001090 }
Howard Chen3f6d5a62019-08-22 15:26:33 +08001091 }
1092}
1093
David Andersonb3aff182019-01-11 14:37:51 -08001094void GsiService::RunStartupTasks() {
Howard Chen4663de62019-11-05 20:46:20 +08001095 CleanCorruptedInstallation();
David Andersonb3aff182019-01-11 14:37:51 -08001096
Howard Chenee5c2b12019-11-08 11:57:47 +08001097 std::string active_dsu;
1098 if (!GetActiveDsu(&active_dsu)) {
1099 PLOG(INFO) << "no DSU";
1100 return;
1101 }
David Andersonb3aff182019-01-11 14:37:51 -08001102 std::string boot_key;
1103 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -07001104 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001105 return;
1106 }
1107
1108 if (!IsGsiRunning()) {
1109 // Check if a wipe was requested from fastboot or adb-in-gsi.
1110 if (boot_key == kInstallStatusWipe) {
Howard Chen4663de62019-11-05 20:46:20 +08001111 RemoveGsiFiles(GetInstalledImageDir());
David Andersonb3aff182019-01-11 14:37:51 -08001112 }
1113 } else {
David Anderson564a04c2019-02-27 13:33:44 -08001114 // NB: When single-boot is enabled, init will write "disabled" into the
1115 // install_status file, which will cause GetBootAttempts to return
1116 // false. Thus, we won't write "ok" here.
David Andersonb3aff182019-01-11 14:37:51 -08001117 int ignore;
1118 if (GetBootAttempts(boot_key, &ignore)) {
1119 // Mark the GSI as having successfully booted.
David Anderson9bdf8632019-07-01 14:49:11 -07001120 if (!android::base::WriteStringToFile(kInstallStatusOk, kDsuInstallStatusFile)) {
1121 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001122 }
1123 }
1124 }
1125}
1126
David Anderson73274df2022-01-10 02:37:33 +00001127void GsiService::VerifyImageMaps() {
1128 std::vector<std::pair<std::string, std::string>> paths = {
1129 {"/metadata/gsi/remount", "/data/gsi/remount"},
1130 {"/metadata/gsi/ota", "/data/gsi/ota"},
1131 };
1132
1133 for (const auto& [metadata_dir, data_dir] : paths) {
1134 auto impl = ImageManager::Open(metadata_dir, data_dir);
1135 if (!impl) {
1136 LOG(ERROR) << "Could not open ImageManager for " << metadata_dir << " and " << data_dir;
1137 continue;
1138 }
1139 if (!impl->ValidateImageMaps()) {
1140 LOG(ERROR) << "ImageManager for " << metadata_dir
1141 << " failed validation, device data is at risk. Rebooting.";
1142 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
1143 continue;
1144 }
1145 LOG(INFO) << "ImageManager verification passed for " << metadata_dir;
1146 }
1147}
1148
Yo Chiang53bed1c2020-01-01 16:25:19 +08001149static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) {
1150 // Read the AVB footer from EOF.
1151 int64_t total_size = get_block_device_size(fd);
1152 int64_t footer_offset = total_size - AVB_FOOTER_SIZE;
1153 std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes;
1154 if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) {
1155 PLOG(ERROR) << "cannot read AVB footer";
1156 return false;
1157 }
1158 // Validate the AVB footer data and byte swap to native byte order.
1159 AvbFooter footer;
1160 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) {
1161 LOG(ERROR) << "invalid AVB footer";
1162 return false;
1163 }
1164 // Read the VBMeta image.
1165 std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size);
1166 if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) {
1167 PLOG(ERROR) << "cannot read VBMeta image";
1168 return false;
1169 }
1170 // Validate the VBMeta image and retrieve AVB public key.
1171 // After a successful call to avb_vbmeta_image_verify(), public_key_data
1172 // will point to the serialized AVB public key, in the same format generated
1173 // by the `avbtool extract_public_key` command.
1174 const uint8_t* public_key_data;
1175 size_t public_key_size;
1176 AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(),
1177 &public_key_data, &public_key_size);
1178 if (result != AVB_VBMETA_VERIFY_RESULT_OK) {
1179 LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result);
1180 return false;
1181 }
1182 if (public_key_data != nullptr) {
1183 dst->bytes.resize(public_key_size);
1184 memcpy(dst->bytes.data(), public_key_data, public_key_size);
1185 dst->sha1.resize(SHA_DIGEST_LENGTH);
1186 SHA1(public_key_data, public_key_size, dst->sha1.data());
1187 }
1188 return true;
1189}
1190
David Andersonc053b3b2019-01-08 18:22:07 -08001191} // namespace gsi
1192} // namespace android