use crate::disk::inode::InodeMode; use libc::{F_OK, S_ISGID, S_ISUID, S_IXGRP, X_OK}; use std::fs::File; use std::io::BufRead; pub(crate) fn get_groups(pid: u32) -> Vec { let file = File::open(format!("/proc/{pid}/task/{pid}/status")) .expect(format!("pid {pid} incorrect!").as_str()); for line in std::io::BufReader::new(file).lines() { let line = line.unwrap(); if line.starts_with("Groups:") { return line["Groups: ".len()..] .split(' ') .filter(|x| !x.trim().is_empty()) .map(|x| x.parse::().unwrap()) .collect(); } } Vec::new() } pub(crate) fn clear_suid_sgid(mut mode: InodeMode) -> InodeMode { mode.0 &= !S_ISUID as u16; if mode.0 & S_IXGRP as u16 != 0 { mode.0 &= !S_ISGID as u16; } mode } pub(crate) fn check_access( incoming_uid: u32, incoming_gid: u32, uid: u32, gid: u32, mode: InodeMode, mut mask: i32, ) -> bool { if mask == F_OK { return true; } let perm = i32::from(mode.0); // root if incoming_uid == 0 { // 读写任何东西都是可以的, 执行只有 IXOTH/IXGRP/IXUSR 之一设置才可以 mask &= X_OK; mask -= mask & (perm >> 6); mask -= mask & (perm >> 3); mask -= mask & perm; return mask == 0; } if incoming_uid == uid { mask -= mask & (perm >> 6); } else if incoming_gid == gid { mask -= mask & (perm >> 3); } else { mask -= mask & perm; } mask == 0 }