]> git.proxmox.com Git - pve-lxc-syscalld.git/blame - src/sys_mknod.rs
cleanup
[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;
9be25f82 5use nix::errno::Errno;
937921aa 6use nix::sys::stat;
e420f6f9 7
61bfa355 8use crate::fork::forking_syscall;
e420f6f9 9use crate::lxcseccomp::ProxyMessageBuffer;
275009ec 10use crate::pidfd::PidFd;
942f3c73 11use crate::sc_libc_try;
c95be5f6 12use crate::syscall::SyscallStatus;
937921aa 13use crate::tools::Fd;
e420f6f9 14
c95be5f6 15pub async fn mknod(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
937921aa
WB
16 let mode = msg.arg_mode_t(1)?;
17 let dev = msg.arg_dev_t(2)?;
3bb4df0b 18 if !check_mknod_dev(mode, dev) {
9be25f82 19 return Ok(Errno::EPERM.into());
3bb4df0b
WB
20 }
21
22 let pathname = msg.arg_c_string(0)?;
937921aa 23 let cwd = msg.pid_fd().fd_cwd()?;
275009ec 24
512f780a 25 do_mknodat(msg.pid_fd(), cwd, pathname, mode, dev).await
937921aa
WB
26}
27
28pub async fn mknodat(msg: &ProxyMessageBuffer) -> Result<SyscallStatus, Error> {
937921aa
WB
29 let mode = msg.arg_mode_t(2)?;
30 let dev = msg.arg_dev_t(3)?;
3bb4df0b 31 if !check_mknod_dev(mode, dev) {
9be25f82 32 return Ok(Errno::EPERM.into());
3bb4df0b
WB
33 }
34
35 let dirfd = msg.arg_fd(0, libc::O_DIRECTORY)?;
36 let pathname = msg.arg_c_string(1)?;
275009ec 37
512f780a 38 do_mknodat(msg.pid_fd(), dirfd, pathname, mode, dev).await
e420f6f9
WB
39}
40
3bb4df0b
WB
41fn check_mknod_dev(mode: stat::mode_t, dev: stat::dev_t) -> bool {
42 let sflag = mode & libc::S_IFMT;
43 let major = stat::major(dev);
44 let minor = stat::minor(dev);
45
46 match (sflag, major, minor) {
3be1f04c
WB
47 (libc::S_IFREG, 0, 0) => true, // touch
48 (libc::S_IFCHR, 0, 0) => true, // whiteout
49 (libc::S_IFCHR, 5, 0) => true, // /dev/tty
50 (libc::S_IFCHR, 5, 1) => true, // /dev/console
51 (libc::S_IFCHR, 5, 2) => true, // /dev/ptmx
52 (libc::S_IFCHR, 1, 3) => true, // /dev/null
53 (libc::S_IFCHR, 1, 5) => true, // /dev/zero
54 (libc::S_IFCHR, 1, 7) => true, // /dev/full
55 (libc::S_IFCHR, 1, 8) => true, // /dev/random
56 (libc::S_IFCHR, 1, 9) => true, // /dev/urandom
3bb4df0b
WB
57 _ => false,
58 }
59}
60
937921aa 61async fn do_mknodat(
512f780a 62 pidfd: &PidFd,
275009ec 63 dirfd: Fd,
3bb4df0b
WB
64 pathname: CString,
65 mode: stat::mode_t,
66 dev: stat::dev_t,
937921aa 67) -> Result<SyscallStatus, Error> {
512f780a 68 let caps = pidfd.user_caps()?;
3bb4df0b 69
61bfa355 70 Ok(forking_syscall(move || {
42f25756
WB
71 let this = PidFd::current()?;
72 caps.apply(&this)?;
512f780a
WB
73 let out =
74 sc_libc_try!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) });
3bb4df0b 75 Ok(SyscallStatus::Ok(out.into()))
275009ec
WB
76 })
77 .await?)
e420f6f9 78}