Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No longer able to create an unnamed UnixAddr as of nix 23.0 #1585

Closed
stevenengler opened this issue Oct 27, 2021 · 5 comments · Fixed by #1857
Closed

No longer able to create an unnamed UnixAddr as of nix 23.0 #1585

stevenengler opened this issue Oct 27, 2021 · 5 comments · Fixed by #1857

Comments

@stevenengler
Copy link
Contributor

It seems that the UnixAddr type no longer provides a way to generate an unnamed unix address (a unix address with an addrlen of 2, or UnixAddrKind::Unnamed). This used to be possible in nix 22.0 when the internal struct fields were public.

@asomers
Copy link
Member

asomers commented Oct 27, 2021

Do you mean an abstract socket? What about https://docs.rs/nix/0.23.0/nix/sys/socket/struct.UnixAddr.html#method.new_abstract ?

@stevenengler
Copy link
Contributor Author

No, an abstract socket implies that it is bound in the abstract namespace, and has a length >= 3. The new_abstract method always adds at least one empty byte to the address name, so new_abstract(&[]) returns an address with a length of 3. An unnamed unix socket is not bound to any address and should have a length of 2 for the 2 bytes of the u16 address family.

unix(7) can probably explain it better than me:

unnamed: A stream socket that has not been bound to a pathname using bind(2) has no name. Likewise, the two sockets created by socketpair(2) are unnamed. When the address of an unnamed socket is returned, its length is sizeof(sa_family_t), and sun_path should not be inspected.

@asomers
Copy link
Member

asomers commented Oct 27, 2021

Ok, I get it. And what do you normally do with unnamed UnixAddrs?

@stevenengler
Copy link
Contributor Author

stevenengler commented Oct 27, 2021

We have code that intercepts syscalls, so we need to work with libc::sockaddr types. Within the internals of our application, it's nice to convert these to nix SockAddr types to work with them, and then convert them back to libc::sockaddr types when needed. For example when we intercept socketpair(), we create a custom socket object within our application and set its socket address to a nix UnixAddr which represents an unnamed unix socket, so that later if we intercept getsockname(), we can convert that UnixAddr to a libc::sockaddr using SockAddr::as_ffi_pair() and return it as the result to getsockname(). Calling getsockname() on an unnamed unix socket should return an addrlen of 2, so if UnixSocket supported unnamed sockets, SockAddr::as_ffi_pair() would return an addrlen of 2 and everything would work seamlessly.

Edit: A simpler example, an unnamed socket address can also be passed to bind() to auto-bind the socket to an abstract address.

For a unix socket:

If a bind(2) call specifies addrlen as sizeof(sa_family_t), or the SO_PASSCRED socket option was specified for a socket that was not explicitly bound to an address, then the socket is autobound to an abstract address.

@stevenengler
Copy link
Contributor Author

I think maybe this could be implemented with something like:

impl UnixAddr {
    pub fn new_unnamed() -> Result<UnixAddr> {
        unsafe {
            let mut ret = libc::sockaddr_un {
                sun_family: AddressFamily::Unix as sa_family_t,
                .. mem::zeroed()
            };

            Ok(UnixAddr::from_raw_parts(ret, 2))
        }
    }
}

If you're interested in a PR, let me know. But from #1544 it looks like you might be rewriting the SockAddr code anyways.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants