blob: 77db54bbaa9530f7389508d771e822678045f1c3 [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
19#include <errno.h>
David Andersona141ba82019-01-14 19:09:27 -080020#include <linux/fs.h>
Howard Chen4663de62019-11-05 20:46:20 +080021#include <stdio.h>
David Andersona141ba82019-01-14 19:09:27 -080022#include <sys/ioctl.h>
David Andersonc053b3b2019-01-08 18:22:07 -080023#include <sys/stat.h>
David Andersonc053b3b2019-01-08 18:22:07 -080024#include <sys/types.h>
David Andersone7a8ade2019-03-13 19:21:22 -070025#include <sys/vfs.h>
David Andersonc053b3b2019-01-08 18:22:07 -080026#include <unistd.h>
27
Yo Chiang53bed1c2020-01-01 16:25:19 +080028#include <array>
David Andersonc053b3b2019-01-08 18:22:07 -080029#include <chrono>
30#include <string>
31#include <vector>
32
Yifan Hongd66695b2019-12-23 16:07:45 -080033#include <android-base/errors.h>
David Andersonc053b3b2019-01-08 18:22:07 -080034#include <android-base/file.h>
35#include <android-base/logging.h>
Howard Chen0e188062020-02-26 12:48:41 +080036#include <android-base/properties.h>
David Andersonc053b3b2019-01-08 18:22:07 -080037#include <android-base/stringprintf.h>
David Anderson5f805912019-03-07 12:41:15 -080038#include <android-base/strings.h>
David Anderson551ae3a2019-08-01 12:53:06 -070039#include <android/gsi/BnImageService.h>
David Andersonc053b3b2019-01-08 18:22:07 -080040#include <android/gsi/IGsiService.h>
David Anderson64b53fb2019-07-01 19:05:35 -070041#include <ext4_utils/ext4_utils.h>
David Andersone7a8ade2019-03-13 19:21:22 -070042#include <fs_mgr.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080043#include <libavb/libavb.h>
David Andersond614eca2019-09-09 17:57:06 -070044#include <libdm/dm.h>
David Anderson6f373b72019-06-05 15:04:00 -070045#include <libfiemap/image_manager.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080046#include <openssl/sha.h>
David Anderson3c819cb2019-02-08 17:50:50 -080047#include <private/android_filesystem_config.h>
David Andersonb3aff182019-01-11 14:37:51 -080048
David Andersonc053b3b2019-01-08 18:22:07 -080049#include "file_paths.h"
David Andersonb3aff182019-01-11 14:37:51 -080050#include "libgsi_private.h"
David Andersonc053b3b2019-01-08 18:22:07 -080051
52namespace android {
53namespace gsi {
54
55using namespace std::literals;
56using namespace android::fs_mgr;
David Anderson9ca77282019-07-15 23:56:13 +000057using namespace android::fiemap;
Howard Chen4663de62019-11-05 20:46:20 +080058using android::base::ReadFileToString;
Yo Chiang53bed1c2020-01-01 16:25:19 +080059using android::base::ReadFullyAtOffset;
Howard Chen4663de62019-11-05 20:46:20 +080060using android::base::RemoveFileIfExists;
Howard Chen0e188062020-02-26 12:48:41 +080061using android::base::SetProperty;
David Anderson3c819cb2019-02-08 17:50:50 -080062using android::base::StringPrintf;
David Andersonc86531e2019-02-25 18:50:35 -080063using android::base::unique_fd;
Howard Chen4663de62019-11-05 20:46:20 +080064using android::base::WriteStringToFd;
65using android::base::WriteStringToFile;
David Andersond614eca2019-09-09 17:57:06 -070066using android::dm::DeviceMapper;
David Andersonc053b3b2019-01-08 18:22:07 -080067
Howard Chen5e2d47e2019-12-13 14:03:18 +080068static std::mutex sInstanceLock;
69
David Anderson4c756732019-07-12 14:18:37 -070070android::wp<GsiService> GsiService::sInstance;
71
Howard Chen4663de62019-11-05 20:46:20 +080072// Default userdata image size.
73static constexpr int64_t kDefaultUserdataSize = int64_t(2) * 1024 * 1024 * 1024;
74
Yo Chiang53bed1c2020-01-01 16:25:19 +080075static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst);
76
David Anderson4c756732019-07-12 14:18:37 -070077void Gsid::Register() {
78 auto ret = android::BinderService<Gsid>::publish();
David Andersonc053b3b2019-01-08 18:22:07 -080079 if (ret != android::OK) {
80 LOG(FATAL) << "Could not register gsi service: " << ret;
81 }
82}
83
David Anderson4c756732019-07-12 14:18:37 -070084binder::Status Gsid::getClient(android::sp<IGsiService>* _aidl_return) {
85 *_aidl_return = GsiService::Get(this);
86 return binder::Status::ok();
87}
88
89GsiService::GsiService(Gsid* parent) : parent_(parent) {
David Anderson6a5b8a72019-01-16 16:24:48 -080090 progress_ = {};
91}
92
David Anderson4c756732019-07-12 14:18:37 -070093GsiService::~GsiService() {
Howard Chen5e2d47e2019-12-13 14:03:18 +080094 std::lock_guard<std::mutex> guard(sInstanceLock);
David Anderson4c756732019-07-12 14:18:37 -070095
96 if (sInstance == this) {
97 // No more consumers, gracefully shut down gsid.
98 exit(0);
99 }
100}
101
102android::sp<IGsiService> GsiService::Get(Gsid* parent) {
Howard Chen5e2d47e2019-12-13 14:03:18 +0800103 std::lock_guard<std::mutex> guard(sInstanceLock);
David Anderson4c756732019-07-12 14:18:37 -0700104
105 android::sp<GsiService> service = sInstance.promote();
106 if (!service) {
107 service = new GsiService(parent);
108 sInstance = service.get();
109 }
110 return service.get();
111}
David Andersonc053b3b2019-01-08 18:22:07 -0800112
David Anderson5cc440c2019-04-16 14:34:27 -0700113#define ENFORCE_SYSTEM \
114 do { \
115 binder::Status status = CheckUid(); \
116 if (!status.isOk()) return status; \
David Anderson3c819cb2019-02-08 17:50:50 -0800117 } while (0)
118
David Anderson5cc440c2019-04-16 14:34:27 -0700119#define ENFORCE_SYSTEM_OR_SHELL \
120 do { \
121 binder::Status status = CheckUid(AccessLevel::SystemOrShell); \
122 if (!status.isOk()) return status; \
David Andersonb5f44b32019-02-20 18:04:37 -0800123 } while (0)
124
Howard Chen4663de62019-11-05 20:46:20 +0800125int GsiService::SaveInstallation(const std::string& installation) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800126 auto dsu_slot = GetDsuSlot(installation);
127 auto install_dir_file = DsuInstallDirFile(dsu_slot);
128 auto metadata_dir = android::base::Dirname(install_dir_file);
129 if (access(metadata_dir.c_str(), F_OK) != 0) {
130 if (mkdir(metadata_dir.c_str(), 0777) != 0) {
131 PLOG(ERROR) << "Failed to mkdir " << metadata_dir;
132 return INSTALL_ERROR_GENERIC;
133 }
134 }
Howard Chen4663de62019-11-05 20:46:20 +0800135 auto fd = android::base::unique_fd(
Howard Chenee5c2b12019-11-08 11:57:47 +0800136 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 +0800137 if (!WriteStringToFd(installation, fd)) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800138 PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800139 return INSTALL_ERROR_GENERIC;
140 }
141 return INSTALL_OK;
142}
143
144binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
145 ENFORCE_SYSTEM;
146 std::lock_guard<std::mutex> guard(parent_->lock());
147 if (IsGsiRunning()) {
148 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
149 return binder::Status::ok();
150 }
151 install_dir_ = install_dir;
152 if (int status = ValidateInstallParams(install_dir_)) {
153 *_aidl_return = status;
154 return binder::Status::ok();
155 }
156 std::string message;
Howard Chenee5c2b12019-11-08 11:57:47 +0800157 auto dsu_slot = GetDsuSlot(install_dir_);
158 if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
Howard Chen4663de62019-11-05 20:46:20 +0800159 LOG(ERROR) << message;
160 }
161 // Remember the installation directory before allocate any resource
162 *_aidl_return = SaveInstallation(install_dir_);
163 return binder::Status::ok();
164}
165
166binder::Status GsiService::closeInstall(int* _aidl_return) {
167 ENFORCE_SYSTEM;
168 std::lock_guard<std::mutex> guard(parent_->lock());
Howard Chenee5c2b12019-11-08 11:57:47 +0800169 auto dsu_slot = GetDsuSlot(install_dir_);
170 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800171 if (!WriteStringToFile("OK", file)) {
172 PLOG(ERROR) << "write failed: " << file;
173 *_aidl_return = INSTALL_ERROR_GENERIC;
174 }
Howard Chen4663de62019-11-05 20:46:20 +0800175 *_aidl_return = INSTALL_OK;
176 return binder::Status::ok();
177}
178
179binder::Status GsiService::createPartition(const ::std::string& name, int64_t size, bool readOnly,
180 int32_t* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800181 ENFORCE_SYSTEM;
David Anderson4c756732019-07-12 14:18:37 -0700182 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersonc053b3b2019-01-08 18:22:07 -0800183
Howard Chen4663de62019-11-05 20:46:20 +0800184 if (install_dir_.empty()) {
185 PLOG(ERROR) << "open is required for createPartition";
186 *_aidl_return = INSTALL_ERROR_GENERIC;
187 return binder::Status::ok();
188 }
189
190 // Make sure a pending interrupted installations are cleaned up.
David Andersonb2988ab2019-04-16 17:14:09 -0700191 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800192
David Andersoneb30ac22019-03-12 15:24:53 -0700193 // Do some precursor validation on the arguments before diving into the
194 // install process.
Howard Chen4663de62019-11-05 20:46:20 +0800195 if (size % LP_SECTOR_SIZE) {
196 LOG(ERROR) << " size " << size << " is not a multiple of " << LP_SECTOR_SIZE;
197 *_aidl_return = INSTALL_ERROR_GENERIC;
David Andersoneb30ac22019-03-12 15:24:53 -0700198 return binder::Status::ok();
199 }
200
Howard Chen4663de62019-11-05 20:46:20 +0800201 if (size == 0 && name == "userdata") {
202 size = kDefaultUserdataSize;
203 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800204 installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name,
205 GetDsuSlot(install_dir_), size, readOnly);
Howard Chen9f40baf2019-12-16 13:31:12 +0800206 progress_ = {};
David Andersonb2988ab2019-04-16 17:14:09 -0700207 int status = installer_->StartInstall();
David Anderson868dea52019-01-17 13:34:38 -0800208 if (status != INSTALL_OK) {
David Andersonb2988ab2019-04-16 17:14:09 -0700209 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800210 }
David Anderson868dea52019-01-17 13:34:38 -0800211 *_aidl_return = status;
David Andersonc053b3b2019-01-08 18:22:07 -0800212 return binder::Status::ok();
213}
214
David Anderson1d94d262019-01-11 20:39:51 -0800215binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
David Andersonc053b3b2019-01-08 18:22:07 -0800216 int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800217 ENFORCE_SYSTEM;
David Anderson4c756732019-07-12 14:18:37 -0700218 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersonc053b3b2019-01-08 18:22:07 -0800219
David Andersonb2988ab2019-04-16 17:14:09 -0700220 if (!installer_) {
221 *_aidl_return = false;
222 return binder::Status::ok();
223 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800224
David Andersonb2988ab2019-04-16 17:14:09 -0700225 *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
David Anderson6a5b8a72019-01-16 16:24:48 -0800226 return binder::Status::ok();
227}
228
229void GsiService::StartAsyncOperation(const std::string& step, int64_t total_bytes) {
230 std::lock_guard<std::mutex> guard(progress_lock_);
231
232 progress_.step = step;
233 progress_.status = STATUS_WORKING;
234 progress_.bytes_processed = 0;
235 progress_.total_bytes = total_bytes;
236}
237
238void GsiService::UpdateProgress(int status, int64_t bytes_processed) {
239 std::lock_guard<std::mutex> guard(progress_lock_);
240
241 progress_.status = status;
David Andersona64e3922019-02-01 16:27:18 -0800242 if (status == STATUS_COMPLETE) {
243 progress_.bytes_processed = progress_.total_bytes;
244 } else {
245 progress_.bytes_processed = bytes_processed;
246 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800247}
248
249binder::Status GsiService::getInstallProgress(::android::gsi::GsiProgress* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800250 ENFORCE_SYSTEM;
David Anderson6a5b8a72019-01-16 16:24:48 -0800251 std::lock_guard<std::mutex> guard(progress_lock_);
252
Howard Chen9f40baf2019-12-16 13:31:12 +0800253 if (installer_ == nullptr) {
254 progress_ = {};
255 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800256 *_aidl_return = progress_;
David Andersonc053b3b2019-01-08 18:22:07 -0800257 return binder::Status::ok();
258}
259
Howard Chen5676d962019-08-05 16:21:00 +0800260binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800261 ENFORCE_SYSTEM;
David Anderson4c756732019-07-12 14:18:37 -0700262 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersonc053b3b2019-01-08 18:22:07 -0800263
David Andersonb2988ab2019-04-16 17:14:09 -0700264 if (!installer_) {
265 *_aidl_return = false;
266 return binder::Status::ok();
267 }
Howard Chen5676d962019-08-05 16:21:00 +0800268 *_aidl_return = installer_->CommitGsiChunk(bytes);
269 return binder::Status::ok();
270}
David Andersonb2988ab2019-04-16 17:14:09 -0700271
Howard Chen5676d962019-08-05 16:21:00 +0800272binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem,
273 int64_t size, bool* _aidl_return) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800274 ENFORCE_SYSTEM;
Howard Chen5676d962019-08-05 16:21:00 +0800275 if (!installer_) {
276 *_aidl_return = false;
277 return binder::Status::ok();
278 }
279 *_aidl_return = installer_->MapAshmem(ashmem.get(), size);
David Andersonc053b3b2019-01-08 18:22:07 -0800280 return binder::Status::ok();
281}
282
Howard Chen0e188062020-02-26 12:48:41 +0800283binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
284 const sp<IGsiServiceCallback>& resultCallback) {
285 int result;
286 auto status = enableGsi(one_shot, dsuSlot, &result);
287 if (!status.isOk()) {
288 LOG(ERROR) << "Could not enableGsi: " << status.exceptionMessage().string();
289 result = IGsiService::INSTALL_ERROR_GENERIC;
290 }
291 resultCallback->onResult(result);
292 return binder::Status::ok();
293}
294
Howard Chenee5c2b12019-11-08 11:57:47 +0800295binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
David Anderson4c756732019-07-12 14:18:37 -0700296 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersonc053b3b2019-01-08 18:22:07 -0800297
Howard Chenee5c2b12019-11-08 11:57:47 +0800298 if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) {
299 PLOG(ERROR) << "write failed: " << GetDsuSlot(install_dir_);
300 *_aidl_return = INSTALL_ERROR_GENERIC;
301 return binder::Status::ok();
302 }
David Andersonb2988ab2019-04-16 17:14:09 -0700303 if (installer_) {
David Anderson646b4b22019-02-27 18:26:54 -0800304 ENFORCE_SYSTEM;
Howard Chen4663de62019-11-05 20:46:20 +0800305 installer_ = {};
306 // Note: create the install status file last, since this is the actual boot
307 // indicator.
308 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
309 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
David Anderson5f805912019-03-07 12:41:15 -0800310 } else {
311 *_aidl_return = INSTALL_OK;
312 }
David Andersona141ba82019-01-14 19:09:27 -0800313 } else {
David Anderson646b4b22019-02-27 18:26:54 -0800314 ENFORCE_SYSTEM_OR_SHELL;
David Anderson564a04c2019-02-27 13:33:44 -0800315 *_aidl_return = ReenableGsi(one_shot);
David Andersona141ba82019-01-14 19:09:27 -0800316 }
David Anderson563e29a2019-03-06 19:20:45 -0800317
David Andersonb2988ab2019-04-16 17:14:09 -0700318 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800319 return binder::Status::ok();
320}
321
Howard Chen670b3062019-02-26 18:14:47 +0800322binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
323 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700324 std::lock_guard<std::mutex> guard(parent_->lock());
Howard Chen670b3062019-02-26 18:14:47 +0800325 std::string boot_key;
326 if (!GetInstallStatus(&boot_key)) {
327 *_aidl_return = false;
328 } else {
Howard Chenee5c2b12019-11-08 11:57:47 +0800329 *_aidl_return = (boot_key != kInstallStatusDisabled);
Howard Chen670b3062019-02-26 18:14:47 +0800330 }
331 return binder::Status::ok();
332}
333
Howard Chen0e188062020-02-26 12:48:41 +0800334binder::Status GsiService::removeGsiAsync(const sp<IGsiServiceCallback>& resultCallback) {
335 bool result;
336 auto status = removeGsi(&result);
337 if (!status.isOk()) {
338 LOG(ERROR) << "Could not removeGsi: " << status.exceptionMessage().string();
339 result = IGsiService::INSTALL_ERROR_GENERIC;
340 }
341 resultCallback->onResult(result);
342 return binder::Status::ok();
343}
344
Howard Chen25b18cc2019-08-02 11:21:58 +0800345binder::Status GsiService::removeGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800346 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700347 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersonc053b3b2019-01-08 18:22:07 -0800348
Howard Chen3f6d5a62019-08-22 15:26:33 +0800349 std::string install_dir = GetActiveInstalledImageDir();
David Andersona141ba82019-01-14 19:09:27 -0800350 if (IsGsiRunning()) {
351 // Can't remove gsi files while running.
352 *_aidl_return = UninstallGsi();
353 } else {
Howard Chendee5d302020-02-05 10:58:29 +0800354 installer_ = {};
Howard Chen4663de62019-11-05 20:46:20 +0800355 *_aidl_return = RemoveGsiFiles(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800356 }
357 return binder::Status::ok();
358}
359
Howard Chen25b18cc2019-08-02 11:21:58 +0800360binder::Status GsiService::disableGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800361 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700362 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersona141ba82019-01-14 19:09:27 -0800363
364 *_aidl_return = DisableGsiInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800365 return binder::Status::ok();
366}
367
368binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800369 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700370 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersona141ba82019-01-14 19:09:27 -0800371
David Andersonc053b3b2019-01-08 18:22:07 -0800372 *_aidl_return = IsGsiRunning();
373 return binder::Status::ok();
374}
375
David Andersona141ba82019-01-14 19:09:27 -0800376binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800377 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700378 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersona141ba82019-01-14 19:09:27 -0800379
380 *_aidl_return = IsGsiInstalled();
381 return binder::Status::ok();
382}
383
384binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800385 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700386 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersona141ba82019-01-14 19:09:27 -0800387
David Andersonb2988ab2019-04-16 17:14:09 -0700388 *_aidl_return = !!installer_;
David Andersona141ba82019-01-14 19:09:27 -0800389 return binder::Status::ok();
390}
391
392binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800393 ENFORCE_SYSTEM;
Howard Chenecbc0192019-02-25 18:51:26 +0800394 should_abort_ = true;
David Anderson4c756732019-07-12 14:18:37 -0700395 std::lock_guard<std::mutex> guard(parent_->lock());
David Andersona141ba82019-01-14 19:09:27 -0800396
Howard Chenecbc0192019-02-25 18:51:26 +0800397 should_abort_ = false;
David Andersonb2988ab2019-04-16 17:14:09 -0700398 installer_ = nullptr;
David Andersona141ba82019-01-14 19:09:27 -0800399
David Andersona141ba82019-01-14 19:09:27 -0800400 *_aidl_return = true;
401 return binder::Status::ok();
402}
403
David Anderson5f805912019-03-07 12:41:15 -0800404binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
405 ENFORCE_SYSTEM;
David Anderson4c756732019-07-12 14:18:37 -0700406 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson5f805912019-03-07 12:41:15 -0800407
Howard Chen3f6d5a62019-08-22 15:26:33 +0800408 *_aidl_return = GetActiveInstalledImageDir();
David Anderson5f805912019-03-07 12:41:15 -0800409 return binder::Status::ok();
410}
411
Howard Chenee5c2b12019-11-08 11:57:47 +0800412binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) {
413 ENFORCE_SYSTEM_OR_SHELL;
414 std::lock_guard<std::mutex> guard(parent_->lock());
415
416 *_aidl_return = GetActiveDsuSlot();
417 return binder::Status::ok();
418}
419
420binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) {
421 ENFORCE_SYSTEM;
422 std::lock_guard<std::mutex> guard(parent_->lock());
423 *_aidl_return = GetInstalledDsuSlots();
424 return binder::Status::ok();
425}
426
Howard Chen4663de62019-11-05 20:46:20 +0800427binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) {
David Anderson8bdf6252019-06-11 16:43:24 -0700428 ENFORCE_SYSTEM_OR_SHELL;
David Anderson4c756732019-07-12 14:18:37 -0700429 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson8bdf6252019-06-11 16:43:24 -0700430
431 if (IsGsiRunning() || !IsGsiInstalled()) {
432 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
433 return binder::Status::ok();
434 }
435
Howard Chen3f6d5a62019-08-22 15:26:33 +0800436 std::string install_dir = GetActiveInstalledImageDir();
Howard Chenee5c2b12019-11-08 11:57:47 +0800437 *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name);
David Anderson8bdf6252019-06-11 16:43:24 -0700438
439 return binder::Status::ok();
440}
441
Yifan Hongd66695b2019-12-23 16:07:45 -0800442static binder::Status BinderError(const std::string& message,
443 FiemapStatus::ErrorCode status = FiemapStatus::ErrorCode::ERROR) {
444 return binder::Status::fromServiceSpecificError(static_cast<int32_t>(status), message.c_str());
David Anderson6f373b72019-06-05 15:04:00 -0700445}
446
David Andersond614eca2019-09-09 17:57:06 -0700447binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) {
448 ENFORCE_SYSTEM_OR_SHELL;
449
450 auto& dm = DeviceMapper::Instance();
451
452 std::vector<DeviceMapper::DmBlockDevice> devices;
453 if (!dm.GetAvailableDevices(&devices)) {
454 return BinderError("Could not list devices");
455 }
456
457 std::stringstream text;
458 for (const auto& device : devices) {
459 text << "Device " << device.name() << " (" << device.Major() << ":" << device.Minor()
460 << ")\n";
461
462 std::vector<DeviceMapper::TargetInfo> table;
463 if (!dm.GetTableInfo(device.name(), &table)) {
464 continue;
465 }
466
467 for (const auto& target : table) {
468 const auto& spec = target.spec;
469 auto target_type = DeviceMapper::GetTargetType(spec);
470 text << " " << target_type << " " << spec.sector_start << " " << spec.length << " "
471 << target.data << "\n";
472 }
473 }
474
475 *_aidl_return = text.str();
476 return binder::Status::ok();
477}
478
Yo Chiang53bed1c2020-01-01 16:25:19 +0800479binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) {
480 ENFORCE_SYSTEM;
481 std::lock_guard<std::mutex> guard(parent_->lock());
482
483 if (!installer_) {
484 *_aidl_return = INSTALL_ERROR_GENERIC;
485 return binder::Status::ok();
486 }
487 int fd = installer_->GetPartitionFd();
488 if (!GetAvbPublicKeyFromFd(fd, dst)) {
489 LOG(ERROR) << "Failed to extract AVB public key";
490 *_aidl_return = INSTALL_ERROR_GENERIC;
491 return binder::Status::ok();
492 }
493 *_aidl_return = INSTALL_OK;
494 return binder::Status::ok();
495}
496
Howard Chen4663de62019-11-05 20:46:20 +0800497bool GsiService::CreateInstallStatusFile() {
498 if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
499 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
500 return false;
501 }
Howard Chen0e188062020-02-26 12:48:41 +0800502 SetProperty(kGsiInstalledProp, "1");
Howard Chen4663de62019-11-05 20:46:20 +0800503 return true;
504}
505
506bool GsiService::SetBootMode(bool one_shot) {
507 if (one_shot) {
508 if (!android::base::WriteStringToFile("1", kDsuOneShotBootFile)) {
509 PLOG(ERROR) << "write " << kDsuOneShotBootFile;
510 return false;
511 }
512 } else if (!access(kDsuOneShotBootFile, F_OK)) {
513 std::string error;
514 if (!android::base::RemoveFileIfExists(kDsuOneShotBootFile, &error)) {
515 LOG(ERROR) << error;
516 return false;
517 }
518 }
519 return true;
520}
521
David Anderson6f373b72019-06-05 15:04:00 -0700522static binder::Status UidSecurityError() {
523 uid_t uid = IPCThreadState::self()->getCallingUid();
524 auto message = StringPrintf("UID %d is not allowed", uid);
525 return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
526}
527
David Anderson551ae3a2019-08-01 12:53:06 -0700528class ImageService : public BinderService<ImageService>, public BnImageService {
David Anderson6f373b72019-06-05 15:04:00 -0700529 public:
David Anderson551ae3a2019-08-01 12:53:06 -0700530 ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
Howard Chen96c31fd2019-08-23 17:38:51 +0800531 binder::Status getAllBackingImages(std::vector<std::string>* _aidl_return);
Yifan Hongd66695b2019-12-23 16:07:45 -0800532 binder::Status createBackingImage(const std::string& name, int64_t size, int flags,
533 const sp<IProgressCallback>& on_progress) override;
David Anderson6f373b72019-06-05 15:04:00 -0700534 binder::Status deleteBackingImage(const std::string& name) override;
535 binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
536 MappedImage* mapping) override;
537 binder::Status unmapImageDevice(const std::string& name) override;
David Anderson394f1f22019-07-29 12:49:02 -0700538 binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override;
David Andersonbee55a02019-08-01 15:01:55 -0700539 binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override;
Yo Chiang53bed1c2020-01-01 16:25:19 +0800540 binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
541 int32_t* _aidl_return) override;
Alessio Balsini0829fb22019-08-27 17:50:18 +0100542 binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override;
David Anderson86846bd2019-11-26 16:30:40 -0800543 binder::Status removeAllImages() override;
David Anderson7016a0d2019-12-16 22:06:47 -0800544 binder::Status removeDisabledImages() override;
David Anderson14aa72a2019-12-17 21:27:59 -0800545 binder::Status getMappedImageDevice(const std::string& name, std::string* device) override;
David Anderson6f373b72019-06-05 15:04:00 -0700546
547 private:
548 bool CheckUid();
549
David Anderson4c756732019-07-12 14:18:37 -0700550 android::sp<GsiService> service_;
551 android::sp<Gsid> parent_;
David Anderson6f373b72019-06-05 15:04:00 -0700552 std::unique_ptr<ImageManager> impl_;
553 uid_t uid_;
554};
555
David Anderson551ae3a2019-08-01 12:53:06 -0700556ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
David Anderson4c756732019-07-12 14:18:37 -0700557 : service_(service), parent_(service->parent()), impl_(std::move(impl)), uid_(uid) {}
David Anderson6f373b72019-06-05 15:04:00 -0700558
Howard Chen96c31fd2019-08-23 17:38:51 +0800559binder::Status ImageService::getAllBackingImages(std::vector<std::string>* _aidl_return) {
560 *_aidl_return = impl_->GetAllBackingImages();
561 return binder::Status::ok();
562}
563
Yifan Hongd66695b2019-12-23 16:07:45 -0800564binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags,
565 const sp<IProgressCallback>& on_progress) {
David Anderson6f373b72019-06-05 15:04:00 -0700566 if (!CheckUid()) return UidSecurityError();
567
David Anderson4c756732019-07-12 14:18:37 -0700568 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700569
Yifan Hongd66695b2019-12-23 16:07:45 -0800570 std::function<bool(uint64_t, uint64_t)> callback;
571 if (on_progress) {
572 callback = [on_progress](uint64_t current, uint64_t total) -> bool {
573 auto status = on_progress->onProgress(static_cast<int64_t>(current),
574 static_cast<int64_t>(total));
575 if (!status.isOk()) {
576 LOG(ERROR) << "progress callback returned: " << status.toString8().string();
577 return false;
578 }
579 return true;
580 };
581 }
582
583 auto res = impl_->CreateBackingImage(name, size, flags, std::move(callback));
584 if (!res.is_ok()) {
585 return BinderError("Failed to create: " + res.string(), res.error_code());
David Anderson6f373b72019-06-05 15:04:00 -0700586 }
587 return binder::Status::ok();
588}
589
David Anderson551ae3a2019-08-01 12:53:06 -0700590binder::Status ImageService::deleteBackingImage(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700591 if (!CheckUid()) return UidSecurityError();
592
David Anderson4c756732019-07-12 14:18:37 -0700593 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700594
595 if (!impl_->DeleteBackingImage(name)) {
596 return BinderError("Failed to delete");
597 }
598 return binder::Status::ok();
599}
600
David Anderson551ae3a2019-08-01 12:53:06 -0700601binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
602 MappedImage* mapping) {
David Anderson6f373b72019-06-05 15:04:00 -0700603 if (!CheckUid()) return UidSecurityError();
604
David Anderson4c756732019-07-12 14:18:37 -0700605 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700606
607 if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
608 return BinderError("Failed to map");
609 }
610 return binder::Status::ok();
611}
612
David Anderson551ae3a2019-08-01 12:53:06 -0700613binder::Status ImageService::unmapImageDevice(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700614 if (!CheckUid()) return UidSecurityError();
615
David Anderson4c756732019-07-12 14:18:37 -0700616 std::lock_guard<std::mutex> guard(parent_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700617
618 if (!impl_->UnmapImageDevice(name)) {
619 return BinderError("Failed to unmap");
620 }
621 return binder::Status::ok();
622}
623
David Anderson551ae3a2019-08-01 12:53:06 -0700624binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
David Anderson394f1f22019-07-29 12:49:02 -0700625 if (!CheckUid()) return UidSecurityError();
626
627 std::lock_guard<std::mutex> guard(parent_->lock());
628
629 *_aidl_return = impl_->BackingImageExists(name);
630 return binder::Status::ok();
631}
632
David Andersonbee55a02019-08-01 15:01:55 -0700633binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_return) {
634 if (!CheckUid()) return UidSecurityError();
635
636 std::lock_guard<std::mutex> guard(parent_->lock());
637
638 *_aidl_return = impl_->IsImageMapped(name);
639 return binder::Status::ok();
640}
641
Yo Chiang53bed1c2020-01-01 16:25:19 +0800642binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
643 int32_t* _aidl_return) {
644 if (!CheckUid()) return UidSecurityError();
645
646 std::lock_guard<std::mutex> guard(parent_->lock());
647
648 std::string device_path;
649 std::unique_ptr<MappedDevice> mapped_device;
650 if (!impl_->IsImageMapped(name)) {
651 mapped_device = MappedDevice::Open(impl_.get(), 10s, name);
652 if (!mapped_device) {
653 PLOG(ERROR) << "Fail to map image: " << name;
654 *_aidl_return = IMAGE_ERROR;
655 return binder::Status::ok();
656 }
657 device_path = mapped_device->path();
658 } else {
659 if (!impl_->GetMappedImageDevice(name, &device_path)) {
660 PLOG(ERROR) << "GetMappedImageDevice() failed";
661 *_aidl_return = IMAGE_ERROR;
662 return binder::Status::ok();
663 }
664 }
665 android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
666 if (!fd.ok()) {
667 PLOG(ERROR) << "Fail to open mapped device: " << device_path;
668 *_aidl_return = IMAGE_ERROR;
669 return binder::Status::ok();
670 }
671 bool ok = GetAvbPublicKeyFromFd(fd.get(), dst);
672 fd = {};
673 if (!ok) {
674 LOG(ERROR) << "Failed to extract AVB public key";
675 *_aidl_return = IMAGE_ERROR;
676 return binder::Status::ok();
677 }
678 *_aidl_return = IMAGE_OK;
679 return binder::Status::ok();
680}
681
Alessio Balsini0829fb22019-08-27 17:50:18 +0100682binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) {
683 if (!CheckUid()) return UidSecurityError();
684
685 std::lock_guard<std::mutex> guard(parent_->lock());
686
687 if (bytes < 0) {
688 return BinderError("Cannot use negative values");
689 }
Yifan Hongd66695b2019-12-23 16:07:45 -0800690 auto res = impl_->ZeroFillNewImage(name, bytes);
691 if (!res.is_ok()) {
692 return BinderError("Failed to fill image with zeros: " + res.string(), res.error_code());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100693 }
694 return binder::Status::ok();
695}
696
David Anderson86846bd2019-11-26 16:30:40 -0800697binder::Status ImageService::removeAllImages() {
698 if (!CheckUid()) return UidSecurityError();
699
700 std::lock_guard<std::mutex> guard(parent_->lock());
701 if (!impl_->RemoveAllImages()) {
702 return BinderError("Failed to remove all images");
703 }
704 return binder::Status::ok();
705}
706
David Anderson7016a0d2019-12-16 22:06:47 -0800707binder::Status ImageService::removeDisabledImages() {
708 if (!CheckUid()) return UidSecurityError();
709
710 std::lock_guard<std::mutex> guard(parent_->lock());
711 if (!impl_->RemoveDisabledImages()) {
712 return BinderError("Failed to remove disabled images");
713 }
714 return binder::Status::ok();
715}
716
David Anderson14aa72a2019-12-17 21:27:59 -0800717binder::Status ImageService::getMappedImageDevice(const std::string& name, std::string* device) {
718 if (!CheckUid()) return UidSecurityError();
719
720 std::lock_guard<std::mutex> guard(parent_->lock());
721 if (!impl_->GetMappedImageDevice(name, device)) {
722 *device = "";
723 }
724 return binder::Status::ok();
725}
726
David Andersonbee55a02019-08-01 15:01:55 -0700727bool ImageService::CheckUid() {
David Anderson6f373b72019-06-05 15:04:00 -0700728 return uid_ == IPCThreadState::self()->getCallingUid();
729}
730
David Anderson551ae3a2019-08-01 12:53:06 -0700731binder::Status GsiService::openImageService(const std::string& prefix,
732 android::sp<IImageService>* _aidl_return) {
David Anderson6f373b72019-06-05 15:04:00 -0700733 static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
734 static constexpr char kImageDataPrefix[] = "/data/gsi/";
735
David Anderson6ad45ba2019-07-29 12:51:23 -0700736 auto in_metadata_dir = kImageMetadataPrefix + prefix;
737 auto in_data_dir = kImageDataPrefix + prefix;
Howard Chenee5c2b12019-11-08 11:57:47 +0800738 auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix));
David Anderson6f373b72019-06-05 15:04:00 -0700739
Alessio Balsinibb774d02020-01-21 23:34:39 +0000740 std::string in_data_dir_tmp;
741 if (android::base::ReadFileToString(install_dir_file, &in_data_dir_tmp)) {
742 in_data_dir = in_data_dir_tmp;
Howard Chenee5c2b12019-11-08 11:57:47 +0800743 LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir;
744 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700745 std::string metadata_dir, data_dir;
746 if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000747 PLOG(ERROR) << "realpath failed for metadata: " << in_metadata_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700748 return BinderError("Invalid path");
749 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700750 if (!android::base::Realpath(in_data_dir, &data_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000751 PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700752 return BinderError("Invalid path");
753 }
754 if (!android::base::StartsWith(metadata_dir, kImageMetadataPrefix) ||
755 !android::base::StartsWith(data_dir, kImageDataPrefix)) {
756 return BinderError("Invalid path");
757 }
758
759 uid_t uid = IPCThreadState::self()->getCallingUid();
760 if (uid != AID_ROOT) {
761 return UidSecurityError();
762 }
763
764 auto impl = ImageManager::Open(metadata_dir, data_dir);
765 if (!impl) {
766 return BinderError("Unknown error");
767 }
768
David Anderson551ae3a2019-08-01 12:53:06 -0700769 *_aidl_return = new ImageService(this, std::move(impl), uid);
David Anderson6f373b72019-06-05 15:04:00 -0700770 return binder::Status::ok();
771}
772
David Andersonb5f44b32019-02-20 18:04:37 -0800773binder::Status GsiService::CheckUid(AccessLevel level) {
774 std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
775 if (level == AccessLevel::SystemOrShell) {
776 allowed_uids.push_back(AID_SHELL);
David Anderson3c819cb2019-02-08 17:50:50 -0800777 }
778
David Andersonb5f44b32019-02-20 18:04:37 -0800779 uid_t uid = IPCThreadState::self()->getCallingUid();
780 for (const auto& allowed_uid : allowed_uids) {
781 if (allowed_uid == uid) {
782 return binder::Status::ok();
783 }
784 }
David Anderson6f373b72019-06-05 15:04:00 -0700785 return UidSecurityError();
David Anderson3c819cb2019-02-08 17:50:50 -0800786}
787
David Andersone7a8ade2019-03-13 19:21:22 -0700788static bool IsExternalStoragePath(const std::string& path) {
789 if (!android::base::StartsWith(path, "/mnt/media_rw/")) {
790 return false;
791 }
792 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
793 if (fd < 0) {
794 PLOG(ERROR) << "open failed: " << path;
795 return false;
796 }
797 struct statfs info;
798 if (fstatfs(fd, &info)) {
799 PLOG(ERROR) << "statfs failed: " << path;
800 return false;
801 }
802 LOG(ERROR) << "fs type: " << info.f_type;
803 return info.f_type == MSDOS_SUPER_MAGIC;
804}
805
Howard Chen4663de62019-11-05 20:46:20 +0800806int GsiService::ValidateInstallParams(std::string& install_dir) {
David Anderson49eea5f2019-05-23 13:27:01 -0700807 // If no install path was specified, use the default path. We also allow
808 // specifying the top-level folder, and then we choose the correct location
809 // underneath.
Howard Chen4663de62019-11-05 20:46:20 +0800810 if (install_dir.empty() || install_dir == "/data/gsi") {
811 install_dir = kDefaultDsuImageFolder;
David Andersoneb30ac22019-03-12 15:24:53 -0700812 }
813
814 // Normalize the path and add a trailing slash.
Howard Chen4663de62019-11-05 20:46:20 +0800815 std::string origInstallDir = install_dir;
816 if (!android::base::Realpath(origInstallDir, &install_dir)) {
David Andersoneb30ac22019-03-12 15:24:53 -0700817 PLOG(ERROR) << "realpath failed: " << origInstallDir;
818 return INSTALL_ERROR_GENERIC;
819 }
David Anderson64b53fb2019-07-01 19:05:35 -0700820 // Ensure the path ends in / for consistency.
Howard Chen4663de62019-11-05 20:46:20 +0800821 if (!android::base::EndsWith(install_dir, "/")) {
822 install_dir += "/";
David Andersoneb30ac22019-03-12 15:24:53 -0700823 }
824
David Andersone7a8ade2019-03-13 19:21:22 -0700825 // Currently, we can only install to /data/gsi/ or external storage.
Howard Chen4663de62019-11-05 20:46:20 +0800826 if (IsExternalStoragePath(install_dir)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700827 Fstab fstab;
828 if (!ReadDefaultFstab(&fstab)) {
829 LOG(ERROR) << "cannot read default fstab";
830 return INSTALL_ERROR_GENERIC;
831 }
832 FstabEntry* system = GetEntryForMountPoint(&fstab, "/system");
833 if (!system) {
834 LOG(ERROR) << "cannot find /system fstab entry";
835 return INSTALL_ERROR_GENERIC;
836 }
837 if (fs_mgr_verity_is_check_at_most_once(*system)) {
838 LOG(ERROR) << "cannot install GSIs to external media if verity uses check_at_most_once";
839 return INSTALL_ERROR_GENERIC;
840 }
Howard Chen4663de62019-11-05 20:46:20 +0800841 } else if (install_dir != kDefaultDsuImageFolder) {
842 LOG(ERROR) << "cannot install DSU to " << install_dir;
David Andersoneb30ac22019-03-12 15:24:53 -0700843 return INSTALL_ERROR_GENERIC;
844 }
845 return INSTALL_OK;
846}
847
Howard Chenee5c2b12019-11-08 11:57:47 +0800848std::string GsiService::GetActiveDsuSlot() {
849 if (!install_dir_.empty()) {
850 return GetDsuSlot(install_dir_);
851 } else {
852 std::string active_dsu;
853 return GetActiveDsu(&active_dsu) ? active_dsu : "";
854 }
855}
856
Howard Chen3f6d5a62019-08-22 15:26:33 +0800857std::string GsiService::GetActiveInstalledImageDir() {
858 // Just in case an install was left hanging.
859 if (installer_) {
860 return installer_->install_dir();
861 } else {
862 return GetInstalledImageDir();
863 }
864}
865
David Anderson5f805912019-03-07 12:41:15 -0800866std::string GsiService::GetInstalledImageDir() {
867 // If there's no install left, just return /data/gsi since that's where
868 // installs go by default.
Howard Chenee5c2b12019-11-08 11:57:47 +0800869 std::string active_dsu;
David Anderson5f805912019-03-07 12:41:15 -0800870 std::string dir;
Howard Chenee5c2b12019-11-08 11:57:47 +0800871 if (GetActiveDsu(&active_dsu) &&
872 android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) {
David Anderson5f805912019-03-07 12:41:15 -0800873 return dir;
874 }
David Anderson9bdf8632019-07-01 14:49:11 -0700875 return kDefaultDsuImageFolder;
David Anderson5f805912019-03-07 12:41:15 -0800876}
877
David Anderson564a04c2019-02-27 13:33:44 -0800878int GsiService::ReenableGsi(bool one_shot) {
David Andersona141ba82019-01-14 19:09:27 -0800879 if (!android::gsi::IsGsiInstalled()) {
880 LOG(ERROR) << "no gsi installed - cannot re-enable";
David Anderson868dea52019-01-17 13:34:38 -0800881 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800882 }
David Andersona141ba82019-01-14 19:09:27 -0800883 std::string boot_key;
884 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -0700885 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Anderson868dea52019-01-17 13:34:38 -0800886 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800887 }
888 if (boot_key != kInstallStatusDisabled) {
889 LOG(ERROR) << "GSI is not currently disabled";
David Anderson868dea52019-01-17 13:34:38 -0800890 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800891 }
Howard Chen4663de62019-11-05 20:46:20 +0800892 if (IsGsiRunning()) {
893 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
894 return IGsiService::INSTALL_ERROR_GENERIC;
895 }
896 return IGsiService::INSTALL_OK;
897 }
898 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
899 return IGsiService::INSTALL_ERROR_GENERIC;
900 }
901 return IGsiService::INSTALL_OK;
David Andersond81e1252019-02-28 23:36:09 -0800902}
903
Howard Chen4663de62019-11-05 20:46:20 +0800904bool GsiService::RemoveGsiFiles(const std::string& install_dir) {
David Anderson563e29a2019-03-06 19:20:45 -0800905 bool ok = true;
Howard Chenee5c2b12019-11-08 11:57:47 +0800906 auto active_dsu = GetDsuSlot(install_dir);
907 if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) {
Howard Chen18109b12019-08-13 17:00:44 +0800908 std::vector<std::string> images = manager->GetAllBackingImages();
909 for (auto&& image : images) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800910 if (!android::base::EndsWith(image, kDsuPostfix)) {
Howard Chen18109b12019-08-13 17:00:44 +0800911 continue;
Howard Chen3f6d5a62019-08-22 15:26:33 +0800912 }
913 if (manager->IsImageMapped(image)) {
914 ok &= manager->UnmapImageDevice(image);
915 }
Howard Chen4663de62019-11-05 20:46:20 +0800916 ok &= manager->DeleteBackingImage(image);
David Anderson64b53fb2019-07-01 19:05:35 -0700917 }
David Anderson563e29a2019-03-06 19:20:45 -0800918 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800919 auto dsu_slot = GetDsuSlot(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800920 std::vector<std::string> files{
David Anderson9bdf8632019-07-01 14:49:11 -0700921 kDsuInstallStatusFile,
David Anderson9bdf8632019-07-01 14:49:11 -0700922 kDsuOneShotBootFile,
Howard Chenee5c2b12019-11-08 11:57:47 +0800923 DsuInstallDirFile(dsu_slot),
924 GetCompleteIndication(dsu_slot),
David Andersonc053b3b2019-01-08 18:22:07 -0800925 };
David Andersonc053b3b2019-01-08 18:22:07 -0800926 for (const auto& file : files) {
David Anderson64b53fb2019-07-01 19:05:35 -0700927 std::string message;
Howard Chen4663de62019-11-05 20:46:20 +0800928 if (!RemoveFileIfExists(file, &message)) {
David Andersonc053b3b2019-01-08 18:22:07 -0800929 LOG(ERROR) << message;
930 ok = false;
931 }
932 }
Howard Chen0e188062020-02-26 12:48:41 +0800933 if (ok) {
934 SetProperty(kGsiInstalledProp, "0");
935 }
David Andersonb3aff182019-01-11 14:37:51 -0800936 return ok;
937}
938
David Andersona141ba82019-01-14 19:09:27 -0800939bool GsiService::DisableGsiInstall() {
940 if (!android::gsi::IsGsiInstalled()) {
941 LOG(ERROR) << "cannot disable gsi install - no install detected";
942 return false;
David Andersonb3aff182019-01-11 14:37:51 -0800943 }
David Andersonb2988ab2019-04-16 17:14:09 -0700944 if (installer_) {
David Andersona141ba82019-01-14 19:09:27 -0800945 LOG(ERROR) << "cannot disable gsi during GSI installation";
946 return false;
947 }
948 if (!DisableGsi()) {
949 PLOG(ERROR) << "could not write gsi status";
950 return false;
951 }
952 return true;
David Andersonc053b3b2019-01-08 18:22:07 -0800953}
954
Howard Chenee5c2b12019-11-08 11:57:47 +0800955std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) {
956 return DSU_METADATA_PREFIX + dsu_slot + "/complete";
Howard Chen4663de62019-11-05 20:46:20 +0800957}
958
Howard Chenee5c2b12019-11-08 11:57:47 +0800959bool GsiService::IsInstallationComplete(const std::string& dsu_slot) {
960 if (access(kDsuInstallStatusFile, F_OK) != 0) {
961 return false;
962 }
963 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800964 std::string content;
965 if (!ReadFileToString(file, &content)) {
966 return false;
967 }
968 return content == "OK";
969}
970
Howard Chenee5c2b12019-11-08 11:57:47 +0800971std::vector<std::string> GsiService::GetInstalledDsuSlots() {
972 std::vector<std::string> dsu_slots;
973 auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir);
974 if (d != nullptr) {
975 struct dirent* de;
976 while ((de = readdir(d.get())) != nullptr) {
977 if (de->d_name[0] == '.') {
978 continue;
979 }
980 auto dsu_slot = std::string(de->d_name);
981 if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) {
982 continue;
983 }
984 dsu_slots.push_back(dsu_slot);
985 }
986 }
987 return dsu_slots;
988}
989
Howard Chen3f6d5a62019-08-22 15:26:33 +0800990void GsiService::CleanCorruptedInstallation() {
Howard Chenee5c2b12019-11-08 11:57:47 +0800991 for (auto&& slot : GetInstalledDsuSlots()) {
992 bool is_complete = IsInstallationComplete(slot);
993 if (!is_complete) {
994 LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot;
995 std::string install_dir;
996 if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) ||
997 !RemoveGsiFiles(install_dir)) {
998 LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot;
999 }
Howard Chen4663de62019-11-05 20:46:20 +08001000 }
Howard Chen3f6d5a62019-08-22 15:26:33 +08001001 }
1002}
1003
David Andersonb3aff182019-01-11 14:37:51 -08001004void GsiService::RunStartupTasks() {
Howard Chen4663de62019-11-05 20:46:20 +08001005 CleanCorruptedInstallation();
David Andersonb3aff182019-01-11 14:37:51 -08001006
Howard Chenee5c2b12019-11-08 11:57:47 +08001007 std::string active_dsu;
1008 if (!GetActiveDsu(&active_dsu)) {
1009 PLOG(INFO) << "no DSU";
1010 return;
1011 }
David Andersonb3aff182019-01-11 14:37:51 -08001012 std::string boot_key;
1013 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -07001014 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001015 return;
1016 }
1017
1018 if (!IsGsiRunning()) {
1019 // Check if a wipe was requested from fastboot or adb-in-gsi.
1020 if (boot_key == kInstallStatusWipe) {
Howard Chen4663de62019-11-05 20:46:20 +08001021 RemoveGsiFiles(GetInstalledImageDir());
David Andersonb3aff182019-01-11 14:37:51 -08001022 }
1023 } else {
David Anderson564a04c2019-02-27 13:33:44 -08001024 // NB: When single-boot is enabled, init will write "disabled" into the
1025 // install_status file, which will cause GetBootAttempts to return
1026 // false. Thus, we won't write "ok" here.
David Andersonb3aff182019-01-11 14:37:51 -08001027 int ignore;
1028 if (GetBootAttempts(boot_key, &ignore)) {
1029 // Mark the GSI as having successfully booted.
David Anderson9bdf8632019-07-01 14:49:11 -07001030 if (!android::base::WriteStringToFile(kInstallStatusOk, kDsuInstallStatusFile)) {
1031 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001032 }
1033 }
1034 }
1035}
1036
Yo Chiang53bed1c2020-01-01 16:25:19 +08001037static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) {
1038 // Read the AVB footer from EOF.
1039 int64_t total_size = get_block_device_size(fd);
1040 int64_t footer_offset = total_size - AVB_FOOTER_SIZE;
1041 std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes;
1042 if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) {
1043 PLOG(ERROR) << "cannot read AVB footer";
1044 return false;
1045 }
1046 // Validate the AVB footer data and byte swap to native byte order.
1047 AvbFooter footer;
1048 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) {
1049 LOG(ERROR) << "invalid AVB footer";
1050 return false;
1051 }
1052 // Read the VBMeta image.
1053 std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size);
1054 if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) {
1055 PLOG(ERROR) << "cannot read VBMeta image";
1056 return false;
1057 }
1058 // Validate the VBMeta image and retrieve AVB public key.
1059 // After a successful call to avb_vbmeta_image_verify(), public_key_data
1060 // will point to the serialized AVB public key, in the same format generated
1061 // by the `avbtool extract_public_key` command.
1062 const uint8_t* public_key_data;
1063 size_t public_key_size;
1064 AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(),
1065 &public_key_data, &public_key_size);
1066 if (result != AVB_VBMETA_VERIFY_RESULT_OK) {
1067 LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result);
1068 return false;
1069 }
1070 if (public_key_data != nullptr) {
1071 dst->bytes.resize(public_key_size);
1072 memcpy(dst->bytes.data(), public_key_data, public_key_size);
1073 dst->sha1.resize(SHA_DIGEST_LENGTH);
1074 SHA1(public_key_data, public_key_size, dst->sha1.data());
1075 }
1076 return true;
1077}
1078
David Andersonc053b3b2019-01-08 18:22:07 -08001079} // namespace gsi
1080} // namespace android