1 /*
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 <sys/statvfs.h>
20 #include <sys/vfs.h>
21 #include <unistd.h>
22
23 #include <array>
24 #include <chrono>
25 #include <string>
26 #include <vector>
27
28 #include <android-base/errors.h>
29 #include <android-base/file.h>
30 #include <android-base/logging.h>
31 #include <android-base/properties.h>
32 #include <android-base/stringprintf.h>
33 #include <android-base/strings.h>
34 #include <android/gsi/BnImageService.h>
35 #include <android/gsi/IGsiService.h>
36 #include <android/os/IVold.h>
37 #include <binder/IServiceManager.h>
38 #include <binder/LazyServiceRegistrar.h>
39 #include <cutils/android_reboot.h>
40 #include <ext4_utils/ext4_utils.h>
41 #include <fs_mgr.h>
42 #include <libavb/libavb.h>
43 #include <libdm/dm.h>
44 #include <libfiemap/image_manager.h>
45 #include <openssl/sha.h>
46 #include <private/android_filesystem_config.h>
47 #include <selinux/android.h>
48 #include <storage_literals/storage_literals.h>
49
50 #include "file_paths.h"
51 #include "libgsi_private.h"
52
53 namespace android {
54 namespace gsi {
55
56 using namespace std::literals;
57 using namespace android::fs_mgr;
58 using namespace android::fiemap;
59 using namespace android::storage_literals;
60 using android::base::ReadFileToString;
61 using android::base::ReadFullyAtOffset;
62 using android::base::RemoveFileIfExists;
63 using android::base::SetProperty;
64 using android::base::StringPrintf;
65 using android::base::unique_fd;
66 using android::base::WriteStringToFd;
67 using android::base::WriteStringToFile;
68 using android::binder::LazyServiceRegistrar;
69 using android::dm::DeviceMapper;
70
71 // Default userdata image size.
72 static constexpr int64_t kDefaultUserdataSize = int64_t(2) * 1024 * 1024 * 1024;
73
74 static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst);
75
76 // Fix the file contexts of dsu metadata files.
77 // By default, newly created files inherit the file contexts of their parent
78 // directory. Since globally readable public metadata files are labeled with a
79 // different context, gsi_public_metadata_file, we need to call this function to
80 // fix their contexts after creating them.
RestoreconMetadataFiles()81 static void RestoreconMetadataFiles() {
82 auto flags = SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIP_SEHASH;
83 selinux_android_restorecon(DSU_METADATA_PREFIX, flags);
84 }
85
GsiService()86 GsiService::GsiService() {
87 progress_ = {};
88 }
89
Register(const std::string & name)90 void GsiService::Register(const std::string& name) {
91 auto lazyRegistrar = LazyServiceRegistrar::getInstance();
92 android::sp<GsiService> service = new GsiService();
93 auto ret = lazyRegistrar.registerService(service, name);
94
95 if (ret != android::OK) {
96 LOG(FATAL) << "Could not register gsi service: " << ret;
97 }
98 }
99
100 #define ENFORCE_SYSTEM \
101 do { \
102 binder::Status status = CheckUid(); \
103 if (!status.isOk()) return status; \
104 } while (0)
105
106 #define ENFORCE_SYSTEM_OR_SHELL \
107 do { \
108 binder::Status status = CheckUid(AccessLevel::SystemOrShell); \
109 if (!status.isOk()) return status; \
110 } while (0)
111
112 #define ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK \
113 do { \
114 if (!android::base::EndsWith(GetActiveDsuSlot(), ".lock")) { \
115 ENFORCE_SYSTEM_OR_SHELL; \
116 } else { \
117 ENFORCE_SYSTEM; \
118 } \
119 } while (0)
120
SaveInstallation(const std::string & installation)121 int GsiService::SaveInstallation(const std::string& installation) {
122 auto dsu_slot = GetDsuSlot(installation);
123 auto install_dir_file = DsuInstallDirFile(dsu_slot);
124 auto metadata_dir = android::base::Dirname(install_dir_file);
125 if (access(metadata_dir.c_str(), F_OK) != 0) {
126 if (mkdir(metadata_dir.c_str(), 0777) != 0) {
127 PLOG(ERROR) << "Failed to mkdir " << metadata_dir;
128 return INSTALL_ERROR_GENERIC;
129 }
130 }
131 auto fd = android::base::unique_fd(
132 open(install_dir_file.c_str(), O_RDWR | O_SYNC | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR));
133 if (!WriteStringToFd(installation, fd)) {
134 PLOG(ERROR) << "write failed: " << DsuInstallDirFile(dsu_slot);
135 return INSTALL_ERROR_GENERIC;
136 }
137 return INSTALL_OK;
138 }
139
140 static bool IsExternalStoragePath(const std::string& path);
141
openInstall(const std::string & install_dir,int * _aidl_return)142 binder::Status GsiService::openInstall(const std::string& install_dir, int* _aidl_return) {
143 ENFORCE_SYSTEM;
144 std::lock_guard<std::mutex> guard(lock_);
145 if (IsGsiRunning()) {
146 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
147 return binder::Status::ok();
148 }
149 install_dir_ = install_dir;
150 if (int status = ValidateInstallParams(install_dir_)) {
151 *_aidl_return = status;
152 return binder::Status::ok();
153 }
154 std::string message;
155 auto dsu_slot = GetDsuSlot(install_dir_);
156 if (!RemoveFileIfExists(GetCompleteIndication(dsu_slot), &message)) {
157 LOG(ERROR) << message;
158 }
159 // Remember the installation directory before allocate any resource
160 *_aidl_return = SaveInstallation(install_dir_);
161 return binder::Status::ok();
162 }
163
closeInstall(int * _aidl_return)164 binder::Status GsiService::closeInstall(int* _aidl_return) {
165 ENFORCE_SYSTEM;
166 std::lock_guard<std::mutex> guard(lock_);
167
168 installer_ = {};
169
170 auto dsu_slot = GetDsuSlot(install_dir_);
171 std::string file = GetCompleteIndication(dsu_slot);
172 if (!WriteStringToFile("OK", file)) {
173 PLOG(ERROR) << "write failed: " << file;
174 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
175 return binder::Status::ok();
176 }
177
178 // Create installation complete marker files, but set disabled immediately.
179 if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
180 PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
181 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
182 return binder::Status::ok();
183 }
184 RestoreconMetadataFiles();
185
186 // DisableGsi() creates the DSU install status file and mark it as "disabled".
187 if (!DisableGsi()) {
188 PLOG(ERROR) << "cannot write DSU status file: " << kDsuInstallStatusFile;
189 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
190 return binder::Status::ok();
191 }
192
193 SetProperty(kGsiInstalledProp, "1");
194 *_aidl_return = IGsiService::INSTALL_OK;
195 return binder::Status::ok();
196 }
197
createPartition(const::std::string & name,int64_t size,bool readOnly,int32_t * _aidl_return)198 binder::Status GsiService::createPartition(const ::std::string& name, int64_t size, bool readOnly,
199 int32_t* _aidl_return) {
200 ENFORCE_SYSTEM;
201 std::lock_guard<std::mutex> guard(lock_);
202
203 if (install_dir_.empty()) {
204 PLOG(ERROR) << "open is required for createPartition";
205 *_aidl_return = INSTALL_ERROR_GENERIC;
206 return binder::Status::ok();
207 }
208
209 // Do some precursor validation on the arguments before diving into the
210 // install process.
211 if (size % LP_SECTOR_SIZE) {
212 LOG(ERROR) << " size " << size << " is not a multiple of " << LP_SECTOR_SIZE;
213 *_aidl_return = INSTALL_ERROR_GENERIC;
214 return binder::Status::ok();
215 }
216
217 if (size == 0 && name == "userdata") {
218 size = kDefaultUserdataSize;
219 }
220
221 if (name == "userdata") {
222 auto dsu_slot = GetDsuSlot(install_dir_);
223 auto key_dir = DefaultDsuMetadataKeyDir(dsu_slot);
224 auto key_dir_file = DsuMetadataKeyDirFile(dsu_slot);
225 if (!android::base::WriteStringToFile(key_dir, key_dir_file)) {
226 PLOG(ERROR) << "write failed: " << key_dir_file;
227 *_aidl_return = INSTALL_ERROR_GENERIC;
228 return binder::Status::ok();
229 }
230 RestoreconMetadataFiles();
231 }
232
233 installer_ = std::make_unique<PartitionInstaller>(this, install_dir_, name,
234 GetDsuSlot(install_dir_), size, readOnly);
235 progress_ = {};
236 *_aidl_return = installer_->StartInstall();
237 return binder::Status::ok();
238 }
239
closePartition(int32_t * _aidl_return)240 binder::Status GsiService::closePartition(int32_t* _aidl_return) {
241 ENFORCE_SYSTEM;
242 std::lock_guard<std::mutex> guard(lock_);
243
244 if (installer_ == nullptr) {
245 LOG(ERROR) << "createPartition() has to be called before closePartition()";
246 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
247 return binder::Status::ok();
248 }
249 // It is important to not reset |installer_| here because other methods such
250 // as isGsiInstallInProgress() relies on the state of |installer_|.
251 // TODO: Maybe don't do this, use a dedicated |in_progress_| flag?
252 *_aidl_return = installer_->FinishInstall();
253 return binder::Status::ok();
254 }
255
commitGsiChunkFromStream(const android::os::ParcelFileDescriptor & stream,int64_t bytes,bool * _aidl_return)256 binder::Status GsiService::commitGsiChunkFromStream(const android::os::ParcelFileDescriptor& stream,
257 int64_t bytes, bool* _aidl_return) {
258 ENFORCE_SYSTEM;
259 std::lock_guard<std::mutex> guard(lock_);
260
261 if (!installer_) {
262 *_aidl_return = false;
263 return binder::Status::ok();
264 }
265
266 *_aidl_return = installer_->CommitGsiChunk(stream.get(), bytes);
267 return binder::Status::ok();
268 }
269
StartAsyncOperation(const std::string & step,int64_t total_bytes)270 void GsiService::StartAsyncOperation(const std::string& step, int64_t total_bytes) {
271 std::lock_guard<std::mutex> guard(progress_lock_);
272
273 progress_.step = step;
274 progress_.status = STATUS_WORKING;
275 progress_.bytes_processed = 0;
276 progress_.total_bytes = total_bytes;
277 }
278
UpdateProgress(int status,int64_t bytes_processed)279 void GsiService::UpdateProgress(int status, int64_t bytes_processed) {
280 std::lock_guard<std::mutex> guard(progress_lock_);
281
282 progress_.status = status;
283 if (status == STATUS_COMPLETE) {
284 progress_.bytes_processed = progress_.total_bytes;
285 } else {
286 progress_.bytes_processed = bytes_processed;
287 }
288 }
289
getInstallProgress(::android::gsi::GsiProgress * _aidl_return)290 binder::Status GsiService::getInstallProgress(::android::gsi::GsiProgress* _aidl_return) {
291 ENFORCE_SYSTEM;
292 std::lock_guard<std::mutex> guard(progress_lock_);
293
294 if (installer_ == nullptr) {
295 progress_ = {};
296 }
297 *_aidl_return = progress_;
298 return binder::Status::ok();
299 }
300
commitGsiChunkFromAshmem(int64_t bytes,bool * _aidl_return)301 binder::Status GsiService::commitGsiChunkFromAshmem(int64_t bytes, bool* _aidl_return) {
302 ENFORCE_SYSTEM;
303 std::lock_guard<std::mutex> guard(lock_);
304
305 if (!installer_) {
306 *_aidl_return = false;
307 return binder::Status::ok();
308 }
309 *_aidl_return = installer_->CommitGsiChunk(bytes);
310 return binder::Status::ok();
311 }
312
setGsiAshmem(const::android::os::ParcelFileDescriptor & ashmem,int64_t size,bool * _aidl_return)313 binder::Status GsiService::setGsiAshmem(const ::android::os::ParcelFileDescriptor& ashmem,
314 int64_t size, bool* _aidl_return) {
315 ENFORCE_SYSTEM;
316 if (!installer_) {
317 *_aidl_return = false;
318 return binder::Status::ok();
319 }
320 *_aidl_return = installer_->MapAshmem(ashmem.get(), size);
321 return binder::Status::ok();
322 }
323
enableGsiAsync(bool one_shot,const std::string & dsuSlot,const sp<IGsiServiceCallback> & resultCallback)324 binder::Status GsiService::enableGsiAsync(bool one_shot, const std::string& dsuSlot,
325 const sp<IGsiServiceCallback>& resultCallback) {
326 ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK;
327 std::lock_guard<std::mutex> guard(lock_);
328
329 const auto result = EnableGsi(one_shot, dsuSlot);
330 resultCallback->onResult(result);
331 return binder::Status::ok();
332 }
333
enableGsi(bool one_shot,const std::string & dsuSlot,int * _aidl_return)334 binder::Status GsiService::enableGsi(bool one_shot, const std::string& dsuSlot, int* _aidl_return) {
335 ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK;
336 std::lock_guard<std::mutex> guard(lock_);
337
338 *_aidl_return = EnableGsi(one_shot, dsuSlot);
339 return binder::Status::ok();
340 }
341
isGsiEnabled(bool * _aidl_return)342 binder::Status GsiService::isGsiEnabled(bool* _aidl_return) {
343 ENFORCE_SYSTEM_OR_SHELL;
344 std::lock_guard<std::mutex> guard(lock_);
345 std::string boot_key;
346 if (!GetInstallStatus(&boot_key)) {
347 *_aidl_return = false;
348 } else {
349 *_aidl_return = (boot_key != kInstallStatusDisabled);
350 }
351 return binder::Status::ok();
352 }
353
removeGsiAsync(const sp<IGsiServiceCallback> & resultCallback)354 binder::Status GsiService::removeGsiAsync(const sp<IGsiServiceCallback>& resultCallback) {
355 bool result = false;
356 auto status = removeGsi(&result);
357 if (!status.isOk()) {
358 LOG(ERROR) << "Could not removeGsi: " << status.exceptionMessage().string();
359 result = IGsiService::INSTALL_ERROR_GENERIC;
360 }
361 resultCallback->onResult(result);
362 return binder::Status::ok();
363 }
364
removeGsi(bool * _aidl_return)365 binder::Status GsiService::removeGsi(bool* _aidl_return) {
366 ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK;
367 std::lock_guard<std::mutex> guard(lock_);
368
369 std::string install_dir = GetActiveInstalledImageDir();
370 if (IsGsiRunning()) {
371 // Can't remove gsi files while running.
372 *_aidl_return = UninstallGsi();
373 } else {
374 installer_ = {};
375 *_aidl_return = RemoveGsiFiles(install_dir);
376 }
377 return binder::Status::ok();
378 }
379
disableGsi(bool * _aidl_return)380 binder::Status GsiService::disableGsi(bool* _aidl_return) {
381 ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK;
382 std::lock_guard<std::mutex> guard(lock_);
383
384 *_aidl_return = DisableGsiInstall();
385 return binder::Status::ok();
386 }
387
isGsiRunning(bool * _aidl_return)388 binder::Status GsiService::isGsiRunning(bool* _aidl_return) {
389 ENFORCE_SYSTEM_OR_SHELL;
390 std::lock_guard<std::mutex> guard(lock_);
391
392 *_aidl_return = IsGsiRunning();
393 return binder::Status::ok();
394 }
395
isGsiInstalled(bool * _aidl_return)396 binder::Status GsiService::isGsiInstalled(bool* _aidl_return) {
397 ENFORCE_SYSTEM_OR_SHELL;
398 std::lock_guard<std::mutex> guard(lock_);
399
400 *_aidl_return = IsGsiInstalled();
401 return binder::Status::ok();
402 }
403
isGsiInstallInProgress(bool * _aidl_return)404 binder::Status GsiService::isGsiInstallInProgress(bool* _aidl_return) {
405 ENFORCE_SYSTEM_OR_SHELL;
406 std::lock_guard<std::mutex> guard(lock_);
407
408 *_aidl_return = !!installer_;
409 return binder::Status::ok();
410 }
411
cancelGsiInstall(bool * _aidl_return)412 binder::Status GsiService::cancelGsiInstall(bool* _aidl_return) {
413 ENFORCE_SYSTEM;
414 should_abort_ = true;
415 std::lock_guard<std::mutex> guard(lock_);
416
417 should_abort_ = false;
418 installer_ = nullptr;
419
420 *_aidl_return = true;
421 return binder::Status::ok();
422 }
423
getInstalledGsiImageDir(std::string * _aidl_return)424 binder::Status GsiService::getInstalledGsiImageDir(std::string* _aidl_return) {
425 ENFORCE_SYSTEM;
426 std::lock_guard<std::mutex> guard(lock_);
427
428 *_aidl_return = GetActiveInstalledImageDir();
429 return binder::Status::ok();
430 }
431
getActiveDsuSlot(std::string * _aidl_return)432 binder::Status GsiService::getActiveDsuSlot(std::string* _aidl_return) {
433 ENFORCE_SYSTEM_OR_SHELL;
434 std::lock_guard<std::mutex> guard(lock_);
435
436 *_aidl_return = GetActiveDsuSlot();
437 return binder::Status::ok();
438 }
439
getInstalledDsuSlots(std::vector<std::string> * _aidl_return)440 binder::Status GsiService::getInstalledDsuSlots(std::vector<std::string>* _aidl_return) {
441 ENFORCE_SYSTEM;
442 std::lock_guard<std::mutex> guard(lock_);
443 *_aidl_return = GetInstalledDsuSlots();
444 return binder::Status::ok();
445 }
446
zeroPartition(const std::string & name,int * _aidl_return)447 binder::Status GsiService::zeroPartition(const std::string& name, int* _aidl_return) {
448 ENFORCE_SYSTEM_OR_SHELL_IF_UNLOCK;
449 std::lock_guard<std::mutex> guard(lock_);
450
451 if (IsGsiRunning() || !IsGsiInstalled()) {
452 *_aidl_return = IGsiService::INSTALL_ERROR_GENERIC;
453 return binder::Status::ok();
454 }
455
456 std::string install_dir = GetActiveInstalledImageDir();
457 *_aidl_return = PartitionInstaller::WipeWritable(GetDsuSlot(install_dir), install_dir, name);
458
459 return binder::Status::ok();
460 }
461
BinderError(const std::string & message,FiemapStatus::ErrorCode status=FiemapStatus::ErrorCode::ERROR)462 static binder::Status BinderError(const std::string& message,
463 FiemapStatus::ErrorCode status = FiemapStatus::ErrorCode::ERROR) {
464 return binder::Status::fromServiceSpecificError(static_cast<int32_t>(status), message.c_str());
465 }
466
dumpDeviceMapperDevices(std::string * _aidl_return)467 binder::Status GsiService::dumpDeviceMapperDevices(std::string* _aidl_return) {
468 ENFORCE_SYSTEM_OR_SHELL;
469
470 auto& dm = DeviceMapper::Instance();
471
472 std::vector<DeviceMapper::DmBlockDevice> devices;
473 if (!dm.GetAvailableDevices(&devices)) {
474 return BinderError("Could not list devices");
475 }
476
477 std::stringstream text;
478 for (const auto& device : devices) {
479 text << "Device " << device.name() << " (" << device.Major() << ":" << device.Minor()
480 << ")\n";
481
482 std::vector<DeviceMapper::TargetInfo> table;
483 if (!dm.GetTableInfo(device.name(), &table)) {
484 continue;
485 }
486
487 for (const auto& target : table) {
488 const auto& spec = target.spec;
489 auto target_type = DeviceMapper::GetTargetType(spec);
490 text << " " << target_type << " " << spec.sector_start << " " << spec.length << " "
491 << target.data << "\n";
492 }
493 }
494
495 *_aidl_return = text.str();
496 return binder::Status::ok();
497 }
498
getAvbPublicKey(AvbPublicKey * dst,int32_t * _aidl_return)499 binder::Status GsiService::getAvbPublicKey(AvbPublicKey* dst, int32_t* _aidl_return) {
500 ENFORCE_SYSTEM;
501 std::lock_guard<std::mutex> guard(lock_);
502
503 if (!installer_) {
504 *_aidl_return = INSTALL_ERROR_GENERIC;
505 return binder::Status::ok();
506 }
507 int fd = installer_->GetPartitionFd();
508 if (!GetAvbPublicKeyFromFd(fd, dst)) {
509 LOG(ERROR) << "Failed to extract AVB public key";
510 *_aidl_return = INSTALL_ERROR_GENERIC;
511 return binder::Status::ok();
512 }
513 *_aidl_return = INSTALL_OK;
514 return binder::Status::ok();
515 }
516
suggestScratchSize(int64_t * _aidl_return)517 binder::Status GsiService::suggestScratchSize(int64_t* _aidl_return) {
518 ENFORCE_SYSTEM;
519
520 static constexpr uint64_t kMinScratchSize = 512_MiB;
521 static constexpr uint64_t kMaxScratchSize = 2_GiB;
522
523 uint64_t size = 0;
524 struct statvfs info;
525 if (statvfs(install_dir_.c_str(), &info)) {
526 PLOG(ERROR) << "Could not statvfs(" << install_dir_ << ")";
527 } else {
528 uint64_t free_space = static_cast<uint64_t>(info.f_bavail) * info.f_frsize;
529 const auto free_space_threshold =
530 PartitionInstaller::GetMinimumFreeSpaceThreshold(install_dir_);
531 if (free_space_threshold.has_value() && free_space > *free_space_threshold) {
532 // Round down to multiples of filesystem block size.
533 size = (free_space - *free_space_threshold) / info.f_frsize * info.f_frsize;
534 }
535 }
536
537 // We can safely downcast the result here, since we clamped the result within int64_t range.
538 *_aidl_return = std::clamp(size, kMinScratchSize, kMaxScratchSize);
539 return binder::Status::ok();
540 }
541
ResetBootAttemptCounter()542 bool GsiService::ResetBootAttemptCounter() {
543 if (!android::base::WriteStringToFile("0", kDsuInstallStatusFile)) {
544 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
545 return false;
546 }
547 SetProperty(kGsiInstalledProp, "1");
548 return true;
549 }
550
SetBootMode(bool one_shot)551 bool GsiService::SetBootMode(bool one_shot) {
552 if (one_shot) {
553 if (!android::base::WriteStringToFile("1", kDsuOneShotBootFile)) {
554 PLOG(ERROR) << "write " << kDsuOneShotBootFile;
555 return false;
556 }
557 } else if (!access(kDsuOneShotBootFile, F_OK)) {
558 std::string error;
559 if (!android::base::RemoveFileIfExists(kDsuOneShotBootFile, &error)) {
560 LOG(ERROR) << error;
561 return false;
562 }
563 }
564 return true;
565 }
566
UidSecurityError()567 static binder::Status UidSecurityError() {
568 uid_t uid = IPCThreadState::self()->getCallingUid();
569 auto message = StringPrintf("UID %d is not allowed", uid);
570 return binder::Status::fromExceptionCode(binder::Status::EX_SECURITY, String8(message.c_str()));
571 }
572
573 class ImageService : public BinderService<ImageService>, public BnImageService {
574 public:
575 ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid);
576 binder::Status getAllBackingImages(std::vector<std::string>* _aidl_return);
577 binder::Status createBackingImage(const std::string& name, int64_t size, int flags,
578 const sp<IProgressCallback>& on_progress) override;
579 binder::Status deleteBackingImage(const std::string& name) override;
580 binder::Status mapImageDevice(const std::string& name, int32_t timeout_ms,
581 MappedImage* mapping) override;
582 binder::Status unmapImageDevice(const std::string& name) override;
583 binder::Status backingImageExists(const std::string& name, bool* _aidl_return) override;
584 binder::Status isImageMapped(const std::string& name, bool* _aidl_return) override;
585 binder::Status getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
586 int32_t* _aidl_return) override;
587 binder::Status zeroFillNewImage(const std::string& name, int64_t bytes) override;
588 binder::Status removeAllImages() override;
589 binder::Status disableImage(const std::string& name) override;
590 binder::Status removeDisabledImages() override;
591 binder::Status getMappedImageDevice(const std::string& name, std::string* device) override;
592 binder::Status isImageDisabled(const std::string& name, bool* _aidl_return) override;
593
594 private:
595 bool CheckUid();
596
597 android::sp<GsiService> service_;
598 std::unique_ptr<ImageManager> impl_;
599 uid_t uid_;
600 };
601
ImageService(GsiService * service,std::unique_ptr<ImageManager> && impl,uid_t uid)602 ImageService::ImageService(GsiService* service, std::unique_ptr<ImageManager>&& impl, uid_t uid)
603 : service_(service), impl_(std::move(impl)), uid_(uid) {}
604
getAllBackingImages(std::vector<std::string> * _aidl_return)605 binder::Status ImageService::getAllBackingImages(std::vector<std::string>* _aidl_return) {
606 *_aidl_return = impl_->GetAllBackingImages();
607 return binder::Status::ok();
608 }
609
createBackingImage(const std::string & name,int64_t size,int flags,const sp<IProgressCallback> & on_progress)610 binder::Status ImageService::createBackingImage(const std::string& name, int64_t size, int flags,
611 const sp<IProgressCallback>& on_progress) {
612 if (!CheckUid()) return UidSecurityError();
613
614 std::lock_guard<std::mutex> guard(service_->lock());
615
616 std::function<bool(uint64_t, uint64_t)> callback;
617 if (on_progress) {
618 callback = [on_progress](uint64_t current, uint64_t total) -> bool {
619 auto status = on_progress->onProgress(static_cast<int64_t>(current),
620 static_cast<int64_t>(total));
621 if (!status.isOk()) {
622 LOG(ERROR) << "progress callback returned: " << status.toString8().string();
623 return false;
624 }
625 return true;
626 };
627 }
628
629 auto res = impl_->CreateBackingImage(name, size, flags, std::move(callback));
630 if (!res.is_ok()) {
631 return BinderError("Failed to create: " + res.string(), res.error_code());
632 }
633 return binder::Status::ok();
634 }
635
deleteBackingImage(const std::string & name)636 binder::Status ImageService::deleteBackingImage(const std::string& name) {
637 if (!CheckUid()) return UidSecurityError();
638
639 std::lock_guard<std::mutex> guard(service_->lock());
640
641 if (!impl_->DeleteBackingImage(name)) {
642 return BinderError("Failed to delete");
643 }
644 return binder::Status::ok();
645 }
646
mapImageDevice(const std::string & name,int32_t timeout_ms,MappedImage * mapping)647 binder::Status ImageService::mapImageDevice(const std::string& name, int32_t timeout_ms,
648 MappedImage* mapping) {
649 if (!CheckUid()) return UidSecurityError();
650
651 std::lock_guard<std::mutex> guard(service_->lock());
652
653 if (!impl_->MapImageDevice(name, std::chrono::milliseconds(timeout_ms), &mapping->path)) {
654 return BinderError("Failed to map");
655 }
656 return binder::Status::ok();
657 }
658
unmapImageDevice(const std::string & name)659 binder::Status ImageService::unmapImageDevice(const std::string& name) {
660 if (!CheckUid()) return UidSecurityError();
661
662 std::lock_guard<std::mutex> guard(service_->lock());
663
664 if (!impl_->UnmapImageDevice(name)) {
665 return BinderError("Failed to unmap");
666 }
667 return binder::Status::ok();
668 }
669
backingImageExists(const std::string & name,bool * _aidl_return)670 binder::Status ImageService::backingImageExists(const std::string& name, bool* _aidl_return) {
671 if (!CheckUid()) return UidSecurityError();
672
673 std::lock_guard<std::mutex> guard(service_->lock());
674
675 *_aidl_return = impl_->BackingImageExists(name);
676 return binder::Status::ok();
677 }
678
isImageMapped(const std::string & name,bool * _aidl_return)679 binder::Status ImageService::isImageMapped(const std::string& name, bool* _aidl_return) {
680 if (!CheckUid()) return UidSecurityError();
681
682 std::lock_guard<std::mutex> guard(service_->lock());
683
684 *_aidl_return = impl_->IsImageMapped(name);
685 return binder::Status::ok();
686 }
687
getAvbPublicKey(const std::string & name,AvbPublicKey * dst,int32_t * _aidl_return)688 binder::Status ImageService::getAvbPublicKey(const std::string& name, AvbPublicKey* dst,
689 int32_t* _aidl_return) {
690 if (!CheckUid()) return UidSecurityError();
691
692 std::lock_guard<std::mutex> guard(service_->lock());
693
694 std::string device_path;
695 std::unique_ptr<MappedDevice> mapped_device;
696 if (!impl_->IsImageMapped(name)) {
697 mapped_device = MappedDevice::Open(impl_.get(), 10s, name);
698 if (!mapped_device) {
699 PLOG(ERROR) << "Fail to map image: " << name;
700 *_aidl_return = IMAGE_ERROR;
701 return binder::Status::ok();
702 }
703 device_path = mapped_device->path();
704 } else {
705 if (!impl_->GetMappedImageDevice(name, &device_path)) {
706 PLOG(ERROR) << "GetMappedImageDevice() failed";
707 *_aidl_return = IMAGE_ERROR;
708 return binder::Status::ok();
709 }
710 }
711 android::base::unique_fd fd(open(device_path.c_str(), O_RDONLY | O_CLOEXEC));
712 if (!fd.ok()) {
713 PLOG(ERROR) << "Fail to open mapped device: " << device_path;
714 *_aidl_return = IMAGE_ERROR;
715 return binder::Status::ok();
716 }
717 bool ok = GetAvbPublicKeyFromFd(fd.get(), dst);
718 fd = {};
719 if (!ok) {
720 LOG(ERROR) << "Failed to extract AVB public key";
721 *_aidl_return = IMAGE_ERROR;
722 return binder::Status::ok();
723 }
724 *_aidl_return = IMAGE_OK;
725 return binder::Status::ok();
726 }
727
zeroFillNewImage(const std::string & name,int64_t bytes)728 binder::Status ImageService::zeroFillNewImage(const std::string& name, int64_t bytes) {
729 if (!CheckUid()) return UidSecurityError();
730
731 std::lock_guard<std::mutex> guard(service_->lock());
732
733 if (bytes < 0) {
734 return BinderError("Cannot use negative values");
735 }
736 auto res = impl_->ZeroFillNewImage(name, bytes);
737 if (!res.is_ok()) {
738 return BinderError("Failed to fill image with zeros: " + res.string(), res.error_code());
739 }
740 return binder::Status::ok();
741 }
742
removeAllImages()743 binder::Status ImageService::removeAllImages() {
744 if (!CheckUid()) return UidSecurityError();
745
746 std::lock_guard<std::mutex> guard(service_->lock());
747 if (!impl_->RemoveAllImages()) {
748 return BinderError("Failed to remove all images");
749 }
750 return binder::Status::ok();
751 }
752
disableImage(const std::string & name)753 binder::Status ImageService::disableImage(const std::string& name) {
754 if (!CheckUid()) return UidSecurityError();
755
756 std::lock_guard<std::mutex> guard(service_->lock());
757 if (!impl_->DisableImage(name)) {
758 return BinderError("Failed to disable image: " + name);
759 }
760 return binder::Status::ok();
761 }
762
removeDisabledImages()763 binder::Status ImageService::removeDisabledImages() {
764 if (!CheckUid()) return UidSecurityError();
765
766 std::lock_guard<std::mutex> guard(service_->lock());
767 if (!impl_->RemoveDisabledImages()) {
768 return BinderError("Failed to remove disabled images");
769 }
770 return binder::Status::ok();
771 }
772
isImageDisabled(const std::string & name,bool * _aidl_return)773 binder::Status ImageService::isImageDisabled(const std::string& name, bool* _aidl_return) {
774 if (!CheckUid()) return UidSecurityError();
775
776 std::lock_guard<std::mutex> guard(service_->lock());
777 *_aidl_return = impl_->IsImageDisabled(name);
778 return binder::Status::ok();
779 }
780
getMappedImageDevice(const std::string & name,std::string * device)781 binder::Status ImageService::getMappedImageDevice(const std::string& name, std::string* device) {
782 if (!CheckUid()) return UidSecurityError();
783
784 std::lock_guard<std::mutex> guard(service_->lock());
785 if (!impl_->GetMappedImageDevice(name, device)) {
786 *device = "";
787 }
788 return binder::Status::ok();
789 }
790
CheckUid()791 bool ImageService::CheckUid() {
792 return uid_ == IPCThreadState::self()->getCallingUid();
793 }
794
openImageService(const std::string & prefix,android::sp<IImageService> * _aidl_return)795 binder::Status GsiService::openImageService(const std::string& prefix,
796 android::sp<IImageService>* _aidl_return) {
797 using android::base::StartsWith;
798
799 static constexpr char kImageMetadataPrefix[] = "/metadata/gsi/";
800 static constexpr char kImageDataPrefix[] = "/data/gsi/";
801
802 auto in_metadata_dir = kImageMetadataPrefix + prefix;
803 auto in_data_dir = kImageDataPrefix + prefix;
804 auto install_dir_file = DsuInstallDirFile(GetDsuSlot(prefix));
805
806 std::string in_data_dir_tmp;
807 if (android::base::ReadFileToString(install_dir_file, &in_data_dir_tmp)) {
808 in_data_dir = in_data_dir_tmp;
809 LOG(INFO) << "load " << install_dir_file << ":" << in_data_dir;
810 }
811 std::string metadata_dir, data_dir;
812 if (!android::base::Realpath(in_metadata_dir, &metadata_dir)) {
813 PLOG(ERROR) << "realpath failed for metadata: " << in_metadata_dir;
814 return BinderError("Invalid path");
815 }
816 if (!android::base::Realpath(in_data_dir, &data_dir)) {
817 PLOG(ERROR) << "realpath failed for data: " << in_data_dir;
818 return BinderError("Invalid path");
819 }
820 if (!StartsWith(metadata_dir, kImageMetadataPrefix)) {
821 return BinderError("Invalid metadata path");
822 }
823 if (!StartsWith(data_dir, kImageDataPrefix) && !StartsWith(data_dir, kDsuSDPrefix)) {
824 return BinderError("Invalid data path");
825 }
826
827 uid_t uid = IPCThreadState::self()->getCallingUid();
828 if (uid != AID_ROOT) {
829 return UidSecurityError();
830 }
831
832 auto impl = ImageManager::Open(metadata_dir, data_dir);
833 if (!impl) {
834 return BinderError("Unknown error");
835 }
836
837 *_aidl_return = new ImageService(this, std::move(impl), uid);
838 return binder::Status::ok();
839 }
840
CheckUid(AccessLevel level)841 binder::Status GsiService::CheckUid(AccessLevel level) {
842 std::vector<uid_t> allowed_uids{AID_ROOT, AID_SYSTEM};
843 if (level == AccessLevel::SystemOrShell) {
844 allowed_uids.push_back(AID_SHELL);
845 }
846
847 uid_t uid = IPCThreadState::self()->getCallingUid();
848 for (const auto& allowed_uid : allowed_uids) {
849 if (allowed_uid == uid) {
850 return binder::Status::ok();
851 }
852 }
853 return UidSecurityError();
854 }
855
IsExternalStoragePath(const std::string & path)856 static bool IsExternalStoragePath(const std::string& path) {
857 if (!android::base::StartsWith(path, kDsuSDPrefix)) {
858 return false;
859 }
860 unique_fd fd(open(path.c_str(), O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
861 if (fd < 0) {
862 PLOG(ERROR) << "open failed: " << path;
863 return false;
864 }
865 struct statfs info;
866 if (fstatfs(fd, &info)) {
867 PLOG(ERROR) << "statfs failed: " << path;
868 return false;
869 }
870 LOG(ERROR) << "fs type: " << info.f_type;
871 return info.f_type == MSDOS_SUPER_MAGIC;
872 }
873
ValidateInstallParams(std::string & install_dir)874 int GsiService::ValidateInstallParams(std::string& install_dir) {
875 // If no install path was specified, use the default path. We also allow
876 // specifying the top-level folder, and then we choose the correct location
877 // underneath.
878 if (install_dir.empty() || install_dir == "/data/gsi") {
879 install_dir = kDefaultDsuImageFolder;
880 }
881
882 if (access(install_dir.c_str(), F_OK) != 0 && (errno == ENOENT)) {
883 if (android::base::StartsWith(install_dir, kDsuSDPrefix) ||
884 android::base::StartsWith(install_dir, kDefaultDsuImageFolder)) {
885 if (mkdir(install_dir.c_str(), 0755) != 0) {
886 PLOG(ERROR) << "Failed to create " << install_dir;
887 return INSTALL_ERROR_GENERIC;
888 }
889 }
890 }
891 // Normalize the path and add a trailing slash.
892 std::string origInstallDir = install_dir;
893 if (!android::base::Realpath(origInstallDir, &install_dir)) {
894 PLOG(ERROR) << "realpath failed: " << origInstallDir;
895 return INSTALL_ERROR_GENERIC;
896 }
897 // Ensure the path ends in / for consistency.
898 if (!android::base::EndsWith(install_dir, "/")) {
899 install_dir += "/";
900 }
901
902 // Currently, we can only install to /data/gsi/ or external storage.
903 if (IsExternalStoragePath(install_dir)) {
904 Fstab fstab;
905 if (!ReadDefaultFstab(&fstab)) {
906 LOG(ERROR) << "cannot read default fstab";
907 return INSTALL_ERROR_GENERIC;
908 }
909 FstabEntry* system = GetEntryForMountPoint(&fstab, "/system");
910 if (!system) {
911 LOG(ERROR) << "cannot find /system fstab entry";
912 return INSTALL_ERROR_GENERIC;
913 }
914 if (fs_mgr_verity_is_check_at_most_once(*system)) {
915 LOG(ERROR) << "cannot install GSIs to external media if verity uses check_at_most_once";
916 return INSTALL_ERROR_GENERIC;
917 }
918 } else if (!android::base::StartsWith(install_dir, kDefaultDsuImageFolder)) {
919 LOG(ERROR) << "cannot install DSU to " << install_dir;
920 return INSTALL_ERROR_GENERIC;
921 }
922 return INSTALL_OK;
923 }
924
GetActiveDsuSlot()925 std::string GsiService::GetActiveDsuSlot() {
926 if (!install_dir_.empty()) {
927 return GetDsuSlot(install_dir_);
928 } else {
929 std::string active_dsu;
930 return GetActiveDsu(&active_dsu) ? active_dsu : "";
931 }
932 }
933
GetActiveInstalledImageDir()934 std::string GsiService::GetActiveInstalledImageDir() {
935 // Just in case an install was left hanging.
936 if (installer_) {
937 return installer_->install_dir();
938 } else {
939 return GetInstalledImageDir();
940 }
941 }
942
GetInstalledImageDir()943 std::string GsiService::GetInstalledImageDir() {
944 // If there's no install left, just return /data/gsi since that's where
945 // installs go by default.
946 std::string active_dsu;
947 std::string dir;
948 if (GetActiveDsu(&active_dsu) &&
949 android::base::ReadFileToString(DsuInstallDirFile(active_dsu), &dir)) {
950 return dir;
951 }
952 return kDefaultDsuImageFolder;
953 }
954
GetVoldService()955 static android::sp<android::os::IVold> GetVoldService() {
956 return android::waitForService<android::os::IVold>(android::String16("vold"));
957 }
958
RemoveGsiFiles(const std::string & install_dir)959 bool GsiService::RemoveGsiFiles(const std::string& install_dir) {
960 bool ok = true;
961 auto active_dsu = GetDsuSlot(install_dir);
962 if (auto manager = ImageManager::Open(MetadataDir(active_dsu), install_dir)) {
963 std::vector<std::string> images = manager->GetAllBackingImages();
964 for (auto&& image : images) {
965 if (!android::base::EndsWith(image, kDsuPostfix)) {
966 continue;
967 }
968 if (manager->IsImageMapped(image)) {
969 ok &= manager->UnmapImageDevice(image);
970 }
971 ok &= manager->DeleteBackingImage(image);
972 }
973 }
974 auto dsu_slot = GetDsuSlot(install_dir);
975 std::vector<std::string> files{
976 kDsuInstallStatusFile,
977 kDsuOneShotBootFile,
978 DsuInstallDirFile(dsu_slot),
979 GetCompleteIndication(dsu_slot),
980 };
981 for (const auto& file : files) {
982 std::string message;
983 if (!RemoveFileIfExists(file, &message)) {
984 LOG(ERROR) << message;
985 ok = false;
986 }
987 }
988 if (auto vold = GetVoldService()) {
989 auto status = vold->destroyDsuMetadataKey(dsu_slot);
990 if (status.isOk()) {
991 std::string message;
992 if (!RemoveFileIfExists(DsuMetadataKeyDirFile(dsu_slot), &message)) {
993 LOG(ERROR) << message;
994 ok = false;
995 }
996 } else {
997 LOG(ERROR) << "Failed to destroy DSU metadata encryption key.";
998 ok = false;
999 }
1000 } else {
1001 LOG(ERROR) << "Failed to retrieve vold service.";
1002 ok = false;
1003 }
1004 if (ok) {
1005 SetProperty(kGsiInstalledProp, "0");
1006 }
1007 return ok;
1008 }
1009
EnableGsi(bool one_shot,const std::string & dsu_slot)1010 int GsiService::EnableGsi(bool one_shot, const std::string& dsu_slot) {
1011 if (!android::gsi::IsGsiInstalled()) {
1012 LOG(ERROR) << "no gsi installed - cannot enable";
1013 return IGsiService::INSTALL_ERROR_GENERIC;
1014 }
1015 if (installer_) {
1016 LOG(ERROR) << "cannot enable an ongoing installation, was closeInstall() called?";
1017 return IGsiService::INSTALL_ERROR_GENERIC;
1018 }
1019
1020 if (!DisableGsi()) {
1021 PLOG(ERROR) << "cannot write DSU status file";
1022 return IGsiService::INSTALL_ERROR_GENERIC;
1023 }
1024 if (!SetBootMode(one_shot)) {
1025 return IGsiService::INSTALL_ERROR_GENERIC;
1026 }
1027 if (!ResetBootAttemptCounter()) {
1028 return IGsiService::INSTALL_ERROR_GENERIC;
1029 }
1030
1031 if (!WriteStringToFile(dsu_slot, kDsuActiveFile)) {
1032 PLOG(ERROR) << "cannot write active DSU slot (" << dsu_slot << "): " << kDsuActiveFile;
1033 return IGsiService::INSTALL_ERROR_GENERIC;
1034 }
1035 RestoreconMetadataFiles();
1036 return IGsiService::INSTALL_OK;
1037 }
1038
DisableGsiInstall()1039 bool GsiService::DisableGsiInstall() {
1040 if (!android::gsi::IsGsiInstalled()) {
1041 LOG(ERROR) << "cannot disable gsi install - no install detected";
1042 return false;
1043 }
1044 if (installer_) {
1045 LOG(ERROR) << "cannot disable gsi during GSI installation";
1046 return false;
1047 }
1048 if (!DisableGsi()) {
1049 PLOG(ERROR) << "could not write gsi status";
1050 return false;
1051 }
1052 return true;
1053 }
1054
GetCompleteIndication(const std::string & dsu_slot)1055 std::string GsiService::GetCompleteIndication(const std::string& dsu_slot) {
1056 return DSU_METADATA_PREFIX + dsu_slot + "/complete";
1057 }
1058
IsInstallationComplete(const std::string & dsu_slot)1059 bool GsiService::IsInstallationComplete(const std::string& dsu_slot) {
1060 if (access(kDsuInstallStatusFile, F_OK) != 0) {
1061 return false;
1062 }
1063 std::string file = GetCompleteIndication(dsu_slot);
1064 std::string content;
1065 if (!ReadFileToString(file, &content)) {
1066 return false;
1067 }
1068 return content == "OK";
1069 }
1070
GetInstalledDsuSlots()1071 std::vector<std::string> GsiService::GetInstalledDsuSlots() {
1072 std::vector<std::string> dsu_slots;
1073 auto d = std::unique_ptr<DIR, decltype(&closedir)>(opendir(DSU_METADATA_PREFIX), closedir);
1074 if (d != nullptr) {
1075 struct dirent* de;
1076 while ((de = readdir(d.get())) != nullptr) {
1077 if (de->d_name[0] == '.') {
1078 continue;
1079 }
1080 auto dsu_slot = std::string(de->d_name);
1081 if (access(DsuInstallDirFile(dsu_slot).c_str(), F_OK) != 0) {
1082 continue;
1083 }
1084 dsu_slots.push_back(dsu_slot);
1085 }
1086 }
1087 return dsu_slots;
1088 }
1089
CleanCorruptedInstallation()1090 void GsiService::CleanCorruptedInstallation() {
1091 for (auto&& slot : GetInstalledDsuSlots()) {
1092 bool is_complete = IsInstallationComplete(slot);
1093 if (!is_complete) {
1094 LOG(INFO) << "CleanCorruptedInstallation for slot: " << slot;
1095 std::string install_dir;
1096 if (!android::base::ReadFileToString(DsuInstallDirFile(slot), &install_dir) ||
1097 !RemoveGsiFiles(install_dir)) {
1098 LOG(ERROR) << "Failed to CleanCorruptedInstallation on " << slot;
1099 }
1100 }
1101 }
1102 }
1103
RunStartupTasks()1104 void GsiService::RunStartupTasks() {
1105 CleanCorruptedInstallation();
1106
1107 std::string active_dsu;
1108 if (!GetActiveDsu(&active_dsu)) {
1109 PLOG(INFO) << "no DSU";
1110 return;
1111 }
1112 std::string boot_key;
1113 if (!GetInstallStatus(&boot_key)) {
1114 PLOG(ERROR) << "read " << kDsuInstallStatusFile;
1115 return;
1116 }
1117
1118 if (!IsGsiRunning()) {
1119 // Check if a wipe was requested from fastboot or adb-in-gsi.
1120 if (boot_key == kInstallStatusWipe) {
1121 RemoveGsiFiles(GetInstalledImageDir());
1122 }
1123 } else {
1124 // NB: When single-boot is enabled, init will write "disabled" into the
1125 // install_status file, which will cause GetBootAttempts to return
1126 // false. Thus, we won't write "ok" here.
1127 int ignore;
1128 if (GetBootAttempts(boot_key, &ignore)) {
1129 // Mark the GSI as having successfully booted.
1130 if (!android::base::WriteStringToFile(kInstallStatusOk, kDsuInstallStatusFile)) {
1131 PLOG(ERROR) << "write " << kDsuInstallStatusFile;
1132 }
1133 }
1134 }
1135 }
1136
VerifyImageMaps()1137 void GsiService::VerifyImageMaps() {
1138 std::vector<std::pair<std::string, std::string>> paths = {
1139 {"/metadata/gsi/remount", "/data/gsi/remount"},
1140 {"/metadata/gsi/ota", "/data/gsi/ota"},
1141 };
1142
1143 for (const auto& [metadata_dir, data_dir] : paths) {
1144 auto impl = ImageManager::Open(metadata_dir, data_dir);
1145 if (!impl) {
1146 LOG(ERROR) << "Could not open ImageManager for " << metadata_dir << " and " << data_dir;
1147 continue;
1148 }
1149 if (!impl->ValidateImageMaps()) {
1150 LOG(ERROR) << "ImageManager for " << metadata_dir
1151 << " failed validation, device data is at risk. Rebooting.";
1152 android::base::SetProperty(ANDROID_RB_PROPERTY, "reboot,fastboot");
1153 continue;
1154 }
1155 LOG(INFO) << "ImageManager verification passed for " << metadata_dir;
1156 }
1157 }
1158
GetAvbPublicKeyFromFd(int fd,AvbPublicKey * dst)1159 static bool GetAvbPublicKeyFromFd(int fd, AvbPublicKey* dst) {
1160 // Read the AVB footer from EOF.
1161 int64_t total_size = get_block_device_size(fd);
1162 int64_t footer_offset = total_size - AVB_FOOTER_SIZE;
1163 std::array<uint8_t, AVB_FOOTER_SIZE> footer_bytes;
1164 if (!ReadFullyAtOffset(fd, footer_bytes.data(), AVB_FOOTER_SIZE, footer_offset)) {
1165 PLOG(ERROR) << "cannot read AVB footer";
1166 return false;
1167 }
1168 // Validate the AVB footer data and byte swap to native byte order.
1169 AvbFooter footer;
1170 if (!avb_footer_validate_and_byteswap((const AvbFooter*)footer_bytes.data(), &footer)) {
1171 LOG(ERROR) << "invalid AVB footer";
1172 return false;
1173 }
1174 // Read the VBMeta image.
1175 std::vector<uint8_t> vbmeta_bytes(footer.vbmeta_size);
1176 if (!ReadFullyAtOffset(fd, vbmeta_bytes.data(), vbmeta_bytes.size(), footer.vbmeta_offset)) {
1177 PLOG(ERROR) << "cannot read VBMeta image";
1178 return false;
1179 }
1180 // Validate the VBMeta image and retrieve AVB public key.
1181 // After a successful call to avb_vbmeta_image_verify(), public_key_data
1182 // will point to the serialized AVB public key, in the same format generated
1183 // by the `avbtool extract_public_key` command.
1184 const uint8_t* public_key_data;
1185 size_t public_key_size;
1186 AvbVBMetaVerifyResult result = avb_vbmeta_image_verify(vbmeta_bytes.data(), vbmeta_bytes.size(),
1187 &public_key_data, &public_key_size);
1188 if (result != AVB_VBMETA_VERIFY_RESULT_OK) {
1189 LOG(ERROR) << "invalid VBMeta image: " << avb_vbmeta_verify_result_to_string(result);
1190 return false;
1191 }
1192 if (public_key_data != nullptr) {
1193 dst->bytes.resize(public_key_size);
1194 memcpy(dst->bytes.data(), public_key_data, public_key_size);
1195 dst->sha1.resize(SHA_DIGEST_LENGTH);
1196 SHA1(public_key_data, public_key_size, dst->sha1.data());
1197 }
1198 return true;
1199 }
1200
1201 } // namespace gsi
1202 } // namespace android
1203