Skip to content

Commit

Permalink
Solidify Linux changes
Browse files Browse the repository at this point in the history
  • Loading branch information
MEhrn00 committed Feb 18, 2024
1 parent acf33c1 commit 42a74ee
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 119 deletions.
23 changes: 13 additions & 10 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/addrinfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ bitflags! {
}

impl AiFlags {
pub fn as_i32(&self) -> i32 {
pub const fn as_i32(&self) -> i32 {
self.bits()
}
}
Expand All @@ -44,7 +44,7 @@ impl AddrInfoList {

let mut hints_data: libc::addrinfo = unsafe { std::mem::zeroed() };
let hints_ptr = if let Some(h) = hints {
hints_data.ai_family = h.family.into();
hints_data.ai_family = h.family.as_i32();
hints_data.ai_socktype = h.socktype as i32;
hints_data.ai_flags = h.flags.as_i32();

Expand All @@ -67,8 +67,11 @@ impl AddrInfoList {
})
}

pub fn first<'a>(&'a self) -> AddrInfo<'a> {
self.addrinfo.into()
pub const fn first(&self) -> AddrInfo {
AddrInfo {
addrinfo: self.addrinfo,
_marker: PhantomData,
}
}
}

Expand All @@ -85,19 +88,19 @@ pub struct AddrInfo<'a> {
}

impl<'a> AddrInfo<'a> {
pub fn ai_flags(&self) -> i32 {
pub const fn ai_flags(&self) -> i32 {
unsafe { self.addrinfo.as_ref().ai_flags }
}

pub fn ai_family(&self) -> Family {
unsafe { self.addrinfo.as_ref().ai_family }.into()
pub const fn ai_family(&self) -> Family {
Family::from_value(unsafe { self.addrinfo.as_ref().ai_family })
}

pub fn ai_socktype(&self) -> SockType {
unsafe { self.addrinfo.as_ref().ai_socktype }.into()
pub const fn ai_socktype(&self) -> SockType {
SockType::from_value(unsafe { self.addrinfo.as_ref().ai_socktype })
}

pub fn ai_protocol(&self) -> i32 {
pub const fn ai_protocol(&self) -> i32 {
unsafe { self.addrinfo.as_ref().ai_protocol }
}

Expand Down
12 changes: 4 additions & 8 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,23 @@ impl GroupInfo {

pub fn lookup_username(username: &CStr) -> Result<GroupInfo, FfiError> {
let grpasswd = unsafe { libc::getgrnam(username.as_ptr()) };
Ok(Self(
NonNull::new(grpasswd).ok_or_else(|| FfiError::os_error())?,
))
Ok(Self(NonNull::new(grpasswd).ok_or_else(FfiError::os_error)?))
}

pub fn lookup_gid(gid: u32) -> Result<GroupInfo, FfiError> {
let grpasswd = unsafe { libc::getgrgid(gid) };
Ok(Self(
NonNull::new(grpasswd).ok_or_else(|| FfiError::os_error())?,
))
Ok(Self(NonNull::new(grpasswd).ok_or_else(FfiError::os_error)?))
}

pub fn groupname<'a>(&'a self) -> &'a str {
pub fn groupname(&self) -> &str {
unsafe {
CStr::from_ptr(self.0.as_ref().gr_name)
.to_str()
.unwrap_unchecked()
}
}

pub fn passwd<'a>(&'a self) -> &'a str {
pub fn passwd(&self) -> &str {
unsafe {
CStr::from_ptr(self.0.as_ref().gr_passwd)
.to_str()
Expand Down
73 changes: 71 additions & 2 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/ifaddrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@ use std::{ffi::CStr, marker::PhantomData, ptr::NonNull};

use crate::errors::FfiError;

use super::socket::SockAddr;

bitflags::bitflags! {
pub struct IffFlags: i32 {
const UP = libc::IFF_UP;
const BROADCAST = libc::IFF_BROADCAST;
const DEBUG = libc::IFF_DEBUG;
const LOOPBACK = libc::IFF_LOOPBACK;
const POINTTOPOINT = libc::IFF_POINTOPOINT;
const RUNNING = libc::IFF_RUNNING;
const NOARP = libc::IFF_NOARP;
const PROMISC = libc::IFF_PROMISC;
const NOTRAILERS = libc::IFF_NOTRAILERS;
const ALLMULTI = libc::IFF_MULTICAST;
const MASTER = libc::IFF_MASTER;
const SLAVE = libc::IFF_SLAVE;
const MULTICAST = libc::IFF_MULTICAST;
const PORTSEL = libc::IFF_PORTSEL;
const AUTOMEDIA = libc::IFF_AUTOMEDIA;
const DYNAMIC = libc::IFF_DYNAMIC;
const LOWER_UP = libc::IFF_LOWER_UP;
const DORMANT = libc::IFF_DORMANT;
const ECHO = libc::IFF_ECHO;
const _ = !0;
}
}

impl IffFlags {
pub const fn as_i32(&self) -> i32 {
self.bits()
}
}

#[repr(transparent)]
pub struct IfAddrsList {
ifaddrs: NonNull<libc::ifaddrs>,
_marker: PhantomData<libc::addrinfo>,
Expand All @@ -21,8 +55,11 @@ impl IfAddrsList {
})
}

pub fn first<'a>(&'a self) -> IfAddr<'a> {
self.ifaddrs.into()
pub const fn first(&self) -> IfAddr {
IfAddr {
ifaddr: self.ifaddrs,
_marker: PhantomData,
}
}
}

Expand All @@ -32,6 +69,12 @@ impl Drop for IfAddrsList {
}
}

pub enum IfuAddr<'a> {
Broadcast(SockAddr<'a>),
PointToPointDst(SockAddr<'a>),
}

#[repr(transparent)]
pub struct IfAddr<'a> {
ifaddr: NonNull<libc::ifaddrs>,
_marker: PhantomData<&'a libc::ifaddrs>,
Expand All @@ -45,6 +88,32 @@ impl<'a> IfAddr<'a> {
.unwrap_unchecked()
}
}

pub const fn ifa_flags(&self) -> IffFlags {
IffFlags::from_bits_retain(unsafe { self.ifaddr.as_ref().ifa_flags } as i32)
}

pub fn ifa_addr(&self) -> Option<SockAddr> {
unsafe { SockAddr::from_ptr(self.ifaddr.as_ref().ifa_addr) }
}

pub fn ifa_netmask(&self) -> Option<SockAddr> {
unsafe { SockAddr::from_ptr(self.ifaddr.as_ref().ifa_netmask) }
}

pub fn ifa_ifu(&self) -> Option<IfuAddr> {
if self.ifa_flags().contains(IffFlags::BROADCAST) {
Some(IfuAddr::Broadcast(unsafe {
SockAddr::from_ptr(self.ifaddr.as_ref().ifa_ifu)?
}))
} else if self.ifa_flags().contains(IffFlags::POINTTOPOINT) {
Some(IfuAddr::PointToPointDst(unsafe {
SockAddr::from_ptr(self.ifaddr.as_ref().ifa_ifu)?
}))
} else {
None
}
}
}

impl<'a> From<NonNull<libc::ifaddrs>> for IfAddr<'a> {
Expand Down
108 changes: 82 additions & 26 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,26 @@ pub enum Family {
Other(i32),
}

impl From<i32> for Family {
fn from(value: i32) -> Self {
impl Family {
pub const fn from_value(value: i32) -> Family {
match value {
libc::AF_INET => Self::AfInet,
libc::AF_INET6 => Self::AfInet6,
libc::AF_UNSPEC => Self::Unspec,
_ => Self::Other(value),
}
}
}

impl From<Family> for i32 {
fn from(value: Family) -> Self {
match value {
Family::AfInet => libc::AF_INET,
Family::AfInet6 => libc::AF_INET6,
Family::Unspec => libc::AF_UNSPEC,
Family::Other(v) => v,
pub const fn as_i32(&self) -> i32 {
match self {
Self::AfInet => libc::AF_INET,
Self::AfInet6 => libc::AF_INET6,
Self::Unspec => libc::AF_UNSPEC,
Self::Other(v) => *v,
}
}
}

impl From<u16> for Family {
fn from(value: u16) -> Self {
(value as i32).into()
}
}

impl From<Family> for u16 {
fn from(value: Family) -> Self {
value.into()
}
}

#[repr(i32)]
#[derive(Default)]
pub enum SockType {
Expand All @@ -57,8 +43,8 @@ pub enum SockType {
SockPacket = libc::SOCK_PACKET,
}

impl From<i32> for SockType {
fn from(value: i32) -> Self {
impl SockType {
pub const fn from_value(value: i32) -> SockType {
match value {
libc::SOCK_STREAM => Self::SockStream,
libc::SOCK_DGRAM => Self::SockDgram,
Expand Down Expand Up @@ -91,15 +77,53 @@ pub enum SockAddr<'a> {
AfInet6(SockAddrIn<'a, AfInet6>),
}

impl<'a> SockAddr<'a> {
/// # Safety
///
/// The pointer is not validated to ensure that it is of the correct type
pub unsafe fn from_ptr(ptr: *mut libc::sockaddr) -> Option<SockAddr<'a>> {
if ptr.is_null() {
return None;
}

match unsafe { (*ptr).sa_family } as i32 {
libc::AF_INET6 => {
let addr: NonNull<libc::sockaddr_in6> = NonNull::new(ptr.cast())?;
Some(SockAddr::AfInet6(unsafe {
SockAddrIn::<AfInet6>::from_raw(addr)
}))
}
libc::AF_INET => {
let addr: NonNull<libc::sockaddr_in> = NonNull::new(ptr.cast())?;

Some(SockAddr::AfInet(unsafe {
SockAddrIn::<AfInet>::from_raw(addr)
}))
}
_ => None,
}
}
}

#[repr(transparent)]
pub struct SockAddrIn<'a, T: SockAddrFamily> {
addr: NonNull<T::Inner>,
_marker: PhantomData<&'a T::Inner>,
}

impl<'a> SockAddrIn<'a, AfInet> {
pub fn sin_family(&self) -> Family {
unsafe { self.addr.as_ref().sin_family }.into()
/// # Safety
///
/// This pointer is not validated to ensure that it is of the correct type
pub unsafe fn from_raw(addr: NonNull<libc::sockaddr_in>) -> Self {
Self {
addr,
_marker: PhantomData,
}
}

pub const fn sin_family(&self) -> Family {
Family::from_value(unsafe { self.addr.as_ref().sin_family } as i32)
}

pub fn sin_port(&self) -> u16 {
Expand All @@ -110,3 +134,35 @@ impl<'a> SockAddrIn<'a, AfInet> {
unsafe { &self.addr.as_ref().sin_addr }
}
}

impl<'a> SockAddrIn<'a, AfInet6> {
/// # Safety
///
/// This pointer is not validated to ensure that it is of the correct type
pub const unsafe fn from_raw(addr: NonNull<libc::sockaddr_in6>) -> Self {
Self {
addr,
_marker: PhantomData,
}
}

pub fn sin6_family(&self) -> Family {
Family::from_value(unsafe { self.addr.as_ref().sin6_family } as i32)
}

pub fn sin6_port(&self) -> u16 {
unsafe { self.addr.as_ref().sin6_port }
}

pub fn sin6_flowinfo(&self) -> u32 {
unsafe { self.addr.as_ref().sin6_flowinfo }
}

pub fn sin6_addr(&self) -> &libc::in6_addr {
unsafe { &self.addr.as_ref().sin6_addr }
}

pub fn sin6_scope_id(&self) -> u32 {
unsafe { self.addr.as_ref().sin6_scope_id }
}
}
10 changes: 5 additions & 5 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/uname.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl UtsName {
Ok(Self(buf))
}

pub fn sysname<'a>(&'a self) -> &'a str {
pub fn sysname(&self) -> &str {
// SAFETY:
// - This field will always contain a trailing nullbyte according to `uname(2)`
// so the call to `CStr::from_ptr` is safe in this context.
Expand All @@ -29,7 +29,7 @@ impl UtsName {
}
}

pub fn nodename<'a>(&'a self) -> &'a str {
pub fn nodename(&self) -> &str {
// SAFETY:
// - This field will always contain a trailing nullbyte.
// - The node name contains valid ascii characters.
Expand All @@ -40,7 +40,7 @@ impl UtsName {
}
}

pub fn release<'a>(&'a self) -> &'a str {
pub fn release(&self) -> &str {
// SAFETY:
// - This field will always contain a trailing nullbyte.
// - The release name will always contain valid ascii characters.
Expand All @@ -51,7 +51,7 @@ impl UtsName {
}
}

pub fn version<'a>(&'a self) -> &'a str {
pub fn version(&self) -> &str {
// SAFETY:
// - The version field will contain a trailing nullbyte.
// - The version contains only valid utf8 data.
Expand All @@ -62,7 +62,7 @@ impl UtsName {
}
}

pub fn machine<'a>(&'a self) -> &'a str {
pub fn machine(&self) -> &str {
// SAFETY:
// - The machine name will contain a trailing nullbyte.
// - The machine name contains only valid utf8 data.
Expand Down
Loading

0 comments on commit 42a74ee

Please sign in to comment.