Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: base/process_util_linux.cc

Issue 533001: Linux: reenable malloc overrides. (Closed)
Patch Set: Addressing evan's comments Created 10 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/process_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/process_util.h" 5 #include "base/process_util.h"
6 6
7 #include <ctype.h> 7 #include <ctype.h>
8 #include <dirent.h> 8 #include <dirent.h>
9 #include <dlfcn.h> 9 #include <dlfcn.h>
10 #include <errno.h> 10 #include <errno.h>
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 CHECK(false) << "Out of memory."; 506 CHECK(false) << "Out of memory.";
507 } 507 }
508 508
509 void OnNoMemory() { 509 void OnNoMemory() {
510 OnNoMemorySize(0); 510 OnNoMemorySize(0);
511 } 511 }
512 512
513 } // namespace 513 } // namespace
514 514
515 extern "C" { 515 extern "C" {
516 // This code tries to make malloc failures fatal for security reasons. However,
517 // it breaks builds depending on fine details of the linker command line and
518 // the dependencies of other .so's that we pull in. So it's disabled for the
519 // moment. See crbug.com/31809
520 //
521 // If enabling this, remember to reanble the tests in process_util_unittest.cc
522 516
523 #if 0
524 #if !defined(LINUX_USE_TCMALLOC) 517 #if !defined(LINUX_USE_TCMALLOC)
525 518
526 typedef void* (*malloc_type)(size_t size); 519 extern "C" {
527 typedef void* (*valloc_type)(size_t size); 520 void* __libc_malloc(size_t size);
528 typedef void* (*pvalloc_type)(size_t size); 521 void* __libc_realloc(void* ptr, size_t size);
522 void* __libc_calloc(size_t nmemb, size_t size);
523 void* __libc_valloc(size_t size);
524 void* __libc_pvalloc(size_t size);
525 void* __libc_memalign(size_t alignment, size_t size);
526 } // extern "C"
529 527
530 typedef void* (*calloc_type)(size_t nmemb, size_t size); 528 // Overriding the system memory allocation functions:
531 typedef void* (*realloc_type)(void *ptr, size_t size); 529 //
532 typedef void* (*memalign_type)(size_t boundary, size_t size); 530 // For security reasons, we want malloc failures to be fatal. Too much code
531 // doesn't check for a NULL return value from malloc and unconditionally uses
532 // the resulting pointer. If the first offset that they try to access is
533 // attacker controlled, then the attacker can direct the code to access any
534 // part of memory.
535 //
536 // Thus, we define all the standard malloc functions here and mark them as
537 // visibility 'default'. This means that they replace the malloc functions for
538 // all Chromium code and also for all code in shared libraries. There are tests
539 // for this in process_util_unittest.cc.
540 //
541 // If we are using tcmalloc, then the problem is moot since tcmalloc handles
542 // this for us. Thus this code is in a !defined(LINUX_USE_TCMALLOC) block.
543 //
544 // We call the real libc functions in this code by using __libc_malloc etc.
545 // Previously we tried using dlsym(RTLD_NEXT, ...) but that failed depending on
546 // the link order. Since ld.so needs calloc during symbol resolution, it
547 // defines its own versions of several of these functions in dl-minimal.c.
548 // Depending on the runtime library order, dlsym ended up giving us those
549 // functions and bad things happened. See crbug.com/31809
550 //
551 // This means that any code which calls __libc_* gets the raw libc versions of
552 // these functions.
533 553
534 typedef int (*posix_memalign_type)(void **memptr, size_t alignment,
535 size_t size);
536
537 // Override the __libc_FOO name too.
538 #define DIE_ON_OOM_1(function_name) \ 554 #define DIE_ON_OOM_1(function_name) \
539 _DIE_ON_OOM_1(function_name##_type, function_name) \ 555 void* function_name(size_t) __attribute__ ((visibility("default"))); \
540 void* __libc_##function_name(size_t size) { \ 556 \
541 return function_name(size); \
542 }
543
544 #define DIE_ON_OOM_2(function_name, arg1_type) \
545 _DIE_ON_OOM_2(function_name##_type, function_name, arg1_type) \
546 void* __libc_##function_name(arg1_type arg1, size_t size) { \
547 return function_name(arg1, size); \
548 }
549
550 #define _DIE_ON_OOM_1(function_type, function_name) \
551 void* function_name(size_t size) { \ 557 void* function_name(size_t size) { \
552 static function_type original_function = \ 558 void* ret = __libc_##function_name(size); \
553 reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \
554 void* ret = original_function(size); \
555 if (ret == NULL && size != 0) \ 559 if (ret == NULL && size != 0) \
556 OnNoMemorySize(size); \ 560 OnNoMemorySize(size); \
557 return ret; \ 561 return ret; \
558 } 562 }
559 563
560 #define _DIE_ON_OOM_2(function_type, function_name, arg1_type) \ 564 #define DIE_ON_OOM_2(function_name, arg1_type) \
565 void* function_name(arg1_type, size_t) \
566 __attribute__ ((visibility("default"))); \
567 \
561 void* function_name(arg1_type arg1, size_t size) { \ 568 void* function_name(arg1_type arg1, size_t size) { \
562 static function_type original_function = \ 569 void* ret = __libc_##function_name(arg1, size); \
563 reinterpret_cast<function_type>(dlsym(RTLD_NEXT, #function_name)); \
564 void* ret = original_function(arg1, size); \
565 if (ret == NULL && size != 0) \ 570 if (ret == NULL && size != 0) \
566 OnNoMemorySize(size); \ 571 OnNoMemorySize(size); \
567 return ret; \ 572 return ret; \
568 } 573 }
569 574
570 DIE_ON_OOM_1(malloc) 575 DIE_ON_OOM_1(malloc)
571 DIE_ON_OOM_1(valloc) 576 DIE_ON_OOM_1(valloc)
572 DIE_ON_OOM_1(pvalloc) 577 DIE_ON_OOM_1(pvalloc)
573 578
579 DIE_ON_OOM_2(calloc, size_t)
574 DIE_ON_OOM_2(realloc, void*) 580 DIE_ON_OOM_2(realloc, void*)
575 DIE_ON_OOM_2(memalign, size_t) 581 DIE_ON_OOM_2(memalign, size_t)
576 582
577 // dlsym uses calloc so it has to be treated specially. http://crbug.com/28244 583 // posix_memalign has a unique signature and doesn't have a __libc_ variant.
578 static void* null_calloc(size_t nmemb, size_t size) { 584 int posix_memalign(void** ptr, size_t alignment, size_t size)
579 return NULL; 585 __attribute__ ((visibility("default")));
580 }
581 586
582 void* calloc(size_t nmemb, size_t size) {
583 static calloc_type original_function = NULL;
584 if (original_function == NULL) {
585 original_function = null_calloc;
586 original_function = reinterpret_cast<calloc_type>(dlsym(RTLD_NEXT,
587 "calloc"));
588 }
589 void* ret = original_function(nmemb, size);
590 if (ret == NULL && size != 0 && original_function != null_calloc)
591 OnNoMemorySize(size);
592 return ret;
593 }
594
595 void* __libc_calloc(size_t nmemb, size_t size) { \
596 return calloc(nmemb, size);
597 }
598
599 // posix_memalign has a unique signature and doesn't have a __libc_ variant.
600 int posix_memalign(void** ptr, size_t alignment, size_t size) { 587 int posix_memalign(void** ptr, size_t alignment, size_t size) {
601 static posix_memalign_type original_function = 588 // This will use the safe version of memalign, above.
602 reinterpret_cast<posix_memalign_type>(dlsym(RTLD_NEXT, "posix_memalign")); 589 *ptr = memalign(alignment, size);
603 int ret = original_function(ptr, alignment, size); 590 return 0;
604 if (ret == ENOMEM)
605 OnNoMemorySize(size);
606 return ret;
607 } 591 }
608 592
609 #endif // !defined(LINUX_USE_TCMALLOC) 593 #endif // !defined(LINUX_USE_TCMALLOC)
610 #endif
611 } // extern C 594 } // extern C
612 595
613 void EnableTerminationOnOutOfMemory() { 596 void EnableTerminationOnOutOfMemory() {
614 // Set the new-out of memory handler. 597 // Set the new-out of memory handler.
615 std::set_new_handler(&OnNoMemory); 598 std::set_new_handler(&OnNoMemory);
616 // If we're using glibc's allocator, the above functions will override 599 // If we're using glibc's allocator, the above functions will override
617 // malloc and friends and make them die on out of memory. 600 // malloc and friends and make them die on out of memory.
618 } 601 }
619 602
620 bool AdjustOOMScore(ProcessId process, int score) { 603 bool AdjustOOMScore(ProcessId process, int score) {
621 if (score < 0 || score > 15) 604 if (score < 0 || score > 15)
622 return false; 605 return false;
623 606
624 FilePath oom_adj("/proc"); 607 FilePath oom_adj("/proc");
625 oom_adj = oom_adj.Append(Int64ToString(process)); 608 oom_adj = oom_adj.Append(Int64ToString(process));
626 oom_adj = oom_adj.AppendASCII("oom_adj"); 609 oom_adj = oom_adj.AppendASCII("oom_adj");
627 610
628 if (!file_util::PathExists(oom_adj)) 611 if (!file_util::PathExists(oom_adj))
629 return false; 612 return false;
630 613
631 std::string score_str = IntToString(score); 614 std::string score_str = IntToString(score);
632 return (static_cast<int>(score_str.length()) == 615 return (static_cast<int>(score_str.length()) ==
633 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length())); 616 file_util::WriteFile(oom_adj, score_str.c_str(), score_str.length()));
634 } 617 }
635 618
636 } // namespace base 619 } // namespace base
OLDNEW
« no previous file with comments | « no previous file | base/process_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698