blob: 939f60343b362f97de1879bc9195a19cfed54609 [file] [log] [blame]
David Andersonc053b3b2019-01-08 18:22:07 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "gsi_service.h"
18
Yo Chiang721a0e42020-12-28 19:29:47 +080019#include <sys/statvfs.h>
David Andersone7a8ade2019-03-13 19:21:22 -070020#include <sys/vfs.h>
David Andersonc053b3b2019-01-08 18:22:07 -080021#include <unistd.h>
22
Yo Chiang53bed1c2020-01-01 16:25:19 +080023#include <array>
David Andersonc053b3b2019-01-08 18:22:07 -080024#include <chrono>
25#include <string>
26#include <vector>
27
Yifan Hongd66695b2019-12-23 16:07:45 -080028#include <android-base/errors.h>
David Andersonc053b3b2019-01-08 18:22:07 -080029#include <android-base/file.h>
30#include <android-base/logging.h>
Howard Chen7885d3c2020-02-26 12:48:41 +080031#include <android-base/properties.h>
David Andersonc053b3b2019-01-08 18:22:07 -080032#include <android-base/stringprintf.h>
David Anderson5f805912019-03-07 12:41:15 -080033#include <android-base/strings.h>
David Anderson551ae3a2019-08-01 12:53:06 -070034#include <android/gsi/BnImageService.h>
David Andersonc053b3b2019-01-08 18:22:07 -080035#include <android/gsi/IGsiService.h>
Yo Chiang1f080912020-10-07 17:29:57 +080036#include <android/os/IVold.h>
37#include <binder/IServiceManager.h>
Howard Chen67a27092020-02-15 17:32:02 +080038#include <binder/LazyServiceRegistrar.h>
David Anderson64b53fb2019-07-01 19:05:35 -070039#include <ext4_utils/ext4_utils.h>
David Andersone7a8ade2019-03-13 19:21:22 -070040#include <fs_mgr.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080041#include <libavb/libavb.h>
David Andersond614eca2019-09-09 17:57:06 -070042#include <libdm/dm.h>
David Anderson6f373b72019-06-05 15:04:00 -070043#include <libfiemap/image_manager.h>
Yo Chiang53bed1c2020-01-01 16:25:19 +080044#include <openssl/sha.h>
David Anderson3c819cb2019-02-08 17:50:50 -080045#include <private/android_filesystem_config.h>
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +080046#include <selinux/android.h>
Yo Chiang721a0e42020-12-28 19:29:47 +080047#include <storage_literals/storage_literals.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;
Yo Chiang721a0e42020-12-28 19:29:47 +080058using namespace android::storage_literals;
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 Chen7885d3c2020-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 Chen67a27092020-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 Chen4663de62019-11-05 20:46:20 +080070// Default userdata image size.
71static constexpr int64_t kDefaultUserdataSize = int64_t(2) * 1024 * 1024 * 1024;
72
Yo Chiang53bed1c2020-01-01 16:25:19 +080073static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst);
74
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +080075// Fix the file contexts of dsu metadata files.
76// By default, newly created files inherit the file contexts of their parent
77// directory. Since globally readable public metadata files are labeled with a
78// different context, gsi_public_metadata_file, we need to call this function to
79// fix their contexts after creating them.
80static void RestoreconMetadataFiles() {
81 auto flags = SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIP_SEHASH;
82 selinux_android_restorecon(DSU_METADATA_PREFIX, flags);
83}
84
Howard Chen67a27092020-02-15 17:32:02 +080085GsiService::GsiService() {
David Anderson6a5b8a72019-01-16 16:24:48 -080086 progress_ = {};
87}
88
Howard Chen67a27092020-02-15 17:32:02 +080089void GsiService::Register() {
90 auto lazyRegistrar = LazyServiceRegistrar::getInstance();
91 android::sp<GsiService> service = new GsiService();
92 auto ret = lazyRegistrar.registerService(service, kGsiServiceName);
David Anderson4c756732019-07-12 14:18:37 -070093
Howard Chen67a27092020-02-15 17:32:02 +080094 if (ret != android::OK) {
95 LOG(FATAL) << "Could not register gsi service: " << ret;
David Anderson4c756732019-07-12 14:18:37 -070096 }
97}
98
David Anderson5cc440c2019-04-16 14:34:27 -070099#define ENFORCE_SYSTEM \
100 do { \
101 binder::Status status = CheckUid(); \
102 if (!status.isOk()) return status; \
David Anderson3c819cb2019-02-08 17:50:50 -0800103 } while (0)
104
David Anderson5cc440c2019-04-16 14:34:27 -0700105#define ENFORCE_SYSTEM_OR_SHELL \
106 do { \
107 binder::Status status = CheckUid(AccessLevel::SystemOrShell); \
108 if (!status.isOk()) return status; \
David Andersonb5f44b32019-02-20 18:04:37 -0800109 } while (0)
110
Howard Chen4663de62019-11-05 20:46:20 +0800111int GsiService::SaveInstallation(const std::string& installation) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800112 auto dsu_slot = GetDsuSlot(installation);
113 auto install_dir_file = DsuInstallDirFile(dsu_slot);
114 auto metadata_dir = android::base::Dirname(install_dir_file);
115 if (access(metadata_dir.c_str(), F_OK) != 0) {
116 if (mkdir(metadata_dir.c_str(), 0777) != 0) {
117 PLOG(ERROR) << "Failed to mkdir " << metadata_dir;
118 return INSTALL_ERROR_GENERIC;
119 }
120 }
Howard Chen4663de62019-11-05 20:46:20 +0800121 auto fd = android::base::unique_fd(
Howard Chenee5c2b12019-11-08 11:57:47 +0800122 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 +0800123 if (!WriteStringToFd(installation, fd)) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800124 PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800125 return INSTALL_ERROR_GENERIC;
126 }
127 return INSTALL_OK;
128}
129
Howard Chen3a5e19a2021-01-07 16:07:52 +0800130static bool IsExternalStoragePath(const std::string& path);
131
Howard Chen4663de62019-11-05 20:46:20 +0800132binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
133 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800134 std::lock_guard<std::mutex> guard(lock_);
Howard Chen4663de62019-11-05 20:46:20 +0800135 if (IsGsiRunning()) {
136 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
137 return binder::Status::ok();
138 }
139 install_dir_ = install_dir;
140 if (int status = ValidateInstallParams(install_dir_)) {
141 *_aidl_return = status;
142 return binder::Status::ok();
143 }
144 std::string message;
Howard Chenee5c2b12019-11-08 11:57:47 +0800145 auto dsu_slot = GetDsuSlot(install_dir_);
146 if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
Howard Chen4663de62019-11-05 20:46:20 +0800147 LOG(ERROR) << message;
148 }
149 // Remember the installation directory before allocate any resource
150 *_aidl_return = SaveInstallation(install_dir_);
151 return binder::Status::ok();
152}
153
154binder::Status GsiService::closeInstall(int* _aidl_return) {
155 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800156 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800157 auto dsu_slot = GetDsuSlot(install_dir_);
158 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +0800159 if (!WriteStringToFile("OK", file)) {
160 PLOG(ERROR) << "write failed: " << file;
161 *_aidl_return = INSTALL_ERROR_GENERIC;
162 }
Howard Chen4663de62019-11-05 20:46:20 +0800163 *_aidl_return = INSTALL_OK;
164 return binder::Status::ok();
165}
166
167binder::Status GsiService::createPartition(const ::std::string& name, int64_t size, bool readOnly,
168 int32_t* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800169 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800170 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800171
Howard Chen4663de62019-11-05 20:46:20 +0800172 if (install_dir_.empty()) {
173 PLOG(ERROR) << "open is required for createPartition";
174 *_aidl_return = INSTALL_ERROR_GENERIC;
175 return binder::Status::ok();
176 }
177
David Andersoneb30ac22019-03-12 15:24:53 -0700178 // Do some precursor validation on the arguments before diving into the
179 // install process.
Howard Chen4663de62019-11-05 20:46:20 +0800180 if (size % LP_SECTOR_SIZE) {
181 LOG(ERROR) << " size " << size << " is not a multiple of " << LP_SECTOR_SIZE;
182 *_aidl_return = INSTALL_ERROR_GENERIC;
David Andersoneb30ac22019-03-12 15:24:53 -0700183 return binder::Status::ok();
184 }
185
Howard Chen4663de62019-11-05 20:46:20 +0800186 if (size == 0 && name == "userdata") {
187 size = kDefaultUserdataSize;
188 }
Yo Chiang1f080912020-10-07 17:29:57 +0800189
190 if (name == "userdata") {
191 auto dsu_slot = GetDsuSlot(install_dir_);
192 auto key_dir = DefaultDsuMetadataKeyDir(dsu_slot);
193 auto key_dir_file = DsuMetadataKeyDirFile(dsu_slot);
194 if (!android::base::WriteStringToFile(key_dir, key_dir_file)) {
195 PLOG(ERROR) << "write failed: " << key_dir_file;
196 *_aidl_return = INSTALL_ERROR_GENERIC;
197 return binder::Status::ok();
198 }
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +0800199 RestoreconMetadataFiles();
Yo Chiang1f080912020-10-07 17:29:57 +0800200 }
201
Howard Chenee5c2b12019-11-08 11:57:47 +0800202 installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name,
203 GetDsuSlot(install_dir_), size, readOnly);
Howard Chen9f40baf2019-12-16 13:31:12 +0800204 progress_ = {};
Yi-Yo Chiangc4d64002021-02-12 02:17:03 +0800205 *_aidl_return = installer_->StartInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800206 return binder::Status::ok();
207}
208
Yo Chiang36fdbc62020-08-20 19:40:31 +0800209binder::Status GsiService::closePartition(int32_t* _aidl_return) {
210 ENFORCE_SYSTEM;
211 std::lock_guard<std::mutex> guard(lock_);
212
213 if (installer_ == nullptr) {
214 LOG(ERROR) << "createPartition() has to be called before closePartition()";
215 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
216 return binder::Status::ok();
217 }
218 // It is important to not reset |installer_| here because other methods such
219 // as enableGsi() relies on the state of |installer_|.
220 *_aidl_return = installer_->FinishInstall();
221 return binder::Status::ok();
222}
223
David Anderson1d94d262019-01-11 20:39:51 -0800224binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
David Andersonc053b3b2019-01-08 18:22:07 -0800225 int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800226 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800227 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800228
David Andersonb2988ab2019-04-16 17:14:09 -0700229 if (!installer_) {
230 *_aidl_return = false;
231 return binder::Status::ok();
232 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800233
David Andersonb2988ab2019-04-16 17:14:09 -0700234 *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
David Anderson6a5b8a72019-01-16 16:24:48 -0800235 return binder::Status::ok();
236}
237
238void GsiService::StartAsyncOperation(const std::string& step, int64_t total_bytes) {
239 std::lock_guard<std::mutex> guard(progress_lock_);
240
241 progress_.step = step;
242 progress_.status = STATUS_WORKING;
243 progress_.bytes_processed = 0;
244 progress_.total_bytes = total_bytes;
245}
246
247void GsiService::UpdateProgress(int status, int64_t bytes_processed) {
248 std::lock_guard<std::mutex> guard(progress_lock_);
249
250 progress_.status = status;
David Andersona64e3922019-02-01 16:27:18 -0800251 if (status == STATUS_COMPLETE) {
252 progress_.bytes_processed = progress_.total_bytes;
253 } else {
254 progress_.bytes_processed = bytes_processed;
255 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800256}
257
258binder::Status GsiService::getInstallProgress(::android::gsi::GsiProgress* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800259 ENFORCE_SYSTEM;
David Anderson6a5b8a72019-01-16 16:24:48 -0800260 std::lock_guard<std::mutex> guard(progress_lock_);
261
Howard Chen9f40baf2019-12-16 13:31:12 +0800262 if (installer_ == nullptr) {
263 progress_ = {};
264 }
David Anderson6a5b8a72019-01-16 16:24:48 -0800265 *_aidl_return = progress_;
David Andersonc053b3b2019-01-08 18:22:07 -0800266 return binder::Status::ok();
267}
268
Howard Chen5676d962019-08-05 16:21:00 +0800269binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800270 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800271 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800272
David Andersonb2988ab2019-04-16 17:14:09 -0700273 if (!installer_) {
274 *_aidl_return = false;
275 return binder::Status::ok();
276 }
Howard Chen5676d962019-08-05 16:21:00 +0800277 *_aidl_return = installer_->CommitGsiChunk(bytes);
278 return binder::Status::ok();
279}
David Andersonb2988ab2019-04-16 17:14:09 -0700280
Howard Chen5676d962019-08-05 16:21:00 +0800281binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem,
282 int64_t size, bool* _aidl_return) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800283 ENFORCE_SYSTEM;
Howard Chen5676d962019-08-05 16:21:00 +0800284 if (!installer_) {
285 *_aidl_return = false;
286 return binder::Status::ok();
287 }
288 *_aidl_return = installer_->MapAshmem(ashmem.get(), size);
David Andersonc053b3b2019-01-08 18:22:07 -0800289 return binder::Status::ok();
290}
291
Howard Chen7885d3c2020-02-26 12:48:41 +0800292binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
293 const sp<IGsiServiceCallback>& resultCallback) {
294 int result;
295 auto status = enableGsi(one_shot, dsuSlot, &result);
296 if (!status.isOk()) {
297 LOG(ERROR) << "Could not enableGsi: " << status.exceptionMessage().string();
298 result = IGsiService::INSTALL_ERROR_GENERIC;
299 }
300 resultCallback->onResult(result);
301 return binder::Status::ok();
302}
303
Howard Chenee5c2b12019-11-08 11:57:47 +0800304binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
Howard Chen67a27092020-02-15 17:32:02 +0800305 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800306
Howard Chenee5c2b12019-11-08 11:57:47 +0800307 if (!WriteStringToFile(dsuSlot, kDsuActiveFile)) {
308 PLOG(ERROR) << "write failed: " << GetDsuSlot(install_dir_);
309 *_aidl_return = INSTALL_ERROR_GENERIC;
310 return binder::Status::ok();
311 }
Yi-Yo Chiangf72d88a2021-03-22 13:45:39 +0800312 RestoreconMetadataFiles();
David Andersonb2988ab2019-04-16 17:14:09 -0700313 if (installer_) {
David Anderson646b4b22019-02-27 18:26:54 -0800314 ENFORCE_SYSTEM;
Howard Chen4663de62019-11-05 20:46:20 +0800315 installer_ = {};
316 // Note: create the install status file last, since this is the actual boot
317 // indicator.
318 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
319 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
David Anderson5f805912019-03-07 12:41:15 -0800320 } else {
321 *_aidl_return = INSTALL_OK;
322 }
David Andersona141ba82019-01-14 19:09:27 -0800323 } else {
David Anderson646b4b22019-02-27 18:26:54 -0800324 ENFORCE_SYSTEM_OR_SHELL;
David Anderson564a04c2019-02-27 13:33:44 -0800325 *_aidl_return = ReenableGsi(one_shot);
David Andersona141ba82019-01-14 19:09:27 -0800326 }
David Anderson563e29a2019-03-06 19:20:45 -0800327
David Andersonb2988ab2019-04-16 17:14:09 -0700328 installer_ = nullptr;
David Andersonc053b3b2019-01-08 18:22:07 -0800329 return binder::Status::ok();
330}
331
Howard Chen670b3062019-02-26 18:14:47 +0800332binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
333 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800334 std::lock_guard<std::mutex> guard(lock_);
Howard Chen670b3062019-02-26 18:14:47 +0800335 std::string boot_key;
336 if (!GetInstallStatus(&boot_key)) {
337 *_aidl_return = false;
338 } else {
Howard Chenee5c2b12019-11-08 11:57:47 +0800339 *_aidl_return = (boot_key != kInstallStatusDisabled);
Howard Chen670b3062019-02-26 18:14:47 +0800340 }
341 return binder::Status::ok();
342}
343
Howard Chen7885d3c2020-02-26 12:48:41 +0800344binder::Status GsiService::removeGsiAsync(const sp<IGsiServiceCallback>& resultCallback) {
345 bool result;
346 auto status = removeGsi(&result);
347 if (!status.isOk()) {
348 LOG(ERROR) << "Could not removeGsi: " << status.exceptionMessage().string();
349 result = IGsiService::INSTALL_ERROR_GENERIC;
350 }
351 resultCallback->onResult(result);
352 return binder::Status::ok();
353}
354
Howard Chen25b18cc2019-08-02 11:21:58 +0800355binder::Status GsiService::removeGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800356 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800357 std::lock_guard<std::mutex> guard(lock_);
David Andersonc053b3b2019-01-08 18:22:07 -0800358
Howard Chen3f6d5a62019-08-22 15:26:33 +0800359 std::string install_dir = GetActiveInstalledImageDir();
David Andersona141ba82019-01-14 19:09:27 -0800360 if (IsGsiRunning()) {
361 // Can't remove gsi files while running.
362 *_aidl_return = UninstallGsi();
363 } else {
Howard Chendee5d302020-02-05 10:58:29 +0800364 installer_ = {};
Howard Chen4663de62019-11-05 20:46:20 +0800365 *_aidl_return = RemoveGsiFiles(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800366 }
367 return binder::Status::ok();
368}
369
Howard Chen25b18cc2019-08-02 11:21:58 +0800370binder::Status GsiService::disableGsi(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800371 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800372 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800373
374 *_aidl_return = DisableGsiInstall();
David Andersonc053b3b2019-01-08 18:22:07 -0800375 return binder::Status::ok();
376}
377
378binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800379 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800380 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800381
David Andersonc053b3b2019-01-08 18:22:07 -0800382 *_aidl_return = IsGsiRunning();
383 return binder::Status::ok();
384}
385
David Andersona141ba82019-01-14 19:09:27 -0800386binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800387 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800388 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800389
390 *_aidl_return = IsGsiInstalled();
391 return binder::Status::ok();
392}
393
394binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800395 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800396 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800397
David Andersonb2988ab2019-04-16 17:14:09 -0700398 *_aidl_return = !!installer_;
David Andersona141ba82019-01-14 19:09:27 -0800399 return binder::Status::ok();
400}
401
402binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
David Andersonb5f44b32019-02-20 18:04:37 -0800403 ENFORCE_SYSTEM;
Howard Chenecbc0192019-02-25 18:51:26 +0800404 should_abort_ = true;
Howard Chen67a27092020-02-15 17:32:02 +0800405 std::lock_guard<std::mutex> guard(lock_);
David Andersona141ba82019-01-14 19:09:27 -0800406
Howard Chenecbc0192019-02-25 18:51:26 +0800407 should_abort_ = false;
David Andersonb2988ab2019-04-16 17:14:09 -0700408 installer_ = nullptr;
David Andersona141ba82019-01-14 19:09:27 -0800409
David Andersona141ba82019-01-14 19:09:27 -0800410 *_aidl_return = true;
411 return binder::Status::ok();
412}
413
David Anderson5f805912019-03-07 12:41:15 -0800414binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
415 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800416 std::lock_guard<std::mutex> guard(lock_);
David Anderson5f805912019-03-07 12:41:15 -0800417
Howard Chen3f6d5a62019-08-22 15:26:33 +0800418 *_aidl_return = GetActiveInstalledImageDir();
David Anderson5f805912019-03-07 12:41:15 -0800419 return binder::Status::ok();
420}
421
Howard Chenee5c2b12019-11-08 11:57:47 +0800422binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) {
423 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800424 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800425
426 *_aidl_return = GetActiveDsuSlot();
427 return binder::Status::ok();
428}
429
430binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) {
431 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800432 std::lock_guard<std::mutex> guard(lock_);
Howard Chenee5c2b12019-11-08 11:57:47 +0800433 *_aidl_return = GetInstalledDsuSlots();
434 return binder::Status::ok();
435}
436
Howard Chen4663de62019-11-05 20:46:20 +0800437binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) {
David Anderson8bdf6252019-06-11 16:43:24 -0700438 ENFORCE_SYSTEM_OR_SHELL;
Howard Chen67a27092020-02-15 17:32:02 +0800439 std::lock_guard<std::mutex> guard(lock_);
David Anderson8bdf6252019-06-11 16:43:24 -0700440
441 if (IsGsiRunning() || !IsGsiInstalled()) {
442 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
443 return binder::Status::ok();
444 }
445
Howard Chen3f6d5a62019-08-22 15:26:33 +0800446 std::string install_dir = GetActiveInstalledImageDir();
Howard Chenee5c2b12019-11-08 11:57:47 +0800447 *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name);
David Anderson8bdf6252019-06-11 16:43:24 -0700448
449 return binder::Status::ok();
450}
451
Yifan Hongd66695b2019-12-23 16:07:45 -0800452static binder::Status BinderError(const std::string& message,
453 FiemapStatus::ErrorCode status = FiemapStatus::ErrorCode::ERROR) {
454 return binder::Status::fromServiceSpecificError(static_cast<int32_t>(status), message.c_str());
David Anderson6f373b72019-06-05 15:04:00 -0700455}
456
David Andersond614eca2019-09-09 17:57:06 -0700457binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) {
458 ENFORCE_SYSTEM_OR_SHELL;
459
460 auto& dm = DeviceMapper::Instance();
461
462 std::vector<DeviceMapper::DmBlockDevice> devices;
463 if (!dm.GetAvailableDevices(&devices)) {
464 return BinderError("Could not list devices");
465 }
466
467 std::stringstream text;
468 for (const auto& device : devices) {
469 text << "Device " << device.name() << " (" << device.Major() << ":" << device.Minor()
470 << ")\n";
471
472 std::vector<DeviceMapper::TargetInfo> table;
473 if (!dm.GetTableInfo(device.name(), &table)) {
474 continue;
475 }
476
477 for (const auto& target : table) {
478 const auto& spec = target.spec;
479 auto target_type = DeviceMapper::GetTargetType(spec);
480 text << " " << target_type << " " << spec.sector_start << " " << spec.length << " "
481 << target.data << "\n";
482 }
483 }
484
485 *_aidl_return = text.str();
486 return binder::Status::ok();
487}
488
Yo Chiang53bed1c2020-01-01 16:25:19 +0800489binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) {
490 ENFORCE_SYSTEM;
Howard Chen67a27092020-02-15 17:32:02 +0800491 std::lock_guard<std::mutex> guard(lock_);
Yo Chiang53bed1c2020-01-01 16:25:19 +0800492
493 if (!installer_) {
494 *_aidl_return = INSTALL_ERROR_GENERIC;
495 return binder::Status::ok();
496 }
497 int fd = installer_->GetPartitionFd();
498 if (!GetAvbPublicKeyFromFd(fd, dst)) {
499 LOG(ERROR) << "Failed to extract AVB public key";
500 *_aidl_return = INSTALL_ERROR_GENERIC;
501 return binder::Status::ok();
502 }
503 *_aidl_return = INSTALL_OK;
504 return binder::Status::ok();
505}
506
Yo Chiang721a0e42020-12-28 19:29:47 +0800507binder::Status GsiService::suggestScratchSize(int64_t* _aidl_return) {
508 ENFORCE_SYSTEM;
509
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800510 static constexpr uint64_t kMinScratchSize = 512_MiB;
511 static constexpr uint64_t kMaxScratchSize = 2_GiB;
Yo Chiang721a0e42020-12-28 19:29:47 +0800512
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800513 uint64_t size = 0;
Yo Chiang721a0e42020-12-28 19:29:47 +0800514 struct statvfs info;
515 if (statvfs(install_dir_.c_str(), &info)) {
516 PLOG(ERROR) << "Could not statvfs(" << install_dir_ << ")";
517 } else {
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800518 // Keep the storage device at least 40% free, plus 1% for jitter.
519 constexpr int jitter = 1;
520 const uint64_t reserved_blocks =
521 static_cast<uint64_t>(info.f_blocks) * (kMinimumFreeSpaceThreshold + jitter) / 100;
522 if (info.f_bavail > reserved_blocks) {
523 size = (info.f_bavail - reserved_blocks) * info.f_frsize;
524 }
Yo Chiang721a0e42020-12-28 19:29:47 +0800525 }
526
Yi-Yo Chiang645cded2021-02-12 02:10:58 +0800527 // We can safely downcast the result here, since we clamped the result within int64_t range.
Yo Chiang721a0e42020-12-28 19:29:47 +0800528 *_aidl_return = std::clamp(size, kMinScratchSize, kMaxScratchSize);
529 return binder::Status::ok();
530}
531
Howard Chen4663de62019-11-05 20:46:20 +0800532bool GsiService::CreateInstallStatusFile() {
533 if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
534 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
535 return false;
536 }
Howard Chen7885d3c2020-02-26 12:48:41 +0800537 SetProperty(kGsiInstalledProp, "1");
Howard Chen4663de62019-11-05 20:46:20 +0800538 return true;
539}
540
541bool GsiService::SetBootMode(bool one_shot) {
542 if (one_shot) {
543 if (!android::base::WriteStringToFile("1", kDsuOneShotBootFile)) {
544 PLOG(ERROR) << "write " << kDsuOneShotBootFile;
545 return false;
546 }
547 } else if (!access(kDsuOneShotBootFile, F_OK)) {
548 std::string error;
549 if (!android::base::RemoveFileIfExists(kDsuOneShotBootFile, &error)) {
550 LOG(ERROR) << error;
551 return false;
552 }
553 }
554 return true;
555}
556
David Anderson6f373b72019-06-05 15:04:00 -0700557static binder::Status UidSecurityError() {
558 uid_t uid = IPCThreadState::self()->getCallingUid();
559 auto message = StringPrintf("UID %d is not allowed", uid);
560 return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
561}
562
David Anderson551ae3a2019-08-01 12:53:06 -0700563class ImageService : public BinderService<ImageService>, public BnImageService {
David Anderson6f373b72019-06-05 15:04:00 -0700564 public:
David Anderson551ae3a2019-08-01 12:53:06 -0700565 ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
Howard Chen96c31fd2019-08-23 17:38:51 +0800566 binder::Status getAllBackingImages(std::vector<std::string>* _aidl_return);
Yifan Hongd66695b2019-12-23 16:07:45 -0800567 binder::Status createBackingImage(const std::string& name, int64_t size, int flags,
568 const sp<IProgressCallback>& on_progress) override;
David Anderson6f373b72019-06-05 15:04:00 -0700569 binder::Status deleteBackingImage(const std::string& name) override;
570 binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
571 MappedImage* mapping) override;
572 binder::Status unmapImageDevice(const std::string& name) override;
David Anderson394f1f22019-07-29 12:49:02 -0700573 binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override;
David Andersonbee55a02019-08-01 15:01:55 -0700574 binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override;
Yo Chiang53bed1c2020-01-01 16:25:19 +0800575 binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
576 int32_t* _aidl_return) override;
Alessio Balsini0829fb22019-08-27 17:50:18 +0100577 binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override;
David Anderson86846bd2019-11-26 16:30:40 -0800578 binder::Status removeAllImages() override;
David Anderson7016a0d2019-12-16 22:06:47 -0800579 binder::Status removeDisabledImages() override;
David Anderson14aa72a2019-12-17 21:27:59 -0800580 binder::Status getMappedImageDevice(const std::string& name, std::string* device) override;
David Anderson6f373b72019-06-05 15:04:00 -0700581
582 private:
583 bool CheckUid();
584
David Anderson4c756732019-07-12 14:18:37 -0700585 android::sp<GsiService> service_;
David Anderson6f373b72019-06-05 15:04:00 -0700586 std::unique_ptr<ImageManager> impl_;
587 uid_t uid_;
588};
589
David Anderson551ae3a2019-08-01 12:53:06 -0700590ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
Howard Chen67a27092020-02-15 17:32:02 +0800591 : service_(service), impl_(std::move(impl)), uid_(uid) {}
David Anderson6f373b72019-06-05 15:04:00 -0700592
Howard Chen96c31fd2019-08-23 17:38:51 +0800593binder::Status ImageService::getAllBackingImages(std::vector<std::string>* _aidl_return) {
594 *_aidl_return = impl_->GetAllBackingImages();
595 return binder::Status::ok();
596}
597
Yifan Hongd66695b2019-12-23 16:07:45 -0800598binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags,
599 const sp<IProgressCallback>& on_progress) {
David Anderson6f373b72019-06-05 15:04:00 -0700600 if (!CheckUid()) return UidSecurityError();
601
Howard Chen67a27092020-02-15 17:32:02 +0800602 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700603
Yifan Hongd66695b2019-12-23 16:07:45 -0800604 std::function<bool(uint64_t, uint64_t)> callback;
605 if (on_progress) {
606 callback = [on_progress](uint64_t current, uint64_t total) -> bool {
607 auto status = on_progress->onProgress(static_cast<int64_t>(current),
608 static_cast<int64_t>(total));
609 if (!status.isOk()) {
610 LOG(ERROR) << "progress callback returned: " << status.toString8().string();
611 return false;
612 }
613 return true;
614 };
615 }
616
617 auto res = impl_->CreateBackingImage(name, size, flags, std::move(callback));
618 if (!res.is_ok()) {
619 return BinderError("Failed to create: " + res.string(), res.error_code());
David Anderson6f373b72019-06-05 15:04:00 -0700620 }
621 return binder::Status::ok();
622}
623
David Anderson551ae3a2019-08-01 12:53:06 -0700624binder::Status ImageService::deleteBackingImage(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700625 if (!CheckUid()) return UidSecurityError();
626
Howard Chen67a27092020-02-15 17:32:02 +0800627 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700628
629 if (!impl_->DeleteBackingImage(name)) {
630 return BinderError("Failed to delete");
631 }
632 return binder::Status::ok();
633}
634
David Anderson551ae3a2019-08-01 12:53:06 -0700635binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
636 MappedImage* mapping) {
David Anderson6f373b72019-06-05 15:04:00 -0700637 if (!CheckUid()) return UidSecurityError();
638
Howard Chen67a27092020-02-15 17:32:02 +0800639 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700640
641 if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
642 return BinderError("Failed to map");
643 }
644 return binder::Status::ok();
645}
646
David Anderson551ae3a2019-08-01 12:53:06 -0700647binder::Status ImageService::unmapImageDevice(const std::string& name) {
David Anderson6f373b72019-06-05 15:04:00 -0700648 if (!CheckUid()) return UidSecurityError();
649
Howard Chen67a27092020-02-15 17:32:02 +0800650 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson6f373b72019-06-05 15:04:00 -0700651
652 if (!impl_->UnmapImageDevice(name)) {
653 return BinderError("Failed to unmap");
654 }
655 return binder::Status::ok();
656}
657
David Anderson551ae3a2019-08-01 12:53:06 -0700658binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
David Anderson394f1f22019-07-29 12:49:02 -0700659 if (!CheckUid()) return UidSecurityError();
660
Howard Chen67a27092020-02-15 17:32:02 +0800661 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson394f1f22019-07-29 12:49:02 -0700662
663 *_aidl_return = impl_->BackingImageExists(name);
664 return binder::Status::ok();
665}
666
David Andersonbee55a02019-08-01 15:01:55 -0700667binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_return) {
668 if (!CheckUid()) return UidSecurityError();
669
Howard Chen67a27092020-02-15 17:32:02 +0800670 std::lock_guard<std::mutex> guard(service_->lock());
David Andersonbee55a02019-08-01 15:01:55 -0700671
672 *_aidl_return = impl_->IsImageMapped(name);
673 return binder::Status::ok();
674}
675
Yo Chiang53bed1c2020-01-01 16:25:19 +0800676binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
677 int32_t* _aidl_return) {
678 if (!CheckUid()) return UidSecurityError();
679
Howard Chen67a27092020-02-15 17:32:02 +0800680 std::lock_guard<std::mutex> guard(service_->lock());
Yo Chiang53bed1c2020-01-01 16:25:19 +0800681
682 std::string device_path;
683 std::unique_ptr<MappedDevice> mapped_device;
684 if (!impl_->IsImageMapped(name)) {
685 mapped_device = MappedDevice::Open(impl_.get(), 10s, name);
686 if (!mapped_device) {
687 PLOG(ERROR) << "Fail to map image: " << name;
688 *_aidl_return = IMAGE_ERROR;
689 return binder::Status::ok();
690 }
691 device_path = mapped_device->path();
692 } else {
693 if (!impl_->GetMappedImageDevice(name, &device_path)) {
694 PLOG(ERROR) << "GetMappedImageDevice() failed";
695 *_aidl_return = IMAGE_ERROR;
696 return binder::Status::ok();
697 }
698 }
699 android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
700 if (!fd.ok()) {
701 PLOG(ERROR) << "Fail to open mapped device: " << device_path;
702 *_aidl_return = IMAGE_ERROR;
703 return binder::Status::ok();
704 }
705 bool ok = GetAvbPublicKeyFromFd(fd.get(), dst);
706 fd = {};
707 if (!ok) {
708 LOG(ERROR) << "Failed to extract AVB public key";
709 *_aidl_return = IMAGE_ERROR;
710 return binder::Status::ok();
711 }
712 *_aidl_return = IMAGE_OK;
713 return binder::Status::ok();
714}
715
Alessio Balsini0829fb22019-08-27 17:50:18 +0100716binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) {
717 if (!CheckUid()) return UidSecurityError();
718
Howard Chen67a27092020-02-15 17:32:02 +0800719 std::lock_guard<std::mutex> guard(service_->lock());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100720
721 if (bytes < 0) {
722 return BinderError("Cannot use negative values");
723 }
Yifan Hongd66695b2019-12-23 16:07:45 -0800724 auto res = impl_->ZeroFillNewImage(name, bytes);
725 if (!res.is_ok()) {
726 return BinderError("Failed to fill image with zeros: " + res.string(), res.error_code());
Alessio Balsini0829fb22019-08-27 17:50:18 +0100727 }
728 return binder::Status::ok();
729}
730
David Anderson86846bd2019-11-26 16:30:40 -0800731binder::Status ImageService::removeAllImages() {
732 if (!CheckUid()) return UidSecurityError();
733
Howard Chen67a27092020-02-15 17:32:02 +0800734 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson86846bd2019-11-26 16:30:40 -0800735 if (!impl_->RemoveAllImages()) {
736 return BinderError("Failed to remove all images");
737 }
738 return binder::Status::ok();
739}
740
David Anderson7016a0d2019-12-16 22:06:47 -0800741binder::Status ImageService::removeDisabledImages() {
742 if (!CheckUid()) return UidSecurityError();
743
Howard Chen67a27092020-02-15 17:32:02 +0800744 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson7016a0d2019-12-16 22:06:47 -0800745 if (!impl_->RemoveDisabledImages()) {
746 return BinderError("Failed to remove disabled images");
747 }
748 return binder::Status::ok();
749}
750
David Anderson14aa72a2019-12-17 21:27:59 -0800751binder::Status ImageService::getMappedImageDevice(const std::string& name, std::string* device) {
752 if (!CheckUid()) return UidSecurityError();
753
Howard Chen67a27092020-02-15 17:32:02 +0800754 std::lock_guard<std::mutex> guard(service_->lock());
David Anderson14aa72a2019-12-17 21:27:59 -0800755 if (!impl_->GetMappedImageDevice(name, device)) {
756 *device = "";
757 }
758 return binder::Status::ok();
759}
760
David Andersonbee55a02019-08-01 15:01:55 -0700761bool ImageService::CheckUid() {
David Anderson6f373b72019-06-05 15:04:00 -0700762 return uid_ == IPCThreadState::self()->getCallingUid();
763}
764
David Anderson551ae3a2019-08-01 12:53:06 -0700765binder::Status GsiService::openImageService(const std::string& prefix,
766 android::sp<IImageService>* _aidl_return) {
Howard Chen3a5e19a2021-01-07 16:07:52 +0800767 using android::base::StartsWith;
768
David Anderson6f373b72019-06-05 15:04:00 -0700769 static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
770 static constexpr char kImageDataPrefix[] = "/data/gsi/";
771
David Anderson6ad45ba2019-07-29 12:51:23 -0700772 auto in_metadata_dir = kImageMetadataPrefix + prefix;
773 auto in_data_dir = kImageDataPrefix + prefix;
Howard Chenee5c2b12019-11-08 11:57:47 +0800774 auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix));
David Anderson6f373b72019-06-05 15:04:00 -0700775
Alessio Balsinibb774d02020-01-21 23:34:39 +0000776 std::string in_data_dir_tmp;
777 if (android::base::ReadFileToString(install_dir_file, &in_data_dir_tmp)) {
778 in_data_dir = in_data_dir_tmp;
Howard Chenee5c2b12019-11-08 11:57:47 +0800779 LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir;
780 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700781 std::string metadata_dir, data_dir;
782 if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000783 PLOG(ERROR) << "realpath failed for metadata: " << in_metadata_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700784 return BinderError("Invalid path");
785 }
David Anderson6ad45ba2019-07-29 12:51:23 -0700786 if (!android::base::Realpath(in_data_dir, &data_dir)) {
Alessio Balsini4a3bcc62020-02-03 23:17:14 +0000787 PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
David Anderson6f373b72019-06-05 15:04:00 -0700788 return BinderError("Invalid path");
789 }
Howard Chen3a5e19a2021-01-07 16:07:52 +0800790 if (!StartsWith(metadata_dir, kImageMetadataPrefix)) {
791 return BinderError("Invalid metadata path");
792 }
793 if (!StartsWith(data_dir, kImageDataPrefix) && !StartsWith(data_dir, kDsuSDPrefix)) {
794 return BinderError("Invalid data path");
David Anderson6f373b72019-06-05 15:04:00 -0700795 }
796
797 uid_t uid = IPCThreadState::self()->getCallingUid();
798 if (uid != AID_ROOT) {
799 return UidSecurityError();
800 }
801
802 auto impl = ImageManager::Open(metadata_dir, data_dir);
803 if (!impl) {
804 return BinderError("Unknown error");
805 }
806
David Anderson551ae3a2019-08-01 12:53:06 -0700807 *_aidl_return = new ImageService(this, std::move(impl), uid);
David Anderson6f373b72019-06-05 15:04:00 -0700808 return binder::Status::ok();
809}
810
David Andersonb5f44b32019-02-20 18:04:37 -0800811binder::Status GsiService::CheckUid(AccessLevel level) {
812 std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
813 if (level == AccessLevel::SystemOrShell) {
814 allowed_uids.push_back(AID_SHELL);
David Anderson3c819cb2019-02-08 17:50:50 -0800815 }
816
David Andersonb5f44b32019-02-20 18:04:37 -0800817 uid_t uid = IPCThreadState::self()->getCallingUid();
818 for (const auto& allowed_uid : allowed_uids) {
819 if (allowed_uid == uid) {
820 return binder::Status::ok();
821 }
822 }
David Anderson6f373b72019-06-05 15:04:00 -0700823 return UidSecurityError();
David Anderson3c819cb2019-02-08 17:50:50 -0800824}
825
David Andersone7a8ade2019-03-13 19:21:22 -0700826static bool IsExternalStoragePath(const std::string& path) {
Howard Chen3a5e19a2021-01-07 16:07:52 +0800827 if (!android::base::StartsWith(path, kDsuSDPrefix)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700828 return false;
829 }
830 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
831 if (fd < 0) {
832 PLOG(ERROR) << "open failed: " << path;
833 return false;
834 }
835 struct statfs info;
836 if (fstatfs(fd, &info)) {
837 PLOG(ERROR) << "statfs failed: " << path;
838 return false;
839 }
840 LOG(ERROR) << "fs type: " << info.f_type;
841 return info.f_type == MSDOS_SUPER_MAGIC;
842}
843
Howard Chen4663de62019-11-05 20:46:20 +0800844int GsiService::ValidateInstallParams(std::string& install_dir) {
David Anderson49eea5f2019-05-23 13:27:01 -0700845 // If no install path was specified, use the default path. We also allow
846 // specifying the top-level folder, and then we choose the correct location
847 // underneath.
Howard Chen4663de62019-11-05 20:46:20 +0800848 if (install_dir.empty() || install_dir == "/data/gsi") {
849 install_dir = kDefaultDsuImageFolder;
David Andersoneb30ac22019-03-12 15:24:53 -0700850 }
851
Howard Chene1870742021-02-18 18:32:20 +0800852 if (access(install_dir.c_str(), F_OK) != 0 && (errno == ENOENT)) {
853 if (android::base::StartsWith(install_dir, kDsuSDPrefix)) {
854 if (mkdir(install_dir.c_str(), 0755) != 0) {
855 PLOG(ERROR) << "Failed to create " << install_dir;
856 return INSTALL_ERROR_GENERIC;
857 }
858 }
859 }
David Andersoneb30ac22019-03-12 15:24:53 -0700860 // Normalize the path and add a trailing slash.
Howard Chen4663de62019-11-05 20:46:20 +0800861 std::string origInstallDir = install_dir;
862 if (!android::base::Realpath(origInstallDir, &install_dir)) {
David Andersoneb30ac22019-03-12 15:24:53 -0700863 PLOG(ERROR) << "realpath failed: " << origInstallDir;
864 return INSTALL_ERROR_GENERIC;
865 }
David Anderson64b53fb2019-07-01 19:05:35 -0700866 // Ensure the path ends in / for consistency.
Howard Chen4663de62019-11-05 20:46:20 +0800867 if (!android::base::EndsWith(install_dir, "/")) {
868 install_dir += "/";
David Andersoneb30ac22019-03-12 15:24:53 -0700869 }
870
David Andersone7a8ade2019-03-13 19:21:22 -0700871 // Currently, we can only install to /data/gsi/ or external storage.
Howard Chen4663de62019-11-05 20:46:20 +0800872 if (IsExternalStoragePath(install_dir)) {
David Andersone7a8ade2019-03-13 19:21:22 -0700873 Fstab fstab;
874 if (!ReadDefaultFstab(&fstab)) {
875 LOG(ERROR) << "cannot read default fstab";
876 return INSTALL_ERROR_GENERIC;
877 }
878 FstabEntry* system = GetEntryForMountPoint(&fstab, "/system");
879 if (!system) {
880 LOG(ERROR) << "cannot find /system fstab entry";
881 return INSTALL_ERROR_GENERIC;
882 }
883 if (fs_mgr_verity_is_check_at_most_once(*system)) {
884 LOG(ERROR) << "cannot install GSIs to external media if verity uses check_at_most_once";
885 return INSTALL_ERROR_GENERIC;
886 }
Howard Chen4663de62019-11-05 20:46:20 +0800887 } else if (install_dir != kDefaultDsuImageFolder) {
888 LOG(ERROR) << "cannot install DSU to " << install_dir;
David Andersoneb30ac22019-03-12 15:24:53 -0700889 return INSTALL_ERROR_GENERIC;
890 }
891 return INSTALL_OK;
892}
893
Howard Chenee5c2b12019-11-08 11:57:47 +0800894std::string GsiService::GetActiveDsuSlot() {
895 if (!install_dir_.empty()) {
896 return GetDsuSlot(install_dir_);
897 } else {
898 std::string active_dsu;
899 return GetActiveDsu(&active_dsu) ? active_dsu : "";
900 }
901}
902
Howard Chen3f6d5a62019-08-22 15:26:33 +0800903std::string GsiService::GetActiveInstalledImageDir() {
904 // Just in case an install was left hanging.
905 if (installer_) {
906 return installer_->install_dir();
907 } else {
908 return GetInstalledImageDir();
909 }
910}
911
David Anderson5f805912019-03-07 12:41:15 -0800912std::string GsiService::GetInstalledImageDir() {
913 // If there's no install left, just return /data/gsi since that's where
914 // installs go by default.
Howard Chenee5c2b12019-11-08 11:57:47 +0800915 std::string active_dsu;
David Anderson5f805912019-03-07 12:41:15 -0800916 std::string dir;
Howard Chenee5c2b12019-11-08 11:57:47 +0800917 if (GetActiveDsu(&active_dsu) &&
918 android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) {
David Anderson5f805912019-03-07 12:41:15 -0800919 return dir;
920 }
David Anderson9bdf8632019-07-01 14:49:11 -0700921 return kDefaultDsuImageFolder;
David Anderson5f805912019-03-07 12:41:15 -0800922}
923
David Anderson564a04c2019-02-27 13:33:44 -0800924int GsiService::ReenableGsi(bool one_shot) {
David Andersona141ba82019-01-14 19:09:27 -0800925 if (!android::gsi::IsGsiInstalled()) {
926 LOG(ERROR) << "no gsi installed - cannot re-enable";
David Anderson868dea52019-01-17 13:34:38 -0800927 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800928 }
David Andersona141ba82019-01-14 19:09:27 -0800929 std::string boot_key;
930 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -0700931 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Anderson868dea52019-01-17 13:34:38 -0800932 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800933 }
934 if (boot_key != kInstallStatusDisabled) {
935 LOG(ERROR) << "GSI is not currently disabled";
David Anderson868dea52019-01-17 13:34:38 -0800936 return INSTALL_ERROR_GENERIC;
David Andersona141ba82019-01-14 19:09:27 -0800937 }
Howard Chen4663de62019-11-05 20:46:20 +0800938 if (IsGsiRunning()) {
939 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
940 return IGsiService::INSTALL_ERROR_GENERIC;
941 }
942 return IGsiService::INSTALL_OK;
943 }
944 if (!SetBootMode(one_shot) || !CreateInstallStatusFile()) {
945 return IGsiService::INSTALL_ERROR_GENERIC;
946 }
947 return IGsiService::INSTALL_OK;
David Andersond81e1252019-02-28 23:36:09 -0800948}
949
Yo Chiang1f080912020-10-07 17:29:57 +0800950static android::sp<android::os::IVold> GetVoldService() {
951 return android::waitForService<android::os::IVold>(android::String16("vold"));
952}
953
Howard Chen4663de62019-11-05 20:46:20 +0800954bool GsiService::RemoveGsiFiles(const std::string& install_dir) {
David Anderson563e29a2019-03-06 19:20:45 -0800955 bool ok = true;
Howard Chenee5c2b12019-11-08 11:57:47 +0800956 auto active_dsu = GetDsuSlot(install_dir);
957 if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) {
Howard Chen18109b12019-08-13 17:00:44 +0800958 std::vector<std::string> images = manager->GetAllBackingImages();
959 for (auto&& image : images) {
Howard Chenee5c2b12019-11-08 11:57:47 +0800960 if (!android::base::EndsWith(image, kDsuPostfix)) {
Howard Chen18109b12019-08-13 17:00:44 +0800961 continue;
Howard Chen3f6d5a62019-08-22 15:26:33 +0800962 }
963 if (manager->IsImageMapped(image)) {
964 ok &= manager->UnmapImageDevice(image);
965 }
Howard Chen4663de62019-11-05 20:46:20 +0800966 ok &= manager->DeleteBackingImage(image);
David Anderson64b53fb2019-07-01 19:05:35 -0700967 }
David Anderson563e29a2019-03-06 19:20:45 -0800968 }
Howard Chenee5c2b12019-11-08 11:57:47 +0800969 auto dsu_slot = GetDsuSlot(install_dir);
David Andersona141ba82019-01-14 19:09:27 -0800970 std::vector<std::string> files{
David Anderson9bdf8632019-07-01 14:49:11 -0700971 kDsuInstallStatusFile,
David Anderson9bdf8632019-07-01 14:49:11 -0700972 kDsuOneShotBootFile,
Howard Chenee5c2b12019-11-08 11:57:47 +0800973 DsuInstallDirFile(dsu_slot),
974 GetCompleteIndication(dsu_slot),
David Andersonc053b3b2019-01-08 18:22:07 -0800975 };
David Andersonc053b3b2019-01-08 18:22:07 -0800976 for (const auto& file : files) {
David Anderson64b53fb2019-07-01 19:05:35 -0700977 std::string message;
Howard Chen4663de62019-11-05 20:46:20 +0800978 if (!RemoveFileIfExists(file, &message)) {
David Andersonc053b3b2019-01-08 18:22:07 -0800979 LOG(ERROR) << message;
980 ok = false;
981 }
982 }
Yo Chiang1f080912020-10-07 17:29:57 +0800983 if (auto vold = GetVoldService()) {
984 auto status = vold->destroyDsuMetadataKey(dsu_slot);
985 if (status.isOk()) {
986 std::string message;
987 if (!RemoveFileIfExists(DsuMetadataKeyDirFile(dsu_slot), &message)) {
988 LOG(ERROR) << message;
989 ok = false;
990 }
991 } else {
992 LOG(ERROR) << "Failed to destroy DSU metadata encryption key.";
993 ok = false;
994 }
995 } else {
996 LOG(ERROR) << "Failed to retrieve vold service.";
997 ok = false;
998 }
Howard Chen7885d3c2020-02-26 12:48:41 +0800999 if (ok) {
1000 SetProperty(kGsiInstalledProp, "0");
1001 }
David Andersonb3aff182019-01-11 14:37:51 -08001002 return ok;
1003}
1004
David Andersona141ba82019-01-14 19:09:27 -08001005bool GsiService::DisableGsiInstall() {
1006 if (!android::gsi::IsGsiInstalled()) {
1007 LOG(ERROR) << "cannot disable gsi install - no install detected";
1008 return false;
David Andersonb3aff182019-01-11 14:37:51 -08001009 }
David Andersonb2988ab2019-04-16 17:14:09 -07001010 if (installer_) {
David Andersona141ba82019-01-14 19:09:27 -08001011 LOG(ERROR) << "cannot disable gsi during GSI installation";
1012 return false;
1013 }
1014 if (!DisableGsi()) {
1015 PLOG(ERROR) << "could not write gsi status";
1016 return false;
1017 }
1018 return true;
David Andersonc053b3b2019-01-08 18:22:07 -08001019}
1020
Howard Chenee5c2b12019-11-08 11:57:47 +08001021std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) {
1022 return DSU_METADATA_PREFIX + dsu_slot + "/complete";
Howard Chen4663de62019-11-05 20:46:20 +08001023}
1024
Howard Chenee5c2b12019-11-08 11:57:47 +08001025bool GsiService::IsInstallationComplete(const std::string& dsu_slot) {
1026 if (access(kDsuInstallStatusFile, F_OK) != 0) {
1027 return false;
1028 }
1029 std::string file = GetCompleteIndication(dsu_slot);
Howard Chen4663de62019-11-05 20:46:20 +08001030 std::string content;
1031 if (!ReadFileToString(file, &content)) {
1032 return false;
1033 }
1034 return content == "OK";
1035}
1036
Howard Chenee5c2b12019-11-08 11:57:47 +08001037std::vector<std::string> GsiService::GetInstalledDsuSlots() {
1038 std::vector<std::string> dsu_slots;
1039 auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir);
1040 if (d != nullptr) {
1041 struct dirent* de;
1042 while ((de = readdir(d.get())) != nullptr) {
1043 if (de->d_name[0] == '.') {
1044 continue;
1045 }
1046 auto dsu_slot = std::string(de->d_name);
1047 if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) {
1048 continue;
1049 }
1050 dsu_slots.push_back(dsu_slot);
1051 }
1052 }
1053 return dsu_slots;
1054}
1055
Howard Chen3f6d5a62019-08-22 15:26:33 +08001056void GsiService::CleanCorruptedInstallation() {
Howard Chenee5c2b12019-11-08 11:57:47 +08001057 for (auto&& slot : GetInstalledDsuSlots()) {
1058 bool is_complete = IsInstallationComplete(slot);
1059 if (!is_complete) {
1060 LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot;
1061 std::string install_dir;
1062 if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) ||
1063 !RemoveGsiFiles(install_dir)) {
1064 LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot;
1065 }
Howard Chen4663de62019-11-05 20:46:20 +08001066 }
Howard Chen3f6d5a62019-08-22 15:26:33 +08001067 }
1068}
1069
David Andersonb3aff182019-01-11 14:37:51 -08001070void GsiService::RunStartupTasks() {
Howard Chen4663de62019-11-05 20:46:20 +08001071 CleanCorruptedInstallation();
David Andersonb3aff182019-01-11 14:37:51 -08001072
Howard Chenee5c2b12019-11-08 11:57:47 +08001073 std::string active_dsu;
1074 if (!GetActiveDsu(&active_dsu)) {
1075 PLOG(INFO) << "no DSU";
1076 return;
1077 }
David Andersonb3aff182019-01-11 14:37:51 -08001078 std::string boot_key;
1079 if (!GetInstallStatus(&boot_key)) {
David Anderson9bdf8632019-07-01 14:49:11 -07001080 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001081 return;
1082 }
1083
1084 if (!IsGsiRunning()) {
1085 // Check if a wipe was requested from fastboot or adb-in-gsi.
1086 if (boot_key == kInstallStatusWipe) {
Howard Chen4663de62019-11-05 20:46:20 +08001087 RemoveGsiFiles(GetInstalledImageDir());
David Andersonb3aff182019-01-11 14:37:51 -08001088 }
1089 } else {
David Anderson564a04c2019-02-27 13:33:44 -08001090 // NB: When single-boot is enabled, init will write "disabled" into the
1091 // install_status file, which will cause GetBootAttempts to return
1092 // false. Thus, we won't write "ok" here.
David Andersonb3aff182019-01-11 14:37:51 -08001093 int ignore;
1094 if (GetBootAttempts(boot_key, &ignore)) {
1095 // Mark the GSI as having successfully booted.
David Anderson9bdf8632019-07-01 14:49:11 -07001096 if (!android::base::WriteStringToFile(kInstallStatusOk, kDsuInstallStatusFile)) {
1097 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
David Andersonb3aff182019-01-11 14:37:51 -08001098 }
1099 }
1100 }
1101}
1102
Yo Chiang53bed1c2020-01-01 16:25:19 +08001103static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) {
1104 // Read the AVB footer from EOF.
1105 int64_t total_size = get_block_device_size(fd);
1106 int64_t footer_offset = total_size - AVB_FOOTER_SIZE;
1107 std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes;
1108 if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) {
1109 PLOG(ERROR) << "cannot read AVB footer";
1110 return false;
1111 }
1112 // Validate the AVB footer data and byte swap to native byte order.
1113 AvbFooter footer;
1114 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) {
1115 LOG(ERROR) << "invalid AVB footer";
1116 return false;
1117 }
1118 // Read the VBMeta image.
1119 std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size);
1120 if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) {
1121 PLOG(ERROR) << "cannot read VBMeta image";
1122 return false;
1123 }
1124 // Validate the VBMeta image and retrieve AVB public key.
1125 // After a successful call to avb_vbmeta_image_verify(), public_key_data
1126 // will point to the serialized AVB public key, in the same format generated
1127 // by the `avbtool extract_public_key` command.
1128 const uint8_t* public_key_data;
1129 size_t public_key_size;
1130 AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(),
1131 &public_key_data, &public_key_size);
1132 if (result != AVB_VBMETA_VERIFY_RESULT_OK) {
1133 LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result);
1134 return false;
1135 }
1136 if (public_key_data != nullptr) {
1137 dst->bytes.resize(public_key_size);
1138 memcpy(dst->bytes.data(), public_key_data, public_key_size);
1139 dst->sha1.resize(SHA_DIGEST_LENGTH);
1140 SHA1(public_key_data, public_key_size, dst->sha1.data());
1141 }
1142 return true;
1143}
1144
David Andersonc053b3b2019-01-08 18:22:07 -08001145} // namespace gsi
1146} // namespace android