diff src/libpam/question.rs @ 101:94b51fa4f797

Fix memory soundness issues: - Ensure Questions are pinned in memory when sending them through PAM. - Hold on to the PAM conversation struct after we build it. (Linux-PAM is leninent about this and copies the pam_conv structure.)
author Paul Fisher <paul@pfish.zone>
date Tue, 24 Jun 2025 17:54:33 -0400
parents b87100c5eed4
children
line wrap: on
line diff
--- a/src/libpam/question.rs	Tue Jun 24 17:08:01 2025 -0400
+++ b/src/libpam/question.rs	Tue Jun 24 17:54:33 2025 -0400
@@ -11,6 +11,7 @@
 use crate::Result;
 use num_enum::{IntoPrimitive, TryFromPrimitive};
 use std::ffi::{c_void, CStr};
+use std::pin::Pin;
 use std::slice;
 
 /// Abstraction of a collection of questions to be sent in a PAM conversation.
@@ -64,7 +65,7 @@
         Self: Sized;
 
     /// Gets the pointer that is passed .
-    fn ptr(&self) -> *const *const Question;
+    fn ptr(self: Pin<&Self>) -> *const *const Question;
 
     /// Converts a pointer into a borrowed list of Questions.
     ///
@@ -115,7 +116,7 @@
         })
     }
 
-    fn ptr(&self) -> *const *const Question {
+    fn ptr(self: Pin<&Self>) -> *const *const Question {
         &self.pointer as *const *const Question
     }
 
@@ -131,10 +132,9 @@
 #[derive(Debug)]
 #[repr(C)]
 pub struct LinuxPamQuestions {
-    #[allow(clippy::vec_box)] // we need to do this.
+    #[allow(clippy::vec_box)] // we need to box vec items.
     /// The place where the questions are.
     questions: Vec<Box<Question>>,
-    _marker: Immovable,
 }
 
 impl LinuxPamQuestions {
@@ -155,11 +155,10 @@
             .collect();
         Ok(Self {
             questions: questions?,
-            _marker: Default::default(),
         })
     }
 
-    fn ptr(&self) -> *const *const Question {
+    fn ptr(self: Pin<&Self>) -> *const *const Question {
         self.questions.as_ptr().cast()
     }
 
@@ -246,7 +245,6 @@
         Ok(Self {
             style: style.into(),
             data: Some(data),
-            _marker: Default::default(),
         })
     }
 }
@@ -328,15 +326,15 @@
             use super::super::*;
             #[test]
             fn standard() {
-                let interrogation = <$typ>::new(&[
+                let interrogation = Box::pin(<$typ>::new(&[
                     MaskedQAndA::new("hocus pocus").message(),
                     QAndA::new("what").message(),
                     QAndA::new("who").message(),
                     InfoMsg::new("hey").message(),
                     ErrorMsg::new("gasp").message(),
                 ])
-                .unwrap();
-                let indirect = interrogation.ptr();
+                .unwrap());
+                let indirect = interrogation.as_ref().ptr();
 
                 let remade = unsafe { $typ::borrow_ptr(indirect, interrogation.len()) };
                 let messages: Vec<OwnedMessage> = remade
@@ -364,11 +362,11 @@
             #[test]
             #[cfg(feature = "linux-pam-extensions")]
             fn linux_extensions() {
-                let interrogation = <$typ>::new(&[
+                let interrogation = Box::pin(<$typ>::new(&[
                     BinaryQAndA::new((&[5, 4, 3, 2, 1], 66)).message(),
                     RadioQAndA::new("you must choose").message(),
-                ]).unwrap();
-                let indirect = interrogation.ptr();
+                ]).unwrap());
+                let indirect = interrogation.as_ref().ptr();
 
                 let remade = unsafe { $typ::borrow_ptr(indirect, interrogation.len()) };
                 let messages: Vec<OwnedMessage> = remade