| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/debug/stack_trace.h" | 5 #include "base/debug/stack_trace.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <signal.h> | 9 #include <signal.h> |
| 10 #include <stdio.h> | 10 #include <stdio.h> |
| (...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 505 } | 505 } |
| 506 | 506 |
| 507 // Returns a O_RDONLY file descriptor for |file_path| if it was opened | 507 // Returns a O_RDONLY file descriptor for |file_path| if it was opened |
| 508 // sucessfully during the initialization. The file is repositioned at | 508 // sucessfully during the initialization. The file is repositioned at |
| 509 // offset 0. | 509 // offset 0. |
| 510 // IMPORTANT: This function must be async-signal-safe because it can be | 510 // IMPORTANT: This function must be async-signal-safe because it can be |
| 511 // called from a signal handler (symbolizing stack frames for a crash). | 511 // called from a signal handler (symbolizing stack frames for a crash). |
| 512 int GetFileDescriptor(const char* file_path) { | 512 int GetFileDescriptor(const char* file_path) { |
| 513 int fd = -1; | 513 int fd = -1; |
| 514 | 514 |
| 515 #if !defined(OFFICIAL_BUILD) | 515 #if !defined(NDEBUG) |
| 516 if (file_path) { | 516 if (file_path) { |
| 517 // The assumption here is that iterating over std::map<std::string, int> | 517 // The assumption here is that iterating over std::map<std::string, int> |
| 518 // using a const_iterator does not allocate dynamic memory, hense it is | 518 // using a const_iterator does not allocate dynamic memory, hense it is |
| 519 // async-signal-safe. | 519 // async-signal-safe. |
| 520 std::map<std::string, int>::const_iterator it; | 520 std::map<std::string, int>::const_iterator it; |
| 521 for (it = modules_.begin(); it != modules_.end(); ++it) { | 521 for (it = modules_.begin(); it != modules_.end(); ++it) { |
| 522 if (strcmp((it->first).c_str(), file_path) == 0) { | 522 if (strcmp((it->first).c_str(), file_path) == 0) { |
| 523 // POSIX.1-2004 requires an implementation to guarantee that dup() | 523 // POSIX.1-2004 requires an implementation to guarantee that dup() |
| 524 // is async-signal-safe. | 524 // is async-signal-safe. |
| 525 fd = dup(it->second); | 525 fd = dup(it->second); |
| 526 break; | 526 break; |
| 527 } | 527 } |
| 528 } | 528 } |
| 529 // POSIX.1-2004 requires an implementation to guarantee that lseek() | 529 // POSIX.1-2004 requires an implementation to guarantee that lseek() |
| 530 // is async-signal-safe. | 530 // is async-signal-safe. |
| 531 if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) { | 531 if (fd >= 0 && lseek(fd, 0, SEEK_SET) < 0) { |
| 532 // Failed to seek. | 532 // Failed to seek. |
| 533 fd = -1; | 533 fd = -1; |
| 534 } | 534 } |
| 535 } | 535 } |
| 536 #endif // !defined(OFFICIAL_BUILD) | 536 #endif // !defined(NDEBUG) |
| 537 | 537 |
| 538 return fd; | 538 return fd; |
| 539 } | 539 } |
| 540 | 540 |
| 541 // Searches for the object file (from /proc/self/maps) that contains | 541 // Searches for the object file (from /proc/self/maps) that contains |
| 542 // the specified pc. If found, sets |start_address| to the start address | 542 // the specified pc. If found, sets |start_address| to the start address |
| 543 // of where this object file is mapped in memory, sets the module base | 543 // of where this object file is mapped in memory, sets the module base |
| 544 // address into |base_address|, copies the object file name into | 544 // address into |base_address|, copies the object file name into |
| 545 // |out_file_name|, and attempts to open the object file. If the object | 545 // |out_file_name|, and attempts to open the object file. If the object |
| 546 // file is opened successfully, returns the file descriptor. Otherwise, | 546 // file is opened successfully, returns the file descriptor. Otherwise, |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 612 return false; | 612 return false; |
| 613 } | 613 } |
| 614 | 614 |
| 615 is_initialized_ = true; | 615 is_initialized_ = true; |
| 616 return true; | 616 return true; |
| 617 } | 617 } |
| 618 | 618 |
| 619 // Opens all object files and caches their file descriptors. | 619 // Opens all object files and caches their file descriptors. |
| 620 void OpenSymbolFiles() { | 620 void OpenSymbolFiles() { |
| 621 // Pre-opening and caching the file descriptors of all loaded modules is | 621 // Pre-opening and caching the file descriptors of all loaded modules is |
| 622 // not safe for production builds. Hence it is only done in non-official | 622 // not considered safe for retail builds. Hence it is only done in debug |
| 623 // builds. For more details, take a look at: http://crbug.com/341966. | 623 // builds. For more details, take a look at: http://crbug.com/341966 |
| 624 #if !defined(OFFICIAL_BUILD) | 624 // Enabling this to release mode would require approval from the security |
| 625 // team. |
| 626 #if !defined(NDEBUG) |
| 625 // Open the object files for all read-only executable regions and cache | 627 // Open the object files for all read-only executable regions and cache |
| 626 // their file descriptors. | 628 // their file descriptors. |
| 627 std::vector<MappedMemoryRegion>::const_iterator it; | 629 std::vector<MappedMemoryRegion>::const_iterator it; |
| 628 for (it = regions_.begin(); it != regions_.end(); ++it) { | 630 for (it = regions_.begin(); it != regions_.end(); ++it) { |
| 629 const MappedMemoryRegion& region = *it; | 631 const MappedMemoryRegion& region = *it; |
| 630 // Only interesed in read-only executable regions. | 632 // Only interesed in read-only executable regions. |
| 631 if ((region.permissions & MappedMemoryRegion::READ) == | 633 if ((region.permissions & MappedMemoryRegion::READ) == |
| 632 MappedMemoryRegion::READ && | 634 MappedMemoryRegion::READ && |
| 633 (region.permissions & MappedMemoryRegion::WRITE) == 0 && | 635 (region.permissions & MappedMemoryRegion::WRITE) == 0 && |
| 634 (region.permissions & MappedMemoryRegion::EXECUTE) == | 636 (region.permissions & MappedMemoryRegion::EXECUTE) == |
| (...skipping 11 matching lines...) Expand all Loading... |
| 646 int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC); | 648 int fd = open(region.path.c_str(), O_RDONLY | O_CLOEXEC); |
| 647 if (fd >= 0) { | 649 if (fd >= 0) { |
| 648 modules_.insert(std::make_pair(region.path, fd)); | 650 modules_.insert(std::make_pair(region.path, fd)); |
| 649 } else { | 651 } else { |
| 650 LOG(WARNING) << "Failed to open file: " << region.path | 652 LOG(WARNING) << "Failed to open file: " << region.path |
| 651 << "\n Error: " << strerror(errno); | 653 << "\n Error: " << strerror(errno); |
| 652 } | 654 } |
| 653 } | 655 } |
| 654 } | 656 } |
| 655 } | 657 } |
| 656 #endif // !defined(OFFICIAL_BUILD) | 658 #endif // !defined(NDEBUG) |
| 657 } | 659 } |
| 658 | 660 |
| 659 // Initializes and installs the symbolization callback. | 661 // Initializes and installs the symbolization callback. |
| 660 void Init() { | 662 void Init() { |
| 661 if (CacheMemoryRegions()) { | 663 if (CacheMemoryRegions()) { |
| 662 OpenSymbolFiles(); | 664 OpenSymbolFiles(); |
| 663 google::InstallSymbolizeOpenObjectFileCallback( | 665 google::InstallSymbolizeOpenObjectFileCallback( |
| 664 &OpenObjectFileContainingPc); | 666 &OpenObjectFileContainingPc); |
| 665 } | 667 } |
| 666 } | 668 } |
| 667 | 669 |
| 668 // Unregister symbolization callback. | 670 // Unregister symbolization callback. |
| 669 void UnregisterCallback() { | 671 void UnregisterCallback() { |
| 670 if (is_initialized_) { | 672 if (is_initialized_) { |
| 671 google::InstallSymbolizeOpenObjectFileCallback(NULL); | 673 google::InstallSymbolizeOpenObjectFileCallback(NULL); |
| 672 is_initialized_ = false; | 674 is_initialized_ = false; |
| 673 } | 675 } |
| 674 } | 676 } |
| 675 | 677 |
| 676 // Closes all file descriptors owned by this instance. | 678 // Closes all file descriptors owned by this instance. |
| 677 void CloseObjectFiles() { | 679 void CloseObjectFiles() { |
| 678 #if !defined(OFFICIAL_BUILD) | 680 #if !defined(NDEBUG) |
| 679 std::map<std::string, int>::iterator it; | 681 std::map<std::string, int>::iterator it; |
| 680 for (it = modules_.begin(); it != modules_.end(); ++it) { | 682 for (it = modules_.begin(); it != modules_.end(); ++it) { |
| 681 int ret = IGNORE_EINTR(close(it->second)); | 683 int ret = IGNORE_EINTR(close(it->second)); |
| 682 DCHECK(!ret); | 684 DCHECK(!ret); |
| 683 it->second = -1; | 685 it->second = -1; |
| 684 } | 686 } |
| 685 modules_.clear(); | 687 modules_.clear(); |
| 686 #endif // !defined(OFFICIAL_BUILD) | 688 #endif // !defined(NDEBUG) |
| 687 } | 689 } |
| 688 | 690 |
| 689 // Set to true upon successful initialization. | 691 // Set to true upon successful initialization. |
| 690 bool is_initialized_; | 692 bool is_initialized_; |
| 691 | 693 |
| 692 #if !defined(OFFICIAL_BUILD) | 694 #if !defined(NDEBUG) |
| 693 // Mapping from file name to file descriptor. Includes file descriptors | 695 // Mapping from file name to file descriptor. Includes file descriptors |
| 694 // for all successfully opened object files and the file descriptor for | 696 // for all successfully opened object files and the file descriptor for |
| 695 // /proc/self/maps. This code is not safe for production builds. | 697 // /proc/self/maps. This code is not safe for release builds so |
| 698 // this is only done for DEBUG builds. |
| 696 std::map<std::string, int> modules_; | 699 std::map<std::string, int> modules_; |
| 697 #endif // !defined(OFFICIAL_BUILD) | 700 #endif // !defined(NDEBUG) |
| 698 | 701 |
| 699 // Cache for the process memory regions. Produced by parsing the contents | 702 // Cache for the process memory regions. Produced by parsing the contents |
| 700 // of /proc/self/maps cache. | 703 // of /proc/self/maps cache. |
| 701 std::vector<MappedMemoryRegion> regions_; | 704 std::vector<MappedMemoryRegion> regions_; |
| 702 | 705 |
| 703 DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper); | 706 DISALLOW_COPY_AND_ASSIGN(SandboxSymbolizeHelper); |
| 704 }; | 707 }; |
| 705 #endif // USE_SYMBOLIZE | 708 #endif // USE_SYMBOLIZE |
| 706 | 709 |
| 707 bool EnableInProcessStackDumpingForSandbox() { | 710 bool EnableInProcessStackDumpingForSandbox() { |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 835 *ptr = *start; | 838 *ptr = *start; |
| 836 *start++ = ch; | 839 *start++ = ch; |
| 837 } | 840 } |
| 838 return buf; | 841 return buf; |
| 839 } | 842 } |
| 840 | 843 |
| 841 } // namespace internal | 844 } // namespace internal |
| 842 | 845 |
| 843 } // namespace debug | 846 } // namespace debug |
| 844 } // namespace base | 847 } // namespace base |
| OLD | NEW |