1 // 2 // Copyright (C) 2012 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 "update_engine/common/utils.h" 18 19 #include <stdint.h> 20 21 #include <dirent.h> 22 #include <elf.h> 23 #include <endian.h> 24 #include <errno.h> 25 #include <ext2fs/ext2fs.h> 26 #include <fcntl.h> 27 #include <stdio.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <sys/mount.h> 31 #include <sys/resource.h> 32 #include <sys/stat.h> 33 #include <sys/types.h> 34 #include <sys/wait.h> 35 #include <unistd.h> 36 37 #include <algorithm> 38 #include <utility> 39 #include <vector> 40 41 #include <base/callback.h> 42 #include <base/files/file_path.h> 43 #include <base/files/file_util.h> 44 #include <base/files/scoped_file.h> 45 #include <base/format_macros.h> 46 #include <base/location.h> 47 #include <base/logging.h> 48 #include <base/posix/eintr_wrapper.h> 49 #include <base/rand_util.h> 50 #include <base/strings/string_number_conversions.h> 51 #include <base/strings/string_split.h> 52 #include <base/strings/string_util.h> 53 #include <base/strings/stringprintf.h> 54 #include <brillo/data_encoding.h> 55 #include <brillo/message_loops/message_loop.h> 56 57 #include "update_engine/common/clock_interface.h" 58 #include "update_engine/common/constants.h" 59 #include "update_engine/common/platform_constants.h" 60 #include "update_engine/common/prefs_interface.h" 61 #include "update_engine/common/subprocess.h" 62 #include "update_engine/payload_consumer/file_descriptor.h" 63 #include "update_engine/payload_consumer/file_writer.h" 64 #include "update_engine/payload_consumer/payload_constants.h" 65 66 using base::Time; 67 using base::TimeDelta; 68 using std::min; 69 using std::pair; 70 using std::string; 71 using std::vector; 72 73 namespace chromeos_update_engine { 74 75 namespace { 76 77 // The following constants control how UnmountFilesystem should retry if 78 // umount() fails with an errno EBUSY, i.e. retry 5 times over the course of 79 // one second. 80 const int kUnmountMaxNumOfRetries = 5; 81 const int kUnmountRetryIntervalInMicroseconds = 200 * 1000; // 200 ms 82 83 // Number of bytes to read from a file to attempt to detect its contents. Used 84 // in GetFileFormat. 85 const int kGetFileFormatMaxHeaderSize = 32; 86 87 // The path to the kernel's boot_id. 88 const char kBootIdPath[] = "/proc/sys/kernel/random/boot_id"; 89 90 // Return true if |disk_name| is an MTD or a UBI device. Note that this test is 91 // simply based on the name of the device. 92 bool IsMtdDeviceName(const string& disk_name) { 93 return base::StartsWith(disk_name, "/dev/ubi", 94 base::CompareCase::SENSITIVE) || 95 base::StartsWith(disk_name, "/dev/mtd", base::CompareCase::SENSITIVE); 96 } 97 98 // Return the device name for the corresponding partition on a NAND device. 99 // WARNING: This function returns device names that are not mountable. 100 string MakeNandPartitionName(int partition_num) { 101 switch (partition_num) { 102 case 2: 103 case 4: 104 case 6: { 105 return base::StringPrintf("/dev/mtd%d", partition_num); 106 } 107 default: { 108 return base::StringPrintf("/dev/ubi%d_0", partition_num); 109 } 110 } 111 } 112 113 // Return the device name for the corresponding partition on a NAND device that 114 // may be mountable (but may not be writable). 115 string MakeNandPartitionNameForMount(int partition_num) { 116 switch (partition_num) { 117 case 2: 118 case 4: 119 case 6: { 120 return base::StringPrintf("/dev/mtd%d", partition_num); 121 } 122 case 3: 123 case 5: 124 case 7: { 125 return base::StringPrintf("/dev/ubiblock%d_0", partition_num); 126 } 127 default: { 128 return base::StringPrintf("/dev/ubi%d_0", partition_num); 129 } 130 } 131 } 132 133 // If |path| is absolute, or explicit relative to the current working directory, 134 // leaves it as is. Otherwise, uses the system's temp directory, as defined by 135 // base::GetTempDir() and prepends it to |path|. On success stores the full 136 // temporary path in |template_path| and returns true. 137 bool GetTempName(const string& path, base::FilePath* template_path) { 138 if (path[0] == '/' || 139 base::StartsWith(path, "./", base::CompareCase::SENSITIVE) || 140 base::StartsWith(path, "../", base::CompareCase::SENSITIVE)) { 141 *template_path = base::FilePath(path); 142 return true; 143 } 144 145 base::FilePath temp_dir; 146 #ifdef __ANDROID__ 147 temp_dir = base::FilePath(constants::kNonVolatileDirectory).Append("tmp"); 148 if (!base::PathExists(temp_dir)) 149 TEST_AND_RETURN_FALSE(base::CreateDirectory(temp_dir)); 150 #else 151 TEST_AND_RETURN_FALSE(base::GetTempDir(&temp_dir)); 152 #endif // __ANDROID__ 153 *template_path = temp_dir.Append(path); 154 return true; 155 } 156 157 } // namespace 158 159 namespace utils { 160 161 string ParseECVersion(string input_line) { 162 base::TrimWhitespaceASCII(input_line, base::TRIM_ALL, &input_line); 163 164 // At this point we want to convert the format key=value pair from mosys to 165 // a vector of key value pairs. 166 vector<pair<string, string>> kv_pairs; 167 if (base::SplitStringIntoKeyValuePairs(input_line, '=', ' ', &kv_pairs)) { 168 for (const pair<string, string>& kv_pair : kv_pairs) { 169 // Finally match against the fw_verion which may have quotes. 170 if (kv_pair.first == "fw_version") { 171 string output; 172 // Trim any quotes. 173 base::TrimString(kv_pair.second, "\"", &output); 174 return output; 175 } 176 } 177 } 178 LOG(ERROR) << "Unable to parse fwid from ec info."; 179 return ""; 180 } 181 182 bool WriteFile(const char* path, const void* data, int data_len) { 183 DirectFileWriter writer; 184 TEST_AND_RETURN_FALSE_ERRNO(0 == writer.Open(path, 185 O_WRONLY | O_CREAT | O_TRUNC, 186 0600)); 187 ScopedFileWriterCloser closer(&writer); 188 TEST_AND_RETURN_FALSE_ERRNO(writer.Write(data, data_len)); 189 return true; 190 } 191 192 bool ReadAll( 193 int fd, void* buf, size_t count, size_t* out_bytes_read, bool* eof) { 194 char* c_buf = static_cast<char*>(buf); 195 size_t bytes_read = 0; 196 *eof = false; 197 while (bytes_read < count) { 198 ssize_t rc = HANDLE_EINTR(read(fd, c_buf + bytes_read, count - bytes_read)); 199 if (rc < 0) { 200 // EAGAIN and EWOULDBLOCK are normal return values when there's no more 201 // input and we are in non-blocking mode. 202 if (errno != EWOULDBLOCK && errno != EAGAIN) { 203 PLOG(ERROR) << "Error reading fd " << fd; 204 *out_bytes_read = bytes_read; 205 return false; 206 } 207 break; 208 } else if (rc == 0) { 209 // A value of 0 means that we reached EOF and there is nothing else to 210 // read from this fd. 211 *eof = true; 212 break; 213 } else { 214 bytes_read += rc; 215 } 216 } 217 *out_bytes_read = bytes_read; 218 return true; 219 } 220 221 bool WriteAll(int fd, const void* buf, size_t count) { 222 const char* c_buf = static_cast<const char*>(buf); 223 ssize_t bytes_written = 0; 224 while (bytes_written < static_cast<ssize_t>(count)) { 225 ssize_t rc = write(fd, c_buf + bytes_written, count - bytes_written); 226 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 227 bytes_written += rc; 228 } 229 return true; 230 } 231 232 bool PWriteAll(int fd, const void* buf, size_t count, off_t offset) { 233 const char* c_buf = static_cast<const char*>(buf); 234 size_t bytes_written = 0; 235 int num_attempts = 0; 236 while (bytes_written < count) { 237 num_attempts++; 238 ssize_t rc = pwrite(fd, c_buf + bytes_written, count - bytes_written, 239 offset + bytes_written); 240 // TODO(garnold) for debugging failure in chromium-os:31077; to be removed. 241 if (rc < 0) { 242 PLOG(ERROR) << "pwrite error; num_attempts=" << num_attempts 243 << " bytes_written=" << bytes_written 244 << " count=" << count << " offset=" << offset; 245 } 246 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 247 bytes_written += rc; 248 } 249 return true; 250 } 251 252 bool WriteAll(FileDescriptorPtr fd, const void* buf, size_t count) { 253 const char* c_buf = static_cast<const char*>(buf); 254 ssize_t bytes_written = 0; 255 while (bytes_written < static_cast<ssize_t>(count)) { 256 ssize_t rc = fd->Write(c_buf + bytes_written, count - bytes_written); 257 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 258 bytes_written += rc; 259 } 260 return true; 261 } 262 263 bool PWriteAll(FileDescriptorPtr fd, 264 const void* buf, 265 size_t count, 266 off_t offset) { 267 TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) != 268 static_cast<off_t>(-1)); 269 return WriteAll(fd, buf, count); 270 } 271 272 bool PReadAll(int fd, void* buf, size_t count, off_t offset, 273 ssize_t* out_bytes_read) { 274 char* c_buf = static_cast<char*>(buf); 275 ssize_t bytes_read = 0; 276 while (bytes_read < static_cast<ssize_t>(count)) { 277 ssize_t rc = pread(fd, c_buf + bytes_read, count - bytes_read, 278 offset + bytes_read); 279 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 280 if (rc == 0) { 281 break; 282 } 283 bytes_read += rc; 284 } 285 *out_bytes_read = bytes_read; 286 return true; 287 } 288 289 bool PReadAll(FileDescriptorPtr fd, void* buf, size_t count, off_t offset, 290 ssize_t* out_bytes_read) { 291 TEST_AND_RETURN_FALSE_ERRNO(fd->Seek(offset, SEEK_SET) != 292 static_cast<off_t>(-1)); 293 char* c_buf = static_cast<char*>(buf); 294 ssize_t bytes_read = 0; 295 while (bytes_read < static_cast<ssize_t>(count)) { 296 ssize_t rc = fd->Read(c_buf + bytes_read, count - bytes_read); 297 TEST_AND_RETURN_FALSE_ERRNO(rc >= 0); 298 if (rc == 0) { 299 break; 300 } 301 bytes_read += rc; 302 } 303 *out_bytes_read = bytes_read; 304 return true; 305 } 306 307 // Append |nbytes| of content from |buf| to the vector pointed to by either 308 // |vec_p| or |str_p|. 309 static void AppendBytes(const uint8_t* buf, size_t nbytes, 310 brillo::Blob* vec_p) { 311 CHECK(buf); 312 CHECK(vec_p); 313 vec_p->insert(vec_p->end(), buf, buf + nbytes); 314 } 315 static void AppendBytes(const uint8_t* buf, size_t nbytes, 316 string* str_p) { 317 CHECK(buf); 318 CHECK(str_p); 319 str_p->append(buf, buf + nbytes); 320 } 321 322 // Reads from an open file |fp|, appending the read content to the container 323 // pointer to by |out_p|. Returns true upon successful reading all of the 324 // file's content, false otherwise. If |size| is not -1, reads up to |size| 325 // bytes. 326 template <class T> 327 static bool Read(FILE* fp, off_t size, T* out_p) { 328 CHECK(fp); 329 CHECK(size == -1 || size >= 0); 330 uint8_t buf[1024]; 331 while (size == -1 || size > 0) { 332 off_t bytes_to_read = sizeof(buf); 333 if (size > 0 && bytes_to_read > size) { 334 bytes_to_read = size; 335 } 336 size_t nbytes = fread(buf, 1, bytes_to_read, fp); 337 if (!nbytes) { 338 break; 339 } 340 AppendBytes(buf, nbytes, out_p); 341 if (size != -1) { 342 CHECK(size >= static_cast<off_t>(nbytes)); 343 size -= nbytes; 344 } 345 } 346 if (ferror(fp)) { 347 return false; 348 } 349 return size == 0 || feof(fp); 350 } 351 352 // Opens a file |path| for reading and appends its the contents to a container 353 // |out_p|. Starts reading the file from |offset|. If |offset| is beyond the end 354 // of the file, returns success. If |size| is not -1, reads up to |size| bytes. 355 template <class T> 356 static bool ReadFileChunkAndAppend(const string& path, 357 off_t offset, 358 off_t size, 359 T* out_p) { 360 CHECK_GE(offset, 0); 361 CHECK(size == -1 || size >= 0); 362 base::ScopedFILE fp(fopen(path.c_str(), "r")); 363 if (!fp.get()) 364 return false; 365 if (offset) { 366 // Return success without appending any data if a chunk beyond the end of 367 // the file is requested. 368 if (offset >= FileSize(path)) { 369 return true; 370 } 371 TEST_AND_RETURN_FALSE_ERRNO(fseek(fp.get(), offset, SEEK_SET) == 0); 372 } 373 return Read(fp.get(), size, out_p); 374 } 375 376 // TODO(deymo): This is only used in unittest, but requires the private 377 // Read<string>() defined here. Expose Read<string>() or move to base/ version. 378 bool ReadPipe(const string& cmd, string* out_p) { 379 FILE* fp = popen(cmd.c_str(), "r"); 380 if (!fp) 381 return false; 382 bool success = Read(fp, -1, out_p); 383 return (success && pclose(fp) >= 0); 384 } 385 386 bool ReadFile(const string& path, brillo::Blob* out_p) { 387 return ReadFileChunkAndAppend(path, 0, -1, out_p); 388 } 389 390 bool ReadFile(const string& path, string* out_p) { 391 return ReadFileChunkAndAppend(path, 0, -1, out_p); 392 } 393 394 bool ReadFileChunk(const string& path, off_t offset, off_t size, 395 brillo::Blob* out_p) { 396 return ReadFileChunkAndAppend(path, offset, size, out_p); 397 } 398 399 off_t BlockDevSize(int fd) { 400 uint64_t dev_size; 401 int rc = ioctl(fd, BLKGETSIZE64, &dev_size); 402 if (rc == -1) { 403 dev_size = -1; 404 PLOG(ERROR) << "Error running ioctl(BLKGETSIZE64) on " << fd; 405 } 406 return dev_size; 407 } 408 409 off_t FileSize(int fd) { 410 struct stat stbuf; 411 int rc = fstat(fd, &stbuf); 412 CHECK_EQ(rc, 0); 413 if (rc < 0) { 414 PLOG(ERROR) << "Error stat-ing " << fd; 415 return rc; 416 } 417 if (S_ISREG(stbuf.st_mode)) 418 return stbuf.st_size; 419 if (S_ISBLK(stbuf.st_mode)) 420 return BlockDevSize(fd); 421 LOG(ERROR) << "Couldn't determine the type of " << fd; 422 return -1; 423 } 424 425 off_t FileSize(const string& path) { 426 int fd = open(path.c_str(), O_RDONLY | O_CLOEXEC); 427 if (fd == -1) { 428 PLOG(ERROR) << "Error opening " << path; 429 return fd; 430 } 431 off_t size = FileSize(fd); 432 if (size == -1) 433 PLOG(ERROR) << "Error getting file size of " << path; 434 close(fd); 435 return size; 436 } 437 438 void HexDumpArray(const uint8_t* const arr, const size_t length) { 439 LOG(INFO) << "Logging array of length: " << length; 440 const unsigned int bytes_per_line = 16; 441 for (uint32_t i = 0; i < length; i += bytes_per_line) { 442 const unsigned int bytes_remaining = length - i; 443 const unsigned int bytes_per_this_line = min(bytes_per_line, 444 bytes_remaining); 445 char header[100]; 446 int r = snprintf(header, sizeof(header), "0x%08x : ", i); 447 TEST_AND_RETURN(r == 13); 448 string line = header; 449 for (unsigned int j = 0; j < bytes_per_this_line; j++) { 450 char buf[20]; 451 uint8_t c = arr[i + j]; 452 r = snprintf(buf, sizeof(buf), "%02x ", static_cast<unsigned int>(c)); 453 TEST_AND_RETURN(r == 3); 454 line += buf; 455 } 456 LOG(INFO) << line; 457 } 458 } 459 460 bool SplitPartitionName(const string& partition_name, 461 string* out_disk_name, 462 int* out_partition_num) { 463 if (!base::StartsWith(partition_name, "/dev/", 464 base::CompareCase::SENSITIVE)) { 465 LOG(ERROR) << "Invalid partition device name: " << partition_name; 466 return false; 467 } 468 469 size_t last_nondigit_pos = partition_name.find_last_not_of("0123456789"); 470 if (last_nondigit_pos == string::npos || 471 (last_nondigit_pos + 1) == partition_name.size()) { 472 LOG(ERROR) << "Unable to parse partition device name: " << partition_name; 473 return false; 474 } 475 476 size_t partition_name_len = string::npos; 477 if (partition_name[last_nondigit_pos] == '_') { 478 // NAND block devices have weird naming which could be something 479 // like "/dev/ubiblock2_0". We discard "_0" in such a case. 480 size_t prev_nondigit_pos = 481 partition_name.find_last_not_of("0123456789", last_nondigit_pos - 1); 482 if (prev_nondigit_pos == string::npos || 483 (prev_nondigit_pos + 1) == last_nondigit_pos) { 484 LOG(ERROR) << "Unable to parse partition device name: " << partition_name; 485 return false; 486 } 487 488 partition_name_len = last_nondigit_pos - prev_nondigit_pos; 489 last_nondigit_pos = prev_nondigit_pos; 490 } 491 492 if (out_disk_name) { 493 // Special case for MMC devices which have the following naming scheme: 494 // mmcblk0p2 495 size_t disk_name_len = last_nondigit_pos; 496 if (partition_name[last_nondigit_pos] != 'p' || 497 last_nondigit_pos == 0 || 498 !isdigit(partition_name[last_nondigit_pos - 1])) { 499 disk_name_len++; 500 } 501 *out_disk_name = partition_name.substr(0, disk_name_len); 502 } 503 504 if (out_partition_num) { 505 string partition_str = partition_name.substr(last_nondigit_pos + 1, 506 partition_name_len); 507 *out_partition_num = atoi(partition_str.c_str()); 508 } 509 return true; 510 } 511 512 string MakePartitionName(const string& disk_name, int partition_num) { 513 if (partition_num < 1) { 514 LOG(ERROR) << "Invalid partition number: " << partition_num; 515 return string(); 516 } 517 518 if (!base::StartsWith(disk_name, "/dev/", base::CompareCase::SENSITIVE)) { 519 LOG(ERROR) << "Invalid disk name: " << disk_name; 520 return string(); 521 } 522 523 if (IsMtdDeviceName(disk_name)) { 524 // Special case for UBI block devices. 525 // 1. ubiblock is not writable, we need to use plain "ubi". 526 // 2. There is a "_0" suffix. 527 return MakeNandPartitionName(partition_num); 528 } 529 530 string partition_name = disk_name; 531 if (isdigit(partition_name.back())) { 532 // Special case for devices with names ending with a digit. 533 // Add "p" to separate the disk name from partition number, 534 // e.g. "/dev/loop0p2" 535 partition_name += 'p'; 536 } 537 538 partition_name += std::to_string(partition_num); 539 540 return partition_name; 541 } 542 543 string MakePartitionNameForMount(const string& part_name) { 544 if (IsMtdDeviceName(part_name)) { 545 int partition_num; 546 if (!SplitPartitionName(part_name, nullptr, &partition_num)) { 547 return ""; 548 } 549 return MakeNandPartitionNameForMount(partition_num); 550 } 551 return part_name; 552 } 553 554 string ErrnoNumberAsString(int err) { 555 char buf[100]; 556 buf[0] = '\0'; 557 return strerror_r(err, buf, sizeof(buf)); 558 } 559 560 bool FileExists(const char* path) { 561 struct stat stbuf; 562 return 0 == lstat(path, &stbuf); 563 } 564 565 bool IsSymlink(const char* path) { 566 struct stat stbuf; 567 return lstat(path, &stbuf) == 0 && S_ISLNK(stbuf.st_mode) != 0; 568 } 569 570 bool TryAttachingUbiVolume(int volume_num, int timeout) { 571 const string volume_path = base::StringPrintf("/dev/ubi%d_0", volume_num); 572 if (FileExists(volume_path.c_str())) { 573 return true; 574 } 575 576 int exit_code; 577 vector<string> cmd = { 578 "ubiattach", 579 "-m", 580 base::StringPrintf("%d", volume_num), 581 "-d", 582 base::StringPrintf("%d", volume_num) 583 }; 584 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr)); 585 TEST_AND_RETURN_FALSE(exit_code == 0); 586 587 cmd = { 588 "ubiblock", 589 "--create", 590 volume_path 591 }; 592 TEST_AND_RETURN_FALSE(Subprocess::SynchronousExec(cmd, &exit_code, nullptr)); 593 TEST_AND_RETURN_FALSE(exit_code == 0); 594 595 while (timeout > 0 && !FileExists(volume_path.c_str())) { 596 sleep(1); 597 timeout--; 598 } 599 600 return FileExists(volume_path.c_str()); 601 } 602 603 bool MakeTempFile(const string& base_filename_template, 604 string* filename, 605 int* fd) { 606 base::FilePath filename_template; 607 TEST_AND_RETURN_FALSE( 608 GetTempName(base_filename_template, &filename_template)); 609 DCHECK(filename || fd); 610 vector<char> buf(filename_template.value().size() + 1); 611 memcpy(buf.data(), filename_template.value().data(), 612 filename_template.value().size()); 613 buf[filename_template.value().size()] = '\0'; 614 615 int mkstemp_fd = mkstemp(buf.data()); 616 TEST_AND_RETURN_FALSE_ERRNO(mkstemp_fd >= 0); 617 if (filename) { 618 *filename = buf.data(); 619 } 620 if (fd) { 621 *fd = mkstemp_fd; 622 } else { 623 close(mkstemp_fd); 624 } 625 return true; 626 } 627 628 bool MakeTempDirectory(const string& base_dirname_template, 629 string* dirname) { 630 base::FilePath dirname_template; 631 TEST_AND_RETURN_FALSE(GetTempName(base_dirname_template, &dirname_template)); 632 DCHECK(dirname); 633 vector<char> buf(dirname_template.value().size() + 1); 634 memcpy(buf.data(), dirname_template.value().data(), 635 dirname_template.value().size()); 636 buf[dirname_template.value().size()] = '\0'; 637 638 char* return_code = mkdtemp(buf.data()); 639 TEST_AND_RETURN_FALSE_ERRNO(return_code != nullptr); 640 *dirname = buf.data(); 641 return true; 642 } 643 644 bool SetBlockDeviceReadOnly(const string& device, bool read_only) { 645 int fd = HANDLE_EINTR(open(device.c_str(), O_RDONLY | O_CLOEXEC)); 646 if (fd < 0) { 647 PLOG(ERROR) << "Opening block device " << device; 648 return false; 649 } 650 ScopedFdCloser fd_closer(&fd); 651 // We take no action if not needed. 652 int read_only_flag; 653 int expected_flag = read_only ? 1 : 0; 654 int rc = ioctl(fd, BLKROGET, &read_only_flag); 655 // In case of failure reading the setting we will try to set it anyway. 656 if (rc == 0 && read_only_flag == expected_flag) 657 return true; 658 659 rc = ioctl(fd, BLKROSET, &expected_flag); 660 if (rc != 0) { 661 PLOG(ERROR) << "Marking block device " << device << " as read_only=" 662 << expected_flag; 663 return false; 664 } 665 return true; 666 } 667 668 bool MountFilesystem(const string& device, 669 const string& mountpoint, 670 unsigned long mountflags, // NOLINT(runtime/int) 671 const string& type, 672 const string& fs_mount_options) { 673 vector<const char*> fstypes; 674 if (type.empty()) { 675 fstypes = {"ext2", "ext3", "ext4", "squashfs"}; 676 } else { 677 fstypes = {type.c_str()}; 678 } 679 for (const char* fstype : fstypes) { 680 int rc = mount(device.c_str(), mountpoint.c_str(), fstype, mountflags, 681 fs_mount_options.c_str()); 682 if (rc == 0) 683 return true; 684 685 PLOG(WARNING) << "Unable to mount destination device " << device 686 << " on " << mountpoint << " as " << fstype; 687 } 688 if (!type.empty()) { 689 LOG(ERROR) << "Unable to mount " << device << " with any supported type"; 690 } 691 return false; 692 } 693 694 bool UnmountFilesystem(const string& mountpoint) { 695 for (int num_retries = 0; ; ++num_retries) { 696 if (umount(mountpoint.c_str()) == 0) 697 break; 698 699 TEST_AND_RETURN_FALSE_ERRNO(errno == EBUSY && 700 num_retries < kUnmountMaxNumOfRetries); 701 usleep(kUnmountRetryIntervalInMicroseconds); 702 } 703 return true; 704 } 705 706 bool GetFilesystemSize(const string& device, 707 int* out_block_count, 708 int* out_block_size) { 709 int fd = HANDLE_EINTR(open(device.c_str(), O_RDONLY)); 710 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 711 ScopedFdCloser fd_closer(&fd); 712 return GetFilesystemSizeFromFD(fd, out_block_count, out_block_size); 713 } 714 715 bool GetFilesystemSizeFromFD(int fd, 716 int* out_block_count, 717 int* out_block_size) { 718 TEST_AND_RETURN_FALSE(fd >= 0); 719 720 // Determine the filesystem size by directly reading the block count and 721 // block size information from the superblock. Supported FS are ext3 and 722 // squashfs. 723 724 // Read from the fd only once and detect in memory. The first 2 KiB is enough 725 // to read the ext2 superblock (located at offset 1024) and the squashfs 726 // superblock (located at offset 0). 727 const ssize_t kBufferSize = 2048; 728 729 uint8_t buffer[kBufferSize]; 730 if (HANDLE_EINTR(pread(fd, buffer, kBufferSize, 0)) != kBufferSize) { 731 PLOG(ERROR) << "Unable to read the file system header:"; 732 return false; 733 } 734 735 if (GetSquashfs4Size(buffer, kBufferSize, out_block_count, out_block_size)) 736 return true; 737 if (GetExt3Size(buffer, kBufferSize, out_block_count, out_block_size)) 738 return true; 739 740 LOG(ERROR) << "Unable to determine file system type."; 741 return false; 742 } 743 744 bool GetExt3Size(const uint8_t* buffer, size_t buffer_size, 745 int* out_block_count, 746 int* out_block_size) { 747 // See include/linux/ext2_fs.h for more details on the structure. We obtain 748 // ext2 constants from ext2fs/ext2fs.h header but we don't link with the 749 // library. 750 if (buffer_size < SUPERBLOCK_OFFSET + SUPERBLOCK_SIZE) 751 return false; 752 753 const uint8_t* superblock = buffer + SUPERBLOCK_OFFSET; 754 755 // ext3_fs.h: ext3_super_block.s_blocks_count 756 uint32_t block_count = 757 *reinterpret_cast<const uint32_t*>(superblock + 1 * sizeof(int32_t)); 758 759 // ext3_fs.h: ext3_super_block.s_log_block_size 760 uint32_t log_block_size = 761 *reinterpret_cast<const uint32_t*>(superblock + 6 * sizeof(int32_t)); 762 763 // ext3_fs.h: ext3_super_block.s_magic 764 uint16_t magic = 765 *reinterpret_cast<const uint16_t*>(superblock + 14 * sizeof(int32_t)); 766 767 block_count = le32toh(block_count); 768 log_block_size = le32toh(log_block_size) + EXT2_MIN_BLOCK_LOG_SIZE; 769 magic = le16toh(magic); 770 771 // Sanity check the parameters. 772 TEST_AND_RETURN_FALSE(magic == EXT2_SUPER_MAGIC); 773 TEST_AND_RETURN_FALSE(log_block_size >= EXT2_MIN_BLOCK_LOG_SIZE && 774 log_block_size <= EXT2_MAX_BLOCK_LOG_SIZE); 775 TEST_AND_RETURN_FALSE(block_count > 0); 776 777 if (out_block_count) 778 *out_block_count = block_count; 779 if (out_block_size) 780 *out_block_size = 1 << log_block_size; 781 return true; 782 } 783 784 bool GetSquashfs4Size(const uint8_t* buffer, size_t buffer_size, 785 int* out_block_count, 786 int* out_block_size) { 787 // See fs/squashfs/squashfs_fs.h for format details. We only support 788 // Squashfs 4.x little endian. 789 790 // sizeof(struct squashfs_super_block) 791 const size_t kSquashfsSuperBlockSize = 96; 792 if (buffer_size < kSquashfsSuperBlockSize) 793 return false; 794 795 // Check magic, squashfs_fs.h: SQUASHFS_MAGIC 796 if (memcmp(buffer, "hsqs", 4) != 0) 797 return false; // Only little endian is supported. 798 799 // squashfs_fs.h: struct squashfs_super_block.s_major 800 uint16_t s_major = *reinterpret_cast<const uint16_t*>( 801 buffer + 5 * sizeof(uint32_t) + 4 * sizeof(uint16_t)); 802 803 if (s_major != 4) { 804 LOG(ERROR) << "Found unsupported squashfs major version " << s_major; 805 return false; 806 } 807 808 // squashfs_fs.h: struct squashfs_super_block.bytes_used 809 uint64_t bytes_used = *reinterpret_cast<const int64_t*>( 810 buffer + 5 * sizeof(uint32_t) + 6 * sizeof(uint16_t) + sizeof(uint64_t)); 811 812 const int block_size = 4096; 813 814 // The squashfs' bytes_used doesn't need to be aligned with the block boundary 815 // so we round up to the nearest blocksize. 816 if (out_block_count) 817 *out_block_count = (bytes_used + block_size - 1) / block_size; 818 if (out_block_size) 819 *out_block_size = block_size; 820 return true; 821 } 822 823 bool IsExtFilesystem(const string& device) { 824 brillo::Blob header; 825 // The first 2 KiB is enough to read the ext2 superblock (located at offset 826 // 1024). 827 if (!ReadFileChunk(device, 0, 2048, &header)) 828 return false; 829 return GetExt3Size(header.data(), header.size(), nullptr, nullptr); 830 } 831 832 bool IsSquashfsFilesystem(const string& device) { 833 brillo::Blob header; 834 // The first 96 is enough to read the squashfs superblock. 835 const ssize_t kSquashfsSuperBlockSize = 96; 836 if (!ReadFileChunk(device, 0, kSquashfsSuperBlockSize, &header)) 837 return false; 838 return GetSquashfs4Size(header.data(), header.size(), nullptr, nullptr); 839 } 840 841 // Tries to parse the header of an ELF file to obtain a human-readable 842 // description of it on the |output| string. 843 static bool GetFileFormatELF(const uint8_t* buffer, size_t size, 844 string* output) { 845 // 0x00: EI_MAG - ELF magic header, 4 bytes. 846 if (size < SELFMAG || memcmp(buffer, ELFMAG, SELFMAG) != 0) 847 return false; 848 *output = "ELF"; 849 850 // 0x04: EI_CLASS, 1 byte. 851 if (size < EI_CLASS + 1) 852 return true; 853 switch (buffer[EI_CLASS]) { 854 case ELFCLASS32: 855 *output += " 32-bit"; 856 break; 857 case ELFCLASS64: 858 *output += " 64-bit"; 859 break; 860 default: 861 *output += " ?-bit"; 862 } 863 864 // 0x05: EI_DATA, endianness, 1 byte. 865 if (size < EI_DATA + 1) 866 return true; 867 uint8_t ei_data = buffer[EI_DATA]; 868 switch (ei_data) { 869 case ELFDATA2LSB: 870 *output += " little-endian"; 871 break; 872 case ELFDATA2MSB: 873 *output += " big-endian"; 874 break; 875 default: 876 *output += " ?-endian"; 877 // Don't parse anything after the 0x10 offset if endianness is unknown. 878 return true; 879 } 880 881 const Elf32_Ehdr* hdr = reinterpret_cast<const Elf32_Ehdr*>(buffer); 882 // 0x12: e_machine, 2 byte endianness based on ei_data. The position (0x12) 883 // and size is the same for both 32 and 64 bits. 884 if (size < offsetof(Elf32_Ehdr, e_machine) + sizeof(hdr->e_machine)) 885 return true; 886 uint16_t e_machine; 887 // Fix endianess regardless of the host endianess. 888 if (ei_data == ELFDATA2LSB) 889 e_machine = le16toh(hdr->e_machine); 890 else 891 e_machine = be16toh(hdr->e_machine); 892 893 switch (e_machine) { 894 case EM_386: 895 *output += " x86"; 896 break; 897 case EM_MIPS: 898 *output += " mips"; 899 break; 900 case EM_ARM: 901 *output += " arm"; 902 break; 903 case EM_X86_64: 904 *output += " x86-64"; 905 break; 906 default: 907 *output += " unknown-arch"; 908 } 909 return true; 910 } 911 912 string GetFileFormat(const string& path) { 913 brillo::Blob buffer; 914 if (!ReadFileChunkAndAppend(path, 0, kGetFileFormatMaxHeaderSize, &buffer)) 915 return "File not found."; 916 917 string result; 918 if (GetFileFormatELF(buffer.data(), buffer.size(), &result)) 919 return result; 920 921 return "data"; 922 } 923 924 namespace { 925 // Do the actual trigger. We do it as a main-loop callback to (try to) get a 926 // consistent stack trace. 927 void TriggerCrashReporterUpload() { 928 pid_t pid = fork(); 929 CHECK_GE(pid, 0) << "fork failed"; // fork() failed. Something is very wrong. 930 if (pid == 0) { 931 // We are the child. Crash. 932 abort(); // never returns 933 } 934 // We are the parent. Wait for child to terminate. 935 pid_t result = waitpid(pid, nullptr, 0); 936 LOG_IF(ERROR, result < 0) << "waitpid() failed"; 937 } 938 } // namespace 939 940 void ScheduleCrashReporterUpload() { 941 brillo::MessageLoop::current()->PostTask( 942 FROM_HERE, 943 base::Bind(&TriggerCrashReporterUpload)); 944 } 945 946 int FuzzInt(int value, unsigned int range) { 947 int min = value - range / 2; 948 int max = value + range - range / 2; 949 return base::RandInt(min, max); 950 } 951 952 string FormatSecs(unsigned secs) { 953 return FormatTimeDelta(TimeDelta::FromSeconds(secs)); 954 } 955 956 string FormatTimeDelta(TimeDelta delta) { 957 string str; 958 959 // Handle negative durations by prefixing with a minus. 960 if (delta.ToInternalValue() < 0) { 961 delta *= -1; 962 str = "-"; 963 } 964 965 // Canonicalize into days, hours, minutes, seconds and microseconds. 966 unsigned days = delta.InDays(); 967 delta -= TimeDelta::FromDays(days); 968 unsigned hours = delta.InHours(); 969 delta -= TimeDelta::FromHours(hours); 970 unsigned mins = delta.InMinutes(); 971 delta -= TimeDelta::FromMinutes(mins); 972 unsigned secs = delta.InSeconds(); 973 delta -= TimeDelta::FromSeconds(secs); 974 unsigned usecs = delta.InMicroseconds(); 975 976 if (days) 977 base::StringAppendF(&str, "%ud", days); 978 if (days || hours) 979 base::StringAppendF(&str, "%uh", hours); 980 if (days || hours || mins) 981 base::StringAppendF(&str, "%um", mins); 982 base::StringAppendF(&str, "%u", secs); 983 if (usecs) { 984 int width = 6; 985 while ((usecs / 10) * 10 == usecs) { 986 usecs /= 10; 987 width--; 988 } 989 base::StringAppendF(&str, ".%0*u", width, usecs); 990 } 991 base::StringAppendF(&str, "s"); 992 return str; 993 } 994 995 string ToString(const Time utc_time) { 996 Time::Exploded exp_time; 997 utc_time.UTCExplode(&exp_time); 998 return base::StringPrintf("%d/%d/%d %d:%02d:%02d GMT", 999 exp_time.month, 1000 exp_time.day_of_month, 1001 exp_time.year, 1002 exp_time.hour, 1003 exp_time.minute, 1004 exp_time.second); 1005 } 1006 1007 string ToString(bool b) { 1008 return (b ? "true" : "false"); 1009 } 1010 1011 string ToString(DownloadSource source) { 1012 switch (source) { 1013 case kDownloadSourceHttpsServer: return "HttpsServer"; 1014 case kDownloadSourceHttpServer: return "HttpServer"; 1015 case kDownloadSourceHttpPeer: return "HttpPeer"; 1016 case kNumDownloadSources: return "Unknown"; 1017 // Don't add a default case to let the compiler warn about newly added 1018 // download sources which should be added here. 1019 } 1020 1021 return "Unknown"; 1022 } 1023 1024 string ToString(PayloadType payload_type) { 1025 switch (payload_type) { 1026 case kPayloadTypeDelta: return "Delta"; 1027 case kPayloadTypeFull: return "Full"; 1028 case kPayloadTypeForcedFull: return "ForcedFull"; 1029 case kNumPayloadTypes: return "Unknown"; 1030 // Don't add a default case to let the compiler warn about newly added 1031 // payload types which should be added here. 1032 } 1033 1034 return "Unknown"; 1035 } 1036 1037 ErrorCode GetBaseErrorCode(ErrorCode code) { 1038 // Ignore the higher order bits in the code by applying the mask as 1039 // we want the enumerations to be in the small contiguous range 1040 // with values less than ErrorCode::kUmaReportedMax. 1041 ErrorCode base_code = static_cast<ErrorCode>( 1042 static_cast<int>(code) & ~static_cast<int>(ErrorCode::kSpecialFlags)); 1043 1044 // Make additional adjustments required for UMA and error classification. 1045 // TODO(jaysri): Move this logic to UeErrorCode.cc when we fix 1046 // chromium-os:34369. 1047 if (base_code >= ErrorCode::kOmahaRequestHTTPResponseBase) { 1048 // Since we want to keep the enums to a small value, aggregate all HTTP 1049 // errors into this one bucket for UMA and error classification purposes. 1050 LOG(INFO) << "Converting error code " << base_code 1051 << " to ErrorCode::kOmahaErrorInHTTPResponse"; 1052 base_code = ErrorCode::kOmahaErrorInHTTPResponse; 1053 } 1054 1055 return base_code; 1056 } 1057 1058 bool CreatePowerwashMarkerFile(const char* file_path) { 1059 const char* marker_file = file_path ? file_path : kPowerwashMarkerFile; 1060 bool result = utils::WriteFile(marker_file, 1061 kPowerwashCommand, 1062 strlen(kPowerwashCommand)); 1063 if (result) { 1064 LOG(INFO) << "Created " << marker_file << " to powerwash on next reboot"; 1065 } else { 1066 PLOG(ERROR) << "Error in creating powerwash marker file: " << marker_file; 1067 } 1068 1069 return result; 1070 } 1071 1072 bool DeletePowerwashMarkerFile(const char* file_path) { 1073 const char* marker_file = file_path ? file_path : kPowerwashMarkerFile; 1074 const base::FilePath kPowerwashMarkerPath(marker_file); 1075 bool result = base::DeleteFile(kPowerwashMarkerPath, false); 1076 1077 if (result) 1078 LOG(INFO) << "Successfully deleted the powerwash marker file : " 1079 << marker_file; 1080 else 1081 PLOG(ERROR) << "Could not delete the powerwash marker file : " 1082 << marker_file; 1083 1084 return result; 1085 } 1086 1087 Time TimeFromStructTimespec(struct timespec *ts) { 1088 int64_t us = static_cast<int64_t>(ts->tv_sec) * Time::kMicrosecondsPerSecond + 1089 static_cast<int64_t>(ts->tv_nsec) / Time::kNanosecondsPerMicrosecond; 1090 return Time::UnixEpoch() + TimeDelta::FromMicroseconds(us); 1091 } 1092 1093 string StringVectorToString(const vector<string> &vec_str) { 1094 string str = "["; 1095 for (vector<string>::const_iterator i = vec_str.begin(); 1096 i != vec_str.end(); ++i) { 1097 if (i != vec_str.begin()) 1098 str += ", "; 1099 str += '"'; 1100 str += *i; 1101 str += '"'; 1102 } 1103 str += "]"; 1104 return str; 1105 } 1106 1107 string CalculateP2PFileId(const string& payload_hash, size_t payload_size) { 1108 string encoded_hash = brillo::data_encoding::Base64Encode(payload_hash); 1109 return base::StringPrintf("cros_update_size_%" PRIuS "_hash_%s", 1110 payload_size, 1111 encoded_hash.c_str()); 1112 } 1113 1114 bool DecodeAndStoreBase64String(const string& base64_encoded, 1115 base::FilePath *out_path) { 1116 brillo::Blob contents; 1117 1118 out_path->clear(); 1119 1120 if (base64_encoded.size() == 0) { 1121 LOG(ERROR) << "Can't decode empty string."; 1122 return false; 1123 } 1124 1125 if (!brillo::data_encoding::Base64Decode(base64_encoded, &contents) || 1126 contents.size() == 0) { 1127 LOG(ERROR) << "Error decoding base64."; 1128 return false; 1129 } 1130 1131 FILE *file = base::CreateAndOpenTemporaryFile(out_path); 1132 if (file == nullptr) { 1133 LOG(ERROR) << "Error creating temporary file."; 1134 return false; 1135 } 1136 1137 if (fwrite(contents.data(), 1, contents.size(), file) != contents.size()) { 1138 PLOG(ERROR) << "Error writing to temporary file."; 1139 if (fclose(file) != 0) 1140 PLOG(ERROR) << "Error closing temporary file."; 1141 if (unlink(out_path->value().c_str()) != 0) 1142 PLOG(ERROR) << "Error unlinking temporary file."; 1143 out_path->clear(); 1144 return false; 1145 } 1146 1147 if (fclose(file) != 0) { 1148 PLOG(ERROR) << "Error closing temporary file."; 1149 out_path->clear(); 1150 return false; 1151 } 1152 1153 return true; 1154 } 1155 1156 bool ConvertToOmahaInstallDate(Time time, int *out_num_days) { 1157 time_t unix_time = time.ToTimeT(); 1158 // Output of: date +"%s" --date="Jan 1, 2007 0:00 PST". 1159 const time_t kOmahaEpoch = 1167638400; 1160 const int64_t kNumSecondsPerWeek = 7*24*3600; 1161 const int64_t kNumDaysPerWeek = 7; 1162 1163 time_t omaha_time = unix_time - kOmahaEpoch; 1164 1165 if (omaha_time < 0) 1166 return false; 1167 1168 // Note, as per the comment in utils.h we are deliberately not 1169 // handling DST correctly. 1170 1171 int64_t num_weeks_since_omaha_epoch = omaha_time / kNumSecondsPerWeek; 1172 *out_num_days = num_weeks_since_omaha_epoch * kNumDaysPerWeek; 1173 1174 return true; 1175 } 1176 1177 bool GetMinorVersion(const brillo::KeyValueStore& store, 1178 uint32_t* minor_version) { 1179 string result; 1180 if (store.GetString("PAYLOAD_MINOR_VERSION", &result)) { 1181 if (!base::StringToUint(result, minor_version)) { 1182 LOG(ERROR) << "StringToUint failed when parsing delta minor version."; 1183 return false; 1184 } 1185 return true; 1186 } 1187 return false; 1188 } 1189 1190 bool IsZlibCompatible(const string& fingerprint) { 1191 if (fingerprint.size() != sizeof(kCompatibleZlibFingerprint[0]) - 1) { 1192 LOG(ERROR) << "Invalid fingerprint: " << fingerprint; 1193 return false; 1194 } 1195 for (auto& f : kCompatibleZlibFingerprint) { 1196 if (base::CompareCaseInsensitiveASCII(fingerprint, f) == 0) { 1197 return true; 1198 } 1199 } 1200 return false; 1201 } 1202 1203 bool ReadExtents(const string& path, const vector<Extent>& extents, 1204 brillo::Blob* out_data, ssize_t out_data_size, 1205 size_t block_size) { 1206 brillo::Blob data(out_data_size); 1207 ssize_t bytes_read = 0; 1208 int fd = open(path.c_str(), O_RDONLY); 1209 TEST_AND_RETURN_FALSE_ERRNO(fd >= 0); 1210 ScopedFdCloser fd_closer(&fd); 1211 1212 for (const Extent& extent : extents) { 1213 ssize_t bytes_read_this_iteration = 0; 1214 ssize_t bytes = extent.num_blocks() * block_size; 1215 TEST_AND_RETURN_FALSE(bytes_read + bytes <= out_data_size); 1216 TEST_AND_RETURN_FALSE(utils::PReadAll(fd, 1217 &data[bytes_read], 1218 bytes, 1219 extent.start_block() * block_size, 1220 &bytes_read_this_iteration)); 1221 TEST_AND_RETURN_FALSE(bytes_read_this_iteration == bytes); 1222 bytes_read += bytes_read_this_iteration; 1223 } 1224 TEST_AND_RETURN_FALSE(out_data_size == bytes_read); 1225 *out_data = data; 1226 return true; 1227 } 1228 1229 bool GetBootId(string* boot_id) { 1230 TEST_AND_RETURN_FALSE( 1231 base::ReadFileToString(base::FilePath(kBootIdPath), boot_id)); 1232 base::TrimWhitespaceASCII(*boot_id, base::TRIM_TRAILING, boot_id); 1233 return true; 1234 } 1235 1236 } // namespace utils 1237 1238 } // namespace chromeos_update_engine 1239