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

Side by Side Diff: chrome/browser/renderer_host/render_sandbox_host_linux.cc

Issue 112074: Linux: Add support for chrooted renderers. (Closed)
Patch Set: Created 11 years, 6 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/renderer_host/render_sandbox_host_linux.h"
6
7 #include <stdint.h>
8 #include <unistd.h>
9 #include <sys/uio.h>
10 #include <sys/socket.h>
11 #include <sys/epoll.h>
12
13 #include "base/eintr_wrapper.h"
14 #include "base/process_util.h"
15 #include "base/logging.h"
16 #include "base/message_loop.h"
17
18 #include "SkFontHost_fontconfig_direct.h"
19 #include "SkFontHost_fontconfig_ipc.h"
20
21 // http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
22
23 // BEWARE: code in this file run across *processes* (not just threads).
24
25 // This code runs in a child process
26 class SandboxIPCProcess {
27 public:
28 // lifeline_fd: this is the read end of a pipe which the browser process
29 // holds the other end of. If the browser process dies, it's descriptors are
30 // closed and we will noticed an EOF on the pipe. That's our signal to exit.
31 // browser_socket: the 'browser's end of the sandbox IPC socketpair. From the
32 // point of view of the renderer's, it's talking to the browser but this
33 // object actually services the requests.
34 SandboxIPCProcess(int lifeline_fd, int browser_socket)
35 : lifeline_fd_(lifeline_fd),
36 browser_socket_(browser_socket),
37 font_config_(new FontConfigDirect()) {
38 base::InjectiveMultimap multimap;
39 multimap.push_back(base::InjectionArc(0, lifeline_fd, false));
40 multimap.push_back(base::InjectionArc(0, browser_socket, false));
41
42 base::CloseSuperfluousFds(multimap);
43 }
44
45 void Run() {
46 const int epollfd = epoll_create(2);
47 CHECK(epollfd >= 0);
48 struct epoll_event ev;
49
50 ev.events = EPOLLIN;
51 ev.data.fd = lifeline_fd_;
52 CHECK(0 == epoll_ctl(epollfd, EPOLL_CTL_ADD, lifeline_fd_, &ev));
53
54 ev.events = EPOLLIN;
55 ev.data.fd = browser_socket_;
56 CHECK(0 == epoll_ctl(epollfd, EPOLL_CTL_ADD, browser_socket_, &ev));
57
58 for (;;) {
59 CHECK(1 == HANDLE_EINTR(epoll_wait(epollfd, &ev, 1, -1)));
60 if (ev.data.fd == lifeline_fd_) {
61 // our parent died so we should too.
62 _exit(0);
63 } else {
64 CHECK(ev.data.fd == browser_socket_);
65 HandleRequest(browser_socket_);
66 }
67 }
68 }
69
70 void HandleRequest(int fd) {
71 struct msghdr msg = {0};
72 struct iovec iov;
73 uint8_t buf[1024];
74 uint8_t control_buf[CMSG_SPACE(sizeof(int))];
75 iov.iov_base = buf;
76 iov.iov_len = sizeof(buf);
77 msg.msg_iov = &iov;
78 msg.msg_iovlen = 1;
79 msg.msg_control = control_buf;
80 msg.msg_controllen = sizeof(control_buf);
81
82 const ssize_t n = HANDLE_EINTR(recvmsg(fd, &msg, 0));
83
84 if (n < 1) {
85 LOG(ERROR) << "Error reading from sandbox IPC socket. Sandbox IPC is"
86 << " disabled."
87 << " n:" << n
88 << " errno:" << errno;
89 _exit(1);
90 return;
91 }
92
93 if (msg.msg_controllen != sizeof(control_buf) ||
94 n < static_cast<ssize_t>(sizeof(uint16_t)) ||
95 msg.msg_flags) {
96 LOG(ERROR) << "Sandbox IPC: missing control message or truncated message:"
97 << " n:" << n
98 << " msg.msg_controllen:" << msg.msg_controllen
99 << " msg.msg_flags:" << msg.msg_flags;
100 return;
101 }
102
103 // Get the reply socket from the control message
104 int reply_fd = -1;
105 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
106 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
107 // The client cannot send us additional descriptors because the control
108 // message buffer is only sized for a single int.
109 reply_fd = *reinterpret_cast<int*>(CMSG_DATA(cmsg));
110 } else {
111 LOG(ERROR) << "Sandbox IPC: message without reply descriptor:"
112 << " n:" << n
113 << " msg.msg_controllen:" << msg.msg_controllen
114 << " cmsg->cmsg_level:" << cmsg->cmsg_level
115 << " cmsg->cmsg_type:" << cmsg->cmsg_type;
116 return;
117 }
118
119 const uint16_t request_type = *reinterpret_cast<uint16_t*>(buf);
120 switch (request_type) {
121 case FontConfigIPC::METHOD_MATCH:
122 return FontConfigMatch(reply_fd, buf, n);
123 case FontConfigIPC::METHOD_OPEN:
124 return FontConfigOpen(reply_fd, buf, n);
125 default:
126 LOG(ERROR) << "Sandbox IPC: message with unknown type:"
127 << " request_type:" << request_type;
128 HANDLE_EINTR(close(reply_fd));
129 }
130 }
131
132 // Send a reply to a client
133 // reply_fd: the reply channel given to us by the client
134 // iov, iov_len: the contents of the reply message
135 // extra_fd: an fd to include in the reply, or -1
136 //
137 // Both reply_fd and extra_fd (if any) are closed.
138 void SendReplyAndClose(int reply_fd, const struct iovec* iov,
139 unsigned iov_len, int extra_fd) {
140 struct msghdr msg = {0};
141 msg.msg_iov = const_cast<struct iovec*>(iov);
142 msg.msg_iovlen = iov_len;
143
144 uint8_t control_buf[CMSG_SPACE(sizeof(int))];
145
146 if (extra_fd >= 0) {
147 msg.msg_control = control_buf;
148 msg.msg_controllen = sizeof(control_buf);
149
150 struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
151 cmsg->cmsg_level = SOL_SOCKET;
152 cmsg->cmsg_type = SCM_RIGHTS;
153 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
154 *reinterpret_cast<int*>(CMSG_DATA(cmsg)) = extra_fd;
155 }
156
157 HANDLE_EINTR(sendmsg(reply_fd, &msg, MSG_NOSIGNAL | MSG_DONTWAIT));
158 HANDLE_EINTR(close(reply_fd));
159 if (extra_fd >= 0)
160 HANDLE_EINTR(close(extra_fd));
161 }
162
163 void FontConfigMatch(int reply_fd, const uint8_t* request_bytes,
164 unsigned request_len) {
165 if (request_len < sizeof(FontConfigIPC::MatchRequest))
166 return (void) HANDLE_EINTR(close(reply_fd));
167
168 const FontConfigIPC::MatchRequest* request =
169 reinterpret_cast<const FontConfigIPC::MatchRequest*>(request_bytes);
170
171 if (request_len != sizeof(FontConfigIPC::MatchRequest) + request->family_len )
172 return (void) HANDLE_EINTR(close(reply_fd));
173
174 const std::string family(
175 reinterpret_cast<const char*>(request_bytes + sizeof(*request)),
176 request->family_len);
177 std::string result_family;
178 unsigned result_fileid;
179
180 const bool r = font_config_->Match(
181 &result_family, &result_fileid, request->fileid_valid, request->fileid,
182 family, request->is_bold, request->is_italic);
183
184 struct iovec iov[2];
185 FontConfigIPC::MatchReply reply;
186 memset(&reply, 0, sizeof(reply));
187
188 iov[0].iov_base = &reply;
189 iov[0].iov_len = sizeof(reply);
190
191 if (r) {
192 reply.result = 1;
193 reply.result_fileid = result_fileid;
194 reply.filename_len = result_family.size();
195
196 iov[1].iov_base = const_cast<char*>(result_family.data());
197 iov[1].iov_len = result_family.size();
198 }
199
200 SendReplyAndClose(reply_fd, iov, r ? 2 : 1, -1 /* no fd */);
201 }
202
203 void FontConfigOpen(int reply_fd, const uint8_t* request_bytes,
204 unsigned request_len) {
205 if (request_len < sizeof(FontConfigIPC::OpenRequest))
206 return (void) HANDLE_EINTR(close(reply_fd));
207
208 const FontConfigIPC::OpenRequest* request =
209 reinterpret_cast<const FontConfigIPC::OpenRequest*>(request_bytes);
210
211 FontConfigDirect* fc = reinterpret_cast<FontConfigDirect*>(font_config_);
212
213 const int result_fd = fc->Open(request->fileid);
214
215 FontConfigIPC::OpenReply reply;
216 reply.result = result_fd >= 0 ? 1 : 0;
217
218 struct iovec iov;
219 iov.iov_base = &reply;
220 iov.iov_len = sizeof(reply);
221
222 SendReplyAndClose(reply_fd, &iov, 1, result_fd);
223 }
224
225 private:
226 const int lifeline_fd_;
227 const int browser_socket_;
228 FontConfigDirect* const font_config_;
229 };
230
231 // -----------------------------------------------------------------------------
232
233 // Runs on the main thread at startup.
234 RenderSandboxHostLinux::RenderSandboxHostLinux() {
235 int fds[2];
236 CHECK(socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) == 0);
237
238 renderer_socket_ = fds[0];
239 const int browser_socket = fds[1];
240
241 int pipefds[2];
242 CHECK(0 == pipe(pipefds));
243 const int child_lifeline_fd = pipefds[0];
244 childs_lifeline_fd_ = pipefds[1];
245
246 const pid_t child = fork();
247 if (child == 0) {
248 SandboxIPCProcess handler(child_lifeline_fd, browser_socket);
249 handler.Run();
250 _exit(0);
251 }
252 }
253
254 RenderSandboxHostLinux::~RenderSandboxHostLinux() {
255 HANDLE_EINTR(close(renderer_socket_));
256 HANDLE_EINTR(close(childs_lifeline_fd_));
257 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698