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 |