shadow_rs/host/syscall/handler/
prctl.rs1use linux_api::errno::Errno;
2use linux_api::prctl::{ArchPrctlOp, PrctlOp};
3use linux_api::sched::SuidDump;
4use linux_api::signal::Signal;
5use shadow_shim_helper_rs::syscall_types::ForeignPtr;
6
7use crate::host::syscall::handler::{SyscallContext, SyscallHandler};
8use crate::host::syscall::types::SyscallError;
9
10impl SyscallHandler {
11 log_syscall!(
12 prctl,
13 std::ffi::c_int,
14 PrctlOp,
15 std::ffi::c_ulong,
16 std::ffi::c_ulong,
17 std::ffi::c_ulong,
18 std::ffi::c_ulong,
19 );
20 pub fn prctl(
21 ctx: &mut SyscallContext,
22 option: PrctlOp,
23 arg2: std::ffi::c_ulong,
24 _arg3: std::ffi::c_ulong,
25 _arg4: std::ffi::c_ulong,
26 _arg5: std::ffi::c_ulong,
27 ) -> Result<std::ffi::c_int, SyscallError> {
28 match option {
29 PrctlOp::PR_CAP_AMBIENT
30 | PrctlOp::PR_CAPBSET_READ
31 | PrctlOp::PR_CAPBSET_DROP
32 | PrctlOp::PR_SET_CHILD_SUBREAPER
33 | PrctlOp::PR_GET_CHILD_SUBREAPER
34 | PrctlOp::PR_SET_ENDIAN
35 | PrctlOp::PR_GET_ENDIAN
36 | PrctlOp::PR_SET_FP_MODE
37 | PrctlOp::PR_GET_FP_MODE
38 | PrctlOp::PR_SET_FPEMU
39 | PrctlOp::PR_GET_FPEMU
40 | PrctlOp::PR_SET_FPEXC
41 | PrctlOp::PR_GET_FPEXC
42 | PrctlOp::PR_SET_KEEPCAPS
43 | PrctlOp::PR_GET_KEEPCAPS
44 | PrctlOp::PR_MCE_KILL
45 | PrctlOp::PR_MCE_KILL_GET
46 | PrctlOp::PR_MPX_ENABLE_MANAGEMENT
47 | PrctlOp::PR_MPX_DISABLE_MANAGEMENT
48 | PrctlOp::PR_SET_NAME
49 | PrctlOp::PR_GET_NAME
50 | PrctlOp::PR_SET_NO_NEW_PRIVS
51 | PrctlOp::PR_GET_NO_NEW_PRIVS
52 | PrctlOp::PR_SET_MM
53 | PrctlOp::PR_SET_PTRACER
54 | PrctlOp::PR_SET_SECUREBITS
55 | PrctlOp::PR_GET_SECUREBITS
56 | PrctlOp::PR_GET_SPECULATION_CTRL
57 | PrctlOp::PR_SET_THP_DISABLE
58 | PrctlOp::PR_TASK_PERF_EVENTS_DISABLE
59 | PrctlOp::PR_TASK_PERF_EVENTS_ENABLE
60 | PrctlOp::PR_GET_THP_DISABLE
61 | PrctlOp::PR_GET_TIMERSLACK
62 | PrctlOp::PR_SET_TIMING
63 | PrctlOp::PR_GET_TIMING
64 | PrctlOp::PR_GET_TSC
65 | PrctlOp::PR_GET_UNALIGN => {
66 log::trace!("prctl {option} executing natively");
67 Err(SyscallError::Native)
68 }
69 PrctlOp::PR_SET_SECCOMP | PrctlOp::PR_GET_SECCOMP => {
70 log::warn!("Not allowing seccomp prctl {option}");
71 Err(Errno::EINVAL.into())
72 }
73 PrctlOp::PR_SET_UNALIGN
75 | PrctlOp::PR_SET_TSC
78 | PrctlOp::PR_SET_TIMERSLACK
81 | PrctlOp::PR_SET_SPECULATION_CTRL => {
83 log::warn!("Not allowing unimplemented prctl {option}");
84 Err(Errno::EINVAL.into())
85 }
86 PrctlOp::PR_SET_PDEATHSIG => {
87 let signal = if arg2 == 0 {
88 None
89 } else {
90 let signal = i32::try_from(arg2).or(Err(Errno::EINVAL))?;
91 Some(Signal::try_from(signal).or(Err(Errno::EINVAL))?)
92 };
93 ctx.objs.process.set_parent_death_signal(signal);
94 Ok(0)
95 }
96 PrctlOp::PR_GET_PDEATHSIG => {
97 let out_ptr = ForeignPtr::from(arg2).cast::<std::ffi::c_int>();
98 let signal = Signal::as_raw(ctx.objs.process.parent_death_signal());
99 ctx.objs.process.memory_borrow_mut().write(out_ptr, &signal)?;
100 Ok(0)
101 }
102 PrctlOp::PR_GET_TID_ADDRESS => {
103 let out_ptr = ForeignPtr::from(arg2)
104 .cast::<ForeignPtr<linux_api::posix_types::kernel_pid_t>>();
105 let tid_addr = ctx.objs.thread.get_tid_address();
106 ctx.objs.process.memory_borrow_mut().write(out_ptr, &tid_addr)?;
107 Ok(0)
108 }
109 PrctlOp::PR_SET_DUMPABLE => {
110 let dumpable = SuidDump::new(arg2.try_into().or(Err(Errno::EINVAL))?);
111 if [SuidDump::SUID_DUMP_DISABLE, SuidDump::SUID_DUMP_USER].contains(&dumpable) {
112 ctx.objs.process.set_dumpable(dumpable);
113 Ok(0)
114 } else {
115 Err(Errno::EINVAL.into())
116 }
117 }
118 PrctlOp::PR_GET_DUMPABLE => {
119 Ok(ctx.objs.process.dumpable().val())
120 }
121 _ => {
122 log::warn!("Unknown prctl operation {option}");
123 Err(Errno::EINVAL.into())
124 }
125 }
126 }
127
128 log_syscall!(
129 arch_prctl,
130 std::ffi::c_ulong,
131 ArchPrctlOp,
132 *const std::ffi::c_void,
136 );
137 pub fn arch_prctl(
138 _ctx: &mut SyscallContext,
139 option: ArchPrctlOp,
140 _arg: std::ffi::c_ulong,
141 ) -> Result<std::ffi::c_ulong, SyscallError> {
142 match option {
143 ArchPrctlOp::ARCH_GET_CPUID => {
144 Ok(1u64)
148 }
149 ArchPrctlOp::ARCH_SET_CPUID => {
150 Err(Errno::ENODEV.into())
160 }
161 ArchPrctlOp::ARCH_SET_FS
162 | ArchPrctlOp::ARCH_GET_FS
163 | ArchPrctlOp::ARCH_SET_GS
164 | ArchPrctlOp::ARCH_GET_GS => {
165 Err(SyscallError::Native)
167 }
168 x => {
169 log::warn!("Unknown or unsupported arch_prctl operation {x:?}");
175 Err(Errno::EINVAL.into())
176 }
177 }
178 }
179}