How to manage permissions of a UnixListener

How can I set read/write permissions of a UDS socket?

Inside my rust application, I create the socket with:

let listener = std::os::unix::net::UnixListener::bind(uds_path);

or, most of the time, with tokio:

let listener = tokio_uds::UnixListener::bind(uds_path);

After the creation, I need to change the read/write permissions and/or to change the owner of the socket.
Is there a way to achieve it?

You can use File and permissions methods operating on uds_path directly.

Alternatively, if you're worried about race conditions, you can use https://doc.rust-lang.org/std/os/unix/io/trait.AsRawFd.html to get the file descriptor from the socket, and change permissions through it.

Hi @kornel,
thanks for the hint, but I don't understand how the AsRawFd should be used.
listener.as_raw_fd() returns nothing more than an i32.
Could you point me to any sample code?

Then there's https://doc.rust-lang.org/std/os/unix/io/trait.FromRawFd.html that can make File.

Something like that?

let file = File::from_raw_fd(listener.as_raw_fd())?;
    let mut perms = file.metadata()?.permissions();
    perms.set_readonly(true);
    file.set_permissions(perms)?;
let _ = file.into_raw_fd(); // don't close the file

This fd-dance is needed only when you're paranoid that a rogue process on the same machine could hijack the socket before you change the permissions. If you're not worried, then use File::open(uds_path).

Hi @kornel
thanks again!
I think I'll go for the file::open(...) :ok_hand:

Anyway, it's still a mystery to me how File::from_raw_fd(..) can create a File from an i32 :thinking:

That's all a File is - a wrapper around a file descriptor.

@kornel
I am still not able to make it work...
File::from_raw_fd(...) is an unsafe function which is not an option in my case and File.open(uds_path) returns a "file not found error" which is quite strange since the file is definitely there and the path is definitely correct :thinking:
Can it be caused to the fact that the file is a socket?

I'm using fs::set_permissions on a path shared with UnixListener::bind and it works fine for me.

@kornel
I confirm that fs::set_permissions works as expected even if File.open returns a "No such device or address" error