Skip to content

Commit ec4d843

Browse files
committed
Implement capget,capset
In capget, we will always return the empty capability bitfield because we don't allow any capability in the plugin. In capset, we will allow to set with the empty capability bitfield.
1 parent 25223ea commit ec4d843

7 files changed

Lines changed: 91 additions & 13 deletions

File tree

src/Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/lib/pod/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ edition = "2021"
77

88
[dependencies]
99
libc = { version = "0.2.148", default-features = false }
10+
linux-raw-sys = "0.5.2"

src/lib/pod/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,3 +325,7 @@ unsafe impl Pod for libc::utmpx {}
325325
unsafe impl Pod for libc::utsname {}
326326
unsafe impl Pod for libc::winsize {}
327327
unsafe impl Pod for libc::clone_args {}
328+
329+
// linux-raw-sys types
330+
unsafe impl Pod for linux_raw_sys::general::__user_cap_header_struct {}
331+
unsafe impl Pod for linux_raw_sys::general::__user_cap_data_struct {}

src/main/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ crossbeam = "0.8.2"
2323
gml-parser = { path = "../lib/gml-parser" }
2424
libc = "0.2"
2525
linux-api = { path = "../lib/linux-api", features = ["std"] }
26+
linux-raw-sys = "0.5.2"
2627
# don't log debug or trace levels in release mode
2728
log = { version = "0.4", features = ["release_max_level_debug"] }
2829
log-c2rust = { path = "../lib/log-c2rust" }

src/main/host/syscall/handler/clone.rs

Lines changed: 79 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use syscall_logger::log_syscall;
1111

1212
use crate::host::descriptor::descriptor_table::DescriptorTable;
1313
use crate::host::process::ProcessId;
14-
use crate::host::syscall_types::SyscallError;
14+
use crate::host::syscall_types::{SyscallError, SyscallResult};
1515
use crate::host::thread::Thread;
1616

1717
use super::{SyscallContext, SyscallHandler};
@@ -271,12 +271,12 @@ impl SyscallHandler {
271271
// Note that the syscall args are different than the libc wrapper.
272272
// See "C library/kernel differences" in clone(2).
273273
#[log_syscall(
274-
/* rv */kernel_pid_t,
275-
/* flags */i32,
276-
/* child_stack */*const std::ffi::c_void,
277-
/* ptid */*const kernel_pid_t,
278-
/* ctid */*const kernel_pid_t,
279-
/* newtls */*const std::ffi::c_void)]
274+
/* rv */ kernel_pid_t,
275+
/* flags */ i32,
276+
/* child_stack */ *const std::ffi::c_void,
277+
/* ptid */ *const kernel_pid_t,
278+
/* ctid */ *const kernel_pid_t,
279+
/* newtls */ *const std::ffi::c_void)]
280280
pub fn clone(
281281
ctx: &mut SyscallContext,
282282
flags_and_exit_signal: i32,
@@ -307,9 +307,9 @@ impl SyscallHandler {
307307
}
308308

309309
#[log_syscall(
310-
/* rv */kernel_pid_t,
311-
/* args*/*const std::ffi::c_void,
312-
/* args_size*/usize)]
310+
/* rv */ kernel_pid_t,
311+
/* args*/ *const std::ffi::c_void,
312+
/* args_size*/ usize)]
313313
pub fn clone3(
314314
ctx: &mut SyscallContext,
315315
args: ForeignPtr<linux_api::sched::clone_args>,
@@ -346,7 +346,7 @@ impl SyscallHandler {
346346
)
347347
}
348348

349-
#[log_syscall(/* rv */kernel_pid_t)]
349+
#[log_syscall(/* rv */ kernel_pid_t)]
350350
pub fn fork(ctx: &mut SyscallContext) -> Result<kernel_pid_t, SyscallError> {
351351
// This should be the correct call to `clone_internal`, but `clone_internal`
352352
// will currently return an error.
@@ -361,7 +361,7 @@ impl SyscallHandler {
361361
)
362362
}
363363

364-
#[log_syscall(/* rv */kernel_pid_t)]
364+
#[log_syscall(/* rv */ kernel_pid_t)]
365365
pub fn vfork(ctx: &mut SyscallContext) -> Result<kernel_pid_t, SyscallError> {
366366
// This should be the correct call to `clone_internal`, but `clone_internal`
367367
// will currently return an error.
@@ -376,8 +376,74 @@ impl SyscallHandler {
376376
)
377377
}
378378

379-
#[log_syscall(/* rv */kernel_pid_t)]
379+
#[log_syscall(/* rv */ kernel_pid_t)]
380380
pub fn gettid(ctx: &mut SyscallContext) -> Result<kernel_pid_t, SyscallError> {
381381
Ok(kernel_pid_t::from(ctx.objs.thread.id()))
382382
}
383+
384+
#[log_syscall(/* rv */ std::ffi::c_int,
385+
/* hdrp */ *const std::ffi::c_void,
386+
/* datap */ *const std::ffi::c_void)]
387+
pub fn capget(
388+
ctx: &mut SyscallContext,
389+
hdrp: ForeignPtr<linux_raw_sys::general::__user_cap_header_struct>,
390+
datap: ForeignPtr<[linux_raw_sys::general::__user_cap_data_struct; 2]>,
391+
) -> SyscallResult {
392+
// If the version is not 3, we return the error
393+
let hdrp = ctx.objs.process.memory_borrow().read(hdrp)?;
394+
if hdrp.version != linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3 {
395+
warn!(
396+
"The version of Linux capabilities is not supported ({})",
397+
hdrp.version
398+
);
399+
return Err(Errno::EINVAL.into());
400+
}
401+
402+
if !datap.is_null() {
403+
// Since we don't provide any capability to the managed plugin, we return zeroes to both
404+
// datap[0] and datap[1]
405+
let empty = linux_raw_sys::general::__user_cap_data_struct {
406+
effective: 0,
407+
permitted: 0,
408+
inheritable: 0,
409+
};
410+
ctx.objs
411+
.process
412+
.memory_borrow_mut()
413+
.write(datap, &[empty, empty])?;
414+
}
415+
Ok(0.into())
416+
}
417+
418+
#[log_syscall(/* rv */ std::ffi::c_int,
419+
/* hdrp */ *const std::ffi::c_void,
420+
/* datap */ *const std::ffi::c_void)]
421+
pub fn capset(
422+
ctx: &mut SyscallContext,
423+
hdrp: ForeignPtr<linux_raw_sys::general::__user_cap_header_struct>,
424+
datap: ForeignPtr<[linux_raw_sys::general::__user_cap_data_struct; 2]>,
425+
) -> SyscallResult {
426+
// If the version is not 3, we return the error
427+
let hdrp = ctx.objs.process.memory_borrow().read(hdrp)?;
428+
if hdrp.version != linux_raw_sys::general::_LINUX_CAPABILITY_VERSION_3 {
429+
warn!(
430+
"The version of Linux capabilities is not supported ({})",
431+
hdrp.version
432+
);
433+
return Err(Errno::EINVAL.into());
434+
}
435+
436+
let datap: [_; 2] = ctx.objs.process.memory_borrow().read(datap)?;
437+
for data in &datap {
438+
// We don't allow the plugin to set any capability
439+
if data.effective != 0 || data.permitted != 0 || data.inheritable != 0 {
440+
warn!(
441+
"The version of Linux capabilities is not supported ({})",
442+
hdrp.version
443+
);
444+
return Err(Errno::EINVAL.into());
445+
}
446+
}
447+
Ok(0.into())
448+
}
383449
}

src/main/host/syscall/handler/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ impl SyscallHandler {
4545
libc::SYS_accept4 => SyscallHandlerFn::call(Self::accept4, &mut ctx),
4646
libc::SYS_bind => SyscallHandlerFn::call(Self::bind, &mut ctx),
4747
libc::SYS_brk => SyscallHandlerFn::call(Self::brk, &mut ctx),
48+
libc::SYS_capget => SyscallHandlerFn::call(Self::capget, &mut ctx),
49+
libc::SYS_capset => SyscallHandlerFn::call(Self::capset, &mut ctx),
4850
libc::SYS_clock_getres => SyscallHandlerFn::call(Self::clock_getres, &mut ctx),
4951
libc::SYS_clock_nanosleep => SyscallHandlerFn::call(Self::clock_nanosleep, &mut ctx),
5052
libc::SYS_clone => SyscallHandlerFn::call(Self::clone, &mut ctx),

src/main/host/syscall_handler.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ SyscallReturn syscallhandler_make_syscall(SysCallHandler* sys, const SysCallArgs
299299
HANDLE_RUST(accept4);
300300
HANDLE_RUST(bind);
301301
HANDLE_RUST(brk);
302+
HANDLE_RUST(capget);
303+
HANDLE_RUST(capset);
302304
HANDLE_RUST(clock_getres);
303305
SHIM_ONLY(clock_gettime);
304306
HANDLE_RUST(clock_nanosleep);

0 commit comments

Comments
 (0)