summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md5
-rw-r--r--src/sys/socket/addr.rs31
-rw-r--r--test/sys/test_socket.rs22
3 files changed, 52 insertions, 6 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f09b4bed..8f906b6b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -41,6 +41,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Added `nix::sys::uio::{process_vm_readv, process_vm_writev}` on Linux
([#568](https://github.com/nix-rust/nix/pull/568))
- Added `nix::unistd::{getgroups, setgroups, getgrouplist, initgroups}`. ([#733](https://github.com/nix-rust/nix/pull/733))
+- Added `nix::sys::socket::UnixAddr::as_abstract` on Linux and Android.
+ ([#785](https://github.com/nix-rust/nix/pull/785))
### Changed
- Renamed existing `ptrace` wrappers to encourage namespacing ([#692](https://github.com/nix-rust/nix/pull/692))
@@ -69,6 +71,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- Moved constants ptrace request, event and options to enums and updated ptrace functions and argument types accordingly.
([#749](https://github.com/nix-rust/nix/pull/749))
- `AioCb::Drop` will now panic if the `AioCb` is still in-progress ([#715](https://github.com/nix-rust/nix/pull/715))
+- Restricted `nix::sys::socket::UnixAddr::new_abstract` to Linux and Android only.
+ ([#785](https://github.com/nix-rust/nix/pull/785))
+
### Fixed
- Fix compilation and tests for OpenBSD targets
diff --git a/src/sys/socket/addr.rs b/src/sys/socket/addr.rs
index d57207ed..29832b37 100644
--- a/src/sys/socket/addr.rs
+++ b/src/sys/socket/addr.rs
@@ -521,7 +521,9 @@ impl fmt::Display for Ipv6Addr {
*
*/
-/// A wrapper around `sockaddr_un`. We track the length of `sun_path` (excluding
+/// A wrapper around `sockaddr_un`.
+///
+/// This also tracks the length of `sun_path` address (excluding
/// a terminating null), because it may not be null-terminated. For example,
/// unconnected and Linux abstract sockets are never null-terminated, and POSIX
/// does not require that `sun_len` include the terminating null even for normal
@@ -555,10 +557,13 @@ impl UnixAddr {
}))
}
- /// Create a new sockaddr_un representing an address in the
- /// "abstract namespace". This is a Linux-specific extension,
- /// primarily used to allow chrooted processes to communicate with
- /// specific daemons.
+ /// Create a new `sockaddr_un` representing an address in the "abstract namespace".
+ ///
+ /// The leading null byte for the abstract namespace is automatically added;
+ /// thus the input `path` is expected to be the bare name, not null-prefixed.
+ /// This is a Linux-specific extension, primarily used to allow chrooted
+ /// processes to communicate with processes having a different filesystem view.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
pub fn new_abstract(path: &[u8]) -> Result<UnixAddr> {
unsafe {
let mut ret = libc::sockaddr_un {
@@ -587,7 +592,7 @@ impl UnixAddr {
/// If this address represents a filesystem path, return that path.
pub fn path(&self) -> Option<&Path> {
if self.1 == 0 || self.0.sun_path[0] == 0 {
- // unbound or abstract
+ // unnamed or abstract
None
} else {
let p = self.sun_path();
@@ -600,6 +605,20 @@ impl UnixAddr {
Some(Path::new(<OsStr as OsStrExt>::from_bytes(&p[..reallen])))
}
}
+
+ /// If this address represents an abstract socket, return its name.
+ ///
+ /// For abstract sockets only the bare name is returned, without the
+ /// leading null byte. `None` is returned for unnamed or path-backed sockets.
+ #[cfg(any(target_os = "android", target_os = "linux"))]
+ pub fn as_abstract(&self) -> Option<&[u8]> {
+ if self.1 >= 1 && self.0.sun_path[0] == 0 {
+ Some(&self.sun_path()[1..])
+ } else {
+ // unnamed or filesystem path
+ None
+ }
+ }
}
impl PartialEq for UnixAddr {
diff --git a/test/sys/test_socket.rs b/test/sys/test_socket.rs
index 5f9c6fff..b3d983d3 100644
--- a/test/sys/test_socket.rs
+++ b/test/sys/test_socket.rs
@@ -64,6 +64,28 @@ pub fn test_path_to_sock_addr() {
assert_eq!(addr.path(), Some(actual));
}
+// Test getting/setting abstract addresses (without unix socket creation)
+#[cfg(target_os = "linux")]
+#[test]
+pub fn test_abstract_uds_addr() {
+ let empty = String::new();
+ let addr = UnixAddr::new_abstract(empty.as_bytes()).unwrap();
+ assert_eq!(addr.as_abstract(), Some(empty.as_bytes()));
+
+ let name = String::from("nix\0abstract\0test");
+ let addr = UnixAddr::new_abstract(name.as_bytes()).unwrap();
+ assert_eq!(addr.as_abstract(), Some(name.as_bytes()));
+ assert_eq!(addr.path(), None);
+
+ // Internally, name is null-prefixed (abstract namespace)
+ let internal: &[u8] = unsafe {
+ slice::from_raw_parts(addr.0.sun_path.as_ptr() as *const u8, addr.1)
+ };
+ let mut abstract_name = name.clone();
+ abstract_name.insert(0, '\0');
+ assert_eq!(internal, abstract_name.as_bytes());
+}
+
#[test]
pub fn test_getsockname() {
use nix::sys::socket::{socket, AddressFamily, SockType, SockFlag};