mirror of
https://github.com/containers/youki
synced 2024-11-23 09:21:57 +01:00
Merge branch 'main' of github.com:containers/youki into improvement/refactor-dir-structure
This commit is contained in:
commit
40e7b74a65
6
.github/workflows/main.yml
vendored
6
.github/workflows/main.yml
vendored
@ -109,12 +109,6 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Cache runtime-tools
|
||||
id: cache-runtime-tools
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: integration_test
|
||||
key: ${{ runner.os }}-${{ matrix.rust }}-primes
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
|
4
.gitpod.Dockerfile
vendored
4
.gitpod.Dockerfile
vendored
@ -6,4 +6,6 @@ RUN sudo apt-get update && sudo apt-get install -y \
|
||||
libdbus-1-dev \
|
||||
build-essential \
|
||||
libelf-dev \
|
||||
libseccomp-dev
|
||||
libseccomp-dev
|
||||
|
||||
RUN rustup component add clippy rls rust-analysis rust-src rust-docs rustfmt
|
@ -6,4 +6,7 @@ tasks:
|
||||
github:
|
||||
prebuilds:
|
||||
pullRequestsFromForks: true
|
||||
addBadge: true
|
||||
addBadge: true
|
||||
vscode:
|
||||
extensions:
|
||||
- matklad.rust-analyzer
|
163
crates/Cargo.lock
generated
163
crates/Cargo.lock
generated
@ -39,9 +39,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.54"
|
||||
version = "1.0.55"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a99269dff3bc004caa411f38845c20303f1e393ca2bd6581576fa3a7f59577d"
|
||||
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
|
||||
|
||||
[[package]]
|
||||
name = "ascii"
|
||||
@ -174,9 +174,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.1.0"
|
||||
version = "3.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5f1fea81f183005ced9e59cdb01737ef2423956dac5a6d731b06b2ecfaa3467"
|
||||
checksum = "6d76c22c9b9b215eeb8d016ad3a90417bd13cb24cf8142756e6472445876cab7"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@ -468,12 +468,24 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "difflib"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8"
|
||||
|
||||
[[package]]
|
||||
name = "discard"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
|
||||
|
||||
[[package]]
|
||||
name = "downcast"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
@ -598,6 +610,15 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "float-cmp"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -614,6 +635,12 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fragile"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8da1b8f89c5b5a5b7e59405cfcf0bb9588e5ed19f0b57a4cd542bbba3f164a6d"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.21"
|
||||
@ -715,9 +742,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "418d37c8b1d42553c93648be529cb70f920d3baf8ef469b74b9638df426e0b4c"
|
||||
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
@ -845,6 +872,15 @@ dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.10.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.1"
|
||||
@ -910,6 +946,7 @@ dependencies = [
|
||||
"libbpf-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"mockall",
|
||||
"nix",
|
||||
"oci-spec",
|
||||
"procfs",
|
||||
@ -917,6 +954,7 @@ dependencies = [
|
||||
"rbpf",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serial_test 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -944,7 +982,7 @@ dependencies = [
|
||||
"rand",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serial_test",
|
||||
"serial_test 0.6.0",
|
||||
"wasmer",
|
||||
"wasmer-wasi",
|
||||
]
|
||||
@ -1117,6 +1155,33 @@ dependencies = [
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d4d70639a72f972725db16350db56da68266ca368b2a1fe26724a903ad3d6b8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"downcast",
|
||||
"fragile",
|
||||
"lazy_static",
|
||||
"mockall_derive",
|
||||
"predicates",
|
||||
"predicates-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall_derive"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79ef208208a0dea3f72221e26e904cdc6db2e481d9ade89081ddd494f1dbaa6b"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "more-asserts"
|
||||
version = "0.2.2"
|
||||
@ -1136,6 +1201,12 @@ dependencies = [
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "normalize-line-endings"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "61807f77802ff30975e01f4f071c8ba10c022052f98b3294119f3e615d13e5be"
|
||||
|
||||
[[package]]
|
||||
name = "ntapi"
|
||||
version = "0.3.7"
|
||||
@ -1295,6 +1366,36 @@ dependencies = [
|
||||
"nix",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "2.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c"
|
||||
dependencies = [
|
||||
"difflib",
|
||||
"float-cmp",
|
||||
"itertools",
|
||||
"normalize-line-endings",
|
||||
"predicates-core",
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "1.0.4"
|
||||
@ -1525,9 +1626,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.32"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e3791595bf1ee951356964271bea7dafd1e1730e8be812f44a31afc38fa7bba"
|
||||
checksum = "bf98e3e6c7ed44e474b454b1ebded3193ee5aba3428e29c55d59b1d65e49945e"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
"hashbrown 0.12.0",
|
||||
@ -1539,9 +1640,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.32"
|
||||
version = "0.7.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca655472e721430bfb5c995a5602278e089c329cde96a0a53e1f711e3ba39c55"
|
||||
checksum = "cc9940ec6a7c62b1d1f476f607c6caf0d7fbf74e43f77bc022143b878fcd3266"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -1575,7 +1676,7 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
|
||||
dependencies = [
|
||||
"semver 1.0.5",
|
||||
"semver 1.0.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1613,9 +1714,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.5"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0486718e92ec9a68fbed73bb5ef687d71103b142595b406835649bebd33f72c7"
|
||||
checksum = "a4a3381e03edd24287172047536f20cabde766e2cd3e65e6b00fb3af51c4f38d"
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
@ -1671,7 +1772,18 @@ checksum = "e0bccbcf40c8938196944a3da0e133e031a33f4d6b72db3bda3cc556e361905d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
"serial_test_derive",
|
||||
"serial_test_derive 0.5.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5bcc41d18f7a1d50525d080fd3e953be87c4f9f1a974f3c21798ca00d54ec15"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"parking_lot",
|
||||
"serial_test_derive 0.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1685,6 +1797,19 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serial_test_derive"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2881bccd7d60fb32dfa3d7b3136385312f8ad75e2674aab2852867a09790cae8"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustversion",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha1"
|
||||
version = "0.6.1"
|
||||
@ -1845,6 +1970,12 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b"
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.14.2"
|
||||
@ -2413,7 +2544,7 @@ dependencies = [
|
||||
"procfs",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serial_test",
|
||||
"serial_test 0.6.0",
|
||||
"tabwriter",
|
||||
"vergen",
|
||||
]
|
||||
|
@ -24,12 +24,14 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
rbpf = {version = "0.1.0", optional = true }
|
||||
libbpf-sys = { version = "0.6.1-2", optional = true }
|
||||
errno = { version = "0.2.8", optional = true }
|
||||
libc = { version = "0.2.118", optional = true }
|
||||
libc = { version = "0.2.119", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
oci-spec = { version = "0.5.3", features = ["proptests"] }
|
||||
quickcheck = "1"
|
||||
mockall = { version = "0.11.0", features = [] }
|
||||
clap = "3.0.0-beta.5"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
env_logger = "0.9"
|
||||
serial_test = "0.5.1"
|
||||
|
@ -4,6 +4,11 @@
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate quickcheck;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
extern crate mockall;
|
||||
|
||||
mod test;
|
||||
|
||||
pub mod common;
|
||||
|
@ -1,117 +1,124 @@
|
||||
use anyhow::{bail, Result};
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::ptr;
|
||||
|
||||
// FIXME: add tests
|
||||
|
||||
pub fn prog_load(license: &str, insns: &[u8]) -> Result<RawFd> {
|
||||
let insns_cnt = insns.len() / std::mem::size_of::<libbpf_sys::bpf_insn>();
|
||||
let insns = insns as *const _ as *const libbpf_sys::bpf_insn;
|
||||
|
||||
let prog_fd = unsafe {
|
||||
libbpf_sys::bpf_load_program(
|
||||
libbpf_sys::BPF_PROG_TYPE_CGROUP_DEVICE,
|
||||
insns,
|
||||
insns_cnt as u64,
|
||||
license as *const _ as *const i8,
|
||||
0,
|
||||
ptr::null_mut::<i8>(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
|
||||
if prog_fd < 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(prog_fd)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ProgramInfo {
|
||||
pub id: u32,
|
||||
pub fd: i32,
|
||||
}
|
||||
|
||||
pub fn prog_query(cgroup_fd: RawFd) -> Result<Vec<ProgramInfo>> {
|
||||
let mut prog_ids: Vec<u32> = vec![0_u32; 64];
|
||||
let mut attach_flags = 0_u32;
|
||||
for _ in 0..10 {
|
||||
let mut prog_cnt = prog_ids.len() as u32;
|
||||
let ret = unsafe {
|
||||
libbpf_sys::bpf_prog_query(
|
||||
cgroup_fd,
|
||||
libbpf_sys::BPF_CGROUP_DEVICE,
|
||||
#[cfg_attr(test, automock)]
|
||||
pub mod prog {
|
||||
use super::ProgramInfo;
|
||||
use anyhow::{bail, Result};
|
||||
use std::os::unix::io::RawFd;
|
||||
use std::ptr;
|
||||
|
||||
pub fn load(license: &str, insns: &[u8]) -> Result<RawFd> {
|
||||
let insns_cnt = insns.len() / std::mem::size_of::<libbpf_sys::bpf_insn>();
|
||||
let insns = insns as *const _ as *const libbpf_sys::bpf_insn;
|
||||
|
||||
let prog_fd = unsafe {
|
||||
libbpf_sys::bpf_load_program(
|
||||
libbpf_sys::BPF_PROG_TYPE_CGROUP_DEVICE,
|
||||
insns,
|
||||
insns_cnt as u64,
|
||||
license as *const _ as *const i8,
|
||||
0,
|
||||
ptr::null_mut::<i8>(),
|
||||
0,
|
||||
&mut attach_flags,
|
||||
&prog_ids[0] as *const u32 as *mut u32,
|
||||
&mut prog_cnt,
|
||||
)
|
||||
};
|
||||
if ret != 0 {
|
||||
let err = errno::errno();
|
||||
if err.0 == libc::ENOSPC {
|
||||
assert!(prog_cnt as usize > prog_ids.len());
|
||||
|
||||
// allocate more space and try again
|
||||
prog_ids.resize(prog_cnt as usize, 0);
|
||||
continue;
|
||||
if prog_fd < 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(prog_fd)
|
||||
}
|
||||
|
||||
/// Given a fd for a cgroup, collect the programs associated with it
|
||||
pub fn query(cgroup_fd: RawFd) -> Result<Vec<ProgramInfo>> {
|
||||
let mut prog_ids: Vec<u32> = vec![0_u32; 64];
|
||||
let mut attach_flags = 0_u32;
|
||||
for _ in 0..10 {
|
||||
let mut prog_cnt = prog_ids.len() as u32;
|
||||
let ret = unsafe {
|
||||
// collect ids for bpf programs
|
||||
libbpf_sys::bpf_prog_query(
|
||||
cgroup_fd,
|
||||
libbpf_sys::BPF_CGROUP_DEVICE,
|
||||
0,
|
||||
&mut attach_flags,
|
||||
&prog_ids[0] as *const u32 as *mut u32,
|
||||
&mut prog_cnt,
|
||||
)
|
||||
};
|
||||
if ret != 0 {
|
||||
let err = errno::errno();
|
||||
if err.0 == libc::ENOSPC {
|
||||
assert!(prog_cnt as usize > prog_ids.len());
|
||||
|
||||
// allocate more space and try again
|
||||
prog_ids.resize(prog_cnt as usize, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
return Err(err.into());
|
||||
}
|
||||
|
||||
return Err(err.into());
|
||||
prog_ids.resize(prog_cnt as usize, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
prog_ids.resize(prog_cnt as usize, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
let mut prog_fds = Vec::with_capacity(prog_ids.len());
|
||||
for prog_id in &prog_ids {
|
||||
let prog_fd = unsafe { libbpf_sys::bpf_prog_get_fd_by_id(*prog_id) };
|
||||
if prog_fd < 0 {
|
||||
log::debug!("bpf_prog_get_fd_by_id failed: {}", errno::errno());
|
||||
continue;
|
||||
let mut prog_fds = Vec::with_capacity(prog_ids.len());
|
||||
for prog_id in &prog_ids {
|
||||
// collect fds for programs by getting their ids
|
||||
let prog_fd = unsafe { libbpf_sys::bpf_prog_get_fd_by_id(*prog_id) };
|
||||
if prog_fd < 0 {
|
||||
log::debug!("bpf_prog_get_fd_by_id failed: {}", errno::errno());
|
||||
continue;
|
||||
}
|
||||
prog_fds.push(ProgramInfo {
|
||||
id: *prog_id,
|
||||
fd: prog_fd,
|
||||
});
|
||||
}
|
||||
prog_fds.push(ProgramInfo {
|
||||
id: *prog_id,
|
||||
fd: prog_fd,
|
||||
});
|
||||
}
|
||||
Ok(prog_fds)
|
||||
}
|
||||
|
||||
pub fn prog_detach2(prog_fd: RawFd, cgroup_fd: RawFd) -> Result<()> {
|
||||
let ret =
|
||||
unsafe { libbpf_sys::bpf_prog_detach2(prog_fd, cgroup_fd, libbpf_sys::BPF_CGROUP_DEVICE) };
|
||||
if ret != 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn prog_attach(prog_fd: RawFd, cgroup_fd: RawFd) -> Result<()> {
|
||||
let ret = unsafe {
|
||||
libbpf_sys::bpf_prog_attach(
|
||||
prog_fd,
|
||||
cgroup_fd,
|
||||
libbpf_sys::BPF_CGROUP_DEVICE,
|
||||
libbpf_sys::BPF_F_ALLOW_MULTI,
|
||||
)
|
||||
};
|
||||
|
||||
if ret != 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bump_memlock_rlimit() -> Result<()> {
|
||||
let rlimit = libc::rlimit {
|
||||
rlim_cur: 128 << 20,
|
||||
rlim_max: 128 << 20,
|
||||
};
|
||||
|
||||
if unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlimit) } != 0 {
|
||||
bail!("Failed to increase rlimit");
|
||||
Ok(prog_fds)
|
||||
}
|
||||
|
||||
Ok(())
|
||||
pub fn detach2(prog_fd: RawFd, cgroup_fd: RawFd) -> Result<()> {
|
||||
let ret = unsafe {
|
||||
libbpf_sys::bpf_prog_detach2(prog_fd, cgroup_fd, libbpf_sys::BPF_CGROUP_DEVICE)
|
||||
};
|
||||
if ret != 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn attach(prog_fd: RawFd, cgroup_fd: RawFd) -> Result<()> {
|
||||
let ret = unsafe {
|
||||
libbpf_sys::bpf_prog_attach(
|
||||
prog_fd,
|
||||
cgroup_fd,
|
||||
libbpf_sys::BPF_CGROUP_DEVICE,
|
||||
libbpf_sys::BPF_F_ALLOW_MULTI,
|
||||
)
|
||||
};
|
||||
|
||||
if ret != 0 {
|
||||
return Err(errno::errno().into());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn bump_memlock_rlimit() -> Result<()> {
|
||||
let rlimit = libc::rlimit {
|
||||
rlim_cur: 128 << 20,
|
||||
rlim_max: 128 << 20,
|
||||
};
|
||||
|
||||
if unsafe { libc::setrlimit(libc::RLIMIT_MEMLOCK, &rlimit) } != 0 {
|
||||
bail!("Failed to increase rlimit");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,12 @@ use oci_spec::runtime::LinuxDeviceCgroup;
|
||||
use crate::common::{default_allow_devices, default_devices, ControllerOpt};
|
||||
use crate::v2::controller::Controller;
|
||||
|
||||
#[cfg(test)]
|
||||
use bpf::mock_prog as bpf_prog;
|
||||
|
||||
#[cfg(not(test))]
|
||||
use bpf::prog as bpf_prog;
|
||||
|
||||
const LICENSE: &str = "Apache";
|
||||
|
||||
pub struct Devices {}
|
||||
@ -57,8 +63,8 @@ impl Devices {
|
||||
|
||||
// Increase `ulimit -l` limit to avoid BPF_PROG_LOAD error (#2167).
|
||||
// This limit is not inherited into the container.
|
||||
bpf::bump_memlock_rlimit()?;
|
||||
let prog_fd = bpf::prog_load(LICENSE, prog.bytecodes())?;
|
||||
bpf_prog::bump_memlock_rlimit()?;
|
||||
let prog_fd = bpf_prog::load(LICENSE, prog.bytecodes())?;
|
||||
|
||||
// FIXME: simple way to attach BPF program
|
||||
// 1. get list of existing attached programs
|
||||
@ -73,20 +79,99 @@ impl Devices {
|
||||
// IMHO, this is too complicated, and in most cases, we just attach program once without
|
||||
// already attached programs.
|
||||
|
||||
// get the fd of the cgroup root
|
||||
let fd = nix::dir::Dir::open(
|
||||
cgroup_root.as_os_str(),
|
||||
OFlag::O_RDONLY | OFlag::O_DIRECTORY,
|
||||
Mode::from_bits(0o600).unwrap(),
|
||||
)?;
|
||||
|
||||
let old_progs = bpf::prog_query(fd.as_raw_fd())?;
|
||||
bpf::prog_attach(prog_fd, fd.as_raw_fd())?;
|
||||
// collect the programs attached to this cgroup
|
||||
let old_progs = bpf_prog::query(fd.as_raw_fd())?;
|
||||
// attach our new program
|
||||
bpf_prog::attach(prog_fd, fd.as_raw_fd())?;
|
||||
// detach all previous programs
|
||||
for old_prog in old_progs {
|
||||
bpf::prog_detach2(old_prog.fd, fd.as_raw_fd())?;
|
||||
bpf_prog::detach2(old_prog.fd, fd.as_raw_fd())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: add tests, but how to?
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::test::setup;
|
||||
use serial_test::serial;
|
||||
|
||||
use oci_spec::runtime::{LinuxDeviceCgroupBuilder, LinuxDeviceType};
|
||||
use std::os::unix::io::RawFd;
|
||||
|
||||
use bpf::mock_prog;
|
||||
|
||||
#[test]
|
||||
#[serial(bpf)] // mock contexts are shared
|
||||
fn test_apply_devices() {
|
||||
// arrange
|
||||
let (tmp, _) = setup("test_apply_devices", "some.value");
|
||||
let a_type = LinuxDeviceCgroupBuilder::default()
|
||||
.typ(LinuxDeviceType::A)
|
||||
.build()
|
||||
.unwrap();
|
||||
let file_descriptor: RawFd = 6;
|
||||
|
||||
// expect
|
||||
let bump_memlock_rlimit = mock_prog::bump_memlock_rlimit_context();
|
||||
let load = mock_prog::load_context();
|
||||
let query = mock_prog::query_context();
|
||||
let attach = mock_prog::attach_context();
|
||||
let detach2 = mock_prog::detach2_context();
|
||||
bump_memlock_rlimit.expect().once().returning(|| Ok(()));
|
||||
load.expect()
|
||||
.once()
|
||||
.returning(move |_, _| Ok(file_descriptor));
|
||||
query.expect().once().returning(|_| Ok(vec![]));
|
||||
attach.expect().once().returning(|_, _| Ok(()));
|
||||
detach2.expect().never();
|
||||
|
||||
// act
|
||||
Devices::apply_devices(&tmp, &Some(vec![a_type])).expect("Could not apply devices");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[serial(bpf)] // mock contexts are shared
|
||||
fn test_existing_programs() {
|
||||
// arrange
|
||||
let (tmp, _) = setup("test_existing_programs", "some.value");
|
||||
let a_type = LinuxDeviceCgroupBuilder::default()
|
||||
.typ(LinuxDeviceType::A)
|
||||
.build()
|
||||
.unwrap();
|
||||
let file_descriptor: RawFd = 6;
|
||||
let existing_program_1 = bpf::ProgramInfo {
|
||||
id: u32::default(),
|
||||
fd: i32::default(),
|
||||
};
|
||||
|
||||
// expect
|
||||
let bump_memlock_rlimit = mock_prog::bump_memlock_rlimit_context();
|
||||
let load = mock_prog::load_context();
|
||||
let query = mock_prog::query_context();
|
||||
let attach = mock_prog::attach_context();
|
||||
let detach2 = mock_prog::detach2_context();
|
||||
bump_memlock_rlimit.expect().once().returning(|| Ok(()));
|
||||
load.expect()
|
||||
.once()
|
||||
.returning(move |_, _| Ok(file_descriptor));
|
||||
query
|
||||
.expect()
|
||||
.once()
|
||||
.returning(move |_| Ok(vec![existing_program_1.clone()]));
|
||||
attach.expect().once().returning(|_, _| Ok(()));
|
||||
detach2.expect().once().returning(|_, _| Ok(()));
|
||||
|
||||
// act
|
||||
Devices::apply_devices(&tmp, &Some(vec![a_type])).expect("Could not apply devices");
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ use std::{
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
use nix::unistd::Pid;
|
||||
|
||||
@ -30,6 +30,9 @@ use crate::{
|
||||
common::{self, CgroupManager, ControllerOpt, FreezerState, PathBufExt, CGROUP_PROCS},
|
||||
stats::{Stats, StatsProvider},
|
||||
};
|
||||
|
||||
pub const CGROUP_KILL: &str = "cgroup.kill";
|
||||
|
||||
pub struct Manager {
|
||||
root_path: PathBuf,
|
||||
cgroup_path: PathBuf,
|
||||
@ -127,12 +130,17 @@ impl CgroupManager for Manager {
|
||||
fn remove(&self) -> Result<()> {
|
||||
if self.full_path.exists() {
|
||||
log::debug!("remove cgroup {:?}", self.full_path);
|
||||
let procs_path = self.full_path.join(CGROUP_PROCS);
|
||||
let procs = fs::read_to_string(&procs_path)?;
|
||||
let kill_file = self.full_path.join(CGROUP_KILL);
|
||||
if kill_file.exists() {
|
||||
fs::write(kill_file, "1").context("failed to kill cgroup")?;
|
||||
} else {
|
||||
let procs_path = self.full_path.join(CGROUP_PROCS);
|
||||
let procs = fs::read_to_string(&procs_path)?;
|
||||
|
||||
for line in procs.lines() {
|
||||
let pid: i32 = line.parse()?;
|
||||
let _ = nix::sys::signal::kill(Pid::from_raw(pid), nix::sys::signal::SIGKILL);
|
||||
for line in procs.lines() {
|
||||
let pid: i32 = line.parse()?;
|
||||
let _ = nix::sys::signal::kill(Pid::from_raw(pid), nix::sys::signal::SIGKILL);
|
||||
}
|
||||
}
|
||||
|
||||
common::delete_with_retry(&self.full_path, 4, Duration::from_millis(100))?;
|
||||
|
@ -19,7 +19,7 @@ crossbeam-channel = "0.5"
|
||||
dbus = "0.9.5"
|
||||
fastrand = "1.7.0"
|
||||
futures = { version = "0.3", features = ["thread-pool"] }
|
||||
libc = "0.2.118"
|
||||
libc = "0.2.119"
|
||||
log = "0.4"
|
||||
mio = { version = "0.8.0", features = ["os-ext", "os-poll"] }
|
||||
nix = "0.23.1"
|
||||
@ -37,5 +37,5 @@ wasmer-wasi = { version = "2.1.1", optional = true }
|
||||
[dev-dependencies]
|
||||
oci-spec = { version = "0.5.3", features = ["proptests"] }
|
||||
quickcheck = "1"
|
||||
serial_test = "0.5.1"
|
||||
serial_test = "0.6.0"
|
||||
rand = "0.8.5"
|
||||
|
@ -170,6 +170,42 @@ impl FilterContext {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Enable or disable the no new privileges attribute bit.
|
||||
pub fn set_nnp_bit(&self, to: bool) -> Result<()> {
|
||||
self.set_attr(scmp_filter_attr::SCMP_FLTATR_CTL_NNP, to as u32)
|
||||
.context("set no new privileges bit")
|
||||
}
|
||||
|
||||
/// Enable or disable the log attribute bit.
|
||||
pub fn set_log_bit(&self, to: bool) -> Result<()> {
|
||||
self.set_attr(scmp_filter_attr::SCMP_FLTATR_CTL_LOG, to as u32)
|
||||
.context("set log bit")
|
||||
}
|
||||
|
||||
/// Enable or disable the tsync attribute bit.
|
||||
pub fn set_tsync_bit(&self, to: bool) -> Result<()> {
|
||||
self.set_attr(scmp_filter_attr::SCMP_FLTATR_CTL_TSYNC, to as u32)
|
||||
.context("set tsync bit")
|
||||
}
|
||||
|
||||
/// Enable or disable the SSB (Speculative Store Bypass) attribute bit.
|
||||
pub fn set_ssb_bit(&self, to: bool) -> Result<()> {
|
||||
self.set_attr(scmp_filter_attr::SCMP_FLTATR_CTL_SSB, to as u32)
|
||||
.context("set SSB bit")
|
||||
}
|
||||
|
||||
/// Can be used to set any arbitrary seccomp filter attribute.
|
||||
pub fn set_attr(&self, attr: scmp_filter_attr, value: u32) -> Result<()> {
|
||||
let res = unsafe { seccomp_attr_set(self.ctx, attr, value) };
|
||||
if res != 0 {
|
||||
bail!(
|
||||
"unable to set attribute on seccomp filter: {}",
|
||||
nix::errno::from_i32(res)
|
||||
)
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn translate_syscall(syscall_name: &str) -> Result<i32> {
|
||||
@ -261,17 +297,42 @@ fn check_seccomp(seccomp: &LinuxSeccomp) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn initialize_seccomp(seccomp: &LinuxSeccomp) -> Result<Option<io::RawFd>> {
|
||||
if seccomp.flags().is_some() {
|
||||
// runc did not support this, so let's skip it for now.
|
||||
bail!("seccomp flags are not yet supported");
|
||||
}
|
||||
/// All filter return actions except SECCOMP_RET_ALLOW should be logged. An administrator may
|
||||
/// override this filter flag by preventing specific actions from being logged via the
|
||||
/// /proc/sys/kernel/seccomp/actions_logged file. (since Linux 4.14)
|
||||
const SECCOMP_FILTER_FLAG_LOG: &str = "SECCOMP_FILTER_FLAG_LOG";
|
||||
|
||||
/// When adding a new filter, synchronize all other threads of the calling process to the same
|
||||
/// seccomp filter tree. A "filter tree" is the ordered list of filters attached to a thread.
|
||||
/// (Attaching identical filters in separate seccomp() calls results in different filters from this
|
||||
/// perspective.)
|
||||
///
|
||||
/// If any thread cannot synchronize to the same filter tree, the call will not attach the new
|
||||
/// seccomp filter, and will fail, returning the first thread ID found that cannot synchronize.
|
||||
/// Synchronization will fail if another thread in the same process is in SECCOMP_MODE_STRICT or if
|
||||
/// it has attached new seccomp filters to itself, diverging from the calling thread's filter tree.
|
||||
const SECCOMP_FILTER_FLAG_TSYNC: &str = "SECCOMP_FILTER_FLAG_TSYNC";
|
||||
|
||||
/// Disable Speculative Store Bypass mitigation. (since Linux 4.17)
|
||||
const SECCOMP_FILTER_FLAG_SPEC_ALLOW: &str = "SECCOMP_FILTER_FLAG_SPEC_ALLOW";
|
||||
|
||||
pub fn initialize_seccomp(seccomp: &LinuxSeccomp) -> Result<Option<io::RawFd>> {
|
||||
check_seccomp(seccomp)?;
|
||||
|
||||
let default_action = translate_action(seccomp.default_action(), seccomp.default_errno_ret());
|
||||
let mut ctx = FilterContext::default(default_action)?;
|
||||
|
||||
if let Some(flags) = seccomp.flags() {
|
||||
for flag in flags {
|
||||
match flag.as_ref() {
|
||||
SECCOMP_FILTER_FLAG_LOG => ctx.set_log_bit(true)?,
|
||||
SECCOMP_FILTER_FLAG_TSYNC => ctx.set_tsync_bit(true)?,
|
||||
SECCOMP_FILTER_FLAG_SPEC_ALLOW => ctx.set_ssb_bit(true)?,
|
||||
f => bail!("seccomp flag {} is not supported", f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(architectures) = seccomp.architectures() {
|
||||
for &arch in architectures {
|
||||
let arch_token = translate_arch(arch);
|
||||
@ -287,13 +348,7 @@ pub fn initialize_seccomp(seccomp: &LinuxSeccomp) -> Result<Option<io::RawFd>> {
|
||||
// set it here. If the seccomp load operation fails without enough
|
||||
// privilege, so be it. To prevent this automatic behavior, we unset the
|
||||
// value here.
|
||||
let ret = unsafe { seccomp_attr_set(ctx.ctx, scmp_filter_attr::SCMP_FLTATR_CTL_NNP, 0) };
|
||||
if ret != 0 {
|
||||
bail!(
|
||||
"failed to unset the no new privileges bit for seccomp: {}",
|
||||
ret
|
||||
);
|
||||
}
|
||||
ctx.set_nnp_bit(false)?;
|
||||
|
||||
if let Some(syscalls) = seccomp.syscalls() {
|
||||
for syscall in syscalls {
|
||||
|
@ -7,7 +7,7 @@ use std::sync::Arc;
|
||||
use std::{any::Any, mem, path::Path, ptr};
|
||||
|
||||
use anyhow::{anyhow, bail, Result};
|
||||
use caps::{CapSet, Capability, CapsHashSet};
|
||||
use caps::{CapSet, CapsHashSet};
|
||||
use libc::{c_char, uid_t};
|
||||
use nix::{
|
||||
errno::Errno,
|
||||
@ -132,15 +132,7 @@ impl Syscall for LinuxSyscall {
|
||||
// for each such =, drop that capability
|
||||
// after this, only those which are to be set will remain set
|
||||
for c in all.difference(value) {
|
||||
match c {
|
||||
Capability::CAP_PERFMON
|
||||
| Capability::CAP_CHECKPOINT_RESTORE
|
||||
| Capability::CAP_BPF => {
|
||||
log::warn!("{:?} is not supported.", c);
|
||||
continue;
|
||||
}
|
||||
_ => caps::drop(None, CapSet::Bounding, *c)?,
|
||||
}
|
||||
caps::drop(None, CapSet::Bounding, *c)?
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
@ -6,7 +6,7 @@ edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
libc = "0.2.118"
|
||||
libc = "0.2.119"
|
||||
|
||||
[build-dependencies]
|
||||
pkg-config = "0.3.24"
|
||||
|
@ -13,7 +13,7 @@ features = ["std", "suggestions", "derive", "cargo"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.53"
|
||||
anyhow = "1.0.55"
|
||||
chrono = { version="0.4", features = ["serde"] }
|
||||
libcgroups = { version = "0.0.2", path = "../libcgroups" }
|
||||
libcontainer = { version = "0.0.2", path = "../libcontainer" }
|
||||
@ -30,8 +30,8 @@ tabwriter = "1"
|
||||
clap_generate = { version = "3.0.0-beta.5" }
|
||||
|
||||
[dev-dependencies]
|
||||
serial_test = "0.5.1"
|
||||
serial_test = "0.6.0"
|
||||
|
||||
[build-dependencies]
|
||||
anyhow = "1.0.53"
|
||||
anyhow = "1.0.55"
|
||||
vergen = "6.0"
|
||||
|
@ -6,5 +6,5 @@ edition = "2021"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.53"
|
||||
anyhow = "1.0.55"
|
||||
crossbeam = "0.8.1"
|
||||
|
Loading…
Reference in New Issue
Block a user