Skip to content

Commit ab3c1ac

Browse files
committed
Add socket_peerpidfd
Supported on Linux since 6.5.
1 parent 0a6cb07 commit ab3c1ac

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

src/backend/libc/net/sockopt.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use super::ext::{in6_addr_new, in_addr_new};
44
use crate::backend::c;
55
use crate::backend::conv::{borrowed_fd, ret};
6-
use crate::fd::BorrowedFd;
6+
use crate::fd::{BorrowedFd, FromRawFd, OwnedFd, RawFd};
77
#[cfg(feature = "alloc")]
88
#[cfg(any(
99
linux_like,
@@ -1060,6 +1060,13 @@ pub(crate) fn socket_peercred(fd: BorrowedFd<'_>) -> io::Result<UCred> {
10601060
getsockopt(fd, c::SOL_SOCKET, c::SO_PEERCRED)
10611061
}
10621062

1063+
#[cfg(linux_kernel)]
1064+
#[inline]
1065+
pub(crate) fn socket_peerpidfd(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
1066+
let raw = getsockopt::<RawFd>(fd, c::SOL_SOCKET, c::SO_PEERPIDFD)?;
1067+
Ok(unsafe { OwnedFd::from_raw_fd(raw) })
1068+
}
1069+
10631070
#[cfg(target_os = "linux")]
10641071
#[inline]
10651072
pub(crate) fn set_xdp_umem_reg(fd: BorrowedFd<'_>, value: XdpUmemReg) -> io::Result<()> {

src/backend/linux_raw/net/sockopt.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use crate::backend::c;
99
use crate::backend::conv::{by_mut, c_uint, ret, socklen_t};
10-
use crate::fd::BorrowedFd;
10+
use crate::fd::{BorrowedFd, FromRawFd, OwnedFd, RawFd};
1111
#[cfg(feature = "alloc")]
1212
use crate::ffi::CStr;
1313
use crate::io;
@@ -848,6 +848,12 @@ pub(crate) fn socket_peercred(fd: BorrowedFd<'_>) -> io::Result<UCred> {
848848
getsockopt(fd, c::SOL_SOCKET, linux_raw_sys::net::SO_PEERCRED)
849849
}
850850

851+
#[inline]
852+
pub(crate) fn socket_peerpidfd(fd: BorrowedFd<'_>) -> io::Result<OwnedFd> {
853+
let raw = getsockopt::<RawFd>(fd, c::SOL_SOCKET, linux_raw_sys::net::SO_PEERPIDFD)?;
854+
Ok(unsafe { OwnedFd::from_raw_fd(raw) })
855+
}
856+
851857
#[cfg(target_os = "linux")]
852858
#[inline]
853859
pub(crate) fn set_xdp_umem_reg(fd: BorrowedFd<'_>, value: XdpUmemReg) -> io::Result<()> {

src/net/sockopt.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ use crate::{backend, io};
183183
))]
184184
use alloc::string::String;
185185
use backend::c;
186-
use backend::fd::AsFd;
186+
use backend::fd::{AsFd, OwnedFd};
187187
use core::time::Duration;
188188

189189
/// Timeout identifier for use with [`set_socket_timeout`] and
@@ -1536,6 +1536,15 @@ pub fn socket_peercred<Fd: AsFd>(fd: Fd) -> io::Result<super::UCred> {
15361536
backend::net::sockopt::socket_peercred(fd.as_fd())
15371537
}
15381538

1539+
///`getsockopt(fd, SOL_SOCKET, SO_PEERPIDFD)`—Get pidfd of Unix domain peer
1540+
///
1541+
/// Added in Linux 6.5.
1542+
#[cfg(linux_kernel)]
1543+
#[doc(alias = "SO_PEERPIDFD")]
1544+
pub fn socket_peerpidfd<Fd: AsFd>(fd: Fd) -> io::Result<OwnedFd> {
1545+
backend::net::sockopt::socket_peerpidfd(fd.as_fd())
1546+
}
1547+
15391548
/// `setsockopt(fd, SOL_XDP, XDP_UMEM_REG, value)`
15401549
///
15411550
/// On kernel versions only supporting v1, the flags are ignored.

tests/event/select.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fn test_select_with_pipes() {
8888
#[serial] // for `setrlimit` usage
8989
fn test_select_with_great_fds() {
9090
use core::cmp::max;
91+
use rustix::fd::{FromRawFd as _, OwnedFd};
9192
use rustix::io::{read, write};
9293
use rustix::pipe::pipe;
9394
use rustix::process::{getrlimit, setrlimit, Resource};
@@ -277,6 +278,7 @@ fn test_select_with_sockets() {
277278
#[test]
278279
#[serial] // for `setrlimit` usage, and `crate::init`
279280
fn test_select_with_maxfd_sockets() {
281+
use rustix::fd::{FromRawFd as _, OwnedFd};
280282
use rustix::net::{recv, send, AddressFamily, RecvFlags, SendFlags, SocketType};
281283
use rustix::process::{getrlimit, setrlimit, Resource};
282284
use std::net::{IpAddr, Ipv4Addr, SocketAddr};

tests/net/unix_alloc.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -677,6 +677,29 @@ fn test_unix_peercred() {
677677
};
678678
}
679679

680+
#[cfg(all(feature = "process", feature = "net", linux_kernel))]
681+
#[test]
682+
fn test_unix_peerpidfd() {
683+
use rustix::net::{sockopt, AddressFamily, SocketFlags, SocketType};
684+
use rustix::process::PidfdFlags;
685+
686+
let (send_sock, _recv_sock) = rustix::net::socketpair(
687+
AddressFamily::UNIX,
688+
SocketType::STREAM,
689+
SocketFlags::CLOEXEC,
690+
None,
691+
)
692+
.unwrap();
693+
let pidfd = sockopt::socket_peerpidfd(&send_sock).unwrap();
694+
let own_pidfd =
695+
rustix::process::pidfd_open(rustix::process::getpid(), PidfdFlags::empty()).unwrap();
696+
// Two pidfds refer to the same process iff their `st_ino` values are the same.
697+
assert_eq!(
698+
rustix::fs::fstat(pidfd).unwrap().st_ino,
699+
rustix::fs::fstat(own_pidfd).unwrap().st_ino
700+
)
701+
}
702+
680703
/// Like `test_unix_msg_with_scm_rights`, but with multiple file descriptors
681704
/// over multiple control messages.
682705
#[cfg(not(any(target_os = "redox", target_os = "wasi")))]

0 commit comments

Comments
 (0)