diff options
author | Tomasz Kramkowski <tomasz@kramkow.ski> | 2023-01-27 13:58:10 +0000 |
---|---|---|
committer | Tomasz Kramkowski <tomasz@kramkow.ski> | 2023-01-27 13:58:10 +0000 |
commit | 6cef9f0fc159de4c9fd708050ec76adb4e74d390 (patch) | |
tree | 81856b3b4da6d18e10516b0be737a157e13f129b /src | |
parent | 9e8dd00da25273fba9f0cafccbde2236e04fb24e (diff) | |
download | pam_usercg_rust-6cef9f0fc159de4c9fd708050ec76adb4e74d390.tar.gz pam_usercg_rust-6cef9f0fc159de4c9fd708050ec76adb4e74d390.tar.xz pam_usercg_rust-6cef9f0fc159de4c9fd708050ec76adb4e74d390.zip |
openat variant
Diffstat (limited to 'src')
-rw-r--r-- | src/lib.rs | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..23f5b79 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,56 @@ +use libc::mode_t; +use openat::{Dir, AsPath}; +use pam::constants::{PamFlag, PamResultCode}; +use pam::module::{PamHandle, PamHooks}; +use std::ffi::CStr; +use std::io::{ErrorKind, Write}; +use std::process; + +const CG_MOUNT: &str = "/sys/fs/cgroup"; + +struct PAMUserCG; +pam::pam_hooks!(PAMUserCG); + +fn create_and_open_dir<P: AsPath + Copy>( + d: &Dir, path: P, mode: mode_t, + ) -> std::io::Result<Dir> { + match d.create_dir(path, mode) { + Ok(()) => Ok(()), + Err(e) => match e.kind() { + ErrorKind::AlreadyExists => Ok(()), + _ => Err(e), + } + }?; + d.sub_dir(path) +} + +struct SessionError; + +fn open_session(h: &mut PamHandle) -> Result<(), SessionError> { + let user = h.get_user(None).or(Err(SessionError))?; + let user = users::get_user_by_name(&user).ok_or(SessionError)?; + let d = Dir::open(CG_MOUNT).or(Err(SessionError))?; + let d = create_and_open_dir(&d, "user", 0o777).or(Err(SessionError))?; + let d = create_and_open_dir(&d, &user.uid().to_string(), 0o777) + .or(Err(SessionError))?; + let d = create_and_open_dir(&d, "leaf", 0o777).or(Err(SessionError))?; + let pid = process::id().to_string(); + let mut procs = d.open_file_ex("cgroup.procs", libc::O_WRONLY, 0) + .or(Err(SessionError))?; + procs.write_all(pid.as_bytes()).or(Err(SessionError))?; + Ok(()) +} + +impl PamHooks for PAMUserCG { + fn sm_open_session( + h: &mut PamHandle, + _args: Vec<&CStr>, + _flags: PamFlag + ) -> PamResultCode { + if open_session(h).is_ok() { + PamResultCode::PAM_SUCCESS + } else { + PamResultCode::PAM_SESSION_ERR + } + } +} |