comparison src/libpam/conversation.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 3f11b8d30f63
children
comparison
equal deleted inserted replaced
100:3f11b8d30f63 101:94b51fa4f797
1 use crate::conv::{BinaryQAndA, RadioQAndA}; 1 use crate::conv::{BinaryQAndA, RadioQAndA};
2 use crate::conv::{Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA}; 2 use crate::conv::{Conversation, ErrorMsg, InfoMsg, MaskedQAndA, Message, QAndA};
3 use crate::libpam::answer::BinaryAnswer; 3 use crate::libpam::answer::BinaryAnswer;
4 use crate::libpam::answer::{Answer, Answers, TextAnswer}; 4 use crate::libpam::answer::{Answer, Answers, TextAnswer};
5 use crate::libpam::memory::{CBinaryData, Immovable}; 5 use crate::libpam::memory::CBinaryData;
6 use crate::libpam::pam_ffi::AppData; 6 use crate::libpam::pam_ffi::AppData;
7 pub use crate::libpam::pam_ffi::LibPamConversation; 7 pub use crate::libpam::pam_ffi::LibPamConversation;
8 use crate::libpam::question::QuestionsTrait; 8 use crate::libpam::question::QuestionsTrait;
9 use crate::libpam::question::{Question, Questions}; 9 use crate::libpam::question::{Question, Questions};
10 use crate::ErrorCode; 10 use crate::ErrorCode;
19 pub fn wrap<C: Conversation>(conv: &C) -> Self { 19 pub fn wrap<C: Conversation>(conv: &C) -> Self {
20 Self { 20 Self {
21 callback: Self::wrapper_callback::<C>, 21 callback: Self::wrapper_callback::<C>,
22 appdata: (conv as *const C).cast(), 22 appdata: (conv as *const C).cast(),
23 life: PhantomData, 23 life: PhantomData,
24 _marker: Immovable(PhantomData),
25 } 24 }
26 } 25 }
27 26
28 /// Passed as the conversation function into PAM for an owned handle. 27 /// Passed as the conversation function into PAM for an owned handle.
29 /// 28 ///
64 } 63 }
65 64
66 impl Conversation for LibPamConversation<'_> { 65 impl Conversation for LibPamConversation<'_> {
67 fn communicate(&self, messages: &[Message]) { 66 fn communicate(&self, messages: &[Message]) {
68 let internal = || { 67 let internal = || {
69 let questions = Questions::new(messages)?; 68 let questions = Box::pin(Questions::new(messages)?);
70 let mut response_pointer = std::ptr::null_mut(); 69 let mut response_pointer = std::ptr::null_mut();
71 // SAFETY: We're calling into PAM with valid everything. 70 // SAFETY: We're calling into PAM with valid everything.
72 let result = unsafe { 71 let result = unsafe {
73 (self.callback)( 72 (self.callback)(
74 messages.len() as c_int, 73 messages.len() as c_int,
75 questions.ptr(), 74 questions.as_ref().ptr(),
76 &mut response_pointer, 75 &mut response_pointer,
77 self.appdata, 76 self.appdata,
78 ) 77 )
79 }; 78 };
80 ErrorCode::result_from(result)?; 79 ErrorCode::result_from(result)?;