(probe: unsafe fn() -> i64)
| 1708 | #[cfg(unix)] |
| 1709 | #[allow(unsafe_code)] |
| 1710 | fn probe_hardened_child(probe: unsafe fn() -> i64) -> i64 { |
| 1711 | const HARDEN_FAILED: i64 = -2; |
| 1712 | |
| 1713 | let mut fds = [0; 2]; |
| 1714 | let pipe_rc = unsafe { libc::pipe(fds.as_mut_ptr()) }; |
| 1715 | assert_eq!( |
| 1716 | pipe_rc, |
| 1717 | 0, |
| 1718 | "pipe failed: {}", |
| 1719 | std::io::Error::last_os_error() |
| 1720 | ); |
| 1721 | |
| 1722 | match unsafe { fork() }.expect("fork should succeed") { |
| 1723 | ForkResult::Child => { |
| 1724 | unsafe { libc::close(fds[0]) }; |
| 1725 | let value = match harden_child_process() { |
| 1726 | Ok(()) => unsafe { probe() }, |
| 1727 | Err(_) => HARDEN_FAILED, |
| 1728 | }; |
| 1729 | let bytes = value.to_ne_bytes(); |
| 1730 | let written = unsafe { libc::write(fds[1], bytes.as_ptr().cast(), bytes.len()) }; |
| 1731 | unsafe { |
| 1732 | libc::close(fds[1]); |
| 1733 | libc::_exit(i32::from(written != bytes.len().cast_signed())); |
| 1734 | } |
| 1735 | } |
| 1736 | ForkResult::Parent { child } => { |
| 1737 | unsafe { libc::close(fds[1]) }; |
| 1738 | let mut bytes = [0u8; size_of::<i64>()]; |
| 1739 | let read = unsafe { libc::read(fds[0], bytes.as_mut_ptr().cast(), bytes.len()) }; |
| 1740 | unsafe { libc::close(fds[0]) }; |
| 1741 | assert_eq!( |
| 1742 | read.cast_unsigned(), |
| 1743 | bytes.len(), |
| 1744 | "expected {} probe bytes, got {}", |
| 1745 | bytes.len(), |
| 1746 | read |
| 1747 | ); |
| 1748 | |
| 1749 | match waitpid(child, None).expect("waitpid should succeed") { |
| 1750 | WaitStatus::Exited(_, 0) => {} |
| 1751 | status => panic!("probe child exited unexpectedly: {status:?}"), |
| 1752 | } |
| 1753 | |
| 1754 | i64::from_ne_bytes(bytes) |
| 1755 | } |
| 1756 | } |
| 1757 | } |
| 1758 | |
| 1759 | #[cfg(unix)] |
| 1760 | #[allow(unsafe_code)] |
nothing calls this directly
no test coverage detected