This patch changes FdReceiver to create pathname socket in user's runtime directory and receive file descriptor only
from a root owned process.
Issues mentioned in here : https://mail.kde.org/pipermail/kde-frameworks-devel/2018-January/055307.html
thiago | |
dfaure | |
ossi | |
fvogt |
Frameworks |
This patch changes FdReceiver to create pathname socket in user's runtime directory and receive file descriptor only
from a root owned process.
Issues mentioned in here : https://mail.kde.org/pipermail/kde-frameworks-devel/2018-January/055307.html
No Linters Available |
No Unit Test Coverage |
1.Check for overflow condition. In such case file operation will terminate.
2.Return actual length of buffer
3.Use QStandardPaths::RuntimeLocation for socket creation
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
48 | Missing ::close(m_socketDes); m_socketDes = -1; or just move it above the m_socketDes assignment. | |
62 | A quick question: Is it possible that there are two FdReceivers with the same pid? | |
src/ioslaves/file/file_unix.cpp | ||
92 | That looks like a hack. If errno is that important, save and keep it in a variable. Every call into a library can change errno, it's extremely volatile. | |
src/ioslaves/file/sharefd_p.h | ||
53 | Just a suggestion: Remove error() and just return nullptr in address() in the error case. | |
62 | The socket permissions only work that way for linux, so if other OSs can use this code as well it's insecure and should #error out. |
1.Return nullptr when address() is called for an invalid socket path
2.Create SocketAddress object before socket .
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
62 | No. Currently only one FdReceiver is created. | |
src/ioslaves/file/file_unix.cpp | ||
92 | It is the only case for which this hack seems necessary. For all other cases a library call (to perform a file operation) is immediately followed by a call to helper. IMO the chances of errno changing to something unrelated in between these two calls are very slim (is it even possible?) | |
src/ioslaves/file/sharefd_p.h | ||
62 | I didn't follow you here. Can you explain why working of this code on other OSs, specifically FreeBsd and OSX, will be insecure? |
src/ioslaves/file/file_unix.cpp | ||
---|---|---|
92 | I don't see how this could ever work. Even the line immediately below errno = err can change errno. | |
src/ioslaves/file/sharefd_p.h | ||
62 | Look at man 7 unix, section Pathname socket ownership and permissions. |
src/ioslaves/file/file_unix.cpp | ||
---|---|---|
111 | @fvogt I think the errno assignment should be fine here? | |
src/ioslaves/file/sharefd_p.h | ||
62 | I see, it mentions some BSD-derived system ignore read/write permissions on socket file. But in FreeBSD documentation it clearly specifies destination of connect() should be writable. |
src/ioslaves/file/file_unix.cpp | ||
---|---|---|
111 | This looks very much like code smell. Currently you treat errno as a hidden function parameter. | |
src/ioslaves/file/sharefd_p.h | ||
62 | If that is the case you can do something like: #if !defined(__linux__) && !defined(__FreeBSD__) #error No secure implementation available #endif |
Changed parameters of
execWithElevatedPrivileges(), tryChangeAttr() : now they accept action type, list of arguments and error code.
tryOpen(): accepts error code as an additional parameter.
@dfaure please have a look at it.
Almost done!
I just noticed some small issues with reading errno after calling execWithElevatedPrivileges(...) (I only left a single comment, the other places are basically identical)
src/ioslaves/file/file.cpp | ||
---|---|---|
239 | errno might not be the expected value anymore. | |
src/ioslaves/file/sharefd_p.h | ||
47 | Not on most platforms, but man unix says for portability: offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1```. | |
62 | Fair enough. |
I don't feel confident approving the security-related fixes in here. Maybe Thiago or Oswald could have a look...
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
61 ↗ | (On Diff #26045) | This will break if the path contains non-ascii characters. Either use QFile::remove, or use a QByteArray (or std::string) everywhere to avoid a conversion from 16-bit to 8-bit, or third option, do the conversion properly here, using QFile::encodeName(m_path). |
src/ioslaves/file/sharefd_p.h | ||
51 ↗ | (On Diff #26045) | Is strlen needed? It seems to me that sun_path will be null if make_address failed, so a simple null-pointer check would be enough here. Plus I remember some implementations of strlen breaking on null pointers... |
Thiago, Ossi, looks ok to you too?
(Tagging tomorrow...)
src/ioslaves/file/sharefd_p.h | ||
---|---|---|
51 ↗ | (On Diff #26045) | Looks good. My own comment was partly nonsense, I see now (sun_path can't be a null pointer). But still this change is for the better, it makes it faster. |
Why do you ask for a rewview then not wait for the review?
Belated -1. No actual review of the change done, because I can't tell what you've done.
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
33 ↗ | (On Diff #26045) | Don't use toStdString(). I know this is what it used to do, but you can take the opportunity to fix the issue. |
87 ↗ | (On Diff #26045) | Where's the support for other OSes? |
src/ioslaves/file/fdreceiver.h | ||
45 ↗ | (On Diff #26045) | Nitpick: always sort your members by size. |
src/ioslaves/file/file.h | ||
106–107 ↗ | (On Diff #26045) | This change should be in a separate commit. I can't tell what you're doing specifically to fix the bug with so much noise in this commit. |
Thiago: thanks for the review. You didn't say anything about the getsockopt/getpeereid usage so I assume this part looks ok? That's mostly what I wanted you to look at.
The early push was so we don't release 5.43 (planned for today) without this security fix at all, in case of no answer...
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
33 ↗ | (On Diff #26045) | Right, this should be QFile::encodeName(m_path) and using QByteArray in SocketAddress rather than std::string. |
87 ↗ | (On Diff #26045) | This is UNIX-only, but indeed OSX is missing. Does that support getpeereid? |
Timing is not that important. As long as the other issues mentioned in the mail are not fixed, this shouldn't get re-enabled.
src/ioslaves/file/file.h | ||
---|---|---|
106–107 ↗ | (On Diff #26045) | The fixes in this commit uncovered a design issue in the code which this fixes. |
if he wants to look past the already pointed out non-atomicity. i for one just refuse to look at this mess any further.
https://community.kde.org/Policies/Commit_Policy#Commit_complete_changesets (i find https://wiki.qt.io/Commit_Policy point 8 clearer (yeah, i wrote it down myself ^^))
Right, the port to QByteArray could be splitted out of this socket security fix commit.
Moved changes related to SocketAddress to D10273.
Changed #error to #warning. So even if an OS does not have getpeereid or getsockopt compilation will still succeed but copying files will result in an error.
The patch that I can see accomplishes what the description says it should do. And I agree with the idea of the patch.
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
87 ↗ | (On Diff #26045) | APPLE is there. My question is about OpenBSD, NetBSD and DragonflyBSD. Are you breaking them? You may not know the answer, but you need to document the issue if you intentionally cause a Failure To Build From Sources. |
src/ioslaves/file/fdreceiver.cpp | ||
---|---|---|
87 ↗ | (On Diff #26045) | I have replaced #error with #warning |
this dependency tree is a mess. please remove deps to abandoned changes or unabandon what you actually still need, and linearize the history.