-
Notifications
You must be signed in to change notification settings - Fork 25
WIP Implementation of peer credentials. #13
Conversation
Note: I've created a simple test to play with it. |
Stupid mistake. :D Anyway, I've tested it on macOS and it works! 🎉 Could you comment on the code and help with resolving the questions, please? |
unsafe { | ||
let raw_fd = sock.as_raw_fd(); | ||
|
||
let mut cred: super::UCred = mem::uninitialized(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this use zeroed
? Seems like there's no reason to use the unsafer version here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It could be. But I see no point. My reasoning is that the code is already unsafe
so I see no point in zeroing it. However, If you have good reason to do it, I'd probably go with explicit safe version (pid: 0, uid: 0, gid: 0
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's use zeroed
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why? Is that some kind of standard?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because I see no reason to use uninitialized
, please change it to zeroed
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant zeroed
instead of ucred { pid: 0, uid: 0, gid: 0 }
.
I guess that syscall only overwrites it, so the reason would be performance. I agree it's negligible, so I accept zeroig. I'm just interested to know whether there is some difference between using zeroed
and zeroing "manually".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nah those are the same. With libc I tend to use zeroed
because there's often random hidden fields or fields used for padding, but either way is fine in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, OK. I prefer "safe" version in this case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this be udpated to using UCred { ... }
?
src/lib.rs
Outdated
@@ -279,6 +282,12 @@ impl UnixStream { | |||
self.io.get_ref().peer_addr() | |||
} | |||
|
|||
/// Returns effective credentials of the process which called `connect` or `socketpair`. | |||
#[cfg(any(target_os = "linux", target_os = "macos"))] | |||
pub fn peer_cred(&self) -> io::Result<UCred> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could this be added via an extension trait if it's platform-specific?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking about it too. I'm not sure if Rust runs on any platform that has UnixStream
but no way of getting peer credentials. Solaris seems to have different implementation, but I have no machine to test it.
If I wanted to use a trait how to name it? LinuxAndMacPeerCredentials seems long to me. I wouldn't separate them provided there can be a common trait for both. (And I'm actually currently working on code that should be Linux/macOS.) On the other hand, Linux has possibility to provide pid too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think all other unices have an implementation of this function? If that's the case then this should just remove the #[cfg]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Digging into the topic more I found that:
- On Linux,
getsockopt
should be used - BSD families (including macOS) use
getpeereid
- Solaris uses
getpeerucred
I know of no other unix used in the wild with Rust.
So maybe we can just remove #[cfg]
. However, it'd be nice to implement this for Solaris too. But as I said, I have nothing to test it on.
Also, macos
cfg will have to be changed to #[cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd"))]
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This either needs to be ungated to cause compile failures on other platforms to necessitate an implementation, or it needs an extension trait. I don't mind which, but there's no middle between those tw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, I'll go with ungated. Gating pushes the compilation error to consumer, so there'd still be the error. If you have some explanation about why compile error in this crate is better than at consumer, I'm interested in learning it. (I personally don't mind using the one you choose.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't have a cfg here then we're claiming it's available on all unices, both in the code and in the documentation. At that point we need an assertion as such, which is to attempt to compile the code on all platforms.
src/ucred.rs
Outdated
use UnixStream; | ||
use std::os::unix::io::AsRawFd; | ||
|
||
use libc::ucred as UCred; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this avoid being renamed? It confused me when considering the outer one as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, I dislike having lower case types. So maybe LinuxUCred? Or RawUCred? CUCred?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's stick to the name already given to it by libc, ucred
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK.
I've updated the code as you requested. I tested it on Linux and it works. Will test on macOS tomorrow. |
Mind adding a test in this PR? That way it can be tested on Travis |
OK, do you think something like this would be fine? Possibly checking |
Sure! |
🎉 Anything else you would like? Do you think the documentation is sufficient? |
Nah looks good, thanks! |
I'm happy I helped. I've opened rust-lang/rust#42839 now. |
This implements peer credentials for
UnixStream
. Closes #12.This is WIP now. It contains only Linux implementation (macOS coming soon). I published it now so I can have it reviewed to avoid huge rewrite.
I decided to name the method
peer_cred
instead ofget_peer_cred
to be consistent with other methods (e.g.peer_addr
).The implementation is based on one I found in PostgreSQL.
Relevant SO question
I think this might be added to
std
and then forward it but I think it'd be nice to use this crate as a testing ground.Unresolved questions:
unsafe
code (it should be just syscall though, nothing complicated)Should I defineI found it. Fixed in e0da3a9.#[repr(C)] struct UCred
manually or should it be somehow auto-generated? I didn't find it inlibc
. (Maybe PR against `libc?)