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

Side by Side Diff: content/browser/zygote_main_linux.cc

Issue 10031027: Redirect fopen("/dev/urandom") so that NSS can properly seed it's RNG. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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) 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 "content/browser/zygote_host_impl_linux.h" 5 #include "content/browser/zygote_host_impl_linux.h"
6 6
7 #include <dlfcn.h> 7 #include <dlfcn.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #include <pthread.h> 9 #include <pthread.h>
10 #include <stdio.h>
10 #include <sys/socket.h> 11 #include <sys/socket.h>
11 #include <sys/stat.h> 12 #include <sys/stat.h>
12 #include <sys/types.h> 13 #include <sys/types.h>
13 #include <sys/wait.h> 14 #include <sys/wait.h>
14 #include <unistd.h> 15 #include <unistd.h>
15 16
16 #include "base/basictypes.h" 17 #include "base/basictypes.h"
17 #include "base/command_line.h" 18 #include "base/command_line.h"
18 #include "base/eintr_wrapper.h" 19 #include "base/eintr_wrapper.h"
19 #include "base/file_path.h" 20 #include "base/file_path.h"
20 #include "base/file_util.h" 21 #include "base/file_util.h"
21 #include "base/global_descriptors_posix.h" 22 #include "base/global_descriptors_posix.h"
22 #include "base/hash_tables.h" 23 #include "base/hash_tables.h"
23 #include "base/linux_util.h" 24 #include "base/linux_util.h"
24 #include "base/memory/scoped_ptr.h" 25 #include "base/memory/scoped_ptr.h"
25 #include "base/pickle.h" 26 #include "base/pickle.h"
26 #include "base/process_util.h" 27 #include "base/process_util.h"
27 #include "base/rand_util.h" 28 #include "base/rand_util.h"
29 #include "base/rand_util_c.h"
28 #include "base/sys_info.h" 30 #include "base/sys_info.h"
29 #include "build/build_config.h" 31 #include "build/build_config.h"
30 #include "crypto/nss_util.h" 32 #include "crypto/nss_util.h"
31 #include "content/common/chrome_descriptors.h" 33 #include "content/common/chrome_descriptors.h"
32 #include "content/common/font_config_ipc_linux.h" 34 #include "content/common/font_config_ipc_linux.h"
33 #include "content/common/pepper_plugin_registry.h" 35 #include "content/common/pepper_plugin_registry.h"
34 #include "content/common/sandbox_methods_linux.h" 36 #include "content/common/sandbox_methods_linux.h"
35 #include "content/common/seccomp_sandbox.h" 37 #include "content/common/seccomp_sandbox.h"
36 #include "content/common/set_process_title.h" 38 #include "content/common/set_process_title.h"
37 #include "content/common/unix_domain_socket_posix.h" 39 #include "content/common/unix_domain_socket_posix.h"
(...skipping 19 matching lines...) Expand all
57 #include <selinux/context.h> 59 #include <selinux/context.h>
58 #endif 60 #endif
59 61
60 // http://code.google.com/p/chromium/wiki/LinuxZygote 62 // http://code.google.com/p/chromium/wiki/LinuxZygote
61 63
62 static const int kBrowserDescriptor = 3; 64 static const int kBrowserDescriptor = 3;
63 static const int kMagicSandboxIPCDescriptor = 5; 65 static const int kMagicSandboxIPCDescriptor = 5;
64 static const int kZygoteIdDescriptor = 7; 66 static const int kZygoteIdDescriptor = 7;
65 static bool g_suid_sandbox_active = false; 67 static bool g_suid_sandbox_active = false;
66 68
69 static const char kUrandomDevPath[] = "/dev/urandom";
70
67 #if defined(SECCOMP_SANDBOX) 71 #if defined(SECCOMP_SANDBOX)
68 static int g_proc_fd = -1; 72 static int g_proc_fd = -1;
69 #endif 73 #endif
70 74
71 #if defined(CHROMIUM_SELINUX) 75 #if defined(CHROMIUM_SELINUX)
72 static void SELinuxTransitionToTypeOrDie(const char* type) { 76 static void SELinuxTransitionToTypeOrDie(const char* type) {
73 security_context_t security_context; 77 security_context_t security_context;
74 if (getcon(&security_context)) 78 if (getcon(&security_context))
75 LOG(FATAL) << "Cannot get SELinux context"; 79 LOG(FATAL) << "Cannot get SELinux context";
76 80
(...skipping 548 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 // Our first attempt involved some assembly to patch the GOT of the current 629 // Our first attempt involved some assembly to patch the GOT of the current
626 // module. This worked, but was platform specific and doesn't catch the case 630 // module. This worked, but was platform specific and doesn't catch the case
627 // where a library makes a call rather than current module. 631 // where a library makes a call rather than current module.
628 // 632 //
629 // We also considered patching the function in place, but this would again by 633 // We also considered patching the function in place, but this would again by
630 // platform specific and the above technique seems to work well enough. 634 // platform specific and the above technique seems to work well enough.
631 635
632 typedef struct tm* (*LocaltimeFunction)(const time_t* timep); 636 typedef struct tm* (*LocaltimeFunction)(const time_t* timep);
633 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep, 637 typedef struct tm* (*LocaltimeRFunction)(const time_t* timep,
634 struct tm* result); 638 struct tm* result);
639 typedef FILE* (*FopenFunction)(const char* path, const char* mode);
640 typedef int (*XstatFunction)(int version, const char *path, struct stat *buf);
641 typedef int (*Xstat64Function)(int version, const char *path,
642 struct stat64 *buf);
635 643
636 static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT; 644 static pthread_once_t g_libc_localtime_funcs_guard = PTHREAD_ONCE_INIT;
637 static LocaltimeFunction g_libc_localtime; 645 static LocaltimeFunction g_libc_localtime;
638 static LocaltimeRFunction g_libc_localtime_r; 646 static LocaltimeRFunction g_libc_localtime_r;
639 647
648 static pthread_once_t g_libc_file_io_funcs_guard = PTHREAD_ONCE_INIT;
649 static FopenFunction g_libc_fopen;
650 static FopenFunction g_libc_fopen64;
651 static XstatFunction g_libc_xstat;
652 static Xstat64Function g_libc_xstat64;
653
640 static void InitLibcLocaltimeFunctions() { 654 static void InitLibcLocaltimeFunctions() {
641 g_libc_localtime = reinterpret_cast<LocaltimeFunction>( 655 g_libc_localtime = reinterpret_cast<LocaltimeFunction>(
642 dlsym(RTLD_NEXT, "localtime")); 656 dlsym(RTLD_NEXT, "localtime"));
643 g_libc_localtime_r = reinterpret_cast<LocaltimeRFunction>( 657 g_libc_localtime_r = reinterpret_cast<LocaltimeRFunction>(
644 dlsym(RTLD_NEXT, "localtime_r")); 658 dlsym(RTLD_NEXT, "localtime_r"));
645 659
646 if (!g_libc_localtime || !g_libc_localtime_r) { 660 if (!g_libc_localtime || !g_libc_localtime_r) {
647 // http://code.google.com/p/chromium/issues/detail?id=16800 661 // http://code.google.com/p/chromium/issues/detail?id=16800
648 // 662 //
649 // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces 663 // Nvidia's libGL.so overrides dlsym for an unknown reason and replaces
650 // it with a version which doesn't work. In this case we'll get a NULL 664 // it with a version which doesn't work. In this case we'll get a NULL
651 // result. There's not a lot we can do at this point, so we just bodge it! 665 // result. There's not a lot we can do at this point, so we just bodge it!
652 LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been " 666 LOG(ERROR) << "Your system is broken: dlsym doesn't work! This has been "
653 "reported to be caused by Nvidia's libGL. You should expect" 667 "reported to be caused by Nvidia's libGL. You should expect"
654 " time related functions to misbehave. " 668 " time related functions to misbehave. "
(...skipping 24 matching lines...) Expand all
679 if (g_am_zygote_or_renderer) { 693 if (g_am_zygote_or_renderer) {
680 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0); 694 ProxyLocaltimeCallToBrowser(*timep, result, NULL, 0);
681 return result; 695 return result;
682 } else { 696 } else {
683 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard, 697 CHECK_EQ(0, pthread_once(&g_libc_localtime_funcs_guard,
684 InitLibcLocaltimeFunctions)); 698 InitLibcLocaltimeFunctions));
685 return g_libc_localtime_r(timep, result); 699 return g_libc_localtime_r(timep, result);
686 } 700 }
687 } 701 }
688 702
703 // TODO(sergeyu): Currently this code doesn't work properly under ASAN
704 // - it crashes content_unittests. Make sure it works properly and
705 // enable it here. http://crbug.com/123263
706 #if !defined(ADDRESS_SANITIZER)
707
708 static void InitLibcFileIOFunctions() {
709 g_libc_fopen = reinterpret_cast<FopenFunction>(
710 dlsym(RTLD_NEXT, "fopen"));
711 g_libc_fopen64 = reinterpret_cast<FopenFunction>(
712 dlsym(RTLD_NEXT, "fopen64"));
713
714 if (!g_libc_fopen) {
715 LOG(FATAL) << "Failed to get fopen() from libc.";
716 } else if (!g_libc_fopen64) {
717 #if !defined(OS_OPENBSD) && !defined(OS_FREEBSD)
718 LOG(WARNING) << "Failed to get fopen64() from libc. Using fopen() instead.";
719 #endif // !defined(OS_OPENBSD) && !defined(OS_FREEBSD)
720 g_libc_fopen64 = g_libc_fopen;
721 }
722
723 // TODO(sergeyu): This works only on systems with glibc. Fix it to
724 // work properly on other systems if necessary.
725 g_libc_xstat = reinterpret_cast<XstatFunction>(
726 dlsym(RTLD_NEXT, "__xstat"));
727 g_libc_xstat64 = reinterpret_cast<Xstat64Function>(
728 dlsym(RTLD_NEXT, "__xstat64"));
729
730 if (!g_libc_xstat) {
731 LOG(FATAL) << "Failed to get __xstat() from libc.";
732 }
733 if (!g_libc_xstat64) {
734 LOG(WARNING) << "Failed to get __xstat64() from libc.";
735 }
736 }
737
738 // fopen() and fopen64() are intercepted here so that NSS can open
739 // /dev/urandom to seed its random number generator. NSS is used by
740 // remoting in the sendbox.
wtc 2012/04/17 22:02:47 Typo: sendbox => sandbox
741
742 // fopen() call may be redirected to fopen64() in stdio.h using
743 // __REDIRECT(), which sets asm name for fopen() to "fopen64". This
744 // means that we cannot override fopen() directly here. Instead the
745 // the code below defines fopen_override() function with asm name
wtc 2012/04/17 22:02:47 Typo: remove "the" I suggest you just move "the"
746 // "fopen", so that all references to fopen() will resolve to this
747 // function.
748 __attribute__ ((__visibility__("default")))
749 FILE* fopen_override(const char* path, const char* mode) __asm__ ("fopen");
750
751 __attribute__ ((__visibility__("default")))
752 FILE* fopen_override(const char* path, const char* mode) {
753 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
754 int fd = HANDLE_EINTR(dup(GetUrandomFD()));
755 if (fd < 0) {
756 PLOG(ERROR) << "dup() failed.";
757 return NULL;
758 }
759 return fdopen(fd, mode);
760 } else {
761 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
762 InitLibcFileIOFunctions));
763 return g_libc_fopen(path, mode);
764 }
765 }
766
767 __attribute__ ((__visibility__("default")))
768 FILE* fopen64(const char* path, const char* mode) {
769 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
770 int fd = HANDLE_EINTR(dup(GetUrandomFD()));
771 if (fd < 0) {
772 PLOG(ERROR) << "dup() failed.";
773 return NULL;
774 }
775 return fdopen(fd, mode);
776 } else {
777 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
778 InitLibcFileIOFunctions));
779 return g_libc_fopen64(path, mode);
780 }
781 }
782
783 // stat() is subject to the same problem as fopen(), so we have to use
784 // the same trick to override it.
wtc 2012/04/17 22:02:47 You should explain why you need to intercept stat(
785 __attribute__ ((__visibility__("default")))
786 int xstat_override(int version,
787 const char *path,
788 struct stat *buf) __asm__ ("__xstat");
789
790 __attribute__ ((__visibility__("default")))
791 int xstat_override(int version, const char *path, struct stat *buf) {
792 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
793 int result = __fxstat(version, GetUrandomFD(), buf);
794 return result;
795 } else {
796 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
797 InitLibcFileIOFunctions));
798 return g_libc_xstat(version, path, buf);
799 }
800 }
801
802 __attribute__ ((__visibility__("default")))
803 int xstat64_override(int version,
804 const char *path,
805 struct stat64 *buf) __asm__ ("__xstat64");
806
807 __attribute__ ((__visibility__("default")))
808 int xstat64_override(int version, const char *path, struct stat64 *buf) {
809 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
810 int result = __fxstat64(version, GetUrandomFD(), buf);
811 return result;
812 } else {
813 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
814 InitLibcFileIOFunctions));
815 CHECK(g_libc_xstat64);
816 return g_libc_xstat64(version, path, buf);
817 }
818 }
819
820 #endif // !ADDRESS_SANITIZER
821
689 #endif // !CHROMIUM_SELINUX 822 #endif // !CHROMIUM_SELINUX
690 823
691 // This function triggers the static and lazy construction of objects that need 824 // This function triggers the static and lazy construction of objects that need
692 // to be created before imposing the sandbox. 825 // to be created before imposing the sandbox.
693 static void PreSandboxInit() { 826 static void PreSandboxInit() {
694 base::RandUint64(); 827 base::RandUint64();
695 828
696 base::SysInfo::MaxSharedMemorySize(); 829 base::SysInfo::MaxSharedMemorySize();
697 830
698 // ICU DateFormat class (used in base/time_format.cc) needs to get the 831 // ICU DateFormat class (used in base/time_format.cc) needs to get the
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 VLOG(1) << "Enabling experimental Seccomp sandbox."; 1006 VLOG(1) << "Enabling experimental Seccomp sandbox.";
874 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; 1007 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp;
875 } 1008 }
876 } 1009 }
877 #endif // SECCOMP_SANDBOX 1010 #endif // SECCOMP_SANDBOX
878 1011
879 Zygote zygote(sandbox_flags, forkdelegate); 1012 Zygote zygote(sandbox_flags, forkdelegate);
880 // This function call can return multiple times, once per fork(). 1013 // This function call can return multiple times, once per fork().
881 return zygote.ProcessRequests(); 1014 return zygote.ProcessRequests();
882 } 1015 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698