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