Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export interface PtyOptions {
dir?: string;
size?: Size;
cgroupPath?: string;
newCgroupNamespace?: boolean;
apparmorProfile?: string;
interactive?: boolean;
sandbox?: SandboxOptions;
Expand Down
30 changes: 28 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ struct PtyOptions {
pub dir: Option<String>,
pub size: Option<Size>,
pub cgroup_path: Option<String>,
pub new_cgroup_namespace: Option<bool>,
pub apparmor_profile: Option<String>,
pub interactive: Option<bool>,
pub sandbox: Option<SandboxOptions>,
Expand Down Expand Up @@ -127,6 +128,22 @@ impl Pty {
));
}

#[cfg(not(target_os = "linux"))]
if opts.new_cgroup_namespace.unwrap_or(false) {
return Err(napi::Error::new(
napi::Status::GenericFailure,
"new_cgroup_namespace is only supported on Linux",
));
}

#[cfg(target_os = "linux")]
if opts.new_cgroup_namespace.unwrap_or(false) && opts.cgroup_path.is_none() {
return Err(napi::Error::new(
napi::Status::GenericFailure,
"cannot enable new_cgroup_namespace without cgroup_path",
));
}

#[cfg(target_os = "linux")]
if opts.sandbox.is_some() && opts.cgroup_path.is_none() {
return Err(napi::Error::new(
Expand Down Expand Up @@ -188,10 +205,19 @@ impl Pty {
#[cfg(target_os = "linux")]
if let Some(cgroup_path) = &opts.cgroup_path {
let pid = libc::getpid();
let cgroup_path = format!("{}/cgroup.procs", cgroup_path);
let mut cgroup_file = File::create(cgroup_path)?;
let cgroup_procs = format!("{}/cgroup.procs", cgroup_path);
let mut cgroup_file = File::create(cgroup_procs)?;
cgroup_file.write_all(format!("{}", pid).as_bytes())?;

// Unshare the cgroup namespace, rooting it at the scope we just joined.
// This prevents the child from seeing or writing to any cgroup outside its own subtree.
if opts.new_cgroup_namespace.unwrap_or(false) {
let ret = libc::unshare(libc::CLONE_NEWCGROUP);
if ret != 0 {
return Err(Error::last_os_error());
}
}

// also set the sandbox if specified. It's important for it to be in a cgroup so that we don't
// accidentally leak processes if something went wrong.
if let Some(sandbox_opts) = &opts.sandbox {
Expand Down
Loading