OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "sandbox/linux/services/libc_urandom_override.h" | |
6 | |
7 #include <dlfcn.h> | |
8 #include <pthread.h> | |
9 #include <stdio.h> | |
10 #include <sys/stat.h> | |
11 | |
12 #include "base/eintr_wrapper.h" | |
13 #include "base/logging.h" | |
14 #include "base/rand_util.h" | |
15 | |
16 // Note: this file is used by the zygote and nacl_helper. | |
17 | |
18 namespace sandbox { | |
19 | |
20 // With SELinux we can carve out a precise sandbox, so we don't have to play | |
21 // with intercepting libc calls. | |
22 #if !defined(CHROMIUM_SELINUX) | |
23 | |
24 static bool g_override_urandom = false; | |
25 | |
26 void InitLibcUrandomOverrides() { | |
27 base::RandUint64(); | |
jln (very slow on Chromium)
2012/07/12 19:19:05
Should this be base::GetUrandomFD() instead ? I do
Nick Bray (chromium)
2012/07/12 21:42:49
I did the change you suggested.
I was conflicted
jln (very slow on Chromium)
2012/07/13 00:06:24
In practice it won't matter because the "full warm
| |
28 g_override_urandom = true; | |
29 } | |
30 | |
31 // TODO(sergeyu): Currently this code doesn't work properly under ASAN | |
32 // - it crashes content_unittests. Make sure it works properly and | |
33 // enable it here. http://crbug.com/123263 | |
34 #if !defined(ADDRESS_SANITIZER) | |
35 | |
36 static const char kUrandomDevPath[] = "/dev/urandom"; | |
37 | |
38 typedef FILE* (*FopenFunction)(const char* path, const char* mode); | |
39 typedef int (*XstatFunction)(int version, const char *path, struct stat *buf); | |
40 typedef int (*Xstat64Function)(int version, const char *path, | |
41 struct stat64 *buf); | |
42 | |
43 static pthread_once_t g_libc_file_io_funcs_guard = PTHREAD_ONCE_INIT; | |
44 static FopenFunction g_libc_fopen; | |
45 static FopenFunction g_libc_fopen64; | |
46 static XstatFunction g_libc_xstat; | |
47 static Xstat64Function g_libc_xstat64; | |
48 | |
49 static void InitLibcFileIOFunctions() { | |
50 g_libc_fopen = reinterpret_cast<FopenFunction>( | |
51 dlsym(RTLD_NEXT, "fopen")); | |
52 g_libc_fopen64 = reinterpret_cast<FopenFunction>( | |
53 dlsym(RTLD_NEXT, "fopen64")); | |
54 | |
55 if (!g_libc_fopen) { | |
56 LOG(FATAL) << "Failed to get fopen() from libc."; | |
57 } else if (!g_libc_fopen64) { | |
58 #if !defined(OS_OPENBSD) && !defined(OS_FREEBSD) | |
59 LOG(WARNING) << "Failed to get fopen64() from libc. Using fopen() instead."; | |
60 #endif // !defined(OS_OPENBSD) && !defined(OS_FREEBSD) | |
61 g_libc_fopen64 = g_libc_fopen; | |
62 } | |
63 | |
64 // TODO(sergeyu): This works only on systems with glibc. Fix it to | |
65 // work properly on other systems if necessary. | |
66 g_libc_xstat = reinterpret_cast<XstatFunction>( | |
67 dlsym(RTLD_NEXT, "__xstat")); | |
68 g_libc_xstat64 = reinterpret_cast<Xstat64Function>( | |
69 dlsym(RTLD_NEXT, "__xstat64")); | |
70 | |
71 if (!g_libc_xstat) { | |
72 LOG(FATAL) << "Failed to get __xstat() from libc."; | |
73 } | |
74 if (!g_libc_xstat64) { | |
75 LOG(WARNING) << "Failed to get __xstat64() from libc."; | |
76 } | |
77 } | |
78 | |
79 // fopen() and fopen64() are intercepted here so that NSS can open | |
80 // /dev/urandom to seed its random number generator. NSS is used by | |
81 // remoting in the sendbox. | |
82 | |
83 // fopen() call may be redirected to fopen64() in stdio.h using | |
84 // __REDIRECT(), which sets asm name for fopen() to "fopen64". This | |
85 // means that we cannot override fopen() directly here. Instead the | |
86 // the code below defines fopen_override() function with asm name | |
87 // "fopen", so that all references to fopen() will resolve to this | |
88 // function. | |
89 __attribute__ ((__visibility__("default"))) | |
90 FILE* fopen_override(const char* path, const char* mode) __asm__ ("fopen"); | |
91 | |
92 __attribute__ ((__visibility__("default"))) | |
93 FILE* fopen_override(const char* path, const char* mode) { | |
94 if (g_override_urandom && strcmp(path, kUrandomDevPath) == 0) { | |
95 int fd = HANDLE_EINTR(dup(base::GetUrandomFD())); | |
96 if (fd < 0) { | |
97 PLOG(ERROR) << "dup() failed."; | |
98 return NULL; | |
99 } | |
100 return fdopen(fd, mode); | |
101 } else { | |
102 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard, | |
103 InitLibcFileIOFunctions)); | |
104 return g_libc_fopen(path, mode); | |
105 } | |
106 } | |
107 | |
108 __attribute__ ((__visibility__("default"))) | |
109 FILE* fopen64(const char* path, const char* mode) { | |
110 if (g_override_urandom && strcmp(path, kUrandomDevPath) == 0) { | |
111 int fd = HANDLE_EINTR(dup(base::GetUrandomFD())); | |
112 if (fd < 0) { | |
113 PLOG(ERROR) << "dup() failed."; | |
114 return NULL; | |
115 } | |
116 return fdopen(fd, mode); | |
117 } else { | |
118 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard, | |
119 InitLibcFileIOFunctions)); | |
120 return g_libc_fopen64(path, mode); | |
121 } | |
122 } | |
123 | |
124 // stat() is subject to the same problem as fopen(), so we have to use | |
125 // the same trick to override it. | |
126 __attribute__ ((__visibility__("default"))) | |
127 int xstat_override(int version, | |
128 const char *path, | |
129 struct stat *buf) __asm__ ("__xstat"); | |
130 | |
131 __attribute__ ((__visibility__("default"))) | |
132 int xstat_override(int version, const char *path, struct stat *buf) { | |
133 if (g_override_urandom && strcmp(path, kUrandomDevPath) == 0) { | |
134 int result = __fxstat(version, base::GetUrandomFD(), buf); | |
135 return result; | |
136 } else { | |
137 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard, | |
138 InitLibcFileIOFunctions)); | |
139 return g_libc_xstat(version, path, buf); | |
140 } | |
141 } | |
142 | |
143 __attribute__ ((__visibility__("default"))) | |
144 int xstat64_override(int version, | |
145 const char *path, | |
146 struct stat64 *buf) __asm__ ("__xstat64"); | |
147 | |
148 __attribute__ ((__visibility__("default"))) | |
149 int xstat64_override(int version, const char *path, struct stat64 *buf) { | |
150 if (g_override_urandom && strcmp(path, kUrandomDevPath) == 0) { | |
151 int result = __fxstat64(version, base::GetUrandomFD(), buf); | |
152 return result; | |
153 } else { | |
154 CHECK_EQ(0, pthread_once(&g_libc_file_io_funcs_guard, | |
155 InitLibcFileIOFunctions)); | |
156 CHECK(g_libc_xstat64); | |
157 return g_libc_xstat64(version, path, buf); | |
158 } | |
159 } | |
160 | |
161 #endif // !ADDRESS_SANITIZER | |
162 | |
163 #endif // !CHROMIUM_SELINUX | |
164 | |
165 } // namespace content | |
OLD | NEW |