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

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: override stat() 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 static void InitLibcFileIOFunctions() {
704 g_libc_fopen = reinterpret_cast<FopenFunction>(
705 dlsym(RTLD_NEXT, "fopen"));
706 g_libc_fopen64 = reinterpret_cast<FopenFunction>(
707 dlsym(RTLD_NEXT, "fopen64"));
708
709 if (!g_libc_fopen) {
710 LOG(FATAL) << "Failed to get fopen() from libc.";
711 } else if (!g_libc_fopen64) {
712 #if !defined(OS_OPENBSD) && !defined(OS_FREEBSD)
713 LOG(WARNING) << "Failed to get fopen64() from libc. Using fopen() instead.";
714 #endif // !defined(OS_OPENBSD) && !defined(OS_FREEBSD)
715 g_libc_fopen64 = g_libc_fopen;
716 }
717
718 g_libc_xstat = reinterpret_cast<XstatFunction>(
719 dlsym(RTLD_NEXT, "__xstat"));
720 g_libc_xstat64 = reinterpret_cast<Xstat64Function>(
721 dlsym(RTLD_NEXT, "__xstat64"));
722
723 if (!g_libc_xstat) {
724 LOG(FATAL) << "Failed to get __xstat() from libc.";
725 }
726 if (!g_libc_xstat64) {
727 LOG(WARNING) << "Failed to get __xstat64() from libc.";
728 }
729 }
730
731 // fopen() and fopen64() are intercepted here so that NSS can open
732 // /dev/urandom to seed it's random number generator. NSS is used by
733 // remoting in the sendbox.
734
735 // fopen() call may be redirected to fopen64() in stdio.h using
736 // __REDIRECT(), which sets asm name for fopen() to "fopen64". This
737 // means that we cannot override fopen() directly here. Instead the
738 // the code below defines fopen_override() function with asm name
739 // "fopen", so that all references to fopen() will resolve to this
740 // function.
741 __attribute__ ((__visibility__("default")))
742 FILE* fopen_override(const char* path, const char* mode) __asm__ ("fopen");
743
744 __attribute__ ((__visibility__("default")))
745 FILE* fopen_override(const char* path, const char* mode) {
746 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
747 int fd = HANDLE_EINTR(dup(GetUrandomFD()));
748 if (fd < 0) {
749 PLOG(ERROR) << "dup() failed.";
750 return NULL;
751 }
752 return fdopen(fd, mode);
753 } else {
754 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
755 InitLibcFileIOFunctions));
756 return g_libc_fopen(path, mode);
757 }
758 }
759
760 __attribute__ ((__visibility__("default")))
761 FILE* fopen64(const char* path, const char* mode) {
762 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
763 int fd = HANDLE_EINTR(dup(GetUrandomFD()));
764 if (fd < 0) {
765 PLOG(ERROR) << "dup() failed.";
766 return NULL;
767 }
768 return fdopen(fd, mode);
769 } else {
770 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
771 InitLibcFileIOFunctions));
772 return g_libc_fopen64(path, mode);
773 }
774 }
775
776 // stat() is subject to the same problem as fopen(), so we have to use
777 // the same trick to override it.
778 __attribute__ ((__visibility__("default")))
779 int xstat_override(int version,
780 const char *path,
781 struct stat *buf) __asm__ ("__xstat");
Ben Chan 2012/04/11 05:13:47 These symbol names look a bit scary. Do they depen
Sergey Ulanov 2012/04/11 06:36:54 There is LOG(FATAL) that would crash the process i
782
783 __attribute__ ((__visibility__("default")))
784 int xstat_override(int version, const char *path, struct stat *buf) {
785 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
786 int result = __fxstat(version, GetUrandomFD(), buf);
787 return result;
788 } else {
789 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
790 InitLibcFileIOFunctions));
791 return g_libc_xstat(version, path, buf);
792 }
793 }
794
795 __attribute__ ((__visibility__("default")))
796 int xstat64_override(int version,
797 const char *path,
798 struct stat *buf) __asm__ ("__xstat64");
799
800 __attribute__ ((__visibility__("default")))
801 int xstat64_override(int version, const char *path, struct stat64 *buf) {
802 if (g_am_zygote_or_renderer && strcmp(path, kUrandomDevPath) == 0) {
803 int result = __fxstat64(version, GetUrandomFD(), buf);
804 return result;
805 } else {
806 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard,
807 InitLibcFileIOFunctions));
808 CHECK(g_libc_xstat64);
809 return g_libc_xstat64(version, path, buf);
810 }
811 }
812
689 #endif // !CHROMIUM_SELINUX 813 #endif // !CHROMIUM_SELINUX
690 814
691 // This function triggers the static and lazy construction of objects that need 815 // This function triggers the static and lazy construction of objects that need
692 // to be created before imposing the sandbox. 816 // to be created before imposing the sandbox.
693 static void PreSandboxInit() { 817 static void PreSandboxInit() {
694 base::RandUint64(); 818 base::RandUint64();
695 819
696 base::SysInfo::MaxSharedMemorySize(); 820 base::SysInfo::MaxSharedMemorySize();
697 821
698 // ICU DateFormat class (used in base/time_format.cc) needs to get the 822 // 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."; 997 VLOG(1) << "Enabling experimental Seccomp sandbox.";
874 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp; 998 sandbox_flags |= ZygoteHostImpl::kSandboxSeccomp;
875 } 999 }
876 } 1000 }
877 #endif // SECCOMP_SANDBOX 1001 #endif // SECCOMP_SANDBOX
878 1002
879 Zygote zygote(sandbox_flags, forkdelegate); 1003 Zygote zygote(sandbox_flags, forkdelegate);
880 // This function call can return multiple times, once per fork(). 1004 // This function call can return multiple times, once per fork().
881 return zygote.ProcessRequests(); 1005 return zygote.ProcessRequests();
882 } 1006 }
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