Giter Club home page Giter Club logo

libjail-rs's Introduction

fubarnetes

Scalable Kloud Komputing with bhyve

libjail-rs's People

Contributors

akhramov avatar asomers avatar dependabot-preview[bot] avatar dependabot-support avatar fabianfreyer avatar fossabot avatar phyber avatar pkubaj avatar svartalf avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libjail-rs's Issues

Handling tunable parameters

At the moment we just exclude the following variables from the params method, as we are unable to restore this:

libjail-rs/src/param.rs

Lines 805 to 807 in f7de11b

// FIXME: we should really pass these to jail_create
.filter(|name| name != "osreldate")
.filter(|name| name != "osrelease")

Attemting to set these results in a JailSetError("osrelease cannot be changed after creation").

We cannot set these, as we first start the jail, and then later on set all the parameters:

let ret = sys::jail_create(
&path,
self.name.as_ref().map(String::as_str),
self.hostname.as_ref().map(String::as_str),
).map(RunningJail::from_jid)?;

libjail-rs/src/stopped.rs

Lines 110 to 116 in f7de11b

param::set(ret.jid, "ip4.addr", ip4s)?;
param::set(ret.jid, "ip6.addr", ip6s)?;
// Set remaining parameters
for (param, value) in self.params {
param::set(ret.jid, &param, value)?;
}

It would probably be a good idea to just create a big HashMap of values, and pass that into jail_create.

mount.fstab fails

Hi - Thanks for the library kind of cool that so many freebsd primatives are coming to Rust.
I was testing out building a readonly jail using an fstab definition on my system.

.param("mount.fstab", param::Value::String("/etc/fstab.rojail".to_string()))

I got

thread 'main' panicked at 'could not start jail: JailSetError("unknown parameter: mount.fstab")', src/libcore/result.rs:1009:5

Looking at jail(8) I see it's a pseudo-parameter so I wasn't too surprised but thought I would raise this if you start to prioritize them.

serde: StoppedJail

It would be great to serialize the configuration of a StoppedJail into JSON, YAML, TOML, etc. in a as sane as possible way.

Tracking: TryFrom for RunningJail and StoppedJail

as soon as the TryFrom and TryInto traits are stabilized, implement:

impl TryFrom<StoppedJail> for RunningJail {
    fn from(stopped) -> Result<RunningJail, JailError> {
        stopped.start()
    }
}

and vice versa:

impl TryFrom<RunningJail> for StoppedJail {
    fn from(running) -> Result<StoppedJail, JailError> {
        running.stop()
    }
}

RCTL/RACCT statistics

Import the rctl(8) code from phyber/jail_exporter. I guess the API could be something along the lines of:

fn RunningJail::resource_usage(&self) -> Result<HashMap<String,i64>,JailError>

If RCTL/RACCT are unavailable or disabled, an appropriate JailError should be returned.

Nested jails

Testing with nested Jails has brought up some bugs:

  • At the moment, BuildBot builds are failing because we seem to be handling nested jails things rather flakily - namely we're setting properties that we aren't allowed to in the tests.

    • We should conditionally disable these in the tests.
  • RCTL doesn't work in Jails (#22):

    • as of version 0.0.3 of rctl, (#23), the status check reports an invalid kernel state when attempting to use RCTL inside a jail.
    • this broke jail teardown (#24)

API to get general parameter type

At the moment the only way to get a parameter type is calling param on a RunningJail and then getting the type from that:

use jail::param::Type;

let param = running.param("osrelease").unwrap();
let param_type: Type = param.into();

assert_eq!(param_type, Type::String);

It would be great if we could get the type for a parameter without requiring a RunningJail:

use jail::param::Type;
let param_type = Type::of_param("osrelease");

assert_eq!(param_type, Type::String);

This would allow refactoring the huge match in param::get to actually match on the param::Type instead of the sysctl::CtlType, and outsource the handling of the different CtlType::Struct cases:

libjail-rs/src/param.rs

Lines 573 to 652 in f7de11b

match paramtype {
CtlType::Int => Ok(Value::Int(
LittleEndian::read_int(&value, mem::size_of::<libc::c_int>()) as libc::c_int,
)),
CtlType::S64 => Ok(Value::S64(LittleEndian::read_i64(&value))),
CtlType::Uint => Ok(Value::Uint(LittleEndian::read_uint(
&value,
mem::size_of::<libc::c_uint>(),
) as libc::c_uint)),
CtlType::Long => Ok(Value::Long(LittleEndian::read_int(
&value,
mem::size_of::<libc::c_long>(),
) as libc::c_long)),
CtlType::Ulong => Ok(Value::Ulong(LittleEndian::read_uint(
&value,
mem::size_of::<libc::c_ulong>(),
) as libc::c_ulong)),
CtlType::U64 => Ok(Value::U64(LittleEndian::read_u64(&value))),
CtlType::U8 => Ok(Value::U8(value[0])),
CtlType::U16 => Ok(Value::U16(LittleEndian::read_u16(&value))),
CtlType::S8 => Ok(Value::S8(value[0] as i8)),
CtlType::S16 => Ok(Value::S16(LittleEndian::read_i16(&value))),
CtlType::S32 => Ok(Value::S32(LittleEndian::read_i32(&value))),
CtlType::U32 => Ok(Value::U32(LittleEndian::read_u32(&value))),
CtlType::String => Ok(Value::String({
unsafe { CStr::from_ptr(value.as_ptr() as *mut i8) }
.to_string_lossy()
.into_owned()
})),
CtlType::Struct => match name {
// FIXME: The following is just placeholder code.
"ip4.addr" => {
// Make sure we got the right data size
let addrsize = mem::size_of::<libc::in_addr>();
let count = valuesize / addrsize;
assert_eq!(
0,
typesize % addrsize,
"Error: memory size mismatch. Length of data \
retrieved is not a multiple of the size of in_addr."
);
#[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
let ips: Vec<net::Ipv4Addr> = unsafe {
slice::from_raw_parts(value.as_ptr() as *const libc::in_addr, count)
}.iter()
.map(|in_addr| u32::from_be(in_addr.s_addr))
.map(net::Ipv4Addr::from)
.filter(|ip| !ip.is_unspecified())
.collect();
Ok(Value::Ipv4Addrs(ips))
}
"ip6.addr" => {
// Make sure we got the right data size
let addrsize = mem::size_of::<libc::in6_addr>();
let count = valuesize / addrsize;
assert_eq!(
0,
typesize % addrsize,
"Error: memory size mismatch. Length of data \
retrieved is not a multiple of the size of in_addr."
);
#[cfg_attr(feature = "cargo-clippy", allow(cast_ptr_alignment))]
let ips: Vec<net::Ipv6Addr> = unsafe {
slice::from_raw_parts(value.as_ptr() as *const libc::in6_addr, count)
}.iter()
.map(|in6_addr| net::Ipv6Addr::from(in6_addr.s6_addr))
.filter(|ip| !ip.is_unspecified())
.collect();
Ok(Value::Ipv6Addrs(ips))
}
_ => Err(JailError::ParameterTypeUnsupported(paramtype)),
},
_ => Err(JailError::ParameterTypeUnsupported(paramtype)),
}

Overhaul parameter getter

We should probably not filter parameters at this time:

libjail-rs/src/param.rs

Lines 833 to 844 in 1f1e1d9

// The following parameters are dynamic
.filter(|name| name != "jid")
.filter(|name| name != "dying")
.filter(|name| name != "parent")
.filter(|name| name != "children.cur")
.filter(|name| name != "cpuset.id")
// The following parameters are handled separately
.filter(|name| name != "name")
.filter(|name| name != "hostname")
.filter(|name| name != "path")
.filter(|name| name != "ip6.addr")
.filter(|name| name != "ip4.addr")

Consider Cirrus-ci.com instead of buildbot

Like you, I setup a Buildbot server for my Rust projects to test on FreeBSD. But that takes $$$ and ongoing maintenance effort. Recently, https://cirrus-ci.com added a free FreeBSD build option. libc, nix, xattr, mio-aio, and tokio-file are already using it. It runs in a full VM, which is handy when testing jail-related code. You should check it out.

Figure out a CI solution

Most CI providers don't have FreeBSD around. We could however evaluate the following options:

Use a QEMU VM on Travis-CI

Advantages: have full control over image, are root, can build VIMAGE kernel, etc.
Disadvantages: PITA to maintain, and probably not the optimal performance.

Set up a dedicated Jenkins / Buildbot / Whatever

Advantages: full control
Disadvantages: running costs, responsibility for running untrusted code as a privileged user

Wait around until a wild FreeBSD-based CI appears

Advantages: least hassle
Disadvantages: Unclear if own kernel, root, can set RCTL rules, etc.

Python bindings

We could have Python bindings using rust-cpython. This would probably make @gronke happy because it allows libiocage to get rid of shelling out to jail(8) and overcome some of its limitations (e.g. only a single VNET device).

Unable to set jailed process uid

Describe the bug

Inability to set uid of a jailed process.

To Reproduce
Consider the following use-case: I'm trying to change uid of a process running inside the jail.
For that purpose I use std::os::unix::process::CommandExt.uid.

In code:

let stopped_jail = StoppedJail::new(&path)
    .name("container 42")
    .param("vnet", Value::Int(1))
    .param("enforce_statfs", Value::Int(1))
    .unwrap();

Command::new(command)
    .jail(&jail)
    .uid(uid)
    .gid(gid)
    .spawn()
    .unwrap();

The spawn call returns EPERM error.

Expected behavior
The spawn call succeeds

Additional context
Underlying issue is jail_attach call. Per man page

The jail_attach() and jail_remove() system calls will fail if:

[EPERM] A user other than the super-user attempted to attach
to or remove a jail.

stdlib calls setuid here, before calling pre-exec hooks here. Since the process uid set to a non-priveleged user, alas, we fail.

Possible workarounds

Either

  • Attempt to change stdlib (unrealistically)
  • exec.jail_user. Well, not quite. It's not uid, not sure if it works for jail_attach.
  • just create another hook to call setuid there!

WDYT?

VNET Jails

Roadmap:

  • fix current saving non-VNET jails (#34)
  • add check whether VIMAGE is enabled, by checking whether kern.features.vimage sysctl exists and is set to 1 (c163a6a)
  • add support for E,jailsys tri-state parameters, and add handling for vnet parameter
    • Add type to enums (0bda407)
    • wait for johalun/sysctl-rs#19 to be merged or johalun/sysctl-rs#18 to be fixed some other way
    • Set a sane default (probably disable) & verify it works with VIMAGE disabled
    • verify no IP restrictions are set when vnet is not disable.
  • Handle adding epairs / vnets to the jail
    • Add support for vnet to lib(private)ifconfig

RUSTSEC-2020-0036: failure is officially deprecated/unmaintained

failure is officially deprecated/unmaintained

Details
Status unmaintained
Package failure
Version 0.1.8
URL rust-lang-deprecated/failure#347
Date 2020-05-02

The failure crate is officially end-of-life: it has been marked as deprecated
by the former maintainer, who has announced that there will be no updates or
maintenance work on it going forward.

The following are some suggested actively developed alternatives to switch to:

See advisory page for additional details.

Logging

We should have some form of logging, probably using the log crate.

Consumers of libjail-rs need to increase type_length_limit

Describe the bug
Rust 1.35.0 has broken some things via what is described in rust-lang/rust#58952, meaning libjail-rs no longer compiles.

To Reproduce
Attempt to compile under Rust 1.35.0

Expected behavior
The crate compiles.

Additional context
Iโ€™m not sure if there is anything for libjail to do here, but I thought a tracking issue might be good.

Caching parameter metadata

At the moment we query a sysctl every time we read or write a property, to get the type and maximum size of the value. As these are unlikely to change during the lifetime of the library (should check whether they can be changed without rebooting), we can aggressively cache these.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.