diff options
author | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 11:07:13 +0000 |
---|---|---|
committer | wez@chromium.org <wez@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 11:07:13 +0000 |
commit | 464c1e2dc81262c924391affc940a2e122132091 (patch) | |
tree | bc123ebf596bf1dc2d24d6871ac64455a2bbd86a /ipc/ipc_channel_posix.cc | |
parent | 08a62b874cbc45d9b6f9854cd0a11be0662e77e8 (diff) | |
download | chromium_src-464c1e2dc81262c924391affc940a2e122132091.zip chromium_src-464c1e2dc81262c924391affc940a2e122132091.tar.gz chromium_src-464c1e2dc81262c924391affc940a2e122132091.tar.bz2 |
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/6631002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80602 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(); } |