From 3e42c03de2cd7eb8d99c902ccb26f02daf69f415 Mon Sep 17 00:00:00 2001 From: Ethan Pailes Date: Mon, 15 Jul 2024 15:24:32 +0000 Subject: [PATCH] fix: mark PIDFDInfo and PIDRUsage unsafe This patch marks the PIDRUsage and PIDFDInfo traits as unsafe, since incorrect implementations of these traits could lead to unsound behavior. Unfortunately, since these are public traits, this will mean an incompatible version bump for the next release, though hopefully no one is really rolling their own implementation for these guys. https://doc.rust-lang.org/reference/unsafe-keyword.html#unsafe-traits-unsafe-trait --- src/libproc/bsd_info.rs | 3 +++ src/libproc/file_info.rs | 13 +++++++++++-- src/libproc/net_info.rs | 6 +++++- src/libproc/pid_rusage.rs | 33 +++++++++++++++++++++++++++------ src/libproc/proc_pid.rs | 22 +++++++++++++++++++--- src/libproc/task_info.rs | 10 ++++++++-- src/libproc/thread_info.rs | 5 ++++- src/libproc/work_queue_info.rs | 5 ++++- 8 files changed, 81 insertions(+), 16 deletions(-) diff --git a/src/libproc/bsd_info.rs b/src/libproc/bsd_info.rs index 5ff84920..1cea5c17 100644 --- a/src/libproc/bsd_info.rs +++ b/src/libproc/bsd_info.rs @@ -2,6 +2,9 @@ use crate::libproc::proc_pid::{PIDInfo, PidInfoFlavor}; #[cfg(target_os = "macos")] pub use crate::osx_libproc_bindings::proc_bsdinfo as BSDInfo; +/// # Safety +/// +/// `BSDInfo` is correctly sized and flavor indicates the right struct. #[cfg(target_os = "macos")] impl PIDInfo for BSDInfo { fn flavor() -> PidInfoFlavor { diff --git a/src/libproc/file_info.rs b/src/libproc/file_info.rs index eccfbe15..3e035ec2 100644 --- a/src/libproc/file_info.rs +++ b/src/libproc/file_info.rs @@ -30,7 +30,10 @@ pub enum PIDFDInfoFlavor { /// Struct for Listing File Descriptors pub struct ListFDs; -impl ListPIDInfo for ListFDs { +/// # Safety +/// +/// `Item` is correctly sized and the flavor matches. +unsafe impl ListPIDInfo for ListFDs { type Item = ProcFDInfo; fn flavor() -> PidInfoFlavor { PidInfoFlavor::ListFDs @@ -89,7 +92,13 @@ impl From for ProcFDType { /// The `PIDFDInfo` trait is needed for polymorphism on pidfdinfo types, also abstracting flavor /// in order to provide type-guaranteed flavor correctness -pub trait PIDFDInfo: Default { +/// +/// # Safety +/// +/// The type this trait is implemented on must be correctly sized such that +/// a pointer to that type can be passed to the libproc `proc_pidfdinfo` function +/// as the buffer parameter. +pub unsafe trait PIDFDInfo: Default { /// Return the Pid File Descriptor Info flavor of the implementing struct fn flavor() -> PIDFDInfoFlavor; } diff --git a/src/libproc/net_info.rs b/src/libproc/net_info.rs index a2b3162b..7f6dae25 100644 --- a/src/libproc/net_info.rs +++ b/src/libproc/net_info.rs @@ -35,7 +35,11 @@ pub struct ProcFileInfo { pub rfu_1: i32, } -impl PIDFDInfo for SocketFDInfo { +/// # Saftey +/// +/// The size of `SocketFDInfo` is correct for getting passed to +/// `proc_pidfdinfo`. +unsafe impl PIDFDInfo for SocketFDInfo { fn flavor() -> PIDFDInfoFlavor { PIDFDInfoFlavor::SocketInfo } diff --git a/src/libproc/pid_rusage.rs b/src/libproc/pid_rusage.rs index 882bd567..d3777537 100644 --- a/src/libproc/pid_rusage.rs +++ b/src/libproc/pid_rusage.rs @@ -11,7 +11,13 @@ use crate::osx_libproc_bindings::proc_pid_rusage; /// The `PIDRUsage` trait is needed for polymorphism on pidrusage types, also abstracting flavor in order to provide /// type-guaranteed flavor correctness -pub trait PIDRUsage: Default { +/// +/// # Safety +/// +/// The type this trait is implemented on must be correctly sized such that +/// a pointer to that type can be passed to the libproc `proc_pid_rusage` function +/// as the buffer parameter. +pub unsafe trait PIDRUsage: Default { /// Return the `PidRUsageFlavor` for the implementing struct fn flavor() -> PidRUsageFlavor; /// Memory used in bytes @@ -62,7 +68,10 @@ pub struct RUsageInfoV0 { pub ri_proc_exit_abstime: u64, } -impl PIDRUsage for RUsageInfoV0 { +/// # Safety +/// +/// The size is appropriate for getting passed to `proc_pid_pidrusage`. +unsafe impl PIDRUsage for RUsageInfoV0 { fn flavor() -> PidRUsageFlavor { PidRUsageFlavor::V0 } @@ -116,7 +125,10 @@ pub struct RUsageInfoV1 { pub ri_child_elapsed_abstime: u64, } -impl PIDRUsage for RUsageInfoV1 { +/// # Safety +/// +/// The size is appropriate for getting passed to `proc_pid_pidrusage`. +unsafe impl PIDRUsage for RUsageInfoV1 { fn flavor() -> PidRUsageFlavor { PidRUsageFlavor::V1 } @@ -174,7 +186,10 @@ pub struct RUsageInfoV2 { pub ri_diskio_byteswritten: u64, } -impl PIDRUsage for RUsageInfoV2 { +/// # Safety +/// +/// The size is appropriate for getting passed to `proc_pid_pidrusage`. +unsafe impl PIDRUsage for RUsageInfoV2 { fn flavor() -> PidRUsageFlavor { PidRUsageFlavor::V2 } @@ -250,7 +265,10 @@ pub struct RUsageInfoV3 { pub ri_serviced_system_time: u64, } -impl PIDRUsage for RUsageInfoV3 { +/// # Safety +/// +/// The size is appropriate for getting passed to `proc_pid_pidrusage`. +unsafe impl PIDRUsage for RUsageInfoV3 { fn flavor() -> PidRUsageFlavor { PidRUsageFlavor::V3 } @@ -342,7 +360,10 @@ pub struct RUsageInfoV4 { pub ri_unused: [u64; 1], } -impl PIDRUsage for RUsageInfoV4 { +/// # Safety +/// +/// The size is appropriate for getting passed to `proc_pid_pidrusage`. +unsafe impl PIDRUsage for RUsageInfoV4 { fn flavor() -> PidRUsageFlavor { PidRUsageFlavor::V4 } diff --git a/src/libproc/proc_pid.rs b/src/libproc/proc_pid.rs index f9d62404..04940114 100644 --- a/src/libproc/proc_pid.rs +++ b/src/libproc/proc_pid.rs @@ -56,7 +56,13 @@ pub enum ProcType { /// The `PIDInfo` trait is needed for polymorphism on pidinfo types, also abstracting flavor in order to provide /// type-guaranteed flavor correctness -pub trait PIDInfo { +/// +/// # Safety +/// +/// The type this trait is implemented on must be correctly sized such that +/// a pointer to that type can be passed to the libproc `proc_pidinfo` function +/// as the buffer parameter. +pub unsafe trait PIDInfo { /// Return the `PidInfoFlavor` of the implementing struct fn flavor() -> PidInfoFlavor; } @@ -126,7 +132,14 @@ pub enum PidInfo { /// The `ListPIDInfo` trait is needed for polymorphism on listpidinfo types, also abstracting flavor in order to provide /// type-guaranteed flavor correctness -pub trait ListPIDInfo { +/// +/// # Safety +/// +/// The `Item` type associated with this trait on must be correctly sized such that +/// a pointer to an array of that type can be passed to the libproc +/// `proc_pidinfo` function as the buffer parameter, with the `flavor()` +/// value indicating the correct output type. +pub unsafe trait ListPIDInfo { /// Item type Item; /// Return the `PidInfoFlavor` of the implementing struct @@ -136,7 +149,10 @@ pub trait ListPIDInfo { /// Struct for List of Threads pub struct ListThreads; -impl ListPIDInfo for ListThreads { +/// # Safety +/// +/// `Item` is correctly sized and the flavor matches. +unsafe impl ListPIDInfo for ListThreads { type Item = u64; fn flavor() -> PidInfoFlavor { PidInfoFlavor::ListThreads diff --git a/src/libproc/task_info.rs b/src/libproc/task_info.rs index c6b043fd..a3140df0 100644 --- a/src/libproc/task_info.rs +++ b/src/libproc/task_info.rs @@ -4,8 +4,11 @@ use crate::libproc::proc_pid::{PIDInfo, PidInfoFlavor}; #[cfg(target_os = "macos")] pub use crate::osx_libproc_bindings::proc_taskinfo as TaskInfo; +/// # Safety +/// +/// `TaskInfo` is the right size to be passed to `proc_pidinfo`. #[cfg(target_os = "macos")] -impl PIDInfo for TaskInfo { +unsafe impl PIDInfo for TaskInfo { fn flavor() -> PidInfoFlavor { PidInfoFlavor::TaskInfo } @@ -21,8 +24,11 @@ pub struct TaskAllInfo { pub ptinfo: TaskInfo, } +/// # Safety +/// +/// `TaskInfoAll` is the right size to be passed to `proc_pidinfo`. #[cfg(target_os = "macos")] -impl PIDInfo for TaskAllInfo { +unsafe impl PIDInfo for TaskAllInfo { fn flavor() -> PidInfoFlavor { PidInfoFlavor::TaskAllInfo } diff --git a/src/libproc/thread_info.rs b/src/libproc/thread_info.rs index 6054c2d4..ccf82159 100644 --- a/src/libproc/thread_info.rs +++ b/src/libproc/thread_info.rs @@ -2,8 +2,11 @@ use crate::libproc::proc_pid::{PIDInfo, PidInfoFlavor}; #[cfg(target_os = "macos")] pub use crate::osx_libproc_bindings::proc_threadinfo as ThreadInfo; +/// # Safety +/// +/// `ThreadInfo` is the right size to be passed to `proc_pidinfo`. #[cfg(target_os = "macos")] -impl PIDInfo for ThreadInfo { +unsafe impl PIDInfo for ThreadInfo { fn flavor() -> PidInfoFlavor { PidInfoFlavor::ThreadInfo } diff --git a/src/libproc/work_queue_info.rs b/src/libproc/work_queue_info.rs index 44117def..ec016379 100644 --- a/src/libproc/work_queue_info.rs +++ b/src/libproc/work_queue_info.rs @@ -13,7 +13,10 @@ pub struct WorkQueueInfo { pub reserved: [u32; 1], } -impl PIDInfo for WorkQueueInfo { +/// # Safety +/// +/// `WorkQueueInfo` is the right size to be passed to `proc_pidinfo`. +unsafe impl PIDInfo for WorkQueueInfo { fn flavor() -> PidInfoFlavor { PidInfoFlavor::WorkQueueInfo }