diff options
author | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 12:01:44 +0000 |
---|---|---|
committer | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 12:01:44 +0000 |
commit | 8ec3fbec285daa194f6397b998b4c4bc0c1b2a37 (patch) | |
tree | 8e0d6acc844cf4780ae36435f56bbef69d35c043 /ipc/ipc_channel_posix.cc | |
parent | ffc44870db7ad9b179b27644c497e813221888e0 (diff) | |
download | chromium_src-8ec3fbec285daa194f6397b998b4c4bc0c1b2a37.zip chromium_src-8ec3fbec285daa194f6397b998b4c4bc0c1b2a37.tar.gz chromium_src-8ec3fbec285daa194f6397b998b4c4bc0c1b2a37.tar.bz2 |
Revert 80604 - Revert 80602 - Limit access to named IPC channels with SO_PEERCRED, not file permissions.BUG=TEST=Run Chrome & configure a service, to get the service process to start. Close Chrome and run a copy as a different user, but from the same user-data-dir. New Chrome should not be able to communicate with the service process.Review URL: http://codereview.chromium.org/6631002TBR=wez@chromium.orgReview URL: http://codereview.chromium.org/6806006
TBR=wez@chromium.org
Review URL: http://codereview.chromium.org/6806007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80606 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ipc/ipc_channel_posix.cc')
-rw-r--r-- | ipc/ipc_channel_posix.cc | 59 |
1 files changed, 46 insertions, 13 deletions
diff --git a/ipc/ipc_channel_posix.cc b/ipc/ipc_channel_posix.cc index d9156d7..22e4781 100644 --- a/ipc/ipc_channel_posix.cc +++ b/ipc/ipc_channel_posix.cc @@ -193,19 +193,6 @@ bool CreateServerUnixDomainSocket(const std::string& pipe_name, return false; } - // Explicitly set file system permissions on socket, mainly as a precaution - // for Chrome OS. - // Do not rely on these file permissions to provide security - the file is - // created during the above bind() call so there is still a window for - // malicious abuse because the file exists between bind() and chmod(). Also, - // the file permissions may not be enforced for unix sockets on all platforms. - if (chmod(pipe_name.c_str(), 0600)) { - PLOG(ERROR) << "chmod " << pipe_name; - if (HANDLE_EINTR(close(fd)) < 0) - PLOG(ERROR) << "close " << pipe_name; - return false; - } - // Start listening on the socket. const int listen_queue_length = 1; if (listen(fd, listen_queue_length) != 0) { @@ -938,6 +925,33 @@ bool Channel::ChannelImpl::HasAcceptedConnection() const { return AcceptsConnections() && pipe_ != -1; } +bool Channel::ChannelImpl::GetClientEuid(uid_t* client_euid) const { + DCHECK(HasAcceptedConnection()); +#if defined(OS_MACOSX) + uid_t peer_euid; + gid_t peer_gid; + if (getpeereid(pipe_, &peer_euid, &peer_gid) != 0) { + PLOG(ERROR) << "getpeereid " << pipe_; + return false; + } + *client_euid = peer_euid; + return true; +#else + struct ucred cred; + socklen_t cred_len = sizeof(cred); + if (getsockopt(pipe_, SOL_SOCKET, SO_PEERCRED, &cred, &cred_len) != 0) { + PLOG(ERROR) << "getsockopt " << pipe_; + return false; + } + if (cred_len < sizeof(cred)) { + NOTREACHED() << "Truncated ucred from SO_PEERCRED?"; + return false; + } + *client_euid = cred.uid; + return true; +#endif +} + void Channel::ChannelImpl::ResetToAcceptingConnectionState() { // Unregister libevent for the unix domain socket and close it. read_watcher_.StopWatchingFileDescriptor(); @@ -997,6 +1011,21 @@ void Channel::ChannelImpl::OnFileCanReadWithoutBlocking(int fd) { } pipe_ = new_pipe; + if ((mode_ & MODE_OPEN_ACCESS_FLAG) == 0) { + // Verify that the IPC channel peer is running as the same user. + uid_t client_euid; + if (!GetClientEuid(&client_euid)) { + LOG(ERROR) << "Unable to query client euid"; + ResetToAcceptingConnectionState(); + return; + } + if (client_euid != geteuid()) { + LOG(WARNING) << "Client euid is not authorised"; + ResetToAcceptingConnectionState(); + return; + } + } + if (!AcceptConnection()) { NOTREACHED() << "AcceptConnection should not fail on server"; } @@ -1161,6 +1190,10 @@ bool Channel::HasAcceptedConnection() const { return channel_impl_->HasAcceptedConnection(); } +bool Channel::GetClientEuid(uid_t* client_euid) const { + return channel_impl_->GetClientEuid(client_euid); +} + void Channel::ResetToAcceptingConnectionState() { channel_impl_->ResetToAcceptingConnectionState(); } |