1*e0020ba6SChristian Brauner // SPDX-License-Identifier: GPL-2.0 2*e0020ba6SChristian Brauner 3*e0020ba6SChristian Brauner // Copyright (c) 2024 Christian Brauner <brauner@kernel.org> 4*e0020ba6SChristian Brauner 5*e0020ba6SChristian Brauner //! Pid namespaces. 6*e0020ba6SChristian Brauner //! 7*e0020ba6SChristian Brauner //! C header: [`include/linux/pid_namespace.h`](srctree/include/linux/pid_namespace.h) and 8*e0020ba6SChristian Brauner //! [`include/linux/pid.h`](srctree/include/linux/pid.h) 9*e0020ba6SChristian Brauner 10*e0020ba6SChristian Brauner use crate::{ 11*e0020ba6SChristian Brauner bindings, 12*e0020ba6SChristian Brauner types::{AlwaysRefCounted, Opaque}, 13*e0020ba6SChristian Brauner }; 14*e0020ba6SChristian Brauner use core::ptr; 15*e0020ba6SChristian Brauner 16*e0020ba6SChristian Brauner /// Wraps the kernel's `struct pid_namespace`. Thread safe. 17*e0020ba6SChristian Brauner /// 18*e0020ba6SChristian Brauner /// This structure represents the Rust abstraction for a C `struct pid_namespace`. This 19*e0020ba6SChristian Brauner /// implementation abstracts the usage of an already existing C `struct pid_namespace` within Rust 20*e0020ba6SChristian Brauner /// code that we get passed from the C side. 21*e0020ba6SChristian Brauner #[repr(transparent)] 22*e0020ba6SChristian Brauner pub struct PidNamespace { 23*e0020ba6SChristian Brauner inner: Opaque<bindings::pid_namespace>, 24*e0020ba6SChristian Brauner } 25*e0020ba6SChristian Brauner 26*e0020ba6SChristian Brauner impl PidNamespace { 27*e0020ba6SChristian Brauner /// Returns a raw pointer to the inner C struct. 28*e0020ba6SChristian Brauner #[inline] 29*e0020ba6SChristian Brauner pub fn as_ptr(&self) -> *mut bindings::pid_namespace { 30*e0020ba6SChristian Brauner self.inner.get() 31*e0020ba6SChristian Brauner } 32*e0020ba6SChristian Brauner 33*e0020ba6SChristian Brauner /// Creates a reference to a [`PidNamespace`] from a valid pointer. 34*e0020ba6SChristian Brauner /// 35*e0020ba6SChristian Brauner /// # Safety 36*e0020ba6SChristian Brauner /// 37*e0020ba6SChristian Brauner /// The caller must ensure that `ptr` is valid and remains valid for the lifetime of the 38*e0020ba6SChristian Brauner /// returned [`PidNamespace`] reference. 39*e0020ba6SChristian Brauner pub unsafe fn from_ptr<'a>(ptr: *const bindings::pid_namespace) -> &'a Self { 40*e0020ba6SChristian Brauner // SAFETY: The safety requirements guarantee the validity of the dereference, while the 41*e0020ba6SChristian Brauner // `PidNamespace` type being transparent makes the cast ok. 42*e0020ba6SChristian Brauner unsafe { &*ptr.cast() } 43*e0020ba6SChristian Brauner } 44*e0020ba6SChristian Brauner } 45*e0020ba6SChristian Brauner 46*e0020ba6SChristian Brauner // SAFETY: Instances of `PidNamespace` are always reference-counted. 47*e0020ba6SChristian Brauner unsafe impl AlwaysRefCounted for PidNamespace { 48*e0020ba6SChristian Brauner #[inline] 49*e0020ba6SChristian Brauner fn inc_ref(&self) { 50*e0020ba6SChristian Brauner // SAFETY: The existence of a shared reference means that the refcount is nonzero. 51*e0020ba6SChristian Brauner unsafe { bindings::get_pid_ns(self.as_ptr()) }; 52*e0020ba6SChristian Brauner } 53*e0020ba6SChristian Brauner 54*e0020ba6SChristian Brauner #[inline] 55*e0020ba6SChristian Brauner unsafe fn dec_ref(obj: ptr::NonNull<PidNamespace>) { 56*e0020ba6SChristian Brauner // SAFETY: The safety requirements guarantee that the refcount is non-zero. 57*e0020ba6SChristian Brauner unsafe { bindings::put_pid_ns(obj.cast().as_ptr()) } 58*e0020ba6SChristian Brauner } 59*e0020ba6SChristian Brauner } 60*e0020ba6SChristian Brauner 61*e0020ba6SChristian Brauner // SAFETY: 62*e0020ba6SChristian Brauner // - `PidNamespace::dec_ref` can be called from any thread. 63*e0020ba6SChristian Brauner // - It is okay to send ownership of `PidNamespace` across thread boundaries. 64*e0020ba6SChristian Brauner unsafe impl Send for PidNamespace {} 65*e0020ba6SChristian Brauner 66*e0020ba6SChristian Brauner // SAFETY: It's OK to access `PidNamespace` through shared references from other threads because 67*e0020ba6SChristian Brauner // we're either accessing properties that don't change or that are properly synchronised by C code. 68*e0020ba6SChristian Brauner unsafe impl Sync for PidNamespace {} 69