2 use std
::os
::unix
::io
::AsRawFd
;
7 use crate::fork
::forking_syscall
;
8 use crate::lxcseccomp
::ProxyMessageBuffer
;
9 use crate::pidfd
::PidFd
;
10 use crate::sc_libc_try
;
11 use crate::syscall
::SyscallStatus
;
14 pub async
fn mknod(msg
: &ProxyMessageBuffer
) -> Result
<SyscallStatus
, Error
> {
15 let mode
= msg
.arg_mode_t(1)?
;
16 let dev
= msg
.arg_dev_t(2)?
;
17 if !check_mknod_dev(mode
, dev
) {
18 return Ok(SyscallStatus
::Err(libc
::EPERM
));
21 let pathname
= msg
.arg_c_string(0)?
;
22 let cwd
= msg
.pid_fd().fd_cwd()?
;
24 do_mknodat(msg
.pid_fd(), cwd
, pathname
, mode
, dev
).await
27 pub async
fn mknodat(msg
: &ProxyMessageBuffer
) -> Result
<SyscallStatus
, Error
> {
28 let mode
= msg
.arg_mode_t(2)?
;
29 let dev
= msg
.arg_dev_t(3)?
;
30 if !check_mknod_dev(mode
, dev
) {
31 return Ok(SyscallStatus
::Err(libc
::EPERM
));
34 let dirfd
= msg
.arg_fd(0, libc
::O_DIRECTORY
)?
;
35 let pathname
= msg
.arg_c_string(1)?
;
37 do_mknodat(msg
.pid_fd(), dirfd
, pathname
, mode
, dev
).await
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
);
45 match (sflag
, major
, minor
) {
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
66 ) -> Result
<SyscallStatus
, Error
> {
67 let caps
= pidfd
.user_caps()?
;
69 Ok(forking_syscall(move || {
70 let this
= PidFd
::current()?
;
73 sc_libc_try
!(unsafe { libc::mknodat(dirfd.as_raw_fd(), pathname.as_ptr(), mode, dev) }
);
74 Ok(SyscallStatus
::Ok(out
.into()))