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