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

Side by Side Diff: chrome/browser/process_singleton_posix.cc

Issue 2811173003: ProcessSingletonPosix: don't CHECK if trying to connect to existing process with too long socket sy… (Closed)
Patch Set: Created 3 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
« no previous file with comments | « no previous file | chrome/browser/process_singleton_posix_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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 // On Linux, when the user tries to launch a second copy of chrome, we check 5 // On Linux, when the user tries to launch a second copy of chrome, we check
6 // for a socket in the user's profile directory. If the socket file is open we 6 // for a socket in the user's profile directory. If the socket file is open we
7 // send a message to the first chrome browser process with the current 7 // send a message to the first chrome browser process with the current
8 // directory and second process command line flags. The second process then 8 // directory and second process command line flags. The second process then
9 // exits. 9 // exits.
10 // 10 //
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
211 return bytes_read; 211 return bytes_read;
212 } else { 212 } else {
213 bytes_read += rv; 213 bytes_read += rv;
214 } 214 }
215 } while (bytes_read < bufsize); 215 } while (bytes_read < bufsize);
216 216
217 return bytes_read; 217 return bytes_read;
218 } 218 }
219 219
220 // Set up a sockaddr appropriate for messaging. 220 // Set up a sockaddr appropriate for messaging.
221 void SetupSockAddr(const std::string& path, struct sockaddr_un* addr) { 221 bool SetupSockAddr(const std::string& path, struct sockaddr_un* addr) {
222 addr->sun_family = AF_UNIX; 222 addr->sun_family = AF_UNIX;
223 CHECK(path.length() < arraysize(addr->sun_path)) 223 if (path.length() >= arraysize(addr->sun_path))
224 << "Socket path too long: " << path; 224 return false;
225 base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path)); 225 base::strlcpy(addr->sun_path, path.c_str(), arraysize(addr->sun_path));
226 return true;
226 } 227 }
227 228
228 // Set up a socket appropriate for messaging. 229 // Set up a socket appropriate for messaging.
229 int SetupSocketOnly() { 230 int SetupSocketOnly() {
230 int sock = socket(PF_UNIX, SOCK_STREAM, 0); 231 int sock = socket(PF_UNIX, SOCK_STREAM, 0);
231 PCHECK(sock >= 0) << "socket() failed"; 232 PCHECK(sock >= 0) << "socket() failed";
232 233
233 DCHECK(base::SetNonBlocking(sock)) << "Failed to make non-blocking socket."; 234 DCHECK(base::SetNonBlocking(sock)) << "Failed to make non-blocking socket.";
234 int rv = SetCloseOnExec(sock); 235 int rv = SetCloseOnExec(sock);
235 DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket."; 236 DCHECK_EQ(0, rv) << "Failed to set CLOEXEC on socket.";
236 237
237 return sock; 238 return sock;
238 } 239 }
239 240
240 // Set up a socket and sockaddr appropriate for messaging. 241 // Set up a socket and sockaddr appropriate for messaging.
241 void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) { 242 void SetupSocket(const std::string& path, int* sock, struct sockaddr_un* addr) {
242 *sock = SetupSocketOnly(); 243 *sock = SetupSocketOnly();
243 SetupSockAddr(path, addr); 244 CHECK(SetupSockAddr(path, addr)) << "Socket path too long: " << path;
244 } 245 }
245 246
246 // Read a symbolic link, return empty string if given path is not a symbol link. 247 // Read a symbolic link, return empty string if given path is not a symbol link.
247 base::FilePath ReadLink(const base::FilePath& path) { 248 base::FilePath ReadLink(const base::FilePath& path) {
248 base::FilePath target; 249 base::FilePath target;
249 if (!base::ReadSymbolicLink(path, &target)) { 250 if (!base::ReadSymbolicLink(path, &target)) {
250 // The only errno that should occur is ENOENT. 251 // The only errno that should occur is ENOENT.
251 if (errno != 0 && errno != ENOENT) 252 if (errno != 0 && errno != ENOENT)
252 PLOG(ERROR) << "readlink(" << path.value() << ") failed"; 253 PLOG(ERROR) << "readlink(" << path.value() << ") failed";
253 } 254 }
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
379 if (cookie.empty()) 380 if (cookie.empty())
380 return false; 381 return false;
381 base::FilePath remote_cookie = socket_target.DirName(). 382 base::FilePath remote_cookie = socket_target.DirName().
382 Append(chrome::kSingletonCookieFilename); 383 Append(chrome::kSingletonCookieFilename);
383 // Verify the cookie before connecting. 384 // Verify the cookie before connecting.
384 if (!CheckCookie(remote_cookie, cookie)) 385 if (!CheckCookie(remote_cookie, cookie))
385 return false; 386 return false;
386 // Now we know the directory was (at that point) created by the profile 387 // Now we know the directory was (at that point) created by the profile
387 // owner. Try to connect. 388 // owner. Try to connect.
388 sockaddr_un addr; 389 sockaddr_un addr;
389 SetupSockAddr(socket_target.value(), &addr); 390 if (!SetupSockAddr(socket_target.value(), &addr))
391 return false;
390 int ret = HANDLE_EINTR(connect(socket->fd(), 392 int ret = HANDLE_EINTR(connect(socket->fd(),
391 reinterpret_cast<sockaddr*>(&addr), 393 reinterpret_cast<sockaddr*>(&addr),
392 sizeof(addr))); 394 sizeof(addr)));
393 if (ret != 0) 395 if (ret != 0)
394 return false; 396 return false;
395 // Check the cookie again. We only link in /tmp, which is sticky, so, if the 397 // Check the cookie again. We only link in /tmp, which is sticky, so, if the
396 // directory is still correct, it must have been correct in-between when we 398 // directory is still correct, it must have been correct in-between when we
397 // connected. POSIX, sadly, lacks a connectat(). 399 // connected. POSIX, sadly, lacks a connectat().
398 if (!CheckCookie(remote_cookie, cookie)) { 400 if (!CheckCookie(remote_cookie, cookie)) {
399 socket->Reset(); 401 socket->Reset();
400 return false; 402 return false;
401 } 403 }
402 // Success! 404 // Success!
403 return true; 405 return true;
404 } else if (errno == EINVAL) { 406 } else if (errno == EINVAL) {
405 // It exists, but is not a symlink (or some other error we detect 407 // It exists, but is not a symlink (or some other error we detect
406 // later). Just connect to it directly; this is an older version of Chrome. 408 // later). Just connect to it directly; this is an older version of Chrome.
407 sockaddr_un addr; 409 sockaddr_un addr;
408 SetupSockAddr(socket_path.value(), &addr); 410 if (!SetupSockAddr(socket_path.value(), &addr))
411 return false;
409 int ret = HANDLE_EINTR(connect(socket->fd(), 412 int ret = HANDLE_EINTR(connect(socket->fd(),
410 reinterpret_cast<sockaddr*>(&addr), 413 reinterpret_cast<sockaddr*>(&addr),
411 sizeof(addr))); 414 sizeof(addr)));
412 return (ret == 0); 415 return (ret == 0);
413 } else { 416 } else {
414 // File is missing, or other error. 417 // File is missing, or other error.
415 if (errno != ENOENT) 418 if (errno != ENOENT)
416 PLOG(ERROR) << "readlink failed"; 419 PLOG(ERROR) << "readlink failed";
417 return false; 420 return false;
418 } 421 }
(...skipping 556 matching lines...) Expand 10 before | Expand all | Expand 10 after
975 LOG(ERROR) << "Failed to create socket directory."; 978 LOG(ERROR) << "Failed to create socket directory.";
976 return false; 979 return false;
977 } 980 }
978 981
979 // Check that the directory was created with the correct permissions. 982 // Check that the directory was created with the correct permissions.
980 int dir_mode = 0; 983 int dir_mode = 0;
981 CHECK(base::GetPosixFilePermissions(socket_dir_.GetPath(), &dir_mode) && 984 CHECK(base::GetPosixFilePermissions(socket_dir_.GetPath(), &dir_mode) &&
982 dir_mode == base::FILE_PERMISSION_USER_MASK) 985 dir_mode == base::FILE_PERMISSION_USER_MASK)
983 << "Temp directory mode is not 700: " << std::oct << dir_mode; 986 << "Temp directory mode is not 700: " << std::oct << dir_mode;
984 987
985 // Setup the socket symlink and the two cookies. 988 // Create the socket before creating the symlink, so that if the create fails
989 // a dangling link isn't left behind.
986 base::FilePath socket_target_path = 990 base::FilePath socket_target_path =
987 socket_dir_.GetPath().Append(chrome::kSingletonSocketFilename); 991 socket_dir_.GetPath().Append(chrome::kSingletonSocketFilename);
992 SetupSocket(socket_target_path.value(), &sock, &addr);
Nico 2017/04/13 15:54:36 add comment why it's ok if this returns false
mattm 2017/04/13 20:15:27 This one can't return false (SetupSocket does a CH
993
994 // Setup the socket symlink and the two cookies.
988 base::FilePath cookie(GenerateCookie()); 995 base::FilePath cookie(GenerateCookie());
989 base::FilePath remote_cookie_path = 996 base::FilePath remote_cookie_path =
990 socket_dir_.GetPath().Append(chrome::kSingletonCookieFilename); 997 socket_dir_.GetPath().Append(chrome::kSingletonCookieFilename);
991 UnlinkPath(socket_path_); 998 UnlinkPath(socket_path_);
992 UnlinkPath(cookie_path_); 999 UnlinkPath(cookie_path_);
993 if (!SymlinkPath(socket_target_path, socket_path_) || 1000 if (!SymlinkPath(socket_target_path, socket_path_) ||
994 !SymlinkPath(cookie, cookie_path_) || 1001 !SymlinkPath(cookie, cookie_path_) ||
995 !SymlinkPath(cookie, remote_cookie_path)) { 1002 !SymlinkPath(cookie, remote_cookie_path)) {
996 // We've already locked things, so we can't have lost the startup race, 1003 // We've already locked things, so we can't have lost the startup race,
997 // but something doesn't like us. 1004 // but something doesn't like us.
998 LOG(ERROR) << "Failed to create symlinks."; 1005 LOG(ERROR) << "Failed to create symlinks.";
999 if (!socket_dir_.Delete()) 1006 if (!socket_dir_.Delete())
1000 LOG(ERROR) << "Encountered a problem when deleting socket directory."; 1007 LOG(ERROR) << "Encountered a problem when deleting socket directory.";
1001 return false; 1008 return false;
1002 } 1009 }
1003 1010
1004 SetupSocket(socket_target_path.value(), &sock, &addr);
1005
1006 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) { 1011 if (bind(sock, reinterpret_cast<sockaddr*>(&addr), sizeof(addr)) < 0) {
1007 PLOG(ERROR) << "Failed to bind() " << socket_target_path.value(); 1012 PLOG(ERROR) << "Failed to bind() " << socket_target_path.value();
1008 CloseSocket(sock); 1013 CloseSocket(sock);
1009 return false; 1014 return false;
1010 } 1015 }
1011 1016
1012 if (listen(sock, 5) < 0) 1017 if (listen(sock, 5) < 0)
1013 NOTREACHED() << "listen failed: " << base::safe_strerror(errno); 1018 NOTREACHED() << "listen failed: " << base::safe_strerror(errno);
1014 1019
1015 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO)); 1020 DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO));
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1064 } 1069 }
1065 1070
1066 void ProcessSingleton::KillProcess(int pid) { 1071 void ProcessSingleton::KillProcess(int pid) {
1067 // TODO(james.su@gmail.com): Is SIGKILL ok? 1072 // TODO(james.su@gmail.com): Is SIGKILL ok?
1068 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL); 1073 int rv = kill(static_cast<base::ProcessHandle>(pid), SIGKILL);
1069 // ESRCH = No Such Process (can happen if the other process is already in 1074 // ESRCH = No Such Process (can happen if the other process is already in
1070 // progress of shutting down and finishes before we try to kill it). 1075 // progress of shutting down and finishes before we try to kill it).
1071 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: " 1076 DCHECK(rv == 0 || errno == ESRCH) << "Error killing process: "
1072 << base::safe_strerror(errno); 1077 << base::safe_strerror(errno);
1073 } 1078 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/process_singleton_posix_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698