fs_mgr_avb.cpp revision 6879cc1e2ee91f47fa05a01dfbce9dfef7504501
1/* 2 * Copyright (C) 2016 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 "fs_mgr_avb.h" 18 19#include <fcntl.h> 20#include <libgen.h> 21#include <string.h> 22#include <sys/ioctl.h> 23#include <sys/types.h> 24 25#include <sstream> 26#include <string> 27#include <vector> 28 29#include <android-base/file.h> 30#include <android-base/parseint.h> 31#include <android-base/properties.h> 32#include <android-base/stringprintf.h> 33#include <android-base/strings.h> 34#include <android-base/unique_fd.h> 35#include <libavb/libavb.h> 36 37#include "fs_mgr.h" 38#include "fs_mgr_priv.h" 39#include "fs_mgr_priv_avb_ops.h" 40#include "fs_mgr_priv_dm_ioctl.h" 41#include "fs_mgr_priv_sha.h" 42 43static inline bool nibble_value(const char& c, uint8_t* value) { 44 FS_MGR_CHECK(value != nullptr); 45 46 switch (c) { 47 case '0' ... '9': 48 *value = c - '0'; 49 break; 50 case 'a' ... 'f': 51 *value = c - 'a' + 10; 52 break; 53 case 'A' ... 'F': 54 *value = c - 'A' + 10; 55 break; 56 default: 57 return false; 58 } 59 60 return true; 61} 62 63static bool hex_to_bytes(uint8_t* bytes, size_t bytes_len, const std::string& hex) { 64 FS_MGR_CHECK(bytes != nullptr); 65 66 if (hex.size() % 2 != 0) { 67 return false; 68 } 69 if (hex.size() / 2 > bytes_len) { 70 return false; 71 } 72 for (size_t i = 0, j = 0, n = hex.size(); i < n; i += 2, ++j) { 73 uint8_t high; 74 if (!nibble_value(hex[i], &high)) { 75 return false; 76 } 77 uint8_t low; 78 if (!nibble_value(hex[i + 1], &low)) { 79 return false; 80 } 81 bytes[j] = (high << 4) | low; 82 } 83 return true; 84} 85 86static std::string bytes_to_hex(const uint8_t* bytes, size_t bytes_len) { 87 FS_MGR_CHECK(bytes != nullptr); 88 89 static const char* hex_digits = "0123456789abcdef"; 90 std::string hex; 91 92 for (size_t i = 0; i < bytes_len; i++) { 93 hex.push_back(hex_digits[(bytes[i] & 0xF0) >> 4]); 94 hex.push_back(hex_digits[bytes[i] & 0x0F]); 95 } 96 return hex; 97} 98 99template <typename Hasher> 100static std::pair<size_t, bool> verify_vbmeta_digest(const AvbSlotVerifyData& verify_data, 101 const uint8_t* expected_digest) { 102 size_t total_size = 0; 103 Hasher hasher; 104 for (size_t n = 0; n < verify_data.num_vbmeta_images; n++) { 105 hasher.update(verify_data.vbmeta_images[n].vbmeta_data, 106 verify_data.vbmeta_images[n].vbmeta_size); 107 total_size += verify_data.vbmeta_images[n].vbmeta_size; 108 } 109 110 bool matched = (memcmp(hasher.finalize(), expected_digest, Hasher::DIGEST_SIZE) == 0); 111 112 return std::make_pair(total_size, matched); 113} 114 115// Reads the following values from kernel cmdline and provides the 116// VerifyVbmetaImages() to verify AvbSlotVerifyData. 117// - androidboot.vbmeta.device_state 118// - androidboot.vbmeta.hash_alg 119// - androidboot.vbmeta.size 120// - androidboot.vbmeta.digest 121class FsManagerAvbVerifier { 122 public: 123 // The factory method to return a unique_ptr<FsManagerAvbVerifier> 124 static std::unique_ptr<FsManagerAvbVerifier> Create(); 125 bool VerifyVbmetaImages(const AvbSlotVerifyData& verify_data); 126 bool IsDeviceUnlocked() { return is_device_unlocked_; } 127 128 protected: 129 FsManagerAvbVerifier() = default; 130 131 private: 132 enum HashAlgorithm { 133 kInvalid = 0, 134 kSHA256 = 1, 135 kSHA512 = 2, 136 }; 137 138 HashAlgorithm hash_alg_; 139 uint8_t digest_[SHA512_DIGEST_LENGTH]; 140 size_t vbmeta_size_; 141 bool is_device_unlocked_; 142}; 143 144std::unique_ptr<FsManagerAvbVerifier> FsManagerAvbVerifier::Create() { 145 std::string cmdline; 146 if (!android::base::ReadFileToString("/proc/cmdline", &cmdline)) { 147 PERROR << "Failed to read /proc/cmdline"; 148 return nullptr; 149 } 150 151 std::unique_ptr<FsManagerAvbVerifier> avb_verifier(new FsManagerAvbVerifier()); 152 if (!avb_verifier) { 153 LERROR << "Failed to create unique_ptr<FsManagerAvbVerifier>"; 154 return nullptr; 155 } 156 157 std::string digest; 158 std::string hash_alg; 159 for (const auto& entry : android::base::Split(android::base::Trim(cmdline), " ")) { 160 std::vector<std::string> pieces = android::base::Split(entry, "="); 161 const std::string& key = pieces[0]; 162 const std::string& value = pieces[1]; 163 164 if (key == "androidboot.vbmeta.device_state") { 165 avb_verifier->is_device_unlocked_ = (value == "unlocked"); 166 } else if (key == "androidboot.vbmeta.hash_alg") { 167 hash_alg = value; 168 } else if (key == "androidboot.vbmeta.size") { 169 if (!android::base::ParseUint(value.c_str(), &avb_verifier->vbmeta_size_)) { 170 return nullptr; 171 } 172 } else if (key == "androidboot.vbmeta.digest") { 173 digest = value; 174 } 175 } 176 177 // Reads hash algorithm. 178 size_t expected_digest_size = 0; 179 if (hash_alg == "sha256") { 180 expected_digest_size = SHA256_DIGEST_LENGTH * 2; 181 avb_verifier->hash_alg_ = kSHA256; 182 } else if (hash_alg == "sha512") { 183 expected_digest_size = SHA512_DIGEST_LENGTH * 2; 184 avb_verifier->hash_alg_ = kSHA512; 185 } else { 186 LERROR << "Unknown hash algorithm: " << hash_alg.c_str(); 187 return nullptr; 188 } 189 190 // Reads digest. 191 if (digest.size() != expected_digest_size) { 192 LERROR << "Unexpected digest size: " << digest.size() 193 << " (expected: " << expected_digest_size << ")"; 194 return nullptr; 195 } 196 197 if (!hex_to_bytes(avb_verifier->digest_, sizeof(avb_verifier->digest_), digest)) { 198 LERROR << "Hash digest contains non-hexidecimal character: " << digest.c_str(); 199 return nullptr; 200 } 201 202 return avb_verifier; 203} 204 205bool FsManagerAvbVerifier::VerifyVbmetaImages(const AvbSlotVerifyData& verify_data) { 206 if (verify_data.num_vbmeta_images == 0) { 207 LERROR << "No vbmeta images"; 208 return false; 209 } 210 211 size_t total_size = 0; 212 bool digest_matched = false; 213 214 if (hash_alg_ == kSHA256) { 215 std::tie(total_size, digest_matched) = 216 verify_vbmeta_digest<SHA256Hasher>(verify_data, digest_); 217 } else if (hash_alg_ == kSHA512) { 218 std::tie(total_size, digest_matched) = 219 verify_vbmeta_digest<SHA512Hasher>(verify_data, digest_); 220 } 221 222 if (total_size != vbmeta_size_) { 223 LERROR << "total vbmeta size mismatch: " << total_size << " (expected: " << vbmeta_size_ 224 << ")"; 225 return false; 226 } 227 228 if (!digest_matched) { 229 LERROR << "vbmeta digest mismatch"; 230 return false; 231 } 232 233 return true; 234} 235 236// Constructs dm-verity arguments for sending DM_TABLE_LOAD ioctl to kernel. 237// See the following link for more details: 238// https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity 239static std::string construct_verity_table(const AvbHashtreeDescriptor& hashtree_desc, 240 const std::string& salt, const std::string& root_digest, 241 const std::string& blk_device) { 242 // Loads androidboot.veritymode from kernel cmdline. 243 std::string verity_mode; 244 if (!fs_mgr_get_boot_config("veritymode", &verity_mode)) { 245 verity_mode = "enforcing"; // Defaults to enforcing when it's absent. 246 } 247 248 // Converts veritymode to the format used in kernel. 249 std::string dm_verity_mode; 250 if (verity_mode == "enforcing") { 251 dm_verity_mode = "restart_on_corruption"; 252 } else if (verity_mode == "logging") { 253 dm_verity_mode = "ignore_corruption"; 254 } else if (verity_mode != "eio") { // Default dm_verity_mode is eio. 255 LERROR << "Unknown androidboot.veritymode: " << verity_mode; 256 return ""; 257 } 258 259 // dm-verity construction parameters: 260 // <version> <dev> <hash_dev> 261 // <data_block_size> <hash_block_size> 262 // <num_data_blocks> <hash_start_block> 263 // <algorithm> <digest> <salt> 264 // [<#opt_params> <opt_params>] 265 std::ostringstream verity_table; 266 verity_table << hashtree_desc.dm_verity_version << " " << blk_device << " " << blk_device << " " 267 << hashtree_desc.data_block_size << " " << hashtree_desc.hash_block_size << " " 268 << hashtree_desc.image_size / hashtree_desc.data_block_size << " " 269 << hashtree_desc.tree_offset / hashtree_desc.hash_block_size << " " 270 << hashtree_desc.hash_algorithm << " " << root_digest << " " << salt; 271 272 // Continued from the above optional parameters: 273 // [<#opt_params> <opt_params>] 274 int optional_argc = 0; 275 std::ostringstream optional_args; 276 277 // dm-verity optional parameters for FEC (forward error correction): 278 // use_fec_from_device <fec_dev> 279 // fec_roots <num> 280 // fec_blocks <num> 281 // fec_start <offset> 282 if (hashtree_desc.fec_size > 0) { 283 // Note that fec_blocks is the size that FEC covers, *NOT* the 284 // size of the FEC data. Since we use FEC for everything up until 285 // the FEC data, it's the same as the offset (fec_start). 286 optional_argc += 8; 287 // clang-format off 288 optional_args << "use_fec_from_device " << blk_device 289 << " fec_roots " << hashtree_desc.fec_num_roots 290 << " fec_blocks " << hashtree_desc.fec_offset / hashtree_desc.data_block_size 291 << " fec_start " << hashtree_desc.fec_offset / hashtree_desc.data_block_size 292 << " "; 293 // clang-format on 294 } 295 296 if (!dm_verity_mode.empty()) { 297 optional_argc += 1; 298 optional_args << dm_verity_mode << " "; 299 } 300 301 // Always use ignore_zero_blocks. 302 optional_argc += 1; 303 optional_args << "ignore_zero_blocks"; 304 305 verity_table << " " << optional_argc << " " << optional_args.str(); 306 return verity_table.str(); 307} 308 309static bool load_verity_table(struct dm_ioctl* io, const std::string& dm_device_name, int fd, 310 uint64_t image_size, const std::string& verity_table) { 311 fs_mgr_verity_ioctl_init(io, dm_device_name, DM_STATUS_TABLE_FLAG); 312 313 // The buffer consists of [dm_ioctl][dm_target_spec][verity_params]. 314 char* buffer = (char*)io; 315 316 // Builds the dm_target_spec arguments. 317 struct dm_target_spec* dm_target = (struct dm_target_spec*)&buffer[sizeof(struct dm_ioctl)]; 318 io->target_count = 1; 319 dm_target->status = 0; 320 dm_target->sector_start = 0; 321 dm_target->length = image_size / 512; 322 strcpy(dm_target->target_type, "verity"); 323 324 // Builds the verity params. 325 char* verity_params = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 326 size_t bufsize = DM_BUF_SIZE - (verity_params - buffer); 327 328 LINFO << "Loading verity table: '" << verity_table << "'"; 329 330 // Copies verity_table to verity_params (including the terminating null byte). 331 if (verity_table.size() > bufsize - 1) { 332 LERROR << "Verity table size too large: " << verity_table.size() 333 << " (max allowable size: " << bufsize - 1 << ")"; 334 return false; 335 } 336 memcpy(verity_params, verity_table.c_str(), verity_table.size() + 1); 337 338 // Sets ext target boundary. 339 verity_params += verity_table.size() + 1; 340 verity_params = (char*)(((unsigned long)verity_params + 7) & ~7); 341 dm_target->next = verity_params - buffer; 342 343 // Sends the ioctl to load the verity table. 344 if (ioctl(fd, DM_TABLE_LOAD, io)) { 345 PERROR << "Error loading verity table"; 346 return false; 347 } 348 349 return true; 350} 351 352static bool hashtree_dm_verity_setup(struct fstab_rec* fstab_entry, 353 const AvbHashtreeDescriptor& hashtree_desc, 354 const std::string& salt, const std::string& root_digest, 355 bool wait_for_verity_dev) { 356 // Gets the device mapper fd. 357 android::base::unique_fd fd(open("/dev/device-mapper", O_RDWR)); 358 if (fd < 0) { 359 PERROR << "Error opening device mapper"; 360 return false; 361 } 362 363 // Creates the device. 364 alignas(dm_ioctl) char buffer[DM_BUF_SIZE]; 365 struct dm_ioctl* io = (struct dm_ioctl*)buffer; 366 const std::string mount_point(basename(fstab_entry->mount_point)); 367 if (!fs_mgr_create_verity_device(io, mount_point, fd)) { 368 LERROR << "Couldn't create verity device!"; 369 return false; 370 } 371 372 // Gets the name of the device file. 373 std::string verity_blk_name; 374 if (!fs_mgr_get_verity_device_name(io, mount_point, fd, &verity_blk_name)) { 375 LERROR << "Couldn't get verity device number!"; 376 return false; 377 } 378 379 std::string verity_table = 380 construct_verity_table(hashtree_desc, salt, root_digest, fstab_entry->blk_device); 381 if (verity_table.empty()) { 382 LERROR << "Failed to construct verity table."; 383 return false; 384 } 385 386 // Loads the verity mapping table. 387 if (!load_verity_table(io, mount_point, fd, hashtree_desc.image_size, verity_table)) { 388 LERROR << "Couldn't load verity table!"; 389 return false; 390 } 391 392 // Activates the device. 393 if (!fs_mgr_resume_verity_table(io, mount_point, fd)) { 394 return false; 395 } 396 397 // Marks the underlying block device as read-only. 398 fs_mgr_set_blk_ro(fstab_entry->blk_device); 399 400 // Updates fstab_rec->blk_device to verity device name. 401 free(fstab_entry->blk_device); 402 fstab_entry->blk_device = strdup(verity_blk_name.c_str()); 403 404 // Makes sure we've set everything up properly. 405 if (wait_for_verity_dev && fs_mgr_test_access(verity_blk_name.c_str()) < 0) { 406 return false; 407 } 408 409 return true; 410} 411 412static bool get_hashtree_descriptor(const std::string& partition_name, 413 const AvbSlotVerifyData& verify_data, 414 AvbHashtreeDescriptor* out_hashtree_desc, std::string* out_salt, 415 std::string* out_digest) { 416 bool found = false; 417 const uint8_t* desc_partition_name; 418 419 for (size_t i = 0; i < verify_data.num_vbmeta_images && !found; i++) { 420 // Get descriptors from vbmeta_images[i]. 421 size_t num_descriptors; 422 std::unique_ptr<const AvbDescriptor* [], decltype(&avb_free)> descriptors( 423 avb_descriptor_get_all(verify_data.vbmeta_images[i].vbmeta_data, 424 verify_data.vbmeta_images[i].vbmeta_size, &num_descriptors), 425 avb_free); 426 427 if (!descriptors || num_descriptors < 1) { 428 continue; 429 } 430 431 // Ensures that hashtree descriptor is in /vbmeta or /boot or in 432 // the same partition for verity setup. 433 std::string vbmeta_partition_name(verify_data.vbmeta_images[i].partition_name); 434 if (vbmeta_partition_name != "vbmeta" && 435 vbmeta_partition_name != "boot" && // for legacy device to append top-level vbmeta 436 vbmeta_partition_name != partition_name) { 437 LWARNING << "Skip vbmeta image at " << verify_data.vbmeta_images[i].partition_name 438 << " for partition: " << partition_name.c_str(); 439 continue; 440 } 441 442 for (size_t j = 0; j < num_descriptors && !found; j++) { 443 AvbDescriptor desc; 444 if (!avb_descriptor_validate_and_byteswap(descriptors[j], &desc)) { 445 LWARNING << "Descriptor[" << j << "] is invalid"; 446 continue; 447 } 448 if (desc.tag == AVB_DESCRIPTOR_TAG_HASHTREE) { 449 desc_partition_name = (const uint8_t*)descriptors[j] + sizeof(AvbHashtreeDescriptor); 450 if (!avb_hashtree_descriptor_validate_and_byteswap( 451 (AvbHashtreeDescriptor*)descriptors[j], out_hashtree_desc)) { 452 continue; 453 } 454 if (out_hashtree_desc->partition_name_len != partition_name.length()) { 455 continue; 456 } 457 // Notes that desc_partition_name is not NUL-terminated. 458 std::string hashtree_partition_name((const char*)desc_partition_name, 459 out_hashtree_desc->partition_name_len); 460 if (hashtree_partition_name == partition_name) { 461 found = true; 462 } 463 } 464 } 465 } 466 467 if (!found) { 468 LERROR << "Partition descriptor not found: " << partition_name.c_str(); 469 return false; 470 } 471 472 const uint8_t* desc_salt = desc_partition_name + out_hashtree_desc->partition_name_len; 473 *out_salt = bytes_to_hex(desc_salt, out_hashtree_desc->salt_len); 474 475 const uint8_t* desc_digest = desc_salt + out_hashtree_desc->salt_len; 476 *out_digest = bytes_to_hex(desc_digest, out_hashtree_desc->root_digest_len); 477 478 return true; 479} 480 481FsManagerAvbUniquePtr FsManagerAvbHandle::Open(const fstab& fstab) { 482 FsManagerAvbOps avb_ops(fstab); 483 return DoOpen(&avb_ops); 484} 485 486FsManagerAvbUniquePtr FsManagerAvbHandle::Open(ByNameSymlinkMap&& by_name_symlink_map) { 487 if (by_name_symlink_map.empty()) { 488 LERROR << "Empty by_name_symlink_map when opening FsManagerAvbHandle"; 489 return nullptr; 490 } 491 FsManagerAvbOps avb_ops(std::move(by_name_symlink_map)); 492 return DoOpen(&avb_ops); 493} 494 495FsManagerAvbUniquePtr FsManagerAvbHandle::DoOpen(FsManagerAvbOps* avb_ops) { 496 // Gets the expected hash value of vbmeta images from kernel cmdline. 497 std::unique_ptr<FsManagerAvbVerifier> avb_verifier = FsManagerAvbVerifier::Create(); 498 if (!avb_verifier) { 499 LERROR << "Failed to create FsManagerAvbVerifier"; 500 return nullptr; 501 } 502 503 FsManagerAvbUniquePtr avb_handle(new FsManagerAvbHandle()); 504 if (!avb_handle) { 505 LERROR << "Failed to allocate FsManagerAvbHandle"; 506 return nullptr; 507 } 508 509 AvbSlotVerifyFlags flags = avb_verifier->IsDeviceUnlocked() 510 ? AVB_SLOT_VERIFY_FLAGS_ALLOW_VERIFICATION_ERROR 511 : AVB_SLOT_VERIFY_FLAGS_NONE; 512 AvbSlotVerifyResult verify_result = 513 avb_ops->AvbSlotVerify(fs_mgr_get_slot_suffix(), flags, &avb_handle->avb_slot_data_); 514 515 // Only allow two verify results: 516 // - AVB_SLOT_VERIFY_RESULT_OK. 517 // - AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION (for UNLOCKED state). 518 // If the device is UNLOCKED, i.e., |allow_verification_error| is true for 519 // AvbSlotVerify(), then the following return values are all non-fatal: 520 // * AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION 521 // * AVB_SLOT_VERIFY_RESULT_ERROR_PUBLIC_KEY_REJECTED 522 // * AVB_SLOT_VERIFY_RESULT_ERROR_ROLLBACK_INDEX 523 // The latter two results were checked by bootloader prior to start fs_mgr so 524 // we just need to handle the first result here. See *dummy* operations in 525 // FsManagerAvbOps and the comments in external/avb/libavb/avb_slot_verify.h 526 // for more details. 527 switch (verify_result) { 528 case AVB_SLOT_VERIFY_RESULT_OK: 529 avb_handle->status_ = kFsManagerAvbHandleSuccess; 530 break; 531 case AVB_SLOT_VERIFY_RESULT_ERROR_VERIFICATION: 532 if (!avb_verifier->IsDeviceUnlocked()) { 533 LERROR << "ERROR_VERIFICATION isn't allowed when the device is LOCKED"; 534 return nullptr; 535 } 536 avb_handle->status_ = kFsManagerAvbHandleErrorVerification; 537 break; 538 default: 539 LERROR << "avb_slot_verify failed, result: " << verify_result; 540 return nullptr; 541 } 542 543 // Verifies vbmeta images against the digest passed from bootloader. 544 if (!avb_verifier->VerifyVbmetaImages(*avb_handle->avb_slot_data_)) { 545 LERROR << "VerifyVbmetaImages failed"; 546 return nullptr; 547 } 548 549 // Sets the MAJOR.MINOR for init to set it into "ro.boot.avb_version". 550 avb_handle->avb_version_ = 551 android::base::StringPrintf("%d.%d", AVB_VERSION_MAJOR, AVB_VERSION_MINOR); 552 553 // Checks whether FLAGS_HASHTREE_DISABLED is set. 554 AvbVBMetaImageHeader vbmeta_header; 555 avb_vbmeta_image_header_to_host_byte_order( 556 (AvbVBMetaImageHeader*)avb_handle->avb_slot_data_->vbmeta_images[0].vbmeta_data, 557 &vbmeta_header); 558 559 bool hashtree_disabled = 560 ((AvbVBMetaImageFlags)vbmeta_header.flags & AVB_VBMETA_IMAGE_FLAGS_HASHTREE_DISABLED); 561 if (hashtree_disabled) { 562 avb_handle->status_ = kFsManagerAvbHandleHashtreeDisabled; 563 } 564 565 LINFO << "Returning avb_handle with status: " << avb_handle->status_; 566 return avb_handle; 567} 568 569bool FsManagerAvbHandle::SetUpAvb(struct fstab_rec* fstab_entry, bool wait_for_verity_dev) { 570 if (!fstab_entry) return false; 571 if (!avb_slot_data_ || avb_slot_data_->num_vbmeta_images < 1) { 572 return false; 573 } 574 575 if (status_ == kFsManagerAvbHandleUninitialized) return false; 576 if (status_ == kFsManagerAvbHandleHashtreeDisabled) { 577 LINFO << "AVB HASHTREE disabled on:" << fstab_entry->mount_point; 578 return true; 579 } 580 581 std::string partition_name(basename(fstab_entry->mount_point)); 582 if (!avb_validate_utf8((const uint8_t*)partition_name.c_str(), partition_name.length())) { 583 LERROR << "Partition name: " << partition_name.c_str() << " is not valid UTF-8."; 584 return false; 585 } 586 587 AvbHashtreeDescriptor hashtree_descriptor; 588 std::string salt; 589 std::string root_digest; 590 if (!get_hashtree_descriptor(partition_name, *avb_slot_data_, &hashtree_descriptor, &salt, 591 &root_digest)) { 592 return false; 593 } 594 595 // Converts HASHTREE descriptor to verity_table_params. 596 if (!hashtree_dm_verity_setup(fstab_entry, hashtree_descriptor, salt, root_digest, 597 wait_for_verity_dev)) { 598 return false; 599 } 600 return true; 601} 602