blob: ab2339b70e44e8ebecae78fc29cf48f6c6e2decb [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>
Howard Chenf2a0a822020-02-15 17:32:02 +080041#include <binder/LazyServiceRegistrar.h>
David Anderson64b53fb2019-07-01 19:05:35 -070042#include <ext4_utils/ext4_utils.h>
David Andersone7a8ade2019-03-13 19:21:22 -070043#include <fs_mgr.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080044#include <libavb/libavb.h>
David Andersond614eca2019-09-09 17:57:06 -070045#include <libdm/dm.h>
David Anderson6f373b72019-06-05 15:04:00 -070046#include <libfiemap/image_manager.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080047#include <openssl/sha.h>
David Anderson3c819cb2019-02-08 17:50:50 -080048#include <private/android_filesystem_config.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;
Howard Chen4663de62019-11-05 20:46:20 +080059using android::base::ReadFileToString;
Yo Chiang53bed1c2020-01-01 16:25:19 +080060using android::base::ReadFullyAtOffset;
Howard Chen4663de62019-11-05 20:46:20 +080061using android::base::RemoveFileIfExists;
Howard Chen0e188062020-02-26 12:48:41 +080062using android::base::SetProperty;
David Anderson3c819cb2019-02-08 17:50:50 -080063using android::base::StringPrintf;
David Andersonc86531e2019-02-25 18:50:35 -080064using android::base::unique_fd;
Howard Chen4663de62019-11-05 20:46:20 +080065using android::base::WriteStringToFd;
66using android::base::WriteStringToFile;
Howard Chenf2a0a822020-02-15 17:32:02 +080067using android::binder::LazyServiceRegistrar;
David Andersond614eca2019-09-09 17:57:06 -070068using android::dm::DeviceMapper;
David Andersonc053b3b2019-01-08 18:22:07 -080069
Howard Chen5e2d47e2019-12-13 14:03:18 +080070static std::mutex sInstanceLock;
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
Howard Chenf2a0a822020-02-15 17:32:02 +080077GsiService::GsiService() {
David Anderson6a5b8a72019-01-16 16:24:48 -080078 progress_ = {};
79}
80
Howard Chenf2a0a822020-02-15 17:32:02 +080081void GsiService::Register() {
82 auto lazyRegistrar = LazyServiceRegistrar::getInstance();
83 android::sp<GsiService> service = new GsiService();
84 auto ret = lazyRegistrar.registerService(service, kGsiServiceName);
David Anderson4c756732019-07-12 14:18:37 -070085
Howard Chenf2a0a822020-02-15 17:32:02 +080086 if (ret != android::OK) {
87 LOG(FATAL) << "Could not register gsi service: " << ret;
David Anderson4c756732019-07-12 14:18:37 -070088 }
89}
90
David Anderson5cc440c2019-04-16 14:34:27 -070091#define ENFORCE_SYSTEM \
92 do { \
93 binder::Status status = CheckUid(); \
94 if (!status.isOk()) return status; \
David Anderson3c819cb2019-02-08 17:50:50 -080095 } while (0)
96
David Anderson5cc440c2019-04-16 14:34:27 -070097#define ENFORCE_SYSTEM_OR_SHELL \
98 do { \
99 binder::Status status = CheckUid(AccessLevel::SystemOrShell); \
100 if (!status.isOk()) return status; \
David Andersonb5f44b32019-02-20 18:04:37 -0800101 } while (0)
102
Howard Chen4663de62019-11-05 20:46:20 +0800103int GsiService::SaveInstallation(const std::string& installation) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800104 auto dsu_slot = GetDsuSlot(installation);
105 auto install_dir_file = DsuInstallDirFile(dsu_slot);
106 auto metadata_dir = android::base::Dirname(install_dir_file);
107 if (access(metadata_dir.c_str(), F_OK) != 0) {
108 if (mkdir(metadata_dir.c_str(), 0777) != 0) {
109 PLOG(ERROR) << "Failed to mkdir " << metadata_dir;
110 return INSTALL_ERROR_GENERIC;
111 }
112 }
Howard Chen4663de62019-11-05 20:46:20 +0800113 auto fd = android::base::unique_fd(
Howard Chenee5c2b12019-11-08 11:57:47 +0800114 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 +0800115 if (!WriteStringToFd(installation, fd)) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800116 PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800117 return INSTALL_ERROR_GENERIC;
118 }
119 return INSTALL_OK;
120}
121
122binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
123 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800124 std::lock_guard<std::mutex> guard(lock_);
Howard Chen4663de62019-11-05 20:46:20 +0800125 if (IsGsiRunning()) {
126 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
127 return binder::Status::ok();
128 }
129 install_dir_ = install_dir;
130 if (int status = ValidateInstallParams(install_dir_)) {
131 *_aidl_return = status;
132 return binder::Status::ok();
133 }
134 std::string message;
Howard Chenee5c2b12019-11-08 11:57:47 +0800135 auto dsu_slot = GetDsuSlot(install_dir_);
136 if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
Howard Chen4663de62019-11-05 20:46:20 +0800137 LOG(ERROR) << message;
138 }
139 // Remember the installation directory before allocate any resource
140 *_aidl_return = SaveInstallation(install_dir_);
141 return binder::Status::ok();
142}
143
144binder::Status GsiService::closeInstall(int* _aidl_return) {
145 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800146 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800147 auto dsu_slot = GetDsuSlot(install_dir_);
148 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800149 if (!WriteStringToFile("OK", file)) {
150 PLOG(ERROR) << "write failed: " << file;
151 *_aidl_return = INSTALL_ERROR_GENERIC;
152 }
Howard Chen4663de62019-11-05 20:46:20 +0800153 *_aidl_return = INSTALL_OK;
154 return binder::Status::ok();
155}
156
157binder::Status GsiService::createPartition(const ::std::string& name, int64_t size, bool readOnly,
158 int32_t* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800159 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800160 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800161
Howard Chen4663de62019-11-05 20:46:20 +0800162 if (install_dir_.empty()) {
163 PLOG(ERROR) << "open is required for createPartition";
164 *_aidl_return = INSTALL_ERROR_GENERIC;
165 return binder::Status::ok();
166 }
167
168 // Make sure a pending interrupted installations are cleaned up.
David Andersonb2988ab2019-04-16 17:14:09 -0700169 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800170
David Andersoneb30ac22019-03-12 15:24:53 -0700171 // Do some precursor validation on the arguments before diving into the
172 // install process.
Howard Chen4663de62019-11-05 20:46:20 +0800173 if (size % LP_SECTOR_SIZE) {
174 LOG(ERROR) << " size " << size << " is not a multiple of " << LP_SECTOR_SIZE;
175 *_aidl_return = INSTALL_ERROR_GENERIC;
David Andersoneb30ac22019-03-12 15:24:53 -0700176 return binder::Status::ok();
177 }
178
Howard Chen4663de62019-11-05 20:46:20 +0800179 if (size == 0 && name == "userdata") {
180 size = kDefaultUserdataSize;
181 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800182 installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name,
183 GetDsuSlot(install_dir_), size, readOnly);
Howard Chen9f40baf2019-12-16 13:31:12 +0800184 progress_ = {};
David Andersonb2988ab2019-04-16 17:14:09 -0700185 int status = installer_->StartInstall();
David Anderson868dea52019-01-17 13:34:38 -0800186 if (status != INSTALL_OK) {
David Andersonb2988ab2019-04-16 17:14:09 -0700187 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800188 }
David Anderson868dea52019-01-17 13:34:38 -0800189 *_aidl_return = status;
David Andersonc053b3b2019-01-08 18:22:07 -0800190 return binder::Status::ok();
191}
192
David Anderson1d94d262019-01-11 20:39:51 -0800193binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
David Andersonc053b3b2019-01-08 18:22:07 -0800194 int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800195 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800196 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800197
David Andersonb2988ab2019-04-16 17:14:09 -0700198 if (!installer_) {
199 *_aidl_return = false;
200 return binder::Status::ok();
201 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800202
David Andersonb2988ab2019-04-16 17:14:09 -0700203 *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
David Anderson6a5b8a72019-01-16 16:24:48 -0800204 return binder::Status::ok();
205}
206
207void GsiService::StartAsyncOperation(const std::string& step, int64_t total_bytes) {
208 std::lock_guard<std::mutex> guard(progress_lock_);
209
210 progress_.step = step;
211 progress_.status = STATUS_WORKING;
212 progress_.bytes_processed = 0;
213 progress_.total_bytes = total_bytes;
214}
215
216void GsiService::UpdateProgress(int status, int64_t bytes_processed) {
217 std::lock_guard<std::mutex> guard(progress_lock_);
218
219 progress_.status = status;
David Andersona64e3922019-02-01 16:27:18 -0800220 if (status == STATUS_COMPLETE) {
221 progress_.bytes_processed = progress_.total_bytes;
222 } else {
223 progress_.bytes_processed = bytes_processed;
224 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800225}
226
227binder::Status GsiService::getInstallProgress(::android::gsi::GsiProgress* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800228 ENFORCE_SYSTEM;
David Anderson6a5b8a72019-01-16 16:24:48 -0800229 std::lock_guard<std::mutex> guard(progress_lock_);
230
Howard Chen9f40baf2019-12-16 13:31:12 +0800231 if (installer_ == nullptr) {
232 progress_ = {};
233 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800234 *_aidl_return = progress_;
David Andersonc053b3b2019-01-08 18:22:07 -0800235 return binder::Status::ok();
236}
237
Howard Chen5676d962019-08-05 16:21:00 +0800238binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800239 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800240 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800241
David Andersonb2988ab2019-04-16 17:14:09 -0700242 if (!installer_) {
243 *_aidl_return = false;
244 return binder::Status::ok();
245 }
Howard Chen5676d962019-08-05 16:21:00 +0800246 *_aidl_return = installer_->CommitGsiChunk(bytes);
247 return binder::Status::ok();
248}
David Andersonb2988ab2019-04-16 17:14:09 -0700249
Howard Chen5676d962019-08-05 16:21:00 +0800250binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem,
251 int64_t size, bool* _aidl_return) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800252 ENFORCE_SYSTEM;
Howard Chen5676d962019-08-05 16:21:00 +0800253 if (!installer_) {
254 *_aidl_return = false;
255 return binder::Status::ok();
256 }
257 *_aidl_return = installer_->MapAshmem(ashmem.get(), size);
David Andersonc053b3b2019-01-08 18:22:07 -0800258 return binder::Status::ok();
259}
260
Howard Chen0e188062020-02-26 12:48:41 +0800261binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
262 const sp<IGsiServiceCallback>& resultCallback) {
263 int result;
264 auto status = enableGsi(one_shot, dsuSlot, &result);
265 if (!status.isOk()) {
266 LOG(ERROR) << "Could not enableGsi: " << status.exceptionMessage().string();
267 result = IGsiService::INSTALL_ERROR_GENERIC;
268 }
269 resultCallback->onResult(result);
270 return binder::Status::ok();
271}
272
Howard Chenee5c2b12019-11-08 11:57:47 +0800273binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
Howard Chenf2a0a822020-02-15 17:32:02 +0800274 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800275
Howard Chenee5c2b12019-11-08 11:57:47 +0800276 if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) {
277 PLOG(ERROR) << "write failed: " << GetDsuSlot(install_dir_);
278 *_aidl_return = INSTALL_ERROR_GENERIC;
279 return binder::Status::ok();
280 }
David Andersonb2988ab2019-04-16 17:14:09 -0700281 if (installer_) {
David Anderson646b4b22019-02-27 18:26:54 -0800282 ENFORCE_SYSTEM;
Howard Chen4663de62019-11-05 20:46:20 +0800283 installer_ = {};
284 // Note: create the install status file last, since this is the actual boot
285 // indicator.
286 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
287 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
David Anderson5f805912019-03-07 12:41:15 -0800288 } else {
289 *_aidl_return = INSTALL_OK;
290 }
David Andersona141ba82019-01-14 19:09:27 -0800291 } else {
David Anderson646b4b22019-02-27 18:26:54 -0800292 ENFORCE_SYSTEM_OR_SHELL;
David Anderson564a04c2019-02-27 13:33:44 -0800293 *_aidl_return = ReenableGsi(one_shot);
David Andersona141ba82019-01-14 19:09:27 -0800294 }
David Anderson563e29a2019-03-06 19:20:45 -0800295
David Andersonb2988ab2019-04-16 17:14:09 -0700296 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800297 return binder::Status::ok();
298}
299
Howard Chen670b3062019-02-26 18:14:47 +0800300binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
301 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800302 std::lock_guard<std::mutex> guard(lock_);
Howard Chen670b3062019-02-26 18:14:47 +0800303 std::string boot_key;
304 if (!GetInstallStatus(&boot_key)) {
305 *_aidl_return = false;
306 } else {
Howard Chenee5c2b12019-11-08 11:57:47 +0800307 *_aidl_return = (boot_key != kInstallStatusDisabled);
Howard Chen670b3062019-02-26 18:14:47 +0800308 }
309 return binder::Status::ok();
310}
311
Howard Chen0e188062020-02-26 12:48:41 +0800312binder::Status GsiService::removeGsiAsync(const sp<IGsiServiceCallback>& resultCallback) {
313 bool result;
314 auto status = removeGsi(&result);
315 if (!status.isOk()) {
316 LOG(ERROR) << "Could not removeGsi: " << status.exceptionMessage().string();
317 result = IGsiService::INSTALL_ERROR_GENERIC;
318 }
319 resultCallback->onResult(result);
320 return binder::Status::ok();
321}
322
Howard Chen25b18cc2019-08-02 11:21:58 +0800323binder::Status GsiService::removeGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800324 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800325 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800326
Howard Chen3f6d5a62019-08-22 15:26:33 +0800327 std::string install_dir = GetActiveInstalledImageDir();
David Andersona141ba82019-01-14 19:09:27 -0800328 if (IsGsiRunning()) {
329 // Can't remove gsi files while running.
330 *_aidl_return = UninstallGsi();
331 } else {
Howard Chendee5d302020-02-05 10:58:29 +0800332 installer_ = {};
Howard Chen4663de62019-11-05 20:46:20 +0800333 *_aidl_return = RemoveGsiFiles(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800334 }
335 return binder::Status::ok();
336}
337
Howard Chen25b18cc2019-08-02 11:21:58 +0800338binder::Status GsiService::disableGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800339 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800340 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800341
342 *_aidl_return = DisableGsiInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800343 return binder::Status::ok();
344}
345
346binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800347 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800348 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800349
David Andersonc053b3b2019-01-08 18:22:07 -0800350 *_aidl_return = IsGsiRunning();
351 return binder::Status::ok();
352}
353
David Andersona141ba82019-01-14 19:09:27 -0800354binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800355 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800356 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800357
358 *_aidl_return = IsGsiInstalled();
359 return binder::Status::ok();
360}
361
362binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800363 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800364 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800365
David Andersonb2988ab2019-04-16 17:14:09 -0700366 *_aidl_return = !!installer_;
David Andersona141ba82019-01-14 19:09:27 -0800367 return binder::Status::ok();
368}
369
370binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800371 ENFORCE_SYSTEM;
Howard Chenecbc0192019-02-25 18:51:26 +0800372 should_abort_ = true;
Howard Chenf2a0a822020-02-15 17:32:02 +0800373 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800374
Howard Chenecbc0192019-02-25 18:51:26 +0800375 should_abort_ = false;
David Andersonb2988ab2019-04-16 17:14:09 -0700376 installer_ = nullptr;
David Andersona141ba82019-01-14 19:09:27 -0800377
David Andersona141ba82019-01-14 19:09:27 -0800378 *_aidl_return = true;
379 return binder::Status::ok();
380}
381
David Anderson5f805912019-03-07 12:41:15 -0800382binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
383 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800384 std::lock_guard<std::mutex> guard(lock_);
David Anderson5f805912019-03-07 12:41:15 -0800385
Howard Chen3f6d5a62019-08-22 15:26:33 +0800386 *_aidl_return = GetActiveInstalledImageDir();
David Anderson5f805912019-03-07 12:41:15 -0800387 return binder::Status::ok();
388}
389
Howard Chenee5c2b12019-11-08 11:57:47 +0800390binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) {
391 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800392 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800393
394 *_aidl_return = GetActiveDsuSlot();
395 return binder::Status::ok();
396}
397
398binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) {
399 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800400 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800401 *_aidl_return = GetInstalledDsuSlots();
402 return binder::Status::ok();
403}
404
Howard Chen4663de62019-11-05 20:46:20 +0800405binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) {
David Anderson8bdf6252019-06-11 16:43:24 -0700406 ENFORCE_SYSTEM_OR_SHELL;
Howard Chenf2a0a822020-02-15 17:32:02 +0800407 std::lock_guard<std::mutex> guard(lock_);
David Anderson8bdf6252019-06-11 16:43:24 -0700408
409 if (IsGsiRunning() || !IsGsiInstalled()) {
410 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
411 return binder::Status::ok();
412 }
413
Howard Chen3f6d5a62019-08-22 15:26:33 +0800414 std::string install_dir = GetActiveInstalledImageDir();
Howard Chenee5c2b12019-11-08 11:57:47 +0800415 *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name);
David Anderson8bdf6252019-06-11 16:43:24 -0700416
417 return binder::Status::ok();
418}
419
Yifan Hongd66695b2019-12-23 16:07:45 -0800420static binder::Status BinderError(const std::string& message,
421 FiemapStatus::ErrorCode status = FiemapStatus::ErrorCode::ERROR) {
422 return binder::Status::fromServiceSpecificError(static_cast<int32_t>(status), message.c_str());
David Anderson6f373b72019-06-05 15:04:00 -0700423}
424
David Andersond614eca2019-09-09 17:57:06 -0700425binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) {
426 ENFORCE_SYSTEM_OR_SHELL;
427
428 auto& dm = DeviceMapper::Instance();
429
430 std::vector<DeviceMapper::DmBlockDevice> devices;
431 if (!dm.GetAvailableDevices(&devices)) {
432 return BinderError("Could not list devices");
433 }
434
435 std::stringstream text;
436 for (const auto& device : devices) {
437 text << "Device " << device.name() << " (" << device.Major() << ":" << device.Minor()
438 << ")\n";
439
440 std::vector<DeviceMapper::TargetInfo> table;
441 if (!dm.GetTableInfo(device.name(), &table)) {
442 continue;
443 }
444
445 for (const auto& target : table) {
446 const auto& spec = target.spec;
447 auto target_type = DeviceMapper::GetTargetType(spec);
448 text << " " << target_type << " " << spec.sector_start << " " << spec.length << " "
449 << target.data << "\n";
450 }
451 }
452
453 *_aidl_return = text.str();
454 return binder::Status::ok();
455}
456
Yo Chiang53bed1c2020-01-01 16:25:19 +0800457binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) {
458 ENFORCE_SYSTEM;
Howard Chenf2a0a822020-02-15 17:32:02 +0800459 std::lock_guard<std::mutex> guard(lock_);
Yo Chiang53bed1c2020-01-01 16:25:19 +0800460
461 if (!installer_) {
462 *_aidl_return = INSTALL_ERROR_GENERIC;
463 return binder::Status::ok();
464 }
465 int fd = installer_->GetPartitionFd();
466 if (!GetAvbPublicKeyFromFd(fd, dst)) {
467 LOG(ERROR) << "Failed to extract AVB public key";
468 *_aidl_return = INSTALL_ERROR_GENERIC;
469 return binder::Status::ok();
470 }
471 *_aidl_return = INSTALL_OK;
472 return binder::Status::ok();
473}
474
Howard Chen4663de62019-11-05 20:46:20 +0800475bool GsiService::CreateInstallStatusFile() {
476 if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
477 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
478 return false;
479 }
Howard Chen0e188062020-02-26 12:48:41 +0800480 SetProperty(kGsiInstalledProp, "1");
Howard Chen4663de62019-11-05 20:46:20 +0800481 return true;
482}
483
484bool GsiService::SetBootMode(bool one_shot) {
485 if (one_shot) {
486 if (!android::base::WriteStringToFile("1", kDsuOneShotBootFile)) {
487 PLOG(ERROR) << "write " << kDsuOneShotBootFile;
488 return false;
489 }
490 } else if (!access(kDsuOneShotBootFile, F_OK)) {
491 std::string error;
492 if (!android::base::RemoveFileIfExists(kDsuOneShotBootFile, &error)) {
493 LOG(ERROR) << error;
494 return false;
495 }
496 }
497 return true;
498}
499
David Anderson6f373b72019-06-05 15:04:00 -0700500static binder::Status UidSecurityError() {
501 uid_t uid = IPCThreadState::self()->getCallingUid();
502 auto message = StringPrintf("UID %d is not allowed", uid);
503 return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
504}
505
David Anderson551ae3a2019-08-01 12:53:06 -0700506class ImageService : public BinderService<ImageService>, public BnImageService {
David Anderson6f373b72019-06-05 15:04:00 -0700507 public:
David Anderson551ae3a2019-08-01 12:53:06 -0700508 ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
Howard Chen96c31fd2019-08-23 17:38:51 +0800509 binder::Status getAllBackingImages(std::vector<std::string>* _aidl_return);
Yifan Hongd66695b2019-12-23 16:07:45 -0800510 binder::Status createBackingImage(const std::string& name, int64_t size, int flags,
511 const sp<IProgressCallback>& on_progress) override;
David Anderson6f373b72019-06-05 15:04:00 -0700512 binder::Status deleteBackingImage(const std::string& name) override;
513 binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
514 MappedImage* mapping) override;
515 binder::Status unmapImageDevice(const std::string& name) override;
David Anderson394f1f22019-07-29 12:49:02 -0700516 binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override;
David Andersonbee55a02019-08-01 15:01:55 -0700517 binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override;
Yo Chiang53bed1c2020-01-01 16:25:19 +0800518 binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
519 int32_t* _aidl_return) override;
Alessio Balsini0829fb22019-08-27 17:50:18 +0100520 binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override;
David Anderson86846bd2019-11-26 16:30:40 -0800521 binder::Status removeAllImages() override;
David Anderson7016a0d2019-12-16 22:06:47 -0800522 binder::Status removeDisabledImages() override;
David Anderson14aa72a2019-12-17 21:27:59 -0800523 binder::Status getMappedImageDevice(const std::string& name, std::string* device) override;
David Anderson6f373b72019-06-05 15:04:00 -0700524
525 private:
526 bool CheckUid();
527
David Anderson4c756732019-07-12 14:18:37 -0700528 android::sp<GsiService> service_;
David Anderson6f373b72019-06-05 15:04:00 -0700529 std::unique_ptr<ImageManager> impl_;
530 uid_t uid_;
531};
532
David Anderson551ae3a2019-08-01 12:53:06 -0700533ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
Howard Chenf2a0a822020-02-15 17:32:02 +0800534 : service_(service), impl_(std::move(impl)), uid_(uid) {}
David Anderson6f373b72019-06-05 15:04:00 -0700535
Howard Chen96c31fd2019-08-23 17:38:51 +0800536binder::Status ImageService::getAllBackingImages(std::vector<std::string>* _aidl_return) {
537 *_aidl_return = impl_->GetAllBackingImages();
538 return binder::Status::ok();
539}
540
Yifan Hongd66695b2019-12-23 16:07:45 -0800541binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags,
542 const sp<IProgressCallback>& on_progress) {
David Anderson6f373b72019-06-05 15:04:00 -0700543 if (!CheckUid()) return UidSecurityError();
544
Howard Chenf2a0a822020-02-15 17:32:02 +0800545 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700546
Yifan Hongd66695b2019-12-23 16:07:45 -0800547 std::function<bool(uint64_t, uint64_t)> callback;
548 if (on_progress) {
549 callback = [on_progress](uint64_t current, uint64_t total) -> bool {
550 auto status = on_progress->onProgress(static_cast<int64_t>(current),
551 static_cast<int64_t>(total));
552 if (!status.isOk()) {
553 LOG(ERROR) << "progress callback returned: " << status.toString8().string();
554 return false;
555 }
556 return true;
557 };
558 }
559
560 auto res = impl_->CreateBackingImage(name, size, flags, std::move(callback));
561 if (!res.is_ok()) {
562 return BinderError("Failed to create: " + res.string(), res.error_code());
David Anderson6f373b72019-06-05 15:04:00 -0700563 }
564 return binder::Status::ok();
565}
566
David Anderson551ae3a2019-08-01 12:53:06 -0700567binder::Status ImageService::deleteBackingImage(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700568 if (!CheckUid()) return UidSecurityError();
569
Howard Chenf2a0a822020-02-15 17:32:02 +0800570 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700571
572 if (!impl_->DeleteBackingImage(name)) {
573 return BinderError("Failed to delete");
574 }
575 return binder::Status::ok();
576}
577
David Anderson551ae3a2019-08-01 12:53:06 -0700578binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
579 MappedImage* mapping) {
David Anderson6f373b72019-06-05 15:04:00 -0700580 if (!CheckUid()) return UidSecurityError();
581
Howard Chenf2a0a822020-02-15 17:32:02 +0800582 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700583
584 if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
585 return BinderError("Failed to map");
586 }
587 return binder::Status::ok();
588}
589
David Anderson551ae3a2019-08-01 12:53:06 -0700590binder::Status ImageService::unmapImageDevice(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700591 if (!CheckUid()) return UidSecurityError();
592
Howard Chenf2a0a822020-02-15 17:32:02 +0800593 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700594
595 if (!impl_->UnmapImageDevice(name)) {
596 return BinderError("Failed to unmap");
597 }
598 return binder::Status::ok();
599}
600
David Anderson551ae3a2019-08-01 12:53:06 -0700601binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
David Anderson394f1f22019-07-29 12:49:02 -0700602 if (!CheckUid()) return UidSecurityError();
603
Howard Chenf2a0a822020-02-15 17:32:02 +0800604 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson394f1f22019-07-29 12:49:02 -0700605
606 *_aidl_return = impl_->BackingImageExists(name);
607 return binder::Status::ok();
608}
609
David Andersonbee55a02019-08-01 15:01:55 -0700610binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_return) {
611 if (!CheckUid()) return UidSecurityError();
612
Howard Chenf2a0a822020-02-15 17:32:02 +0800613 std::lock_guard<std::mutex> guard(service_->lock());
David Andersonbee55a02019-08-01 15:01:55 -0700614
615 *_aidl_return = impl_->IsImageMapped(name);
616 return binder::Status::ok();
617}
618
Yo Chiang53bed1c2020-01-01 16:25:19 +0800619binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
620 int32_t* _aidl_return) {
621 if (!CheckUid()) return UidSecurityError();
622
Howard Chenf2a0a822020-02-15 17:32:02 +0800623 std::lock_guard<std::mutex> guard(service_->lock());
Yo Chiang53bed1c2020-01-01 16:25:19 +0800624
625 std::string device_path;
626 std::unique_ptr<MappedDevice> mapped_device;
627 if (!impl_->IsImageMapped(name)) {
628 mapped_device = MappedDevice::Open(impl_.get(), 10s, name);
629 if (!mapped_device) {
630 PLOG(ERROR) << "Fail to map image: " << name;
631 *_aidl_return = IMAGE_ERROR;
632 return binder::Status::ok();
633 }
634 device_path = mapped_device->path();
635 } else {
636 if (!impl_->GetMappedImageDevice(name, &device_path)) {
637 PLOG(ERROR) << "GetMappedImageDevice() failed";
638 *_aidl_return = IMAGE_ERROR;
639 return binder::Status::ok();
640 }
641 }
642 android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
643 if (!fd.ok()) {
644 PLOG(ERROR) << "Fail to open mapped device: " << device_path;
645 *_aidl_return = IMAGE_ERROR;
646 return binder::Status::ok();
647 }
648 bool ok = GetAvbPublicKeyFromFd(fd.get(), dst);
649 fd = {};
650 if (!ok) {
651 LOG(ERROR) << "Failed to extract AVB public key";
652 *_aidl_return = IMAGE_ERROR;
653 return binder::Status::ok();
654 }
655 *_aidl_return = IMAGE_OK;
656 return binder::Status::ok();
657}
658
Alessio Balsini0829fb22019-08-27 17:50:18 +0100659binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) {
660 if (!CheckUid()) return UidSecurityError();
661
Howard Chenf2a0a822020-02-15 17:32:02 +0800662 std::lock_guard<std::mutex> guard(service_->lock());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100663
664 if (bytes < 0) {
665 return BinderError("Cannot use negative values");
666 }
Yifan Hongd66695b2019-12-23 16:07:45 -0800667 auto res = impl_->ZeroFillNewImage(name, bytes);
668 if (!res.is_ok()) {
669 return BinderError("Failed to fill image with zeros: " + res.string(), res.error_code());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100670 }
671 return binder::Status::ok();
672}
673
David Anderson86846bd2019-11-26 16:30:40 -0800674binder::Status ImageService::removeAllImages() {
675 if (!CheckUid()) return UidSecurityError();
676
Howard Chenf2a0a822020-02-15 17:32:02 +0800677 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson86846bd2019-11-26 16:30:40 -0800678 if (!impl_->RemoveAllImages()) {
679 return BinderError("Failed to remove all images");
680 }
681 return binder::Status::ok();
682}
683
David Anderson7016a0d2019-12-16 22:06:47 -0800684binder::Status ImageService::removeDisabledImages() {
685 if (!CheckUid()) return UidSecurityError();
686
Howard Chenf2a0a822020-02-15 17:32:02 +0800687 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson7016a0d2019-12-16 22:06:47 -0800688 if (!impl_->RemoveDisabledImages()) {
689 return BinderError("Failed to remove disabled images");
690 }
691 return binder::Status::ok();
692}
693
David Anderson14aa72a2019-12-17 21:27:59 -0800694binder::Status ImageService::getMappedImageDevice(const std::string& name, std::string* device) {
695 if (!CheckUid()) return UidSecurityError();
696
Howard Chenf2a0a822020-02-15 17:32:02 +0800697 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson14aa72a2019-12-17 21:27:59 -0800698 if (!impl_->GetMappedImageDevice(name, device)) {
699 *device = "";
700 }
701 return binder::Status::ok();
702}
703
David Andersonbee55a02019-08-01 15:01:55 -0700704bool ImageService::CheckUid() {
David Anderson6f373b72019-06-05 15:04:00 -0700705 return uid_ == IPCThreadState::self()->getCallingUid();
706}
707
David Anderson551ae3a2019-08-01 12:53:06 -0700708binder::Status GsiService::openImageService(const std::string& prefix,
709 android::sp<IImageService>* _aidl_return) {
David Anderson6f373b72019-06-05 15:04:00 -0700710 static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
711 static constexpr char kImageDataPrefix[] = "/data/gsi/";
712
David Anderson6ad45ba2019-07-29 12:51:23 -0700713 auto in_metadata_dir = kImageMetadataPrefix + prefix;
714 auto in_data_dir = kImageDataPrefix + prefix;
Howard Chenee5c2b12019-11-08 11:57:47 +0800715 auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix));
David Anderson6f373b72019-06-05 15:04:00 -0700716
Alessio Balsinibb774d02020-01-21 23:34:39 +0000717 std::string in_data_dir_tmp;
718 if (android::base::ReadFileToString(install_dir_file, &in_data_dir_tmp)) {
719 in_data_dir = in_data_dir_tmp;
Howard Chenee5c2b12019-11-08 11:57:47 +0800720 LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir;
721 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700722 std::string metadata_dir, data_dir;
723 if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000724 PLOG(ERROR) << "realpath failed for metadata: " << in_metadata_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700725 return BinderError("Invalid path");
726 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700727 if (!android::base::Realpath(in_data_dir, &data_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000728 PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700729 return BinderError("Invalid path");
730 }
731 if (!android::base::StartsWith(metadata_dir, kImageMetadataPrefix) ||
732 !android::base::StartsWith(data_dir, kImageDataPrefix)) {
733 return BinderError("Invalid path");
734 }
735
736 uid_t uid = IPCThreadState::self()->getCallingUid();
737 if (uid != AID_ROOT) {
738 return UidSecurityError();
739 }
740
741 auto impl = ImageManager::Open(metadata_dir, data_dir);
742 if (!impl) {
743 return BinderError("Unknown error");
744 }
745
David Anderson551ae3a2019-08-01 12:53:06 -0700746 *_aidl_return = new ImageService(this, std::move(impl), uid);
David Anderson6f373b72019-06-05 15:04:00 -0700747 return binder::Status::ok();
748}
749
David Andersonb5f44b32019-02-20 18:04:37 -0800750binder::Status GsiService::CheckUid(AccessLevel level) {
751 std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
752 if (level == AccessLevel::SystemOrShell) {
753 allowed_uids.push_back(AID_SHELL);
David Anderson3c819cb2019-02-08 17:50:50 -0800754 }
755
David Andersonb5f44b32019-02-20 18:04:37 -0800756 uid_t uid = IPCThreadState::self()->getCallingUid();
757 for (const auto& allowed_uid : allowed_uids) {
758 if (allowed_uid == uid) {
759 return binder::Status::ok();
760 }
761 }
David Anderson6f373b72019-06-05 15:04:00 -0700762 return UidSecurityError();
David Anderson3c819cb2019-02-08 17:50:50 -0800763}
764
David Andersone7a8ade2019-03-13 19:21:22 -0700765static bool IsExternalStoragePath(const std::string& path) {
766 if (!android::base::StartsWith(path, "/mnt/media_rw/")) {
767 return false;
768 }
769 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
770 if (fd < 0) {
771 PLOG(ERROR) << "open failed: " << path;
772 return false;
773 }
774 struct statfs info;
775 if (fstatfs(fd, &info)) {
776 PLOG(ERROR) << "statfs failed: " << path;
777 return false;
778 }
779 LOG(ERROR) << "fs type: " << info.f_type;
780 return info.f_type == MSDOS_SUPER_MAGIC;
781}
782
Howard Chen4663de62019-11-05 20:46:20 +0800783int GsiService::ValidateInstallParams(std::string& install_dir) {
David Anderson49eea5f2019-05-23 13:27:01 -0700784 // If no install path was specified, use the default path. We also allow
785 // specifying the top-level folder, and then we choose the correct location
786 // underneath.
Howard Chen4663de62019-11-05 20:46:20 +0800787 if (install_dir.empty() || install_dir == "/data/gsi") {
788 install_dir = kDefaultDsuImageFolder;
David Andersoneb30ac22019-03-12 15:24:53 -0700789 }
790
791 // Normalize the path and add a trailing slash.
Howard Chen4663de62019-11-05 20:46:20 +0800792 std::string origInstallDir = install_dir;
793 if (!android::base::Realpath(origInstallDir, &install_dir)) {
David Andersoneb30ac22019-03-12 15:24:53 -0700794 PLOG(ERROR) << "realpath failed: " << origInstallDir;
795 return INSTALL_ERROR_GENERIC;
796 }
David Anderson64b53fb2019-07-01 19:05:35 -0700797 // Ensure the path ends in / for consistency.
Howard Chen4663de62019-11-05 20:46:20 +0800798 if (!android::base::EndsWith(install_dir, "/")) {
799 install_dir += "/";
David Andersoneb30ac22019-03-12 15:24:53 -0700800 }
801
David Andersone7a8ade2019-03-13 19:21:22 -0700802 // Currently, we can only install to /data/gsi/ or external storage.
Howard Chen4663de62019-11-05 20:46:20 +0800803 if (IsExternalStoragePath(install_dir)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700804 Fstab fstab;
805 if (!ReadDefaultFstab(&fstab)) {
806 LOG(ERROR) << "cannot read default fstab";
807 return INSTALL_ERROR_GENERIC;
808 }
809 FstabEntry* system = GetEntryForMountPoint(&fstab, "/system");
810 if (!system) {
811 LOG(ERROR) << "cannot find /system fstab entry";
812 return INSTALL_ERROR_GENERIC;
813 }
814 if (fs_mgr_verity_is_check_at_most_once(*system)) {
815 LOG(ERROR) << "cannot install GSIs to external media if verity uses check_at_most_once";
816 return INSTALL_ERROR_GENERIC;
817 }
Howard Chen4663de62019-11-05 20:46:20 +0800818 } else if (install_dir != kDefaultDsuImageFolder) {
819 LOG(ERROR) << "cannot install DSU to " << install_dir;
David Andersoneb30ac22019-03-12 15:24:53 -0700820 return INSTALL_ERROR_GENERIC;
821 }
822 return INSTALL_OK;
823}
824
Howard Chenee5c2b12019-11-08 11:57:47 +0800825std::string GsiService::GetActiveDsuSlot() {
826 if (!install_dir_.empty()) {
827 return GetDsuSlot(install_dir_);
828 } else {
829 std::string active_dsu;
830 return GetActiveDsu(&active_dsu) ? active_dsu : "";
831 }
832}
833
Howard Chen3f6d5a62019-08-22 15:26:33 +0800834std::string GsiService::GetActiveInstalledImageDir() {
835 // Just in case an install was left hanging.
836 if (installer_) {
837 return installer_->install_dir();
838 } else {
839 return GetInstalledImageDir();
840 }
841}
842
David Anderson5f805912019-03-07 12:41:15 -0800843std::string GsiService::GetInstalledImageDir() {
844 // If there's no install left, just return /data/gsi since that's where
845 // installs go by default.
Howard Chenee5c2b12019-11-08 11:57:47 +0800846 std::string active_dsu;
David Anderson5f805912019-03-07 12:41:15 -0800847 std::string dir;
Howard Chenee5c2b12019-11-08 11:57:47 +0800848 if (GetActiveDsu(&active_dsu) &&
849 android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) {
David Anderson5f805912019-03-07 12:41:15 -0800850 return dir;
851 }
David Anderson9bdf8632019-07-01 14:49:11 -0700852 return kDefaultDsuImageFolder;
David Anderson5f805912019-03-07 12:41:15 -0800853}
854
David Anderson564a04c2019-02-27 13:33:44 -0800855int GsiService::ReenableGsi(bool one_shot) {
David Andersona141ba82019-01-14 19:09:27 -0800856 if (!android::gsi::IsGsiInstalled()) {
857 LOG(ERROR) << "no gsi installed - cannot re-enable";
David Anderson868dea52019-01-17 13:34:38 -0800858 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800859 }
David Andersona141ba82019-01-14 19:09:27 -0800860 std::string boot_key;
861 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -0700862 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Anderson868dea52019-01-17 13:34:38 -0800863 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800864 }
865 if (boot_key != kInstallStatusDisabled) {
866 LOG(ERROR) << "GSI is not currently disabled";
David Anderson868dea52019-01-17 13:34:38 -0800867 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800868 }
Howard Chen4663de62019-11-05 20:46:20 +0800869 if (IsGsiRunning()) {
870 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
871 return IGsiService::INSTALL_ERROR_GENERIC;
872 }
873 return IGsiService::INSTALL_OK;
874 }
875 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
876 return IGsiService::INSTALL_ERROR_GENERIC;
877 }
878 return IGsiService::INSTALL_OK;
David Andersond81e1252019-02-28 23:36:09 -0800879}
880
Howard Chen4663de62019-11-05 20:46:20 +0800881bool GsiService::RemoveGsiFiles(const std::string& install_dir) {
David Anderson563e29a2019-03-06 19:20:45 -0800882 bool ok = true;
Howard Chenee5c2b12019-11-08 11:57:47 +0800883 auto active_dsu = GetDsuSlot(install_dir);
884 if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) {
Howard Chen18109b12019-08-13 17:00:44 +0800885 std::vector<std::string> images = manager->GetAllBackingImages();
886 for (auto&& image : images) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800887 if (!android::base::EndsWith(image, kDsuPostfix)) {
Howard Chen18109b12019-08-13 17:00:44 +0800888 continue;
Howard Chen3f6d5a62019-08-22 15:26:33 +0800889 }
890 if (manager->IsImageMapped(image)) {
891 ok &= manager->UnmapImageDevice(image);
892 }
Howard Chen4663de62019-11-05 20:46:20 +0800893 ok &= manager->DeleteBackingImage(image);
David Anderson64b53fb2019-07-01 19:05:35 -0700894 }
David Anderson563e29a2019-03-06 19:20:45 -0800895 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800896 auto dsu_slot = GetDsuSlot(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800897 std::vector<std::string> files{
David Anderson9bdf8632019-07-01 14:49:11 -0700898 kDsuInstallStatusFile,
David Anderson9bdf8632019-07-01 14:49:11 -0700899 kDsuOneShotBootFile,
Howard Chenee5c2b12019-11-08 11:57:47 +0800900 DsuInstallDirFile(dsu_slot),
901 GetCompleteIndication(dsu_slot),
David Andersonc053b3b2019-01-08 18:22:07 -0800902 };
David Andersonc053b3b2019-01-08 18:22:07 -0800903 for (const auto& file : files) {
David Anderson64b53fb2019-07-01 19:05:35 -0700904 std::string message;
Howard Chen4663de62019-11-05 20:46:20 +0800905 if (!RemoveFileIfExists(file, &message)) {
David Andersonc053b3b2019-01-08 18:22:07 -0800906 LOG(ERROR) << message;
907 ok = false;
908 }
909 }
Howard Chen0e188062020-02-26 12:48:41 +0800910 if (ok) {
911 SetProperty(kGsiInstalledProp, "0");
912 }
David Andersonb3aff182019-01-11 14:37:51 -0800913 return ok;
914}
915
David Andersona141ba82019-01-14 19:09:27 -0800916bool GsiService::DisableGsiInstall() {
917 if (!android::gsi::IsGsiInstalled()) {
918 LOG(ERROR) << "cannot disable gsi install - no install detected";
919 return false;
David Andersonb3aff182019-01-11 14:37:51 -0800920 }
David Andersonb2988ab2019-04-16 17:14:09 -0700921 if (installer_) {
David Andersona141ba82019-01-14 19:09:27 -0800922 LOG(ERROR) << "cannot disable gsi during GSI installation";
923 return false;
924 }
925 if (!DisableGsi()) {
926 PLOG(ERROR) << "could not write gsi status";
927 return false;
928 }
929 return true;
David Andersonc053b3b2019-01-08 18:22:07 -0800930}
931
Howard Chenee5c2b12019-11-08 11:57:47 +0800932std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) {
933 return DSU_METADATA_PREFIX + dsu_slot + "/complete";
Howard Chen4663de62019-11-05 20:46:20 +0800934}
935
Howard Chenee5c2b12019-11-08 11:57:47 +0800936bool GsiService::IsInstallationComplete(const std::string& dsu_slot) {
937 if (access(kDsuInstallStatusFile, F_OK) != 0) {
938 return false;
939 }
940 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800941 std::string content;
942 if (!ReadFileToString(file, &content)) {
943 return false;
944 }
945 return content == "OK";
946}
947
Howard Chenee5c2b12019-11-08 11:57:47 +0800948std::vector<std::string> GsiService::GetInstalledDsuSlots() {
949 std::vector<std::string> dsu_slots;
950 auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir);
951 if (d != nullptr) {
952 struct dirent* de;
953 while ((de = readdir(d.get())) != nullptr) {
954 if (de->d_name[0] == '.') {
955 continue;
956 }
957 auto dsu_slot = std::string(de->d_name);
958 if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) {
959 continue;
960 }
961 dsu_slots.push_back(dsu_slot);
962 }
963 }
964 return dsu_slots;
965}
966
Howard Chen3f6d5a62019-08-22 15:26:33 +0800967void GsiService::CleanCorruptedInstallation() {
Howard Chenee5c2b12019-11-08 11:57:47 +0800968 for (auto&& slot : GetInstalledDsuSlots()) {
969 bool is_complete = IsInstallationComplete(slot);
970 if (!is_complete) {
971 LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot;
972 std::string install_dir;
973 if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) ||
974 !RemoveGsiFiles(install_dir)) {
975 LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot;
976 }
Howard Chen4663de62019-11-05 20:46:20 +0800977 }
Howard Chen3f6d5a62019-08-22 15:26:33 +0800978 }
979}
980
David Andersonb3aff182019-01-11 14:37:51 -0800981void GsiService::RunStartupTasks() {
Howard Chen4663de62019-11-05 20:46:20 +0800982 CleanCorruptedInstallation();
David Andersonb3aff182019-01-11 14:37:51 -0800983
Howard Chenee5c2b12019-11-08 11:57:47 +0800984 std::string active_dsu;
985 if (!GetActiveDsu(&active_dsu)) {
986 PLOG(INFO) << "no DSU";
987 return;
988 }
David Andersonb3aff182019-01-11 14:37:51 -0800989 std::string boot_key;
990 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -0700991 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -0800992 return;
993 }
994
995 if (!IsGsiRunning()) {
996 // Check if a wipe was requested from fastboot or adb-in-gsi.
997 if (boot_key == kInstallStatusWipe) {
Howard Chen4663de62019-11-05 20:46:20 +0800998 RemoveGsiFiles(GetInstalledImageDir());
David Andersonb3aff182019-01-11 14:37:51 -0800999 }
1000 } else {
David Anderson564a04c2019-02-27 13:33:44 -08001001 // NB: When single-boot is enabled, init will write "disabled" into the
1002 // install_status file, which will cause GetBootAttempts to return
1003 // false. Thus, we won't write "ok" here.
David Andersonb3aff182019-01-11 14:37:51 -08001004 int ignore;
1005 if (GetBootAttempts(boot_key, &ignore)) {
1006 // Mark the GSI as having successfully booted.
David Anderson9bdf8632019-07-01 14:49:11 -07001007 if (!android::base::WriteStringToFile(kInstallStatusOk, kDsuInstallStatusFile)) {
1008 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001009 }
1010 }
1011 }
1012}
1013
Yo Chiang53bed1c2020-01-01 16:25:19 +08001014static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) {
1015 // Read the AVB footer from EOF.
1016 int64_t total_size = get_block_device_size(fd);
1017 int64_t footer_offset = total_size - AVB_FOOTER_SIZE;
1018 std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes;
1019 if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) {
1020 PLOG(ERROR) << "cannot read AVB footer";
1021 return false;
1022 }
1023 // Validate the AVB footer data and byte swap to native byte order.
1024 AvbFooter footer;
1025 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) {
1026 LOG(ERROR) << "invalid AVB footer";
1027 return false;
1028 }
1029 // Read the VBMeta image.
1030 std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size);
1031 if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) {
1032 PLOG(ERROR) << "cannot read VBMeta image";
1033 return false;
1034 }
1035 // Validate the VBMeta image and retrieve AVB public key.
1036 // After a successful call to avb_vbmeta_image_verify(), public_key_data
1037 // will point to the serialized AVB public key, in the same format generated
1038 // by the `avbtool extract_public_key` command.
1039 const uint8_t* public_key_data;
1040 size_t public_key_size;
1041 AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(),
1042 &public_key_data, &public_key_size);
1043 if (result != AVB_VBMETA_VERIFY_RESULT_OK) {
1044 LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result);
1045 return false;
1046 }
1047 if (public_key_data != nullptr) {
1048 dst->bytes.resize(public_key_size);
1049 memcpy(dst->bytes.data(), public_key_data, public_key_size);
1050 dst->sha1.resize(SHA_DIGEST_LENGTH);
1051 SHA1(public_key_data, public_key_size, dst->sha1.data());
1052 }
1053 return true;
1054}
1055
David Andersonc053b3b2019-01-08 18:22:07 -08001056} // namespace gsi
1057} // namespace android