]>
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; |
bff40ab9 | 12 | use crate::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) { | |
3be1f04c WB |
46 | (libc::S_IFREG, 0, 0) => true, // touch |
47 | (libc::S_IFCHR, 0, 0) => true, // whiteout | |
48 | (libc::S_IFCHR, 5, 0) => true, // /dev/tty | |
49 | (libc::S_IFCHR, 5, 1) => true, // /dev/console | |
50 | (libc::S_IFCHR, 5, 2) => true, // /dev/ptmx | |
51 | (libc::S_IFCHR, 1, 3) => true, // /dev/null | |
52 | (libc::S_IFCHR, 1, 5) => true, // /dev/zero | |
53 | (libc::S_IFCHR, 1, 7) => true, // /dev/full | |
54 | (libc::S_IFCHR, 1, 8) => true, // /dev/random | |
55 | (libc::S_IFCHR, 1, 9) => true, // /dev/urandom | |
3bb4df0b WB |
56 | _ => false, |
57 | } | |
58 | } | |
59 | ||
937921aa | 60 | async fn do_mknodat( |
512f780a | 61 | pidfd: &PidFd, |
275009ec | 62 | dirfd: Fd, |
3bb4df0b WB |
63 | pathname: CString, |
64 | mode: stat::mode_t, | |
65 | dev: stat::dev_t, | |
937921aa | 66 | ) -> Result<SyscallStatus, Error> { |
512f780a | 67 | let caps = pidfd.user_caps()?; |
3bb4df0b | 68 | |
61bfa355 | 69 | Ok(forking_syscall(move || { |
42f25756 WB |
70 | let this = PidFd::current()?; |
71 | caps.apply(&this)?; | |
512f780a WB |
72 | let out = |
73 | sc_libc_try!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) }); | |
3bb4df0b | 74 | Ok(SyscallStatus::Ok(out.into())) |
275009ec WB |
75 | }) |
76 | .await?) | |
e420f6f9 | 77 | } |