more quota code
Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
6651043d52
commit
7470f14b85
@ -2,7 +2,7 @@
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::c_int;
|
||||
use std::os::raw::{c_int, c_uint};
|
||||
use std::os::unix::fs::FileExt;
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::{io, mem};
|
||||
@ -317,6 +317,36 @@ impl ProxyMessageBuffer {
|
||||
.ok_or_else(|| Errno::EINVAL.into())
|
||||
}
|
||||
|
||||
/// Read a user space pointer parameter.
|
||||
#[inline]
|
||||
pub fn arg_struct<T>(&self, arg: u32) -> Result<T, Error> {
|
||||
let offset = self.arg(arg)?;
|
||||
let mut data: T = unsafe { mem::zeroed() };
|
||||
let slice = unsafe {
|
||||
std::slice::from_raw_parts_mut(&mut data as *mut _ as *mut u8, mem::size_of::<T>())
|
||||
};
|
||||
let got = self.mem_fd().read_at(slice, offset)?;
|
||||
if got != mem::size_of::<T>() {
|
||||
Err(Errno::EINVAL.into())
|
||||
} else {
|
||||
Ok(data)
|
||||
}
|
||||
}
|
||||
|
||||
/// Read a user space pointer parameter.
|
||||
#[inline]
|
||||
pub fn mem_write_struct<T>(&self, offset: u64, data: &T) -> io::Result<()> {
|
||||
let slice = unsafe {
|
||||
std::slice::from_raw_parts(data as *const T as *const u8, mem::size_of::<T>())
|
||||
};
|
||||
let got = self.mem_fd().write_at(slice, offset)?;
|
||||
if got != mem::size_of::<T>() {
|
||||
Err(Errno::EINVAL.into())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Checked way to get a `mode_t` argument.
|
||||
#[inline]
|
||||
pub fn arg_mode_t(&self, arg: u32) -> Result<nix::sys::stat::mode_t, Error> {
|
||||
@ -340,10 +370,16 @@ impl ProxyMessageBuffer {
|
||||
}
|
||||
}
|
||||
|
||||
/// Checked way to get a c_uint argument.
|
||||
#[inline]
|
||||
pub fn arg_uint(&self, arg: u32) -> Result<c_uint, Error> {
|
||||
c_uint::try_from(self.arg(arg)?).map_err(|_| Errno::EINVAL.into())
|
||||
}
|
||||
|
||||
/// Checked way to get a c_int argument.
|
||||
#[inline]
|
||||
pub fn arg_int(&self, arg: u32) -> Result<c_int, Error> {
|
||||
c_int::try_from(self.arg(arg)?).map_err(|_| Errno::EINVAL.into())
|
||||
self.arg_uint(arg).map(|u| u as c_int)
|
||||
}
|
||||
|
||||
/// Checked way to get a `caddr_t` argument.
|
||||
|
31
src/pidfd.rs
31
src/pidfd.rs
@ -386,6 +386,7 @@ impl Capabilities {
|
||||
#[must_use = "not using UserCaps may be a security issue"]
|
||||
pub struct UserCaps<'a> {
|
||||
pidfd: &'a PidFd,
|
||||
apply_uids: bool,
|
||||
euid: libc::uid_t,
|
||||
egid: libc::gid_t,
|
||||
fsuid: libc::uid_t,
|
||||
@ -405,6 +406,7 @@ impl UserCaps<'_> {
|
||||
|
||||
Ok(UserCaps {
|
||||
pidfd,
|
||||
apply_uids: true,
|
||||
euid: status.uids.euid,
|
||||
egid: status.uids.egid,
|
||||
fsuid: status.uids.fsuid,
|
||||
@ -440,20 +442,31 @@ impl UserCaps<'_> {
|
||||
|
||||
fn apply_user_caps(&self) -> io::Result<()> {
|
||||
use crate::capability::SecureBits;
|
||||
unsafe {
|
||||
libc::umask(self.umask);
|
||||
if self.apply_uids {
|
||||
unsafe {
|
||||
libc::umask(self.umask);
|
||||
}
|
||||
let mut secbits = SecureBits::get_current()?;
|
||||
secbits |= SecureBits::KEEP_CAPS | SecureBits::NO_SETUID_FIXUP;
|
||||
secbits.apply()?;
|
||||
c_try!(unsafe { libc::setegid(self.egid) });
|
||||
c_try!(unsafe { libc::setfsgid(self.fsgid) });
|
||||
c_try!(unsafe { libc::seteuid(self.euid) });
|
||||
c_try!(unsafe { libc::setfsuid(self.fsuid) });
|
||||
}
|
||||
let mut secbits = SecureBits::get_current()?;
|
||||
secbits |= SecureBits::KEEP_CAPS | SecureBits::NO_SETUID_FIXUP;
|
||||
secbits.apply()?;
|
||||
c_try!(unsafe { libc::setegid(self.egid) });
|
||||
c_try!(unsafe { libc::setfsgid(self.fsgid) });
|
||||
c_try!(unsafe { libc::seteuid(self.euid) });
|
||||
c_try!(unsafe { libc::setfsuid(self.fsuid) });
|
||||
self.capabilities.capset()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable_uid_change(&mut self) {
|
||||
self.apply_uids = false;
|
||||
}
|
||||
|
||||
pub fn disable_cgroup_change(&mut self) {
|
||||
self.cgroup_v1_devices = None;
|
||||
self.cgroup_v2 = None;
|
||||
}
|
||||
|
||||
pub fn apply(self, own_pidfd: &PidFd) -> io::Result<()> {
|
||||
self.apply_cgroups()?;
|
||||
self.pidfd.mount_namespace()?.setns()?;
|
||||
|
@ -68,8 +68,7 @@ async fn do_mknodat(
|
||||
let caps = pidfd.user_caps()?;
|
||||
|
||||
Ok(forking_syscall(move || {
|
||||
let this = PidFd::current()?;
|
||||
caps.apply(&this)?;
|
||||
caps.apply(&PidFd::current()?)?;
|
||||
let out =
|
||||
sc_libc_try!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) });
|
||||
Ok(SyscallStatus::Ok(out.into()))
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use std::os::raw::c_int;
|
||||
use std::{mem, ptr};
|
||||
use std::os::raw::{c_int, c_uint};
|
||||
|
||||
use failure::Error;
|
||||
use nix::errno::Errno;
|
||||
@ -54,12 +54,75 @@ pub async fn quotactl(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error>
|
||||
// let _id = msg.arg_int(2)?;
|
||||
// let _addr = msg.arg_caddr_t(3)?;
|
||||
|
||||
match cmd >> SUBCMDSHIFT {
|
||||
let subcmd = ((cmd as c_uint) >> SUBCMDSHIFT) as c_int;
|
||||
match subcmd {
|
||||
libc::Q_GETINFO => q_getinfo(msg, cmd, special).await,
|
||||
libc::Q_GETFMT => q_getfmt(msg, cmd, special).await,
|
||||
libc::Q_QUOTAON => q_quotaon(msg, cmd, special).await,
|
||||
_ => Ok(Errno::ENOSYS.into()),
|
||||
_ => {
|
||||
eprintln!("Unhandled quota subcommand: {}", subcmd);
|
||||
Ok(Errno::ENOSYS.into())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//#[allow(non_camel_case_names)]
|
||||
#[repr(C)]
|
||||
struct dqinfo {
|
||||
dqi_bgrace: u64,
|
||||
dqi_igrace: u64,
|
||||
dqi_flags: u32,
|
||||
dqi_valid: u32,
|
||||
}
|
||||
|
||||
pub async fn q_getinfo(
|
||||
msg: &ProxyMessageBuffer,
|
||||
cmd: c_int,
|
||||
special: Option<CString>,
|
||||
) -> Result<SyscallStatus, Error> {
|
||||
let id = msg.arg_int(2)?;
|
||||
let addr = msg.arg_caddr_t(3)? as u64;
|
||||
|
||||
let mut caps = msg.pid_fd().user_caps()?;
|
||||
Ok(forking_syscall(move || {
|
||||
caps.apply(&PidFd::current()?)?;
|
||||
|
||||
let mut data: dqinfo = unsafe { mem::zeroed() };
|
||||
let special = special.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||
sc_libc_try!(unsafe {
|
||||
libc::quotactl(cmd, special, id, &mut data as *mut dqinfo as *mut i8)
|
||||
});
|
||||
msg.mem_write_struct(addr, &data)?;
|
||||
Ok(SyscallStatus::Ok(0))
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
pub async fn q_getfmt(
|
||||
msg: &ProxyMessageBuffer,
|
||||
cmd: c_int,
|
||||
special: Option<CString>,
|
||||
) -> Result<SyscallStatus, Error> {
|
||||
let id = msg.arg_int(2)?;
|
||||
let addr = msg.arg_caddr_t(3)? as u64;
|
||||
|
||||
let mut caps = msg.pid_fd().user_caps()?;
|
||||
Ok(forking_syscall(move || {
|
||||
caps.apply(&PidFd::current()?)?;
|
||||
|
||||
let mut data: u32 = 0;
|
||||
let special = special.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||
sc_libc_try!(unsafe {
|
||||
libc::quotactl(cmd, special, id, &mut data as *mut u32 as *mut i8)
|
||||
});
|
||||
|
||||
msg.mem_write_struct(addr, &data)?;
|
||||
Ok(SyscallStatus::Ok(0))
|
||||
})
|
||||
.await?)
|
||||
}
|
||||
|
||||
|
||||
pub async fn q_quotaon(
|
||||
msg: &ProxyMessageBuffer,
|
||||
cmd: c_int,
|
||||
@ -67,13 +130,14 @@ pub async fn q_quotaon(
|
||||
) -> Result<SyscallStatus, Error> {
|
||||
let id = msg.arg_int(2)?;
|
||||
let addr = msg.arg_caddr_t(3)? as usize;
|
||||
let special = special.map(|c| c.as_ptr()).unwrap_or(ptr::null()) as usize;
|
||||
|
||||
let caps = msg.pid_fd().user_caps()?;
|
||||
let mut caps = msg.pid_fd().user_caps()?;
|
||||
Ok(forking_syscall(move || {
|
||||
let this = PidFd::current()?;
|
||||
caps.apply(&this)?;
|
||||
let out = sc_libc_try!(unsafe { libc::quotactl(cmd, special as _, id, addr as _) });
|
||||
caps.apply(&PidFd::current()?)?;
|
||||
|
||||
let special = special.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
||||
let out = sc_libc_try!(unsafe { libc::quotactl(cmd, special, id, addr as _) });
|
||||
|
||||
Ok(SyscallStatus::Ok(out.into()))
|
||||
})
|
||||
.await?)
|
||||
|
@ -21,6 +21,7 @@ impl From<Errno> for SyscallStatus {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Syscall {
|
||||
Mknod,
|
||||
MknodAt,
|
||||
|
Loading…
x
Reference in New Issue
Block a user