]> git.proxmox.com Git - pve-lxc-syscalld.git/blame - src/sys_mknod.rs
handle capabilities and permission checks for mknod
[pve-lxc-syscalld.git] / src / sys_mknod.rs
CommitLineData
937921aa 1use std::ffi::CString;
512f780a 2use std::os::unix::io::AsRawFd;
937921aa 3
e420f6f9 4use failure::Error;
937921aa 5use nix::sys::stat;
e420f6f9 6
61bfa355 7use crate::fork::forking_syscall;
e420f6f9 8use crate::lxcseccomp::ProxyMessageBuffer;
275009ec 9use crate::pidfd::PidFd;
c95be5f6 10use crate::syscall::SyscallStatus;
937921aa 11use crate::tools::Fd;
512f780a 12use crate::{libc_try, sc_libc_try};
e420f6f9 13
c95be5f6 14pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
937921aa
WB
15 let mode = msg.arg_mode_t(1)?;
16 let dev = msg.arg_dev_t(2)?;
3bb4df0b
WB
17 if !check_mknod_dev(mode, dev) {
18 return Ok(SyscallStatus::Err(libc::EPERM));
19 }
20
21 let pathname = msg.arg_c_string(0)?;
937921aa 22 let cwd = msg.pid_fd().fd_cwd()?;
275009ec 23
512f780a 24 do_mknodat(msg.pid_fd(), cwd, pathname, mode, dev).await
937921aa
WB
25}
26
27pub async fn mknodat(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
937921aa
WB
28 let mode = msg.arg_mode_t(2)?;
29 let dev = msg.arg_dev_t(3)?;
3bb4df0b
WB
30 if !check_mknod_dev(mode, dev) {
31 return Ok(SyscallStatus::Err(libc::EPERM));
32 }
33
34 let dirfd = msg.arg_fd(0, libc::O_DIRECTORY)?;
35 let pathname = msg.arg_c_string(1)?;
275009ec 36
512f780a 37 do_mknodat(msg.pid_fd(), dirfd, pathname, mode, dev).await
e420f6f9
WB
38}
39
3bb4df0b
WB
40fn check_mknod_dev(mode: stat::mode_t, dev: stat::dev_t) -> bool {
41 let sflag = mode & libc::S_IFMT;
42 let major = stat::major(dev);
43 let minor = stat::minor(dev);
44
45 match (sflag, major, minor) {
46 (libc::S_IFCHR, 1, 3) => true,
47 _ => false,
48 }
49}
50
937921aa 51async fn do_mknodat(
512f780a 52 pidfd: &PidFd,
275009ec 53 dirfd: Fd,
3bb4df0b
WB
54 pathname: CString,
55 mode: stat::mode_t,
56 dev: stat::dev_t,
937921aa 57) -> Result<SyscallStatus, Error> {
512f780a 58 let caps = pidfd.user_caps()?;
3bb4df0b
WB
59
60 // FIXME: !!! ALSO COPY THE PROCESS' CAPABILITY SET AND USE KEEP_CAPS!
61
61bfa355 62 Ok(forking_syscall(move || {
512f780a 63 caps.apply_cgroups()?;
275009ec 64 pidfd.mount_namespace()?.setns()?;
512f780a 65 pidfd.chroot()?;
3bb4df0b 66 libc_try!(unsafe { libc::fchdir(dirfd.as_raw_fd()) });
512f780a
WB
67 caps.apply_user_caps()?;
68 let out =
69 sc_libc_try!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) });
3bb4df0b 70 Ok(SyscallStatus::Ok(out.into()))
275009ec
WB
71 })
72 .await?)
e420f6f9 73}