]>
Commit | Line | Data |
---|---|---|
937921aa | 1 | use std::ffi::CString; |
512f780a | 2 | use std::os::unix::io::AsRawFd; |
937921aa | 3 | |
e420f6f9 | 4 | use failure::Error; |
937921aa | 5 | use nix::sys::stat; |
e420f6f9 | 6 | |
61bfa355 | 7 | use crate::fork::forking_syscall; |
e420f6f9 | 8 | use crate::lxcseccomp::ProxyMessageBuffer; |
275009ec | 9 | use crate::pidfd::PidFd; |
c95be5f6 | 10 | use crate::syscall::SyscallStatus; |
937921aa | 11 | use crate::tools::Fd; |
512f780a | 12 | use crate::{libc_try, sc_libc_try}; |
e420f6f9 | 13 | |
c95be5f6 | 14 | pub 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 | ||
27 | pub 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 |
40 | fn 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 | 51 | async 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 | } |