apparmor support
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
f6a483ad15
commit
42f2575678
42
src/apparmor.rs
Normal file
42
src/apparmor.rs
Normal file
@ -0,0 +1,42 @@
|
||||
//! AppArmor utility functions.
|
||||
|
||||
use std::ffi::{CStr, OsStr, OsString};
|
||||
use std::io::{self, Write};
|
||||
use std::os::unix::ffi::{OsStrExt, OsStringExt};
|
||||
|
||||
use crate::pidfd::PidFd;
|
||||
|
||||
pub fn get_label(pidfd: &PidFd) -> io::Result<Option<OsString>> {
|
||||
let mut out = match pidfd.read_file(unsafe {
|
||||
CStr::from_bytes_with_nul_unchecked(b"attr/current\0")
|
||||
}) {
|
||||
Ok(out) => out,
|
||||
Err(ref e) if e.raw_os_error() == Some(libc::EINVAL) => return Ok(None),
|
||||
Err(other) => return Err(other.into()),
|
||||
};
|
||||
|
||||
if out.len() == 0 {
|
||||
return Err(io::ErrorKind::UnexpectedEof.into());
|
||||
}
|
||||
|
||||
if let Some(pos) = out.iter().position(|c| *c == b' ' || *c == b'\n') {
|
||||
out.truncate(pos);
|
||||
}
|
||||
|
||||
Ok(Some(OsString::from_vec(out)))
|
||||
}
|
||||
|
||||
pub fn set_label(pidfd: &PidFd, label: &OsStr) -> io::Result<()> {
|
||||
let mut file = pidfd.open_file(
|
||||
unsafe { CStr::from_bytes_with_nul_unchecked(b"attr/current\0") },
|
||||
libc::O_RDWR | libc::O_CLOEXEC,
|
||||
0
|
||||
)?;
|
||||
|
||||
let mut bytes = Vec::with_capacity(14 + label.len());
|
||||
bytes.extend_from_slice(b"changeprofile ");
|
||||
bytes.extend_from_slice(label.as_bytes());
|
||||
|
||||
file.write_all(&bytes)?;
|
||||
Ok(())
|
||||
}
|
@ -6,6 +6,7 @@ use std::io;
|
||||
use failure::{bail, format_err, Error};
|
||||
use nix::sys::socket::SockAddr;
|
||||
|
||||
pub mod apparmor;
|
||||
pub mod client;
|
||||
pub mod fork;
|
||||
pub mod lxcseccomp;
|
||||
|
25
src/pidfd.rs
25
src/pidfd.rs
@ -45,6 +45,14 @@ pub struct ProcStatus {
|
||||
}
|
||||
|
||||
impl PidFd {
|
||||
pub fn current() -> io::Result<Self> {
|
||||
let fd = libc_try!(unsafe {
|
||||
libc::open(b"/proc/self\0".as_ptr() as _, libc::O_DIRECTORY | libc::O_CLOEXEC)
|
||||
});
|
||||
|
||||
Ok(Self(fd, unsafe { libc::getpid() }))
|
||||
}
|
||||
|
||||
pub fn open(pid: pid_t) -> io::Result<Self> {
|
||||
let path = CString::new(format!("/proc/{}", pid)).unwrap();
|
||||
|
||||
@ -260,6 +268,15 @@ impl PidFd {
|
||||
Ok(cgroups)
|
||||
}
|
||||
|
||||
pub fn read_file(&self, file: &CStr) -> io::Result<Vec<u8>> {
|
||||
use io::Read;
|
||||
|
||||
let mut reader = self.open_file(file, libc::O_RDONLY | libc::O_CLOEXEC, 0)?;
|
||||
let mut out = Vec::new();
|
||||
reader.read_to_end(&mut out)?;
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
pub fn user_caps(&self) -> Result<UserCaps, Error> {
|
||||
UserCaps::new(self)
|
||||
}
|
||||
@ -380,12 +397,14 @@ pub struct UserCaps<'a> {
|
||||
umask: libc::mode_t,
|
||||
cgroup_v1_devices: Option<OsString>,
|
||||
cgroup_v2: Option<OsString>,
|
||||
apparmor_profile: Option<OsString>,
|
||||
}
|
||||
|
||||
impl UserCaps<'_> {
|
||||
pub fn new(pidfd: &PidFd) -> Result<UserCaps, Error> {
|
||||
let status = pidfd.get_status()?;
|
||||
let cgroups = pidfd.get_cgroups()?;
|
||||
let apparmor_profile = crate::apparmor::get_label(pidfd)?;
|
||||
|
||||
Ok(UserCaps {
|
||||
pidfd,
|
||||
@ -397,6 +416,7 @@ impl UserCaps<'_> {
|
||||
umask: status.umask,
|
||||
cgroup_v1_devices: cgroups.get("devices").map(|s| s.to_owned()),
|
||||
cgroup_v2: cgroups.v2().map(|s| s.to_owned()),
|
||||
apparmor_profile,
|
||||
})
|
||||
}
|
||||
|
||||
@ -434,11 +454,14 @@ impl UserCaps<'_> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn apply(self) -> io::Result<()> {
|
||||
pub fn apply(self, own_pidfd: &PidFd) -> io::Result<()> {
|
||||
self.apply_cgroups()?;
|
||||
self.pidfd.mount_namespace()?.setns()?;
|
||||
self.pidfd.enter_chroot()?;
|
||||
self.pidfd.enter_cwd()?;
|
||||
if let Some(ref label) = self.apparmor_profile {
|
||||
crate::apparmor::set_label(own_pidfd, label)?;
|
||||
}
|
||||
self.apply_user_caps()?;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -67,7 +67,8 @@ async fn do_mknodat(
|
||||
let caps = pidfd.user_caps()?;
|
||||
|
||||
Ok(forking_syscall(move || {
|
||||
caps.apply()?;
|
||||
let this = PidFd::current()?;
|
||||
caps.apply(&this)?;
|
||||
let out =
|
||||
sc_libc_try!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) });
|
||||
Ok(SyscallStatus::Ok(out.into()))
|
||||
|
Loading…
x
Reference in New Issue
Block a user