]> git.proxmox.com Git - pve-lxc-syscalld.git/blame - src/sys_mknod.rs
WIP
[pve-lxc-syscalld.git] / src / sys_mknod.rs
CommitLineData
937921aa 1use std::ffi::CString;
275009ec 2use std::os::unix::io::{AsRawFd, FromRawFd};
937921aa 3
e420f6f9 4use failure::Error;
937921aa 5use nix::sys::stat;
e420f6f9 6
61bfa355 7use crate::fork::forking_syscall;
3bb4df0b 8use crate::{libc_try, sc_libc_try};
e420f6f9 9use crate::lxcseccomp::ProxyMessageBuffer;
275009ec 10use crate::pidfd::PidFd;
c95be5f6 11use crate::syscall::SyscallStatus;
937921aa 12use crate::tools::Fd;
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
WB
23
24 let pidfd = unsafe { PidFd::from_raw_fd(msg.pid_fd().as_raw_fd()) };
25 do_mknodat(pidfd, 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
WB
31 if !check_mknod_dev(mode, dev) {
32 return Ok(SyscallStatus::Err(libc::EPERM));
33 }
34
35 let dirfd = msg.arg_fd(0, libc::O_DIRECTORY)?;
36 let pathname = msg.arg_c_string(1)?;
275009ec
WB
37
38 let pidfd = unsafe { PidFd::from_raw_fd(msg.pid_fd().as_raw_fd()) };
39 do_mknodat(pidfd, dirfd, pathname, mode, dev).await
e420f6f9
WB
40}
41
3bb4df0b
WB
42fn check_mknod_dev(mode: stat::mode_t, dev: stat::dev_t) -> bool {
43 let sflag = mode & libc::S_IFMT;
44 let major = stat::major(dev);
45 let minor = stat::minor(dev);
46
47 match (sflag, major, minor) {
48 (libc::S_IFCHR, 1, 3) => true,
49 _ => false,
50 }
51}
52
937921aa 53async fn do_mknodat(
275009ec
WB
54 pidfd: PidFd,
55 dirfd: Fd,
3bb4df0b
WB
56 pathname: CString,
57 mode: stat::mode_t,
58 dev: stat::dev_t,
937921aa 59) -> Result<SyscallStatus, Error> {
3bb4df0b
WB
60 let (uid, gid) = pidfd.get_euid_egid()?;
61
62 // FIXME: !!! ALSO COPY THE PROCESS' CAPABILITY SET AND USE KEEP_CAPS!
63
61bfa355 64 Ok(forking_syscall(move || {
275009ec 65 pidfd.mount_namespace()?.setns()?;
3bb4df0b
WB
66 libc_try!(unsafe { libc::fchdir(dirfd.as_raw_fd()) });
67 libc_try!(unsafe { libc::setegid(gid) });
68 libc_try!(unsafe { libc::seteuid(uid) });
69 let out = sc_libc_try!(unsafe {
70 libc::mknodat(
71 dirfd.as_raw_fd(),
72 pathname.as_ptr(),
73 mode,
74 dev,
75 )
76 });
77 Ok(SyscallStatus::Ok(out.into()))
275009ec
WB
78 })
79 .await?)
e420f6f9 80}