├── .copr ├── contrib ├── seccomp-receiver │ ├── Makefile │ └── seccomp-receiver.c ├── terminal-receiver │ └── Makefile ├── notify-socket-server │ ├── Makefile │ └── notify-socket-server.c ├── seccomp-notify-plugin-example │ ├── Makefile │ └── full.c ├── honggfuzz.sh └── seccomp-notify-plugin-rust │ ├── Cargo.toml │ └── src │ └── seccompwatcher.rs ├── tests ├── codespell │ └── Dockerfile ├── wasmedge-build │ ├── hello_wasm │ │ ├── Containerfile │ │ ├── expected_output │ │ └── hello │ │ │ ├── Cargo.toml │ │ │ └── src │ │ │ └── main.rs │ ├── run-tests.sh │ └── Dockerfile ├── alpine-build │ ├── run-tests.sh │ └── Dockerfile ├── clang-format │ ├── Dockerfile │ └── run-tests.sh ├── fedora-rawhide-mockbuild │ ├── Dockerfile │ └── run-mockbuild.sh ├── centos8-build │ ├── run-tests.sh │ └── Dockerfile ├── centos9-build │ ├── run-tests.sh │ └── Dockerfile ├── clang-check │ ├── Dockerfile │ └── run-tests.sh ├── Makefile.tests ├── containerd │ ├── run-tests.sh │ └── Dockerfile ├── fuzzing │ ├── Dockerfile │ └── run-tests.sh ├── oci-validation │ ├── Dockerfile │ └── run-tests.sh ├── run_all_tests.sh ├── podman │ ├── Dockerfile │ └── run-tests.sh ├── test_cwd.py ├── test_hostname.py ├── test_pid_file.py ├── test_detach.py ├── test_pid.py ├── test_paths.py ├── test_limits.py ├── cri-o │ ├── Dockerfile │ └── run-tests.sh ├── test_update.py ├── test_tty.py ├── test_preserve_fds.py ├── test_rlimits.py ├── test_hooks.py ├── tests_libcrun_errors.c ├── test_domainname.py ├── test_seccomp.py ├── test_uid_gid.py ├── test_devices.py └── test_delete.py ├── .gitmodules ├── .lgtm.yml ├── .github ├── dependabot.yml └── workflows │ ├── codeql-analysis.yml │ └── release.yaml ├── .codespellrc ├── CODE-OF-CONDUCT.md ├── autogen.sh ├── SECURITY.md ├── nix ├── nixpkgs.nix ├── static.nix ├── nixpkgs.json ├── default.nix └── default-arm64.nix ├── libcrun.lds ├── cfg.mk ├── src ├── ps.h ├── restore.h ├── run.h ├── exec.h ├── kill.h ├── list.h ├── spec.h ├── pause.h ├── start.h ├── state.h ├── update.h ├── create.h ├── delete.h ├── unpause.h ├── checkpoint.h ├── libcrun │ ├── cgroup-cgroupfs.h │ ├── handlers │ │ ├── handler-utils.h │ │ └── handler-utils.c │ ├── cgroup-setup.h │ ├── cgroup-systemd.h │ ├── cgroup-resources.h │ ├── mount_flags.h │ ├── terminal.h │ ├── cgroup-utils.h │ ├── ebpf.h │ ├── seccomp_notify.h │ ├── criu.h │ ├── seccomp.h │ ├── signals.perf │ ├── custom-handler.h │ ├── seccomp_notify_plugin.h │ ├── cgroup-internal.h │ ├── mount_flags.perf │ ├── status.h │ ├── cgroup.h │ ├── cgroup-cgroupfs.c │ ├── error.h │ └── terminal.c ├── crun.h ├── pause.c ├── start.c ├── unpause.c ├── state.c ├── ps.c ├── delete.c ├── spec.c └── kill.c ├── .gitignore ├── rpm ├── Makefile └── crun.spec.in ├── docs ├── wasm-wasi-example.md ├── mono-example.md └── wasm-wasi-on-kubernetes.md └── .clang-format /.copr: -------------------------------------------------------------------------------- 1 | rpm/ -------------------------------------------------------------------------------- /contrib/seccomp-receiver/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -I../.. 2 | seccomp-receiver: seccomp-receiver.c 3 | -------------------------------------------------------------------------------- /contrib/terminal-receiver/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -I../.. 2 | terminal-receiver: terminal-receiver.c 3 | -------------------------------------------------------------------------------- /contrib/notify-socket-server/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS = -I../.. 2 | notify-socket-server: notify-socket-server.c 3 | -------------------------------------------------------------------------------- /tests/codespell/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | RUN yum install -y codespell && yum clean all -y 4 | -------------------------------------------------------------------------------- /contrib/seccomp-notify-plugin-example/Makefile: -------------------------------------------------------------------------------- 1 | full.so: full.c 2 | $(CC) -fPIC -shared -o $@ $< -lpthread 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libocispec"] 2 | path = libocispec 3 | url = https://github.com/containers/libocispec.git 4 | -------------------------------------------------------------------------------- /.lgtm.yml: -------------------------------------------------------------------------------- 1 | extraction: 2 | cpp: 3 | configure: 4 | command: 5 | - ./autogen.sh 6 | - ./configure 7 | -------------------------------------------------------------------------------- /tests/wasmedge-build/hello_wasm/Containerfile: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | COPY hello.wasm / 3 | ENV key=value 4 | CMD ["/hello.wasm", "arg1", "arg2"] 5 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | --- 2 | version: 2 3 | updates: 4 | - package-ecosystem: "github-actions" 5 | directory: "/" 6 | schedule: 7 | interval: "weekly" 8 | -------------------------------------------------------------------------------- /.codespellrc: -------------------------------------------------------------------------------- 1 | [codespell] 2 | skip = libocispec,build-aux,contrib,*.1,.git,configure,Makefile,libtool,m4,autom4te.cache,*.m4,*.mk 3 | count = 4 | ignore-words-list = trun,ser 5 | -------------------------------------------------------------------------------- /tests/alpine-build/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd /crun 5 | ./autogen.sh 6 | ./configure CFLAGS='-Wall -Wextra -Werror' --disable-systemd 7 | make -j "$(nproc)" 8 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## The crun Project Community Code of Conduct 2 | 3 | The crun project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md). 4 | -------------------------------------------------------------------------------- /tests/wasmedge-build/hello_wasm/expected_output: -------------------------------------------------------------------------------- 1 | Print env::args() 2 | /hello.wasm 3 | arg1 4 | arg2 5 | Print env::vars() 6 | container: "podman" 7 | key: "value" 8 | This is from a main function from a wasm module 9 | -------------------------------------------------------------------------------- /tests/clang-format/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | RUN dnf install -y git make clang-tools-extra 'dnf-command(builddep)' && dnf builddep -y crun 4 | 5 | COPY run-tests.sh /usr/local/bin 6 | ENTRYPOINT /usr/local/bin/run-tests.sh 7 | -------------------------------------------------------------------------------- /tests/wasmedge-build/hello_wasm/hello/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hello" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | if ! (pkg-config --version > /dev/null 2>&1); then 3 | echo "pkg-config not found. Please install it">&2 4 | exit 1 5 | fi 6 | 7 | mkdir -p m4 8 | 9 | git submodule update --init --recursive 10 | 11 | exec autoreconf -fi 12 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting a Vulnerability 2 | 3 | If you discover a potential security issue in this project we ask that 4 | you notify us directly via email to security@oci.run (not affiliated 5 | with opencontainers.org). 6 | 7 | Please do **not** create a public issue. 8 | -------------------------------------------------------------------------------- /tests/fedora-rawhide-mockbuild/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM registry.fedoraproject.org/fedora:rawhide 2 | 3 | RUN dnf install -y git-core go-md2man make python python3-libmount rpm-build 4 | 5 | COPY run-mockbuild.sh /usr/local/bin 6 | 7 | ENTRYPOINT /usr/local/bin/run-mockbuild.sh 8 | -------------------------------------------------------------------------------- /nix/nixpkgs.nix: -------------------------------------------------------------------------------- 1 | let 2 | json = builtins.fromJSON (builtins.readFile ./nixpkgs.json); 3 | nixpkgs = import (builtins.fetchTarball { 4 | name = "nixos-unstable"; 5 | url = "${json.url}/archive/${json.rev}.tar.gz"; 6 | inherit (json) sha256; 7 | }); 8 | in nixpkgs 9 | -------------------------------------------------------------------------------- /nix/static.nix: -------------------------------------------------------------------------------- 1 | pkg: pkg.overrideAttrs (x: { 2 | doCheck = false; 3 | configureFlags = (x.configureFlags or [ ]) ++ [ 4 | "--without-shared" 5 | "--disable-shared" 6 | ]; 7 | dontDisableStatic = true; 8 | enableSharedExecutables = false; 9 | enableStatic = true; 10 | }) 11 | -------------------------------------------------------------------------------- /tests/alpine-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine 2 | 3 | RUN apk add gcc automake autoconf libtool gettext pkgconf git make musl-dev \ 4 | python3 libcap-dev libgcrypt-dev libseccomp-dev yajl-dev argp-standalone go-md2man 5 | 6 | COPY run-tests.sh /usr/local/bin 7 | 8 | ENTRYPOINT /usr/local/bin/run-tests.sh 9 | -------------------------------------------------------------------------------- /libcrun.lds: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | /* Not all the libcrun_ functions are exported, only those marked LIBCRUN_PUBLIC. */ 4 | libcrun_*; 5 | /* libocispec functions */ 6 | runtime_spec_*; 7 | free_runtime_spec_*; 8 | make_runtime_spec_*; 9 | local: *; 10 | }; 11 | -------------------------------------------------------------------------------- /tests/centos8-build/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd /crun 5 | 6 | git clean -fdx 7 | ./autogen.sh 8 | ./configure CFLAGS='-Wall -Wextra -Werror' 9 | make -j "$(nproc)" 10 | 11 | git clean -fdx 12 | ./autogen.sh 13 | ./configure CFLAGS='-Wall -Wextra -Werror' --disable-systemd 14 | make -j "$(nproc)" 15 | -------------------------------------------------------------------------------- /tests/centos9-build/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd /crun 5 | 6 | git clean -fdx 7 | ./autogen.sh 8 | ./configure CFLAGS='-Wall -Wextra -Werror' 9 | make -j "$(nproc)" 10 | 11 | git clean -fdx 12 | ./autogen.sh 13 | ./configure CFLAGS='-Wall -Wextra -Werror' --disable-systemd 14 | make -j "$(nproc)" 15 | -------------------------------------------------------------------------------- /tests/clang-check/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | RUN yum install -y git protobuf-c protobuf-c-devel make clang-tools-extra clang python3-pip 'dnf-command(builddep)' && \ 4 | dnf builddep -y crun && pip install scan-build 5 | 6 | COPY run-tests.sh /usr/local/bin 7 | 8 | ENTRYPOINT /usr/local/bin/run-tests.sh 9 | -------------------------------------------------------------------------------- /contrib/honggfuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # systemd-run --scope --user become-root -a -P -S -C bash 4 | 5 | test -e rootfs || mkdir rootfs 6 | 7 | ./configure --enable-embedded-yajl CC=hfuzz-clang CPPFLAGS='-D FUZZER' CFLAGS="-ggdb3" 8 | 9 | make 10 | 11 | honggfuzz --verifier --timeout 10 --linux_perf_instr --threads 4 -i testcases -- tests/tests_libcrun_fuzzer 12 | -------------------------------------------------------------------------------- /tests/centos8-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/centos/centos:stream8 2 | 3 | RUN yum --enablerepo='powertools' install -y make automake autoconf gettext \ 4 | criu-devel libtool gcc libcap-devel systemd-devel yajl-devel \ 5 | libgcrypt-devel libseccomp-devel python36 libtool git 6 | 7 | COPY run-tests.sh /usr/local/bin 8 | 9 | ENTRYPOINT /usr/local/bin/run-tests.sh 10 | -------------------------------------------------------------------------------- /tests/clang-format/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e -x 4 | 5 | cd /crun 6 | 7 | # Recent git complains that the directory is owned by someone else, 8 | # which happens if we run it via a Dockefile with a volume mounted. 9 | git config --global --add safe.directory "$(pwd)" 10 | 11 | ./configure 12 | make clang-format 13 | git diff --ignore-submodules --exit-code 14 | -------------------------------------------------------------------------------- /tests/Makefile.tests: -------------------------------------------------------------------------------- 1 | TESTS := $(shell find . -name "test_*.py") 2 | 3 | INIT ?= init 4 | OCI_RUNTIME ?= /usr/bin/crun 5 | 6 | check: $(INIT) tap-driver.sh 7 | OCI_RUNTIME=${OCI_RUNTIME} INIT=${INIT} ./run_all_tests.sh 8 | 9 | tap-driver.sh: 10 | wget https://git.savannah.gnu.org/cgit/automake.git/plain/lib/tap-driver.sh 11 | chmod +x tap-driver.sh 12 | 13 | init: init.c 14 | $(CC) -static $< -o $@ 15 | -------------------------------------------------------------------------------- /nix/nixpkgs.json: -------------------------------------------------------------------------------- 1 | { 2 | "url": "https://github.com/nixos/nixpkgs", 3 | "rev": "4d76a8a81f1a918ae273225692eef5d684ea02ca", 4 | "date": "2022-07-20T02:11:28-05:00", 5 | "path": "/nix/store/nnw6a319s2q7m9qfhqd4crgf0wk11kyc-nixpkgs", 6 | "sha256": "1jhgpdpv2761ky9djagrdjxcp24khvqp7xkcbq4j5srlkbaf2hrk", 7 | "fetchLFS": false, 8 | "fetchSubmodules": false, 9 | "deepClone": false, 10 | "leaveDotGit": false 11 | } 12 | -------------------------------------------------------------------------------- /tests/centos9-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/centos/centos:stream9 2 | 3 | RUN yum --enablerepo='appstream' --enablerepo='baseos' --enablerepo='crb' install -y make \ 4 | automake autoconf gettext criu-devel libtool gcc libcap-devel systemd-devel yajl-devel \ 5 | libgcrypt-devel libseccomp-devel python3 libtool git protobuf-c protobuf-c-devel 6 | 7 | COPY run-tests.sh /usr/local/bin 8 | 9 | ENTRYPOINT /usr/local/bin/run-tests.sh 10 | -------------------------------------------------------------------------------- /tests/containerd/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if test "$(id -u)" != 0; then 4 | echo "run as root" 5 | exit 1 6 | fi 7 | 8 | set -e 9 | ( 10 | cd /crun 11 | ./autogen.sh 12 | ./configure CFLAGS='-Wall -Wextra -Werror' 13 | make -j "$(nproc)" 14 | cp crun /usr/bin/runc 15 | ) 16 | 17 | ulimit -u unlimited 18 | 19 | export PATH=$PATH:${PWD}/bin 20 | 21 | make RUNC_FLAVOR=crun TEST_RUNTIME=io.containerd.runc.v2 TESTFLAGS="-timeout 120m" integration 22 | -------------------------------------------------------------------------------- /contrib/seccomp-notify-plugin-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "seccomp-watcher" 3 | version = "0.1.0" 4 | authors = ["Giuseppe Scrivano "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | libc = { version = "0.2.14", default-features = false } 9 | nc = "0.4.7" 10 | 11 | [lib] 12 | name = "seccompwatcher_rs" 13 | path = "src/seccompwatcher.rs" 14 | crate-type = ["dylib"] 15 | 16 | [profile.release] 17 | panic = "abort" 18 | lto = true 19 | -------------------------------------------------------------------------------- /tests/fuzzing/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | RUN yum install -y golang python git automake autoconf libcap-devel \ 4 | libgcrypt-devel systemd-devel yajl-devel libseccomp-devel go-md2man \ 5 | glibc-static python3-libmount libtool make honggfuzz git 6 | 7 | RUN git clone https://github.com/giuseppe/containers-fuzzing-corpus /testcases 8 | 9 | COPY run-tests.sh /usr/local/bin 10 | 11 | WORKDIR /crun 12 | 13 | ENTRYPOINT /usr/local/bin/run-tests.sh 14 | -------------------------------------------------------------------------------- /tests/fedora-rawhide-mockbuild/run-mockbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | cd /crun 5 | # needed to silence ambiguous directory ownership error 6 | git config --global --add safe.directory /crun 7 | git clean -fdx 8 | 9 | make -f .copr/Makefile srpm 10 | 11 | dnf -y install 'dnf-command(copr)' 12 | # Copr repo subject to change after discussions with wasmtime upstream 13 | dnf -y copr enable lsm5/wasmtime 14 | dnf -y install libkrun-devel wasmtime-c-api-devel 15 | make rpm 16 | -------------------------------------------------------------------------------- /tests/oci-validation/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | ENV GOPATH=/root/go 4 | ENV PATH=/usr/bin:/usr/sbin:/root/go/bin:/usr/local/bin::/usr/local/sbin 5 | 6 | RUN yum install -y golang python git gcc automake autoconf libcap-devel \ 7 | systemd-devel yajl-devel libseccomp-devel libselinux-devel \ 8 | glibc-static python3-libmount libtool make npm go-md2man && \ 9 | npm install -g tap 10 | 11 | COPY run-tests.sh /usr/local/bin 12 | 13 | ENTRYPOINT /usr/local/bin/run-tests.sh 14 | -------------------------------------------------------------------------------- /tests/run_all_tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | INIT=${INIT:-init} 4 | OCI_RUNTIME=${OCI_RUNTIME:-/usr/bin/crun} 5 | 6 | export INIT 7 | export OCI_RUNTIME 8 | 9 | rm -f *.trs 10 | 11 | COLOR= 12 | if [ -t 1 ]; then 13 | COLOR="--color-tests yes" 14 | fi 15 | 16 | for i in test_*.py 17 | do 18 | ./tap-driver.sh --test-name $i --log-file $i.log --trs-file $i.trs ${COLOR} --enable-hard-errors yes --expect-failure no -- /usr/bin/python $i 19 | done 20 | 21 | if grep FAIL *.trs; then 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /tests/clang-check/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | cd /crun 5 | 6 | git config --global --add safe.directory /crun 7 | git clean -fdx 8 | ./autogen.sh 9 | ./configure CFLAGS='-Wall -Wextra -Werror' CC=clang 10 | intercept-build make 11 | 12 | echo -e "\n\n----------------------------- clang-check -------------------------------\n\n" 13 | 14 | git ls-files src | grep -E "\\.[c]" | \ 15 | grep -v "chroot_realpath.c\|cloned_binary.c\|signals.c" | \ 16 | xargs clang-check --analyze 17 | -------------------------------------------------------------------------------- /tests/wasmedge-build/hello_wasm/hello/src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | fn main() { 3 | println!("Print env::args()"); 4 | for arg in env::args() { 5 | println!("{arg}"); 6 | } 7 | println!("Print env::vars()"); 8 | // In this test, the `container=podman` 9 | match env::var("container") { 10 | Ok(val) => println!("container: {val:?}"), 11 | Err(e) => println!("couldn't interpret container: {e}"), 12 | } 13 | // In this test, the `key=value` 14 | match env::var("key") { 15 | Ok(val) => println!("key: {val:?}"), 16 | Err(e) => println!("couldn't interpret key: {e}"), 17 | } 18 | println!("{}", "This is from a main function from a wasm module"); 19 | } 20 | -------------------------------------------------------------------------------- /cfg.mk: -------------------------------------------------------------------------------- 1 | export VC_LIST_EXCEPT_DEFAULT=^(lib/.*|m4/.*|md5/.*|build-aux/.*|src/gettext\.h|.*ChangeLog|src/libcrun/cloned_binary.c|src/libcrun/chroot_realpath.c|.*\.1)$$ 2 | 3 | local-checks-to-skip = \ 4 | sc_immutable_NEWS \ 5 | sc_copyright_check \ 6 | \ 7 | sc_prohibit_path_max_allocation \ 8 | sc_prohibit_strcmp \ 9 | sc_program_name \ 10 | sc_bindtextdomain \ 11 | sc_unmarked_diagnostics \ 12 | sc_prohibit_intprops_without_use \ 13 | sc_error_message_uppercase \ 14 | sc_GPL_version \ 15 | sc_cast_of_x_alloc_return_value \ 16 | sc_indent \ 17 | sc_prohibit_always-defined_macros \ 18 | sc_prohibit_gnu_make_extensions 19 | 20 | #SHELL=bash -x 21 | show-vc-list-except: 22 | @$(VC_LIST_EXCEPT) 23 | 24 | VC_LIST_ALWAYS_EXCLUDE_REGEX = ^ABOUT-NLS|maint.mk|git.mk|tests.*|COPYING|contrib/.*$$ 25 | 26 | export gl_public_submodule_commit= 27 | -------------------------------------------------------------------------------- /tests/podman/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | ENV GOPATH=/root/go 4 | ENV PATH=/usr/bin:/usr/sbin:/root/go/bin:/usr/local/bin::/usr/local/sbin 5 | 6 | RUN dnf install -y golang python git gcc automake autoconf libcap-devel \ 7 | systemd-devel yajl-devel libseccomp-devel go-md2man libgcrypt-devel \ 8 | glibc-static python3-libmount libtool make podman xz nmap-ncat \ 9 | containernetworking-plugins 'dnf-command(builddep)' && \ 10 | dnf builddep -y podman && \ 11 | chmod 755 /root && \ 12 | git clone https://github.com/containers/podman /root/go/src/github.com/containers/podman && \ 13 | cd /root/go/src/github.com/containers/podman && \ 14 | make .install.ginkgo install.catatonit && \ 15 | make 16 | 17 | ## Change default log driver to k8s-file for tests 18 | RUN sed -i 's/journald/k8s-file/g' /usr/share/containers/containers.conf 19 | COPY run-tests.sh /usr/local/bin 20 | WORKDIR /root/go/src/github.com/containers/podman 21 | ENTRYPOINT /usr/local/bin/run-tests.sh 22 | -------------------------------------------------------------------------------- /src/ps.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef PS_H 19 | #define PS_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_ps (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/restore.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Adrian Reber 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef RESTORE_H 19 | #define RESTORE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_restore (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/run.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef RUN_H 19 | #define RUN_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_run (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/exec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef EXEC_H 19 | #define EXEC_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_exec (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/kill.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef KILL_H 19 | #define KILL_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_kill (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef LIST_H 19 | #define LIST_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_list (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/spec.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef SPEC_H 19 | #define SPEC_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_spec (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/pause.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef PAUSE_H 19 | #define PAUSE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_pause (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/start.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef START_H 19 | #define START_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_start (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/state.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef STATE_H 19 | #define STATE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_state (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/update.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef UPDATE_H 19 | #define UPDATE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_update (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/create.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CREATE_H 19 | #define CREATE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_create (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/delete.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef DELETE_H 19 | #define DELETE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_delete (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/unpause.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef UNPAUSE_H 19 | #define UNPAUSE_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_command_unpause (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/checkpoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Adrian Reber 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CHECKPOINT_H 19 | #define CHECKPOINT_H 20 | 21 | #include "crun.h" 22 | 23 | int crun_parse_manage_cgroups_mode (char *param); 24 | int crun_command_checkpoint (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *error); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-cgroupfs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_CGROUPFS_H 19 | #define CGROUP_CGROUPFS_H 20 | 21 | #include "container.h" 22 | #include "cgroup.h" 23 | #include 24 | 25 | extern struct libcrun_cgroup_manager cgroup_manager_cgroupfs; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/libcrun/handlers/handler-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef HANDLER_UTILS_H 19 | #define HANDLER_UTILS_H 20 | 21 | #include "../container.h" 22 | #include 23 | 24 | int wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.a 2 | *.cov 3 | *.gcda 4 | *.gcno 5 | *.gcov 6 | *.i 7 | *.la 8 | *.lo 9 | *.o 10 | *.orig 11 | *.pyc 12 | *.rej 13 | *.s 14 | *.service 15 | *.socket 16 | *.swp 17 | .version 18 | git-version.h 19 | *~ 20 | .#* 21 | .color_coded 22 | .deps 23 | .dirstamp 24 | .gdb_history 25 | .git 26 | .git-module-status 27 | .deps 28 | .dirstamp 29 | .gdb_history 30 | .git 31 | .git-module-status 32 | .libs 33 | .lvimrc 34 | .memdump 35 | .sc-start-sc_* 36 | .ycm_extra_conf.py 37 | /aclocal.m4 38 | /autom4te.cache 39 | build-aux/compile 40 | build-aux/config.guess 41 | build-aux/config.sub 42 | build-aux/depcomp 43 | build-aux/install-sh 44 | build-aux/ltmain.sh 45 | build-aux/missing 46 | build-aux/tap-driver.sh 47 | crun 48 | /config.h 49 | /config.h.in 50 | /config.log 51 | /config.status 52 | /configure 53 | libtool 54 | m4/libtool.m4 55 | m4/ltoptions.m4 56 | m4/ltsugar.m4 57 | m4/ltversion.m4 58 | m4/lt~obsolete.m4 59 | /Makefile 60 | libocispec/Makefile 61 | Makefile.in 62 | result 63 | rpm/crun.spec 64 | stamp-h 65 | stamp-h.in 66 | stamp-h1 67 | tests/init 68 | tests/tests_* 69 | tests/*.log 70 | tests/*.trs 71 | test-suite.log 72 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-setup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_SETUP_H 19 | #define CGROUP_SETUP_H 20 | 21 | #include "container.h" 22 | #include "utils.h" 23 | 24 | int enter_cgroup (int cgroup_mode, pid_t pid, pid_t init_pid, const char *path, 25 | bool create_if_missing, libcrun_error_t *err); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-systemd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_SYSTEMD_H 19 | #define CGROUP_SYSTEMD_H 20 | 21 | #include "container.h" 22 | #include 23 | 24 | int parse_sd_array (char *s, char **out, char **next, libcrun_error_t *err); 25 | 26 | extern struct libcrun_cgroup_manager cgroup_manager_systemd; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /tests/wasmedge-build/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | 5 | # Build crun with wasmedge support 6 | cd /crun 7 | 8 | git config --global --add safe.directory /crun 9 | git clean -fdx 10 | ./autogen.sh 11 | ./configure CFLAGS='-Wall -Wextra -Werror' --with-wasmedge 12 | make -j "$(nproc)" 13 | make install 14 | 15 | # Remove the installed crun to make sure the built crun is used 16 | rm -rf /usr/bin/crun 17 | ln -s /usr/local/bin/crun /usr/bin/crun 18 | 19 | # Test crun is used in podman 20 | if [[ $(podman info | grep SYSTEMD) != *WASM:wasmedge* ]]; then 21 | echo "podman cannot find the built crun with +WASM:wasmedge" 22 | exit 1 23 | fi 24 | 25 | # Build hellowasm image 26 | cd /hello_wasm && \ 27 | chmod +x ./hello.wasm && \ 28 | buildah build --annotation "module.wasm.image/variant=compat-smart" -t hellowasm-image . 29 | 30 | # Run hello.wasm with crun 31 | OUTPUT=$(podman run hellowasm-image:latest) 32 | FILE1="tmp.output" 33 | FILE2="expected_output" 34 | echo "$OUTPUT" > "$FILE1" 35 | if cmp -s "$FILE1" "$FILE2"; then 36 | echo "Run wasm success. The execution result is exactly matched" 37 | else 38 | echo "Run wasm failed. The execution result is not matched" 39 | exit 1 40 | fi 41 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-resources.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_RESOURCES_H 19 | #define CGROUP_RESOURCES_H 20 | 21 | #include "container.h" 22 | #include "cgroup.h" 23 | #include 24 | 25 | int update_cgroup_resources (const char *path, 26 | runtime_spec_schema_config_linux_resources *resources, 27 | libcrun_error_t *err); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /tests/fuzzing/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -xeu 4 | 5 | TIMEOUT=${TIMEOUT:=10} 6 | RUN_TIME=${RUN_TIME:=600} 7 | VERBOSITY=${VERBOSITY:=} 8 | 9 | N_TESTS=8 10 | 11 | SINGLE_RUN_TIME=$(( RUN_TIME / N_TESTS )) 12 | 13 | CORPUS=${CORPUS:=/testcases} 14 | 15 | git config --global --add safe.directory /crun 16 | git clean -fdx 17 | ./autogen.sh 18 | ./configure --enable-embedded-yajl HFUZZ_CC_UBSAN=1 HFUZZ_CC_ASAN=1 CC=hfuzz-clang CPPFLAGS="-D FUZZER" CFLAGS="-ggdb3 -fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div,indirect-calls" 19 | make -j "$(nproc)" 20 | 21 | mkdir rootfs 22 | mkdir random-data 23 | 24 | function run_test { 25 | export FUZZING_MODE=$1 26 | TEST_CASE=$2 27 | 28 | result=$(honggfuzz --exit_upon_crash $VERBOSITY --run_time "$SINGLE_RUN_TIME" --timeout $TIMEOUT -T -i "$TEST_CASE" -- tests/tests_libcrun_fuzzer 2>&1 | tail -n 2) 29 | echo "$result" 30 | echo "$result" | grep -q crashes_count:0 31 | } 32 | 33 | run_test 0 $CORPUS/config-json 34 | run_test 1 $CORPUS/config-json 35 | run_test 2 $CORPUS/seccomp 36 | run_test 3 $CORPUS/signals 37 | run_test 4 $CORPUS/paths 38 | run_test 5 random-data 39 | run_test 6 $CORPUS/annotations 40 | run_test 7 $CORPUS/idmapped-mounts-option 41 | -------------------------------------------------------------------------------- /.github/workflows/codeql-analysis.yml: -------------------------------------------------------------------------------- 1 | name: "CodeQL" 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | # The branches below must be a subset of the branches above 8 | branches: [ main ] 9 | schedule: 10 | - cron: '39 22 * * 5' 11 | 12 | jobs: 13 | analyze: 14 | name: Analyze 15 | runs-on: ubuntu-latest 16 | permissions: 17 | actions: read 18 | contents: read 19 | security-events: write 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | language: [ 'cpp' ] 25 | 26 | steps: 27 | - name: Checkout repository 28 | uses: actions/checkout@v3 29 | 30 | # Initializes the CodeQL tools for scanning. 31 | - name: Initialize CodeQL 32 | uses: github/codeql-action/init@v2 33 | with: 34 | languages: ${{ matrix.language }} 35 | 36 | - run: | 37 | sudo apt-get update 38 | sudo apt-get install -y make git gcc build-essential pkgconf libtool libsystemd-dev libcap-dev libseccomp-dev libyajl-dev go-md2man libtool autoconf python3 automake libprotobuf-c-dev 39 | ./autogen.sh 40 | ./configure 41 | make -j $(nproc) 42 | 43 | - name: Perform CodeQL Analysis 44 | uses: github/codeql-action/analyze@v2 45 | -------------------------------------------------------------------------------- /tests/test_cwd.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_cwd(): 21 | conf = base_config() 22 | conf['process']['args'] = ['/init', 'cwd'] 23 | conf['process']['cwd'] = "/var" 24 | add_all_namespaces(conf) 25 | out, _ = run_and_get_output(conf) 26 | if "/var" not in out: 27 | return -1 28 | return 0 29 | 30 | all_tests = { 31 | "cwd" : test_cwd, 32 | } 33 | 34 | if __name__ == "__main__": 35 | tests_main(all_tests) 36 | -------------------------------------------------------------------------------- /src/libcrun/mount_flags.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019, 2021 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #ifndef MOUNT_FLAGS_H 20 | #define MOUNT_FLAGS_H 21 | 22 | enum 23 | { 24 | OPTION_TMPCOPYUP = (1 << 0), 25 | OPTION_RECURSIVE = (1 << 1), 26 | OPTION_IDMAP = (1 << 2), 27 | }; 28 | 29 | struct propagation_flags_s 30 | { 31 | char *name; 32 | int clear; 33 | int flags; 34 | int extra_flags; 35 | }; 36 | 37 | const struct propagation_flags_s *libcrun_str2mount_flags (const char *name); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /tests/test_hostname.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_hostname(): 21 | conf = base_config() 22 | conf['process']['args'] = ['/init', 'gethostname'] 23 | conf['hostname'] = "foomachine" 24 | add_all_namespaces(conf) 25 | out, _ = run_and_get_output(conf) 26 | if "foomachine" not in out: 27 | return -1 28 | return 0 29 | 30 | all_tests = { 31 | "hostname" : test_hostname, 32 | } 33 | 34 | if __name__ == "__main__": 35 | tests_main(all_tests) 36 | -------------------------------------------------------------------------------- /tests/containerd/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:jammy 2 | 3 | ENV GOPATH=/root/go 4 | ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/root/go/bin 5 | 6 | RUN apt-get update \ 7 | && apt-get -y upgrade \ 8 | && apt-get install -y bash golang-1.18 libbtrfs-dev libnl-3-dev libnet1-dev \ 9 | protobuf-c-compiler libgcrypt20-dev libcap-dev libaio-dev \ 10 | curl libprotobuf-c-dev libprotobuf-dev socat libseccomp-dev \ 11 | pigz lsof make git gcc build-essential pkgconf libtool \ 12 | libsystemd-dev libcap-dev libyajl-dev \ 13 | go-md2man libtool autoconf python3 automake sudo \ 14 | && update-alternatives --install /usr/bin/go go /usr/lib/go-1.18/bin/go 0 \ 15 | && mkdir -p /root/go/src/github.com/containerd \ 16 | && chmod 755 /root \ 17 | && (cd /root/go/src/github.com/containerd \ 18 | && git clone https://github.com/containerd/containerd \ 19 | && cd containerd \ 20 | && git reset --hard v1.6.8 \ 21 | && make \ 22 | && make binaries \ 23 | && make install \ 24 | && script/setup/install-cni \ 25 | && script/setup/install-critools) \ 26 | && rm -rf /bin/runc /sbin/runc /usr/sbin/runc /usr/bin/runc 27 | 28 | COPY run-tests.sh /usr/local/bin 29 | WORKDIR /root/go/src/github.com/containerd/containerd 30 | ENTRYPOINT /usr/local/bin/run-tests.sh 31 | -------------------------------------------------------------------------------- /tests/wasmedge-build/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:rawhide 2 | ARG WASM_EDGE_VERSION="0.11.0" 3 | 4 | # Install the deps for building crun 5 | RUN dnf update -y && dnf install -y make python git gcc automake autoconf libcap-devel \ 6 | systemd-devel yajl-devel libseccomp-devel pkg-config diffutils \ 7 | libgcrypt-devel systemd-devel yajl-devel libseccomp-devel pkg-config \ 8 | go-md2man glibc-static python3-libmount libtool buildah podman 9 | 10 | # Install WasmEdge 11 | RUN curl -sSf -o install.sh https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh 12 | RUN bash ./install.sh -p /usr/local -v $WASM_EDGE_VERSION 13 | 14 | # The hello_wasm contains: 15 | # 1. The example rust application called hello, which will print something to console. 16 | # 2. The Containerfile for building the image including hello.wasm 17 | ADD hello_wasm /hello_wasm 18 | 19 | # Install Rust for building wasm application 20 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y 21 | SHELL ["/bin/bash", "-c"] 22 | RUN source "$HOME/.cargo/env" && \ 23 | rustup target add wasm32-wasi && \ 24 | cd /hello_wasm/hello && \ 25 | cargo build --release --target wasm32-wasi && \ 26 | cp ./target/wasm32-wasi/release/hello.wasm /hello_wasm && \ 27 | cd / && \ 28 | rm -rf /hello_wasm/hello 29 | 30 | COPY run-tests.sh /usr/local/bin 31 | 32 | ENTRYPOINT ["/usr/local/bin/run-tests.sh"] 33 | -------------------------------------------------------------------------------- /src/crun.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CRUN_H 19 | #define CRUN_H 20 | 21 | #include "libcrun/container.h" 22 | 23 | struct crun_global_arguments 24 | { 25 | char *root; 26 | char *log; 27 | char *log_format; 28 | const char *handler; 29 | 30 | bool command; 31 | bool debug; 32 | bool option_systemd_cgroup; 33 | bool option_force_no_cgroup; 34 | }; 35 | 36 | char *argp_mandatory_argument (char *arg, struct argp_state *state); 37 | int init_libcrun_context (libcrun_context_t *con, const char *id, struct crun_global_arguments *glob, 38 | libcrun_error_t *err); 39 | void crun_assert_n_args (int n, int min, int max); 40 | #endif 41 | -------------------------------------------------------------------------------- /src/libcrun/terminal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef TERMINAL_H 19 | #define TERMINAL_H 20 | #include 21 | 22 | #include "container.h" 23 | #include 24 | 25 | void cleanup_terminalp (void *p); 26 | #define cleanup_terminal __attribute__ ((cleanup (cleanup_terminalp))) 27 | 28 | int libcrun_new_terminal (char **pty, libcrun_error_t *err); 29 | 30 | int libcrun_set_stdio (char *pty, libcrun_error_t *err); 31 | 32 | int libcrun_setup_terminal_ptmx (int fd, void **current_status, libcrun_error_t *err); 33 | 34 | int libcrun_terminal_setup_size (int fd, unsigned short rows, unsigned short cols, libcrun_error_t *err); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tests/oci-validation/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | if test "$(id -u)" != 0; then 7 | echo "run as root" 8 | exit 1 9 | fi 10 | 11 | ( 12 | cd /crun 13 | git config --global --add safe.directory /crun 14 | git clean -fdx 15 | ./autogen.sh 16 | ./configure 17 | make -j "$(nproc)" 18 | ) 19 | 20 | export GO111MODULE=off 21 | 22 | # Install and run runtime-tools' validation tests 23 | go get -d -u github.com/opencontainers/runtime-tools || true 24 | 25 | export GOCACHE=/var/tmp/gocache 26 | export TMPDIR=/var/tmp 27 | export XDG_RUNTIME_DIR=/run 28 | 29 | cd "$GOPATH/src/github.com/opencontainers/runtime-tools" 30 | 31 | # Skip: 32 | # cgroup tests as they require special configurations on the host 33 | # readonly_paths, masked_paths and seccomp timeouts or don't work on Travis 34 | # misc_props, kill, hostname, process and pidfile are flaky. 35 | # start - expect to not fail if the specified process doesn't exist (support process unset) 36 | # hooks_stdin - tests are racy 37 | # delete - both crun and runc allow to delete a container in the "created" state. 38 | VALIDATION_TESTS=$(make print-validation-tests | tr ' ' '\n' | grep -Ev "(hooks_stdin|misc_props|start|cgroup|readonly_paths|kill|masked_paths|seccomp|process|pidfile|hostname|delete)" | tr '\n' ' ') 39 | export VALIDATION_TESTS 40 | export RUNTIME="/crun/crun" 41 | 42 | # Build test binaries 43 | make -j "$(nproc)" runtimetest validation-executables 44 | # Run tests 45 | make localvalidation 46 | -------------------------------------------------------------------------------- /tests/test_pid_file.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def test_pid_file(): 22 | conf = base_config() 23 | add_all_namespaces(conf) 24 | conf['process']['args'] = ['/init', 'cwd', ''] 25 | pid_file = os.path.abspath('test-pid-%s' % os.getpid()) 26 | try: 27 | run_and_get_output(conf, pid_file=pid_file) 28 | with open(pid_file) as p: 29 | content = p.read() 30 | if len(content) > 0: 31 | return 0 32 | finally: 33 | os.unlink(pid_file) 34 | return -1 35 | 36 | all_tests = { 37 | "test_pid_file" : test_pid_file, 38 | } 39 | 40 | if __name__ == "__main__": 41 | tests_main(all_tests) 42 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-utils.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_UTILS_H 19 | #define CGROUP_UTILS_H 20 | 21 | #include "container.h" 22 | #include "cgroup.h" 23 | #include 24 | 25 | int libcrun_move_process_to_cgroup (pid_t pid, pid_t init_pid, char *path, libcrun_error_t *err); 26 | 27 | int libcrun_cgroups_create_symlinks (int dirfd, libcrun_error_t *err); 28 | 29 | int libcrun_get_current_unified_cgroup (char **path, libcrun_error_t *err); 30 | 31 | int libcrun_get_cgroup_mode (libcrun_error_t *err); 32 | 33 | int libcrun_get_cgroup_dirfd (struct libcrun_cgroup_status *status, const char *sub_cgroup, libcrun_error_t *err); 34 | 35 | int make_cgroup_threaded (const char *path, libcrun_error_t *err); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /rpm/Makefile: -------------------------------------------------------------------------------- 1 | CWD:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 2 | 3 | SUDO_CMD := 4 | ifneq ($(shell id -u), 0) 5 | SUDO_CMD := sudo 6 | endif 7 | 8 | # Only install deps for Copr's make_srpm method to be happy. Doesn't include all 9 | # rpm build deps 10 | srpm-dep: 11 | $(SUDO_CMD) dnf -y install autoconf automake git git-archive-all \ 12 | libcap-devel libseccomp-devel libtool m4 rpm-build systemd-devel \ 13 | yajl-devel 14 | 15 | .ONESHELL: 16 | tarball-prep: srpm-dep 17 | cd "$(CWD)/.."; 18 | git config --global --add safe.directory /crun 19 | git config --global --add safe.directory /crun/libocispec 20 | git config --global --add safe.directory /crun/libocispec/image-spec 21 | git config --global --add safe.directory /crun/libocispec/runtime-spec 22 | git config --global --add safe.directory /crun/libocispec/yajl 23 | git config --global --add safe.directory $(shell pwd)/libocispec 24 | git config --global --add safe.directory $(shell pwd)/libocispec/image-spec 25 | git config --global --add safe.directory $(shell pwd)/libocispec/runtime-spec 26 | git config --global --add safe.directory $(shell pwd)/libocispec/yajl 27 | git-archive-all --prefix=crun-HEAD/ --force-submodules crun-HEAD.tar.gz 28 | 29 | # Configure options intentionally don't match the ones used in crun.spec.in to 30 | # minimize the dependencies required for Copr's make_srpm method. 31 | .ONESHELL: 32 | setup: tarball-prep 33 | cd "$(CWD)/.."; 34 | ./autogen.sh 35 | ./configure --disable-silent-rules 36 | 37 | .ONESHELL: 38 | srpm: setup 39 | cd "$(CWD)/.."; 40 | make libocispec 41 | make srpm 42 | -------------------------------------------------------------------------------- /tests/test_detach.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import json 19 | from tests_utils import * 20 | 21 | def test_detach(): 22 | conf = base_config() 23 | conf['process']['args'] = ['/init', 'pause'] 24 | add_all_namespaces(conf) 25 | 26 | out, container_id = run_and_get_output(conf, detach=True, hide_stderr=True) 27 | if out != "": 28 | return -1 29 | try: 30 | 31 | state = json.loads(run_crun_command(["state", container_id])) 32 | if state['status'] != "running": 33 | return -1 34 | if state['id'] != container_id: 35 | return -1 36 | finally: 37 | run_crun_command(["delete", "-f", container_id]) 38 | return 0 39 | 40 | all_tests = { 41 | "test-detach" : test_detach, 42 | } 43 | 44 | if __name__ == "__main__": 45 | tests_main(all_tests) 46 | -------------------------------------------------------------------------------- /tests/test_pid.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_pid(): 21 | if is_rootless(): 22 | return 77 23 | conf = base_config() 24 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 25 | conf['linux']['namespaces'].append({"type" : "pid"}) 26 | out, _ = run_and_get_output(conf) 27 | pid = parse_proc_status(out)['Pid'] 28 | if pid == "1": 29 | return 0 30 | return -1 31 | 32 | def test_pid_user(): 33 | conf = base_config() 34 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 35 | add_all_namespaces(conf) 36 | out, _ = run_and_get_output(conf) 37 | pid = parse_proc_status(out)['Pid'] 38 | if pid == "1": 39 | return 0 40 | return -1 41 | 42 | all_tests = { 43 | "pid" : test_pid, 44 | "pid-user" : test_pid_user, 45 | } 46 | 47 | if __name__ == "__main__": 48 | tests_main(all_tests) 49 | -------------------------------------------------------------------------------- /src/libcrun/ebpf.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef EBPF_H 19 | #define EBPF_H 20 | 21 | #include 22 | #include 23 | #include 24 | #include "error.h" 25 | #include 26 | #include 27 | #include 28 | #include "container.h" 29 | 30 | struct bpf_program; 31 | 32 | struct bpf_program *bpf_program_new (size_t size); 33 | struct bpf_program *bpf_program_append (struct bpf_program *p, void *data, size_t size); 34 | 35 | struct bpf_program *bpf_program_init_dev (struct bpf_program *program, libcrun_error_t *err); 36 | struct bpf_program *bpf_program_append_dev (struct bpf_program *program, const char *access, char type, int major, 37 | int minor, bool accept, libcrun_error_t *err); 38 | struct bpf_program *bpf_program_complete_dev (struct bpf_program *program, libcrun_error_t *err); 39 | 40 | int libcrun_ebpf_load (struct bpf_program *program, int dirfd, const char *pin, libcrun_error_t *err); 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /tests/test_paths.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_readonly_paths(): 21 | conf = base_config() 22 | conf['root']['readonly'] = False 23 | conf['process']['args'] = ['/init', 'write', '/var/file', 'hello'] 24 | conf['linux']['readonlyPaths'] = ['/var/file'] 25 | add_all_namespaces(conf) 26 | try: 27 | run_and_get_output(conf) 28 | except Exception as e: 29 | if "Read-only file system" in e.output.decode(): 30 | return 0 31 | return -1 32 | 33 | def test_masked_paths(): 34 | conf = base_config() 35 | conf['process']['args'] = ['/init', 'cat', '/var/file'] 36 | conf['linux']['maskedPaths'] = ['/var/file'] 37 | add_all_namespaces(conf) 38 | out, _ = run_and_get_output(conf, hide_stderr=True) 39 | if len(out) > 0: 40 | return -1 41 | return 0 42 | 43 | all_tests = { 44 | "readonly-paths" : test_readonly_paths, 45 | "masked-paths" : test_masked_paths, 46 | } 47 | 48 | if __name__ == "__main__": 49 | tests_main(all_tests) 50 | -------------------------------------------------------------------------------- /tests/test_limits.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_limit_pid_0(): 21 | conf = base_config() 22 | add_all_namespaces(conf) 23 | if is_rootless(): 24 | return 77 25 | conf['process']['args'] = ['/init', 'cat', '/dev/null'] 26 | conf['linux']['resources'] = {"pids" : {"limit" : 0}} 27 | out, _ = run_and_get_output(conf) 28 | if len(out) == 0: 29 | return 0 30 | return -1 31 | 32 | def test_limit_pid_n(): 33 | conf = base_config() 34 | if is_rootless(): 35 | return 77 36 | add_all_namespaces(conf) 37 | conf['process']['args'] = ['/init', 'forkbomb', '20'] 38 | conf['linux']['resources'] = {"pids" : {"limit" : 10}} 39 | try: 40 | run_and_get_output(conf) 41 | except Exception as e: 42 | if "fork: Resource temporarily unavailable" in e.output.decode(): 43 | return 0 44 | return -1 45 | 46 | all_tests = { 47 | "limit-pid-0" : test_limit_pid_0, 48 | "limit-pid-n" : test_limit_pid_n, 49 | } 50 | 51 | if __name__ == "__main__": 52 | tests_main(all_tests) 53 | -------------------------------------------------------------------------------- /tests/cri-o/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM fedora:latest 2 | 3 | ENV GOPATH=/root/go 4 | ENV PATH=/usr/bin:/usr/sbin:/root/go/bin:/usr/local/bin::/usr/local/sbin 5 | 6 | RUN yum install -y python git gcc automake autoconf libcap-devel \ 7 | systemd-devel yajl-devel libseccomp-devel go-md2man conntrack-tools which \ 8 | glibc-static python3-libmount libtool make podman xz nmap-ncat jq bats \ 9 | libgcrypt-devel iproute openssl iputils socat && \ 10 | dnf install -y 'dnf-command(builddep)' && dnf builddep -y podman && \ 11 | dnf remove -y golang && \ 12 | sudo dnf update -y && \ 13 | curl -LO https://go.dev/dl/go1.18.1.linux-amd64.tar.gz && \ 14 | sudo tar -C /usr/local -xzf go1.18.1.linux-amd64.tar.gz && \ 15 | export GOPATH=$HOME/go && \ 16 | export GOROOT=/usr/local/go && \ 17 | export PATH=$GOPATH/bin:$GOROOT/bin:$PATH && \ 18 | mkdir -p /root/go/src/github.com/cri-o && \ 19 | chmod 755 /root && \ 20 | (cd /root/go/src/github.com/cri-o && git clone https://github.com/cri-o/cri-o && \ 21 | cd cri-o && \ 22 | make all test-binaries) && \ 23 | (mkdir -p /root/go/src/github.com/containernetworking && \ 24 | cd /root/go/src/github.com/containernetworking && \ 25 | git clone https://github.com/containernetworking/plugins.git && \ 26 | cd /root/go/src/github.com/containernetworking/plugins && \ 27 | ./build_linux.sh && \ 28 | mkdir -p /opt/cni/bin && \ 29 | cp bin/* /opt/cni/bin/) && \ 30 | (mkdir -p /root/go/src/github.com/kubernetes-sigs && \ 31 | cd /root/go/src/github.com/kubernetes-sigs && \ 32 | git clone https://github.com/kubernetes-sigs/cri-tools && \ 33 | cd /root/go/src/github.com/kubernetes-sigs/cri-tools && \ 34 | make && \ 35 | cp build/bin/crictl /usr/local/bin/) 36 | 37 | COPY run-tests.sh /usr/local/bin 38 | WORKDIR /root/go/src/github.com/cri-o/cri-o 39 | ENTRYPOINT /usr/local/bin/run-tests.sh 40 | -------------------------------------------------------------------------------- /docs/wasm-wasi-example.md: -------------------------------------------------------------------------------- 1 | # crun-wasi-wasm example 2 | * Make sure oci config contains handler for **wasm** or image contains annotation **module.wasm.image/variant=compat**. 3 | * Entrypoint must point to a valid **.wat** (webassembly text) or **.wasm** (webassembly binary). 4 | ```json 5 | ... 6 | "annotations": { 7 | "run.oci.handler": "wasm" 8 | }, 9 | ... 10 | ``` 11 | 12 | ## Examples 13 | #### Compile and run `wasm` modules directly 14 | * Following example is using `rust` to compile a webassembly module but you can use any supported language. 15 | * Create a new rust binary using `cargo new hello_wasm --bin`. 16 | * Add relevant function to `src/main.rs` for this example we will be using a print. 17 | ```rust 18 | fn main() { 19 | println!("{}", "This is from a main function from a wasm module"); 20 | } 21 | ``` 22 | * Compile to `wasm32-wasi` target using `wasm-pack` or any other relevant tool. We are going to be using `cargo build --target wasm32-wasi` 23 | * Create relevant image and use your container manager. But for this example we will be running directly using crun and plub config manually. 24 | ```console 25 | $ crun run wasm-container 26 | This is from a main function from a wasm module 27 | ``` 28 | 29 | #### Running OCI `wasm` compat images with buildah and podman 30 | * Compile your `.wasm` module using instructions from step one. 31 | * Prepare a `Containerfile` with your `.wasm` module. 32 | ```Containerfile 33 | FROM scratch 34 | COPY hello.wasm / 35 | CMD ["/hello.wasm"] 36 | ``` 37 | * Build wasm image using buildah with annotation `module.wasm.image/variant=compat` 38 | ```console 39 | $ buildah build --annotation "module.wasm.image/variant=compat" -t mywasm-image . 40 | ``` 41 | * Make sure your podman points to oci runtime `crun` build with `wasm` support. 42 | * Run image using podman 43 | ```console 44 | $ podman run mywasm-image:latest 45 | This is from a main function from a wasm module 46 | ``` 47 | -------------------------------------------------------------------------------- /src/libcrun/seccomp_notify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef SECCOMP_NOTIFY_H 19 | #define SECCOMP_NOTIFY_H 20 | 21 | #include 22 | #include "error.h" 23 | 24 | #if ! (HAVE_DLOPEN && HAVE_SECCOMP_GET_NOTIF_SIZES) 25 | # define SECCOMP_NOTIFY_SKIP_TYPEDEF 26 | #endif 27 | #include "seccomp_notify_plugin.h" 28 | 29 | struct seccomp_notify_context_s; 30 | 31 | LIBCRUN_PUBLIC int libcrun_load_seccomp_notify_plugins (struct seccomp_notify_context_s **out, const char *plugins, 32 | struct libcrun_load_seccomp_notify_conf_s *conf, 33 | libcrun_error_t *err); 34 | LIBCRUN_PUBLIC int libcrun_seccomp_notify_plugins (struct seccomp_notify_context_s *ctx, int seccomp_fd, 35 | libcrun_error_t *err); 36 | LIBCRUN_PUBLIC int libcrun_free_seccomp_notify_plugins (struct seccomp_notify_context_s *ctx, libcrun_error_t *err); 37 | 38 | #define cleanup_seccomp_notify_context __attribute__ ((cleanup (cleanup_seccomp_notify_pluginsp))) 39 | void cleanup_seccomp_notify_pluginsp (void *p); 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /tests/test_update.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | import shutil 20 | from tests_utils import * 21 | 22 | def test_update(): 23 | conf = base_config() 24 | conf['process']['args'] = ['/init', 'pause'] 25 | add_all_namespaces(conf) 26 | 27 | temp_dir = tempfile.mkdtemp(dir=get_tests_root()) 28 | out, container_id = run_and_get_output(conf, detach=True) 29 | try: 30 | p = "/sys/fs/cgroup/memory/system.slice/libcrun-%s.scope/memory.limit_in_bytes" % container_id 31 | if not os.path.exists(p): 32 | return 77 33 | with open(p) as f: 34 | oldval = f.read() 35 | 36 | res_file = os.path.join(temp_dir, "resources") 37 | with open(res_file, 'w') as f: 38 | f.write('{"memory": {"limit": 2000000}}') 39 | 40 | run_crun_command(["update", "-r", res_file, container_id]) 41 | 42 | with open(p) as f: 43 | newval = f.read() 44 | 45 | if newval != oldval: 46 | return 0 47 | finally: 48 | run_crun_command(["delete", "-f", container_id]) 49 | shutil.rmtree(temp_dir) 50 | return 1 51 | 52 | 53 | all_tests = { 54 | "test-update" : test_update, 55 | } 56 | 57 | if __name__ == "__main__": 58 | tests_main(all_tests) 59 | -------------------------------------------------------------------------------- /tests/test_tty.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def tty_helper(fd): 22 | if os.isatty(1) == False: 23 | return 77 24 | conf = base_config() 25 | conf['process']['args'] = ['/init', 'isatty', fd] 26 | conf['process']['terminal'] = True 27 | add_all_namespaces(conf) 28 | out, _ = run_and_get_output(conf) 29 | if "true" not in out: 30 | return -1 31 | return 0 32 | 33 | def test_stdin_tty(): 34 | return tty_helper("0") 35 | 36 | def test_stdout_tty(): 37 | return tty_helper("1") 38 | 39 | def test_stderr_tty(): 40 | return tty_helper("2") 41 | 42 | def test_tty_and_detach(): 43 | if os.isatty(1) == False: 44 | return 77 45 | conf = base_config() 46 | conf['process']['args'] = ['/init', 'isatty', 0] 47 | conf['process']['terminal'] = True 48 | add_all_namespaces(conf) 49 | try: 50 | out, _ = run_and_get_output(conf, detach=True) 51 | except Exception as e: 52 | if "use --console-socket" in e.output.decode(): 53 | return 0 54 | return -1 55 | 56 | all_tests = { 57 | "test-stdin-tty" : test_stdin_tty, 58 | "test-stdout-tty" : test_stdout_tty, 59 | "test-stderr-tty" : test_stderr_tty, 60 | "test-detach-tty" : test_tty_and_detach, 61 | } 62 | 63 | if __name__ == "__main__": 64 | tests_main(all_tests) 65 | -------------------------------------------------------------------------------- /docs/mono-example.md: -------------------------------------------------------------------------------- 1 | # mono windows dotnet handler 2 | * Make sure oci config contains handler for **mono** or image contains annotation **run.oci.handler=dotnet**. 3 | * Entrypoint must point to a valid **.exe** (windows .NET compatible executable). 4 | ```json 5 | ... 6 | "annotations": { 7 | "run.oci.handler": "dotnet" 8 | }, 9 | ... 10 | ``` 11 | 12 | ## Examples 13 | #### Compile and run `mono` compatible dotnet executables inside containers natively 14 | * Following example is using `mono` to compile a cross platform executable but you can also use visual studio or any other build tools on windows. 15 | * Add relevant function to `hello.cs` for this example we will be using a print. 16 | ```c# 17 | using System; 18 | using System.Runtime.CompilerServices; 19 | 20 | class MonoEmbed { 21 | static int Main () 22 | { 23 | System.Console.WriteLine("hello"); 24 | return 0; 25 | } 26 | } 27 | 28 | ``` 29 | * Compile a new `.exe` using `mcs -out:hello.exe hello.cs` if you have `mono` or you can `VisualStudio` or `dotnet build` as specified here: https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-build 30 | * Create relevant image and use your container manager. But for this example we will be running directly using crun and plub config manually. 31 | ```console 32 | $ crun run container-with-mono 33 | hello 34 | ``` 35 | 36 | #### Running OCI `mono` compat images with buildah and podman 37 | * Compile your `.exe` module using instructions from step one. 38 | * Prepare a `Containerfile` with your `.exe`. 39 | ```Containerfile 40 | FROM scratch 41 | COPY hello.exe / 42 | CMD ["/hello.exe"] 43 | ``` 44 | * Build wasm image using buildah with annotation `run.oci.handler=dotnet` 45 | ```console 46 | $ buildah build --annotation "run.oci.handler=dotnet" -t my-windows-executable . 47 | ``` 48 | * Make sure your podman points to oci runtime `crun` build with `mono` support. 49 | * Run image using podman 50 | ```console 51 | $ podman run --userns=keep-id my-windows-executable:latest 52 | hello 53 | ``` 54 | 55 | #### Known-Issues 56 | * Crun-mono containers needs user namespace for containers so with podman use `--userns=auto` or `--userns=keep-id`. 57 | -------------------------------------------------------------------------------- /tests/test_preserve_fds.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def test_preserve_fds_0(): 22 | conf = base_config() 23 | add_all_namespaces(conf) 24 | conf['process']['args'] = ['/init', 'ls', '/proc/1/fd'] 25 | out, _ = run_and_get_output(conf, preserve_fds="0", hide_stderr=True) 26 | files = [x for x in out.split('\n') if len(x) > 0 and x[0] != '.'] 27 | if all([int(x) < 3 for x in files]): 28 | return 0 29 | return -1 30 | 31 | def test_preserve_fds_some(): 32 | conf = base_config() 33 | add_all_namespaces(conf) 34 | conf['process']['args'] = ['/init', 'ls', '/proc/1/fd'] 35 | with open('/dev/null', 'r') as f1, open('/dev/null', 'r') as f2, open('/dev/null', 'r') as f3: 36 | if hasattr(os, 'set_inheritable'): 37 | for i in range(100): 38 | try: 39 | os.set_inheritable(i, True) 40 | except: 41 | pass 42 | out, _ = run_and_get_output(conf, preserve_fds="100", hide_stderr=True) 43 | files = [x for x in out.split('\n') if len(x) > 0 and x[0] != '.'] 44 | if any([int(x) > 3 for x in files]): 45 | return 0 46 | return -1 47 | 48 | all_tests = { 49 | "preserve-fds-0" : test_preserve_fds_0, 50 | "preserve-fds-some" : test_preserve_fds_some, 51 | } 52 | 53 | if __name__ == "__main__": 54 | tests_main(all_tests) 55 | -------------------------------------------------------------------------------- /src/libcrun/criu.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Adrian Reber 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #ifndef CRIU_H 20 | #define CRIU_H 21 | 22 | #include 23 | #include "container.h" 24 | #include "error.h" 25 | #include "utils.h" 26 | 27 | #ifdef HAVE_CRIU 28 | 29 | int libcrun_container_checkpoint_linux_criu (libcrun_container_status_t *status, libcrun_container_t *container, 30 | libcrun_checkpoint_restore_t *cr_options, libcrun_error_t *err); 31 | 32 | int libcrun_container_restore_linux_criu (libcrun_container_status_t *status, libcrun_container_t *container, 33 | libcrun_checkpoint_restore_t *cr_options, libcrun_error_t *err); 34 | 35 | #else 36 | 37 | static inline int 38 | libcrun_container_checkpoint_linux_criu (arg_unused libcrun_container_status_t *status, 39 | arg_unused libcrun_container_t *container, 40 | arg_unused libcrun_checkpoint_restore_t *cr_options, libcrun_error_t *err) 41 | { 42 | return crun_make_error (err, 0, "compiled without CRIU support. Checkpointing not available"); 43 | } 44 | 45 | static inline int 46 | libcrun_container_restore_linux_criu (arg_unused libcrun_container_status_t *status, 47 | arg_unused libcrun_container_t *container, 48 | arg_unused libcrun_checkpoint_restore_t *cr_options, libcrun_error_t *err) 49 | { 50 | return crun_make_error (err, 0, "compiled without CRIU support. Restore not available"); 51 | } 52 | 53 | #endif 54 | #endif 55 | -------------------------------------------------------------------------------- /src/pause.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "crun.h" 29 | #include "libcrun/container.h" 30 | #include "libcrun/status.h" 31 | #include "libcrun/utils.h" 32 | 33 | static char doc[] = "OCI runtime"; 34 | 35 | struct pause_options_s 36 | { 37 | }; 38 | 39 | static struct pause_options_s pause_options; 40 | 41 | static struct argp_option options[] = { { 42 | 0, 43 | } }; 44 | 45 | static char args_doc[] = "pause CONTAINER"; 46 | 47 | static error_t 48 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 49 | { 50 | switch (key) 51 | { 52 | case ARGP_KEY_NO_ARGS: 53 | libcrun_fail_with_error (0, "please specify a ID for the container"); 54 | 55 | default: 56 | return ARGP_ERR_UNKNOWN; 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 63 | 64 | int 65 | crun_command_pause (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 66 | { 67 | int first_arg = 0, ret; 68 | 69 | libcrun_context_t crun_context = { 70 | 0, 71 | }; 72 | 73 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &pause_options); 74 | crun_assert_n_args (argc - first_arg, 1, 2); 75 | 76 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 77 | if (UNLIKELY (ret < 0)) 78 | return ret; 79 | 80 | return libcrun_container_pause (&crun_context, argv[first_arg], err); 81 | } 82 | -------------------------------------------------------------------------------- /src/start.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "crun.h" 28 | #include "libcrun/container.h" 29 | #include "libcrun/utils.h" 30 | 31 | static char doc[] = "OCI runtime"; 32 | 33 | enum 34 | { 35 | OPTION_CONSOLE_SOCKET = 1000, 36 | OPTION_PID_FILE, 37 | OPTION_NO_SUBREAPER, 38 | OPTION_NO_NEW_KEYRING, 39 | OPTION_PRESERVE_FDS 40 | }; 41 | 42 | static struct argp_option options[] = { { 43 | 0, 44 | } }; 45 | 46 | static char args_doc[] = "start CONTAINER"; 47 | 48 | static error_t 49 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 50 | { 51 | switch (key) 52 | { 53 | case ARGP_KEY_NO_ARGS: 54 | libcrun_fail_with_error (0, "please specify a ID for the container"); 55 | 56 | default: 57 | return ARGP_ERR_UNKNOWN; 58 | } 59 | 60 | return 0; 61 | } 62 | 63 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 64 | 65 | int 66 | crun_command_start (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 67 | { 68 | int first_arg = 0, ret; 69 | 70 | libcrun_context_t crun_context = { 71 | 0, 72 | }; 73 | 74 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, NULL); 75 | crun_assert_n_args (argc - first_arg, 1, 1); 76 | 77 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 78 | if (UNLIKELY (ret < 0)) 79 | return ret; 80 | 81 | return libcrun_container_start (&crun_context, argv[first_arg], err); 82 | } 83 | -------------------------------------------------------------------------------- /src/unpause.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "crun.h" 29 | #include "libcrun/container.h" 30 | #include "libcrun/status.h" 31 | #include "libcrun/utils.h" 32 | 33 | static char doc[] = "OCI runtime"; 34 | 35 | struct unpause_options_s 36 | { 37 | }; 38 | 39 | static struct unpause_options_s unpause_options; 40 | 41 | static struct argp_option options[] = { { 42 | 0, 43 | } }; 44 | 45 | static char args_doc[] = "resume CONTAINER"; 46 | 47 | static error_t 48 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 49 | { 50 | switch (key) 51 | { 52 | case ARGP_KEY_NO_ARGS: 53 | libcrun_fail_with_error (0, "please specify a ID for the container"); 54 | 55 | default: 56 | return ARGP_ERR_UNKNOWN; 57 | } 58 | 59 | return 0; 60 | } 61 | 62 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 63 | 64 | int 65 | crun_command_unpause (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 66 | { 67 | int first_arg = 0, ret; 68 | 69 | libcrun_context_t crun_context = { 70 | 0, 71 | }; 72 | 73 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &unpause_options); 74 | crun_assert_n_args (argc - first_arg, 1, 2); 75 | 76 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 77 | if (UNLIKELY (ret < 0)) 78 | return ret; 79 | 80 | return libcrun_container_unpause (&crun_context, argv[first_arg], err); 81 | } 82 | -------------------------------------------------------------------------------- /src/libcrun/seccomp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef SECCOMP_H 19 | #define SECCOMP_H 20 | #include 21 | #include 22 | #include 23 | #include "error.h" 24 | #include 25 | #include 26 | #include 27 | #include "container.h" 28 | 29 | enum 30 | { 31 | LIBCRUN_SECCOMP_FAIL_UNKNOWN_SYSCALL = 1 << 0, 32 | LIBCRUN_SECCOMP_SKIP_CACHE = 1 << 1, 33 | }; 34 | 35 | typedef char seccomp_checksum_t[65]; 36 | 37 | struct libcrun_seccomp_gen_ctx_s 38 | { 39 | libcrun_container_t *container; 40 | seccomp_checksum_t checksum; 41 | unsigned int options; 42 | bool create; 43 | bool from_cache; 44 | 45 | /* Not owned here, it is the caller responsibility to close it. */ 46 | int fd; 47 | }; 48 | 49 | static inline void 50 | libcrun_seccomp_gen_ctx_init (struct libcrun_seccomp_gen_ctx_s *ctx, libcrun_container_t *container, bool create, unsigned int seccomp_gen_options) 51 | { 52 | memset (ctx, 0, sizeof (*ctx)); 53 | ctx->create = create; 54 | ctx->container = container; 55 | ctx->options = seccomp_gen_options; 56 | } 57 | 58 | int libcrun_generate_seccomp (struct libcrun_seccomp_gen_ctx_s *gen_ctx, libcrun_error_t *err); 59 | int libcrun_copy_seccomp (struct libcrun_seccomp_gen_ctx_s *gen_ctx, const char *b64_bpf, libcrun_error_t *err); 60 | int libcrun_apply_seccomp (int infd, int listener_receiver_fd, const char *receiver_fd_payload, 61 | size_t receiver_fd_payload_len, char **flags, size_t flags_len, libcrun_error_t *err); 62 | int libcrun_open_seccomp_bpf (struct libcrun_seccomp_gen_ctx_s *ctx, int *fd, libcrun_error_t *err); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /tests/test_rlimits.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import sys 19 | from tests_utils import * 20 | 21 | def parse_proc_limits(content): 22 | lines = content.split("\n") 23 | r = {} 24 | mappings = {'Max open files' : "RLIMIT_NOFILE", 25 | 'Max processes' : "RLIMIT_NPROC", 26 | 'Max cpu time' : "RLIMIT_CPU", 27 | 'Max pending signals' : "RLIMIT_SIGPENDING"} 28 | for i in lines[1:-1]: 29 | s = [x.strip() for x in i.split(" ") if x != ""] 30 | r[mappings.get(s[0], s[0])] = s 31 | return r 32 | 33 | def test_rlimits(): 34 | if is_rootless(): 35 | return 77 36 | conf = base_config() 37 | conf['process']['args'] = ['/init', 'cat', '/proc/self/limits'] 38 | rlimits = [ 39 | {"type" : "RLIMIT_SIGPENDING", 40 | "soft" : 100, 41 | "hard" : 200}, 42 | {"type" : "RLIMIT_NPROC", 43 | "soft" : 50, 44 | "hard" : 100}, 45 | {"type" : "RLIMIT_NOFILE", 46 | "soft" : 512, 47 | "hard" : 512}, 48 | {"type" : "RLIMIT_CPU", 49 | "soft" : 2, 50 | "hard" : 3}, 51 | ] 52 | conf['process']['rlimits'] = rlimits 53 | add_all_namespaces(conf) 54 | out, _ = run_and_get_output(conf) 55 | limits = parse_proc_limits(out) 56 | 57 | for v in rlimits: 58 | limit = limits.get(v['type']) 59 | if str(limit[1]) != str(v['soft']) or str(limit[2]) != str(v['hard']): 60 | sys.stderr.write("%s: %s %s\n" % (limit[0], limit[1], limit[2])) 61 | return -1 62 | return 0 63 | 64 | all_tests = { 65 | "rlimits" : test_rlimits, 66 | } 67 | 68 | if __name__ == "__main__": 69 | tests_main(all_tests) 70 | -------------------------------------------------------------------------------- /tests/podman/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | if test "$(id -u)" != 0; then 4 | echo "run as root" 5 | exit 1 6 | fi 7 | 8 | set -e 9 | ( 10 | cd /crun 11 | git config --global --add safe.directory /crun 12 | git clean -fdx 13 | ./autogen.sh 14 | ./configure CFLAGS='-Wall -Wextra -Werror' --prefix=/usr 15 | make -j "$(nproc)" 16 | make install 17 | ) 18 | 19 | export OCI_RUNTIME=/usr/bin/crun 20 | export CGROUP_MANAGER=cgroupfs 21 | export STORAGE_OPTIONS="--storage-driver=vfs" 22 | 23 | export GO111MODULE=off 24 | 25 | ulimit -u unlimited 26 | export TMPDIR=/var/tmp 27 | 28 | # Skip some tests that are not currently supported in the testing environment: 29 | # 30 | # - search|pull from docker|trust|inspect|logs|generate|import|mounted rw|inherit host devices|privileged CapEff|prune unused images|podman images filter|image list filter 31 | # Flaky or not using the runtime. 32 | # 33 | # - selinux 34 | # Travis runs on Ubuntu. 35 | # 36 | # - systemd 37 | # - notify_socket 38 | # 39 | # - podman run exit 12*|podman run exit code on failure to exec|failed to start 40 | # assumption that "create" must fail if the executable is not found. We must add lookup for the executable in $PATH to mimic the runc behavior. 41 | # device-cgroup-rule|capabilities|network|overlay volume flag|prune removes a pod with a stopped container: not working on github actions 42 | # 43 | # - Podman run with specified static IPv6 has correct IP 44 | # Does not work inside test environment. 45 | 46 | 47 | ginkgo --focus='.*' --skip='.*(selinux|notify_socket|systemd|podman run exit 12*|podman run exit code on failure to exec|failed to start|search|trust|inspect|logs|generate|import|mounted rw|inherit host devices|play kube|cgroups=disabled|privileged CapEff|device-cgroup-rule|capabilities|network|pull from docker|--add-host|removes a pod with a container|prune removes a pod with a stopped container|overlay volume flag|prune unused images|podman images filter|image list filter|create --pull|podman ps json format|using journald for container|image tree|--pull|shared layers|child images|cached images|flag with multiple mounts|overlay and used as workdir|image_copy_tmp_dir|Podman run with specified static IPv6 has correct IP|authenticated push|pod create --share-parent|podman kill paused container|login and logout|podman top on privileged container|local registry with authorization).*' \ 48 | -v -tags "seccomp ostree selinux varlink exclude_graphdriver_devicemapper" \ 49 | -timeout=50m -cover -flakeAttempts 3 -progress -trace -noColor test/e2e/. 50 | -------------------------------------------------------------------------------- /src/state.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "crun.h" 28 | #include "libcrun/container.h" 29 | #include "libcrun/utils.h" 30 | 31 | static char doc[] = "OCI runtime"; 32 | 33 | enum 34 | { 35 | OPTION_CONSOLE_SOCKET = 1000, 36 | OPTION_PID_FILE, 37 | OPTION_NO_SUBREAPER, 38 | OPTION_NO_NEW_KEYRING, 39 | OPTION_PRESERVE_FDS 40 | }; 41 | 42 | struct state_options_s 43 | { 44 | }; 45 | 46 | static struct state_options_s state_options; 47 | 48 | static struct argp_option options[] = { { 49 | 0, 50 | } }; 51 | 52 | static char args_doc[] = "state CONTAINER"; 53 | 54 | static error_t 55 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 56 | { 57 | switch (key) 58 | { 59 | case ARGP_KEY_NO_ARGS: 60 | libcrun_fail_with_error (0, "please specify a ID for the container"); 61 | 62 | default: 63 | return ARGP_ERR_UNKNOWN; 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 70 | 71 | int 72 | crun_command_state (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 73 | { 74 | int first_arg = 0, ret; 75 | libcrun_context_t crun_context = { 76 | 0, 77 | }; 78 | 79 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &state_options); 80 | crun_assert_n_args (argc - first_arg, 1, 1); 81 | 82 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 83 | if (UNLIKELY (ret < 0)) 84 | return ret; 85 | 86 | return libcrun_container_state (&crun_context, argv[first_arg], stdout, err); 87 | } 88 | -------------------------------------------------------------------------------- /tests/test_hooks.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def test_fail_prestart(): 22 | conf = base_config() 23 | conf['hooks'] = {"prestart" : [{"path" : "/bin/false"}]} 24 | add_all_namespaces(conf) 25 | try: 26 | out, _ = run_and_get_output(conf) 27 | except: 28 | return 0 29 | return -1 30 | 31 | def test_success_prestart(): 32 | conf = base_config() 33 | conf['hooks'] = {"prestart" : [{"path" : "/bin/true"}]} 34 | add_all_namespaces(conf) 35 | try: 36 | out, _ = run_and_get_output(conf) 37 | except: 38 | return -1 39 | return 0 40 | 41 | def test_hook_env_inherit(): 42 | conf = base_config() 43 | path = os.getenv("PATH") 44 | 45 | hook = {"path" : "/bin/sh", "args" : ["/bin/sh", "-c", "test \"$PATH\" = %s" % path]} 46 | conf['hooks'] = {"prestart" : [hook]} 47 | 48 | add_all_namespaces(conf) 49 | print(conf['hooks']) 50 | try: 51 | out, _ = run_and_get_output(conf) 52 | except: 53 | return -1 54 | return 0 55 | 56 | def test_hook_env_no_inherit(): 57 | conf = base_config() 58 | 59 | hook = {"path" : "/bin/sh", "env": ["PATH=/foo"], "args" : ["/bin/sh", "-c", "/bin/test \"$PATH\" == '/foo'"]} 60 | conf['hooks'] = {"prestart" : [hook]} 61 | 62 | add_all_namespaces(conf) 63 | print(conf['hooks']) 64 | try: 65 | out, _ = run_and_get_output(conf) 66 | except: 67 | return -1 68 | return 0 69 | 70 | all_tests = { 71 | "test-fail-prestart" : test_fail_prestart, 72 | "test-success-prestart" : test_success_prestart, 73 | "test-hook-env-inherit" : test_hook_env_inherit, 74 | "test-hook-env-no-inherit" : test_hook_env_no_inherit, 75 | } 76 | 77 | if __name__ == "__main__": 78 | tests_main(all_tests) 79 | -------------------------------------------------------------------------------- /src/libcrun/signals.perf: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | %{ 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | #include "utils.h" 26 | %} 27 | struct signal_s 28 | { 29 | int name; 30 | int value; 31 | }; 32 | %% 33 | HUP, 1 34 | INT, 2 35 | QUIT, 3 36 | ILL, 4 37 | TRAP, 5 38 | ABRT, 6 39 | BUS, 7 40 | FPE, 8 41 | KILL, 9 42 | USR1, 10 43 | SEGV, 11 44 | USR2, 12 45 | PIPE, 13 46 | ALRM, 14 47 | TERM, 15 48 | STKFLT, 16 49 | CHLD, 17 50 | CONT, 18 51 | STOP, 19 52 | TSTP, 20 53 | TTIN, 21 54 | TTOU, 22 55 | URG, 23 56 | XCPU, 24 57 | XFSZ, 25 58 | VTALRM, 26 59 | PROF, 27 60 | WINCH, 28 61 | IO, 29 62 | PWR, 30 63 | SYS, 31 64 | RTMIN, 34 65 | RTMIN+1, 35 66 | RTMIN+2, 36 67 | RTMIN+3, 37 68 | RTMIN+4, 38 69 | RTMIN+5, 39 70 | RTMIN+6, 40 71 | RTMIN+7, 41 72 | RTMIN+8, 42 73 | RTMIN+9, 43 74 | RTMIN+10, 44 75 | RTMIN+11, 45 76 | RTMIN+12, 46 77 | RTMIN+13, 47 78 | RTMIN+14, 48 79 | RTMIN+15, 49 80 | RTMAX-14, 50 81 | RTMAX-13, 51 82 | RTMAX-12, 52 83 | RTMAX-11, 53 84 | RTMAX-10, 54 85 | RTMAX-9, 55 86 | RTMAX-8, 56 87 | RTMAX-7, 57 88 | RTMAX-6, 58 89 | RTMAX-5, 59 90 | RTMAX-4, 60 91 | RTMAX-3, 61 92 | RTMAX-2, 62 93 | RTMAX-1, 63 94 | RTMAX, 64 95 | %% 96 | int 97 | str2sig (const char *name) 98 | { 99 | const struct signal_s *s; 100 | 101 | if (has_prefix (name, "SIG")) 102 | name += 3; 103 | 104 | s = libcrun_signal_in_word_set (name, strlen (name)); 105 | if (s == NULL) 106 | { 107 | long int value; 108 | 109 | errno = 0; 110 | value = strtol (name, NULL, 10); 111 | if (errno == 0) 112 | return value; 113 | 114 | errno = ENOENT; 115 | return -1; 116 | } 117 | 118 | return s->value; 119 | } 120 | -------------------------------------------------------------------------------- /tests/cri-o/run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if test "$(id -u)" != 0; then 4 | echo "run as root" 5 | exit 1 6 | fi 7 | set -e 8 | 9 | ( 10 | cd /crun 11 | git config --global --add safe.directory /crun 12 | git clean -fdx 13 | ./autogen.sh 14 | ./configure CFLAGS='-Wall -Wextra -Werror' --prefix=/usr 15 | make -j "$(nproc)" 16 | make install 17 | ) 18 | 19 | # make sure runc is not used 20 | rm -f /usr/bin/runc /usr/local/bin/runc 21 | ln /usr/bin/crun /usr/bin/runc 22 | 23 | rm -f /usr/bin/journalctl 24 | 25 | export CONTAINER_CGROUP_MANAGER=cgroupfs 26 | export RUNTIME_BINARY_PATH=/usr/bin/crun 27 | export CONTAINER_CONMON_CGROUP=pod 28 | export JOBS=2 29 | 30 | # adapt tests to cgroupfs 31 | sed -i 's/\.slice//g' test/testdata/*.json 32 | sed -i -e 's|@test "conmon custom cgroup" {|@test "conmon custom cgroup" {\nskip\n|g' test/*.bats 33 | sed -i -e 's|@test "privileged ctr device add" {|@test "privileged ctr device add" {\nskip\n|g' test/*.bats 34 | sed -i -e 's|@test "checkpoint and restore one container into a new pod using --export" {|@test "checkpoint and restore one container into a new pod using --export" {\nskip\n|g' test/*.bats 35 | sed -i -e 's|@test "ctr device add" {|@test "ctr device add" {\nskip\n|g' test/*.bats 36 | sed -i -e 's|@test "privileged ctr -- check for rw mounts" {|@test "privileged ctr -- check for rw mounts" {\nskip\n|g' test/*.bats 37 | sed -i -e 's|@test "kubernetes pod terminationGracePeriod passthru" {|@test "kubernetes pod terminationGracePeriod passthru" {\nskip\n|g' test/*.bats 38 | sed -i -e 's|@test "userns annotation auto should succeed" {|@test "userns annotation auto should succeed" {\nskip\n|g' test/*.bats 39 | sed -i -e 's|@test "userns annotation auto should map host run_as_user" {|@test "userns annotation auto should map host run_as_user" {\nskip\n|g' test/*.bats 40 | sed -i -e 's|@test "ctr execsync" {|@test "ctr execsync" {\nskip\n|g' test/*.bats 41 | sed -i -e 's|@test "image volume ignore" {|@test "image volume ignore" {\nskip\n|g' test/*.bats 42 | sed -i -e 's|@test "image volume bind" {|@test "image volume bind" {\nskip\n|g' test/*.bats 43 | sed -i -e 's|@test "image volume user mkdir" {|@test "image volume user mkdir" {\nskip\n|g' test/*.bats 44 | sed -i -e 's|@test "crio restore with missing config.json" {|@test "crio restore with missing config.json" {\nskip\n|g' test/*.bats 45 | sed -i -e 's|@test "crio restore upon exiting KUBENSMNT" {|@test "crio restore upon exiting KUBENSMNT" {\nskip\n|g' test/*.bats 46 | 47 | 48 | # remove useless tests 49 | rm test/image.* test/config* test/reload_config.bats test/crio-wipe.bats test/network_ping.bats 50 | 51 | test/test_runner.sh 52 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Artifact 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | artifact: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@v3 10 | 11 | - uses: actions/cache@v3 12 | with: 13 | path: .cache 14 | key: nix-v1-${{ hashFiles('nix/nixpkgs.json') }} 15 | 16 | - run: sudo apt-get update 17 | 18 | - run: sudo apt-get install -y make git gcc build-essential pkgconf libtool libsystemd-dev libcap-dev libseccomp-dev libyajl-dev go-md2man libtool autoconf python3 automake libprotobuf-c-dev 19 | 20 | - run: | 21 | set -ex 22 | sudo mkdir -p .cache 23 | sudo mv .cache /nix 24 | if [[ -z $(ls -A /nix) ]]; then sudo docker run --rm --privileged -v /:/mnt nixos/nix:2.3.12 cp -rfT /nix /mnt/nix; fi 25 | sudo RUNTIME=docker SKIP_CHECKS=1 SKIP_GPG=1 build-aux/release.sh 26 | sudo mv /nix .cache 27 | sudo chown -Rf $(whoami) .cache 28 | 29 | - run: | 30 | sudo mv release-* /tmp/artifact 31 | sudo mv /tmp/artifact/crun-*-linux-amd64 /tmp/artifact/crun-linux-amd64 32 | sudo mv /tmp/artifact/crun-*-linux-amd64-disable-systemd /tmp/artifact/crun-linux-amd64-disable-systemd 33 | sudo mv /tmp/artifact/crun-*-linux-arm64 /tmp/artifact/crun-linux-arm64 34 | sudo mv /tmp/artifact/crun-*-linux-arm64-disable-systemd /tmp/artifact/crun-linux-arm64-disable-systemd 35 | sudo mv /tmp/artifact/*.tar.gz /tmp/artifact/crun.tar.gz 36 | sudo mv /tmp/artifact/*.tar.xz /tmp/artifact/crun.tar.xz 37 | (cd /tmp/artifact; sha256sum * | sudo tee CHECKSUMS) 38 | 39 | - uses: actions/upload-artifact@v3 40 | with: 41 | name: crun-linux-amd64 42 | path: /tmp/artifact/crun-linux-amd64 43 | 44 | - uses: actions/upload-artifact@v3 45 | with: 46 | name: crun-linux-amd64-disable-systemd 47 | path: /tmp/artifact/crun-linux-amd64-disable-systemd 48 | 49 | - uses: actions/upload-artifact@v3 50 | with: 51 | name: crun-linux-arm64 52 | path: /tmp/artifact/crun-linux-arm64 53 | 54 | - uses: actions/upload-artifact@v3 55 | with: 56 | name: crun-linux-arm64-disable-systemd 57 | path: /tmp/artifact/crun-linux-arm64-disable-systemd 58 | 59 | - uses: actions/upload-artifact@v3 60 | with: 61 | name: crun.tar.gz 62 | path: /tmp/artifact/crun.tar.gz 63 | 64 | - uses: actions/upload-artifact@v3 65 | with: 66 | name: crun.tar.xz 67 | path: /tmp/artifact/crun.tar.xz 68 | 69 | - uses: actions/upload-artifact@v3 70 | with: 71 | name: CHECKSUMS 72 | path: /tmp/artifact/CHECKSUMS 73 | -------------------------------------------------------------------------------- /src/libcrun/custom-handler.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #ifndef CUSTOM_HANDLER_H 20 | #define CUSTOM_HANDLER_H 21 | 22 | #include "container.h" 23 | #include 24 | 25 | struct custom_handler_s 26 | { 27 | const char *name; 28 | const char *feature_string; 29 | 30 | int (*load) (void **cookie, libcrun_error_t *err); 31 | int (*unload) (void *cookie, libcrun_error_t *err); 32 | 33 | int (*exec_func) (void *cookie, libcrun_container_t *container, 34 | const char *pathname, char *const argv[]); 35 | 36 | int (*configure_container) (void *cookie, enum handler_configure_phase phase, 37 | libcrun_context_t *context, libcrun_container_t *container, 38 | const char *rootfs, libcrun_error_t *err); 39 | 40 | int (*can_handle_container) (libcrun_container_t *container, libcrun_error_t *err); 41 | }; 42 | 43 | struct custom_handler_manager_s; 44 | 45 | LIBCRUN_PUBLIC struct custom_handler_manager_s *libcrun_handler_manager_create (libcrun_error_t *err); 46 | LIBCRUN_PUBLIC int libcrun_handler_manager_load_directory (struct custom_handler_manager_s *manager, const char *path, libcrun_error_t *err); 47 | LIBCRUN_PUBLIC void handler_manager_free (struct custom_handler_manager_s *manager); 48 | 49 | LIBCRUN_PUBLIC struct custom_handler_s *handler_by_name (struct custom_handler_manager_s *manager, const char *name); 50 | LIBCRUN_PUBLIC void libcrun_handler_manager_print_feature_tags (struct custom_handler_manager_s *manager, FILE *out); 51 | 52 | LIBCRUN_PUBLIC int libcrun_configure_handler (struct custom_handler_manager_s *manager, 53 | libcrun_context_t *context, 54 | libcrun_container_t *container, 55 | struct custom_handler_s **out, 56 | void **cookie, libcrun_error_t *err); 57 | 58 | typedef struct custom_handler_s *(*run_oci_get_handler_cb) (); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /rpm/crun.spec.in: -------------------------------------------------------------------------------- 1 | %global krun_opts %{nil} 2 | 3 | %if 0%{?fedora} >= 37 4 | %ifarch aarch64 || x86_64 5 | %global krun_support enabled 6 | %global krun_opts --with-libkrun 7 | %endif 8 | %endif 9 | 10 | %ifnarch %{ix86} || ppc64le 11 | %global wasmtime_support enabled 12 | %endif 13 | 14 | Summary: OCI runtime written in C 15 | Name: crun 16 | Epoch: 101 17 | #FIXME: copr build env replaces this with a strange version number 18 | #Version: @RPM_VERSION@ 19 | Version: 0.0 20 | %define build_timestamp %{lua: print(os.date("%Y%m%d%H%M%S"))} 21 | Release: %{build_timestamp}.@GIT_COMMIT_ID@%{?dist} 22 | # `make tarball-prep` will generate this from HEAD commit in the repo root dir 23 | Source0: %{name}-HEAD.tar.gz 24 | License: GPLv2+ 25 | URL: https://github.com/containers/%{name} 26 | 27 | BuildRequires: autoconf 28 | BuildRequires: automake 29 | BuildRequires: gcc 30 | BuildRequires: git-core 31 | BuildRequires: libcap-devel 32 | %if "%{krun_support}" == "enabled" 33 | BuildRequires: libkrun-devel 34 | %endif 35 | BuildRequires: systemd-devel 36 | BuildRequires: yajl-devel 37 | BuildRequires: libseccomp-devel 38 | BuildRequires: python3-libmount 39 | BuildRequires: libtool 40 | BuildRequires: go-md2man 41 | %if "%{wasmtime_support}" == "enabled" 42 | BuildRequires: wasmtime-c-api-devel 43 | Requires: wasmtime-c-api 44 | %endif 45 | %if 0%{?rhel} == 8 46 | BuildRequires: python3 47 | %else 48 | BuildRequires: python 49 | %endif 50 | Provides: oci-runtime 51 | 52 | %description 53 | %{name} is a OCI runtime 54 | 55 | %if "%{krun_support}" == "enabled" 56 | %package -n krun 57 | Summary: %{name} with libkrun support 58 | Requires: libkrun 59 | 60 | %description -n krun 61 | krun is a symlink to the crun binary, with libkrun as an additional dependency. 62 | %endif 63 | 64 | %prep 65 | %autosetup -Sgit -n %{name}-HEAD 66 | 67 | %build 68 | ./autogen.sh 69 | %if "%{wasmtime_support}" == "enabled" 70 | ./configure --disable-silent-rules --with-wasmtime %{krun_opts} 71 | %else 72 | ./configure --disable-silent-rules %{krun_opts} 73 | %endif 74 | %make_build 75 | 76 | %install 77 | # FIXME: make_install no longer finds files as expected, 78 | # so need to run install steps explicitly 79 | #%%make_install 80 | install -dp %{buildroot}%{_bindir} 81 | install -Dp -m0755 %{name} %{buildroot}%{_bindir} 82 | install -dp %{buildroot}%{_mandir}/man1 83 | install -Dp -m0644 %{name}.1 %{buildroot}%{_mandir}/man1 84 | rm -rf %{buildroot}%{_usr}/lib* 85 | 86 | %if "%{krun_support}" == "enabled" 87 | ln -s %{_bindir}/%{name} %{buildroot}%{_bindir}/krun 88 | %endif 89 | 90 | %files 91 | %license COPYING 92 | %{_bindir}/%{name} 93 | %{_mandir}/man1/* 94 | 95 | %if "%{krun_support}" == "enabled" 96 | %files -n krun 97 | %license COPYING 98 | %{_bindir}/krun 99 | %endif 100 | -------------------------------------------------------------------------------- /src/libcrun/handlers/handler-utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #define _GNU_SOURCE 20 | 21 | #include 22 | #include "../container.h" 23 | #include "../utils.h" 24 | #include "handler-utils.h" 25 | 26 | int 27 | wasm_can_handle_container (libcrun_container_t *container, libcrun_error_t *err arg_unused) 28 | { 29 | const char *annotation; 30 | const char *entrypoint_executable = container->container_def->process->args[0]; 31 | 32 | annotation = find_annotation (container, "run.oci.handler"); 33 | if (annotation) 34 | { 35 | 36 | /* wasm-smart: annotation is a smart switch which only toggles wasm if its necessary, 37 | following annotation is very useful for cases where users intends to run wasm workload on 38 | kuberentes cluster but workload also contains side-cars which could execute non-wasm workload. 39 | Example: Kubernetes clusters with service-mesh such as istio, linkerd etc 40 | */ 41 | if (strcmp (annotation, "wasm-smart") == 0) 42 | { 43 | return ((has_suffix (entrypoint_executable, ".wat") > 0) || (has_suffix (entrypoint_executable, ".wasm") > 0)) ? 1 : 0; 44 | } 45 | return strcmp (annotation, "wasm") == 0 ? 1 : 0; 46 | } 47 | 48 | annotation = find_annotation (container, "module.wasm.image/variant"); 49 | if (annotation) 50 | { 51 | 52 | /* compat-smart: annotation is a smart switch which only toggles wasm if its necessary, 53 | following annotation is very useful for cases where users intends to run wasm workload on 54 | kuberentes cluster but workload also contains side-cars which could execute non-wasm worload. 55 | Example: Kubernetes clusters with service-mesh such as istio, linkerd etc 56 | */ 57 | if (strcmp (annotation, "compat-smart") == 0) 58 | { 59 | return ((has_suffix (entrypoint_executable, ".wat") > 0) || (has_suffix (entrypoint_executable, ".wasm") > 0)) ? 1 : 0; 60 | } 61 | 62 | return strcmp (annotation, "compat") == 0 ? 1 : 0; 63 | } 64 | 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /contrib/seccomp-notify-plugin-example/full.c: -------------------------------------------------------------------------------- 1 | /* 2 | A simple plugin that always returns ENOSPC. 3 | It handles the notification in an async way. Spawning a thread for each request. 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "../../src/libcrun/seccomp_notify_plugin.h" 16 | 17 | struct args_s 18 | { 19 | uint64_t id; 20 | int seccomp_fd; 21 | struct seccomp_notif_resp *resp; 22 | }; 23 | 24 | static void * 25 | start_routine (void *arg) 26 | { 27 | struct args_s *args = arg; 28 | int ret; 29 | 30 | /* Pretend we are busy. */ 31 | sleep (3); 32 | 33 | args->resp->id = args->id; 34 | args->resp->error = -ENOSPC; 35 | args->resp->flags = 0; 36 | 37 | ret = ioctl (args->seccomp_fd, SECCOMP_IOCTL_NOTIF_SEND, args->resp); 38 | if (ret < 0) 39 | abort (); 40 | 41 | free (args->resp); 42 | free (args); 43 | 44 | return NULL; 45 | } 46 | 47 | static int 48 | handle_async (struct seccomp_notif_sizes *sizes, struct seccomp_notif *sreq, int seccomp_fd) 49 | { 50 | /* On errors we leak memory, but anyway we return the error and the watcher is terminated immediately. */ 51 | pthread_t thread; 52 | struct args_s *args; 53 | pthread_attr_t attr; 54 | 55 | args = malloc (sizeof (*args)); 56 | if (args == NULL) 57 | return -errno; 58 | 59 | args->resp = malloc (sizes->seccomp_notif_resp); 60 | if (args->resp == NULL) 61 | return -errno; 62 | 63 | args->id = sreq->id; 64 | args->seccomp_fd = seccomp_fd; 65 | 66 | if (pthread_attr_init (&attr) < 0) 67 | return -errno; 68 | 69 | if (pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED) < 0) 70 | return -errno; 71 | 72 | if (pthread_create (&thread, &attr, start_routine, args) < 0) 73 | return -errno; 74 | 75 | if (pthread_attr_destroy (&attr) < 0) 76 | return -errno; 77 | 78 | return 0; 79 | } 80 | 81 | int 82 | run_oci_seccomp_notify_start (void **opaque, struct libcrun_load_seccomp_notify_conf_s *conf, size_t size_configuration) 83 | { 84 | if (size_configuration != sizeof (struct libcrun_load_seccomp_notify_conf_s)) 85 | return -EINVAL; 86 | 87 | return 0; 88 | } 89 | 90 | int 91 | run_oci_seccomp_notify_handle_request (void *opaque, struct seccomp_notif_sizes *sizes, struct seccomp_notif *sreq, struct seccomp_notif_resp *sresp, int seccomp_fd, int *handled) 92 | { 93 | int ret; 94 | 95 | ret = handle_async (sizes, sreq, seccomp_fd); 96 | if (ret < 0) 97 | return ret; 98 | 99 | *handled = RUN_OCI_SECCOMP_NOTIFY_HANDLE_DELAYED_RESPONSE; 100 | return 0; 101 | } 102 | 103 | int 104 | run_oci_seccomp_notify_stop (void *opaque) 105 | { 106 | return 0; 107 | } 108 | 109 | int 110 | run_oci_seccomp_notify_plugin_version () 111 | { 112 | return 1; 113 | } 114 | -------------------------------------------------------------------------------- /tests/tests_libcrun_errors.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | typedef int (*test) (); 24 | 25 | static int 26 | test_crun_make_error () 27 | { 28 | 29 | libcrun_error_t err = NULL; 30 | int ret = crun_make_error (&err, 12, "HELLO %s", "WORLD"); 31 | if (ret >= 0) 32 | return -1; 33 | 34 | if (err->status != 12) 35 | return -1; 36 | 37 | if (strcmp (err->msg, "HELLO WORLD") != 0) 38 | return -1; 39 | 40 | crun_error_release (&err); 41 | 42 | return 0; 43 | } 44 | 45 | static int 46 | test_crun_write_warning_and_release () 47 | { 48 | 49 | libcrun_error_t err_data = NULL; 50 | libcrun_error_t *err = &err_data; 51 | cleanup_free char *buffer = NULL; 52 | size_t len; 53 | FILE *stream; 54 | 55 | int ret = crun_make_error (err, 0, "HELLO %s", "WORLD"); 56 | if (ret >= 0) 57 | return -1; 58 | 59 | if ((*err)->status != 0) 60 | return -1; 61 | if ((*err)->msg == NULL) 62 | return -1; 63 | 64 | stream = open_memstream (&buffer, &len); 65 | crun_error_write_warning_and_release (stream, &err); 66 | fclose (stream); 67 | 68 | if (len != 12) 69 | return -1; 70 | 71 | if (*err) 72 | return -1; 73 | 74 | if (strcmp (buffer, "HELLO WORLD\n") != 0) 75 | return -1; 76 | 77 | return 0; 78 | } 79 | 80 | static void 81 | run_and_print_test_result (const char *name, int id, test t) 82 | { 83 | int ret = t (); 84 | if (ret == 0) 85 | printf ("ok %d - %s\n", id, name); 86 | else if (ret == 77) 87 | printf ("ok %d - %s #SKIP\n", id, name); 88 | else 89 | printf ("not ok %d - %s\n", id, name); 90 | } 91 | 92 | #define RUN_TEST(T) \ 93 | do \ 94 | { \ 95 | run_and_print_test_result (#T, id++, T); \ 96 | } while (0) 97 | 98 | int 99 | main () 100 | { 101 | int id = 1; 102 | printf ("1..2\n"); 103 | RUN_TEST (test_crun_make_error); 104 | RUN_TEST (test_crun_write_warning_and_release); 105 | return 0; 106 | } 107 | -------------------------------------------------------------------------------- /nix/default.nix: -------------------------------------------------------------------------------- 1 | { system ? builtins.currentSystem, enableSystemd ? true }: 2 | let 3 | static = import ./static.nix; 4 | pkgs = (import ./nixpkgs.nix { 5 | config = { 6 | packageOverrides = pkg: { 7 | criu = (static pkg.criu); 8 | gpgme = (static pkg.gpgme); 9 | libassuan = (static pkg.libassuan); 10 | libgpgerror = (static pkg.libgpgerror); 11 | libseccomp = (static pkg.libseccomp); 12 | protobufc = (static pkg.protobufc); 13 | glib = (static pkg.glib).overrideAttrs (x: { 14 | outputs = [ "bin" "out" "dev" ]; 15 | mesonFlags = [ 16 | "-Ddefault_library=static" 17 | "-Ddevbindir=${placeholder ''dev''}/bin" 18 | "-Dgtk_doc=false" 19 | "-Dnls=disabled" 20 | ]; 21 | }); 22 | libcap = (static pkg.libcap).overrideAttrs (x: { 23 | postInstall = '' 24 | mkdir -p "$doc/share/doc/${x.pname}-${x.version}" 25 | cp License "$doc/share/doc/${x.pname}-${x.version}/" 26 | mkdir -p "$pam/lib/security" 27 | mv "$lib"/lib/security "$pam/lib" 28 | ''; 29 | }); 30 | systemd = (static pkg.systemd).overrideAttrs (x: { 31 | outputs = [ "out" "dev" ]; 32 | mesonFlags = x.mesonFlags ++ [ 33 | "-Dglib=false" 34 | "-Dstatic-libsystemd=true" 35 | ]; 36 | }); 37 | yajl = (static pkg.yajl).overrideAttrs (x: { 38 | preConfigure = '' 39 | export CMAKE_STATIC_LINKER_FLAGS="-static" 40 | ''; 41 | }); 42 | }; 43 | }; 44 | }); 45 | 46 | self = with pkgs; stdenv.mkDerivation rec { 47 | name = "crun"; 48 | src = ./..; 49 | vendorSha256 = null; 50 | doCheck = false; 51 | enableParallelBuilding = true; 52 | outputs = [ "out" ]; 53 | nativeBuildInputs = [ 54 | autoreconfHook 55 | bash 56 | gitMinimal 57 | pkg-config 58 | python3 59 | which 60 | ]; 61 | buildInputs = [ 62 | criu 63 | glibc 64 | glibc.static 65 | libcap 66 | libseccomp 67 | protobufc 68 | systemd 69 | yajl 70 | ]; 71 | configureFlags = [ "--enable-static" ] 72 | ++ lib.optional (!enableSystemd) [ "--disable-systemd" ]; 73 | prePatch = '' 74 | export CFLAGS='-static -pthread' 75 | export LDFLAGS='-s -w -static-libgcc -static' 76 | export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"' 77 | export CRUN_LDFLAGS='-all-static' 78 | export LIBS='${criu}/lib/libcriu.a ${glibc.static}/lib/libc.a ${glibc.static}/lib/libpthread.a ${glibc.static}/lib/librt.a ${lib.getLib libcap}/lib/libcap.a ${lib.getLib libseccomp}/lib/libseccomp.a ${protobufc}/lib/libprotobuf-c.a ${protobuf}/lib/libprotobuf.a ${lib.getLib systemd}/lib/libsystemd.a ${yajl}/lib/libyajl_s.a' 79 | ''; 80 | buildPhase = '' 81 | patchShebangs . 82 | make 83 | ''; 84 | installPhase = '' 85 | install -Dm755 crun $out/bin/crun 86 | ''; 87 | }; 88 | in 89 | self 90 | -------------------------------------------------------------------------------- /src/libcrun/seccomp_notify_plugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef SECCOMP_NOTIFY_PLUGINPLUGIN_H 19 | 20 | # include 21 | 22 | struct libcrun_load_seccomp_notify_conf_s 23 | { 24 | const char *runtime_root_path; 25 | const char *name; 26 | const char *bundle_path; 27 | const char *oci_config_path; 28 | }; 29 | 30 | /* The plugin doesn't know how to handle the request. */ 31 | # define RUN_OCI_SECCOMP_NOTIFY_HANDLE_NOT_HANDLED 0 32 | /* The plugin filled the response and it is ready to write. */ 33 | # define RUN_OCI_SECCOMP_NOTIFY_HANDLE_SEND_RESPONSE 1 34 | /* The plugin will handle the request and write directly to the fd. */ 35 | # define RUN_OCI_SECCOMP_NOTIFY_HANDLE_DELAYED_RESPONSE 2 36 | /* Specify SECCOMP_USER_NOTIF_FLAG_CONTINUE in the flags. */ 37 | # define RUN_OCI_SECCOMP_NOTIFY_HANDLE_SEND_RESPONSE_AND_CONTINUE 3 38 | 39 | # ifndef SECCOMP_NOTIFY_SKIP_TYPEDEF 40 | 41 | /* Configure the plugin. Return an opaque pointer that will be used for successive calls. */ 42 | typedef int (*run_oci_seccomp_notify_start_cb) (void **opaque, struct libcrun_load_seccomp_notify_conf_s *conf, 43 | size_t size_configuration); 44 | 45 | /* Try to handle a single request. It MUST be defined. 46 | HANDLED specifies how the request was handled by the plugin: 47 | 0: not handled, try next plugin or return ENOTSUP if it is the last plugin. 48 | RUN_OCI_SECCOMP_NOTIFY_HANDLE_SEND_RESPONSE: sresp filled and ready to be notified to seccomp. 49 | RUN_OCI_SECCOMP_NOTIFY_HANDLE_DELAYED_RESPONSE: the notification will be handled internally by the plugin and 50 | forwarded to seccomp_fd. It is useful for asynchronous handling. 51 | */ 52 | typedef int (*run_oci_seccomp_notify_handle_request_cb) (void *opaque, struct seccomp_notif_sizes *sizes, 53 | struct seccomp_notif *sreq, struct seccomp_notif_resp *sresp, 54 | int seccomp_fd, int *handled); 55 | 56 | /* Stop the plugin. The opaque value is the return value from run_oci_seccomp_notify_start. */ 57 | typedef int (*run_oci_seccomp_notify_stop_cb) (void *opaque); 58 | 59 | /* Retrieve the API version used by the plugin. It MUST return 1. */ 60 | typedef int (*run_oci_seccomp_notify_plugin_version_cb) (); 61 | 62 | # endif 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_INTERNAL_H 19 | #define CGROUP_INTERNAL_H 20 | 21 | #include "container.h" 22 | #include "utils.h" 23 | 24 | enum 25 | { 26 | CGROUP_MEMORY = 1 << 0, 27 | CGROUP_CPU = 1 << 1, 28 | CGROUP_HUGETLB = 1 << 2, 29 | CGROUP_CPUSET = 1 << 3, 30 | CGROUP_PIDS = 1 << 4, 31 | CGROUP_IO = 1 << 5, 32 | }; 33 | 34 | struct libcrun_cgroup_status 35 | { 36 | char *path; 37 | char *scope; 38 | 39 | int manager; 40 | }; 41 | 42 | struct libcrun_cgroup_manager 43 | { 44 | /* Create a new cgroup and fill PATH in OUT. */ 45 | int (*create_cgroup) (struct libcrun_cgroup_args *args, struct libcrun_cgroup_status *out, libcrun_error_t *err); 46 | int (*precreate_cgroup) (struct libcrun_cgroup_args *args, int *dirfd, libcrun_error_t *err); 47 | /* Destroy the cgroup and kill any process if needed. */ 48 | int (*destroy_cgroup) (struct libcrun_cgroup_status *cgroup_status, libcrun_error_t *err); 49 | /* Additional resources configuration specific to this manager. */ 50 | int (*update_resources) (struct libcrun_cgroup_status *cgroup_status, runtime_spec_schema_config_linux_resources *resources, libcrun_error_t *err); 51 | }; 52 | 53 | int move_process_to_cgroup (pid_t pid, const char *subsystem, const char *path, libcrun_error_t *err); 54 | int enter_cgroup_subsystem (pid_t pid, const char *subsystem, const char *path, bool create_if_missing, 55 | libcrun_error_t *err); 56 | int enable_controllers (const char *path, libcrun_error_t *err); 57 | int chown_cgroups (const char *path, uid_t uid, gid_t gid, libcrun_error_t *err); 58 | int destroy_cgroup_path (const char *path, int mode, libcrun_error_t *err); 59 | int cgroup_killall_path (const char *path, int signal, libcrun_error_t *err); 60 | 61 | int libcrun_cgroup_read_pids_from_path (const char *path, bool recurse, pid_t **pids, libcrun_error_t *err); 62 | 63 | bool read_proc_cgroup (char *content, char **saveptr, char **id, char **controller_list, char **path); 64 | 65 | static inline int 66 | is_rootless (libcrun_error_t *err) 67 | { 68 | if (geteuid ()) 69 | return 1; 70 | 71 | return check_running_in_user_namespace (err); 72 | } 73 | 74 | int libcrun_cgroup_pause_unpause_path (const char *cgroup_path, const bool pause, libcrun_error_t *err); 75 | 76 | static inline uint64_t 77 | convert_shares_to_weight (uint64_t shares) 78 | { 79 | /* convert linearly from 2-262144 to 1-10000. */ 80 | return (1 + ((shares - 2) * 9999) / 262142); 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /src/libcrun/mount_flags.perf: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | %{ 20 | #define _GNU_SOURCE 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "utils.h" 31 | #include "mount_flags.h" 32 | 33 | %} 34 | struct propagation_flags_s; 35 | %% 36 | defaults, 0, 0, 0 37 | bind, 0, MS_BIND, 0 38 | rbind, 0, MS_REC|MS_BIND, 0 39 | ro, 0, MS_RDONLY, 0 40 | rw, 1, MS_RDONLY, 0 41 | suid, 1, MS_NOSUID, 0 42 | nosuid, 0, MS_NOSUID, 0 43 | dev, 1, MS_NODEV, 0 44 | nodev, 0, MS_NODEV, 0 45 | exec, 1, MS_NOEXEC, 0 46 | noexec, 0, MS_NOEXEC, 0 47 | sync, 0, MS_SYNCHRONOUS, 0 48 | async, 1, MS_SYNCHRONOUS, 0 49 | dirsync, 0, MS_DIRSYNC, 0 50 | remount, 0, MS_REMOUNT, 0 51 | mand, 0, MS_MANDLOCK, 0 52 | nomand, 1, MS_MANDLOCK, 0 53 | atime, 1, MS_NOATIME, 0 54 | noatime, 0, MS_NOATIME, 0 55 | diratime, 1, MS_NODIRATIME, 0 56 | nodiratime, 0, MS_NODIRATIME, 0 57 | relatime, 0, MS_RELATIME, 0 58 | norelatime, 1, MS_RELATIME, 0 59 | strictatime, 0, MS_STRICTATIME, 0 60 | nostrictatime, 1, MS_STRICTATIME, 0 61 | shared, 0, MS_SHARED, 0 62 | rshared, 0, MS_REC|MS_SHARED, 0 63 | slave, 0, MS_SLAVE, 0 64 | rslave, 0, MS_REC|MS_SLAVE, 0 65 | private, 0, MS_PRIVATE, 0 66 | rprivate, 0, MS_REC|MS_PRIVATE, 0 67 | unbindable, 0, MS_UNBINDABLE, 0 68 | runbindable, 0, MS_REC|MS_UNBINDABLE, 0 69 | rro, 0, MS_RDONLY, OPTION_RECURSIVE 70 | rrw, 1, MS_RDONLY, OPTION_RECURSIVE 71 | rsuid, 1, MS_NOSUID, OPTION_RECURSIVE 72 | rnosuid, 0, MS_NOSUID, OPTION_RECURSIVE 73 | rdev, 1, MS_NODEV, OPTION_RECURSIVE 74 | rnodev, 0, MS_NODEV, OPTION_RECURSIVE 75 | rexec, 1, MS_NOEXEC, OPTION_RECURSIVE 76 | rnoexec, 0, MS_NOEXEC, OPTION_RECURSIVE 77 | rsync, 0, MS_SYNCHRONOUS, OPTION_RECURSIVE 78 | rasync, 1, MS_SYNCHRONOUS, OPTION_RECURSIVE 79 | rdirsync, 0, MS_DIRSYNC, OPTION_RECURSIVE 80 | rmand, 0, MS_MANDLOCK, OPTION_RECURSIVE 81 | rnomand, 1, MS_MANDLOCK, OPTION_RECURSIVE 82 | ratime, 1, MS_NOATIME, OPTION_RECURSIVE 83 | rnoatime, 0, MS_NOATIME, OPTION_RECURSIVE 84 | rdiratime, 1, MS_NODIRATIME, OPTION_RECURSIVE 85 | rnodiratime, 0, MS_NODIRATIME, OPTION_RECURSIVE 86 | rrelatime, 0, MS_RELATIME, OPTION_RECURSIVE 87 | rnorelatime, 1, MS_RELATIME, OPTION_RECURSIVE 88 | rstrictatime, 0, MS_STRICTATIME, OPTION_RECURSIVE 89 | rnostrictatime, 1, MS_STRICTATIME, OPTION_RECURSIVE 90 | tmpcopyup, 0, 0, OPTION_TMPCOPYUP 91 | idmap, 0, 0, OPTION_IDMAP 92 | %% 93 | 94 | const struct propagation_flags_s * 95 | libcrun_str2mount_flags (const char *name) 96 | { 97 | return libcrun_mount_flag_in_word_set (name, strlen (name)); 98 | } 99 | -------------------------------------------------------------------------------- /tests/test_domainname.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | from tests_utils import * 19 | 20 | def test_domainname(): 21 | conf = base_config() 22 | conf['process']['args'] = ['/init', 'getdomainname'] 23 | conf['domainname'] = "foomachine" 24 | add_all_namespaces(conf) 25 | out, _ = run_and_get_output(conf) 26 | if "foomachine" not in out: 27 | return -1 28 | conf = base_config() 29 | conf['process']['args'] = ['/init', 'getdomainname'] 30 | add_all_namespaces(conf, utsns=False) 31 | # getdomainname returns `(none)` if domainname is not set or will return error, 32 | # in both of the above situation the test should pass. Anything other than this 33 | # must be considered as failure. 34 | try: 35 | out, cid = run_and_get_output(conf) 36 | if out == "(none)\n": 37 | return 0 38 | sys.stderr.write("unexpected success\n") 39 | return -1 40 | except: 41 | return 0 42 | finally: 43 | if cid is not None: 44 | run_crun_command(["delete", "-f", cid]) 45 | 46 | def test_domainname_conflict_sysctl(): 47 | # Setting sysctl `kernel.domainname` and OCI field `domainname` must fail 48 | # since it produces unexpected behaviour for the end-users. 49 | conf = base_config() 50 | conf['process']['args'] = ['/init', 'getdomainname'] 51 | conf['domainname'] = "foomachine" 52 | add_all_namespaces(conf) 53 | conf['linux']['sysctl'] = {'kernel.domainname' : 'foo'} 54 | cid = None 55 | try: 56 | out, cid = run_and_get_output(conf) 57 | if out == "(none)\n": 58 | return 0 59 | sys.stderr.write("unexpected success\n") 60 | return -1 61 | except: 62 | return 0 63 | finally: 64 | if cid is not None: 65 | run_crun_command(["delete", "-f", cid]) 66 | return 0 67 | 68 | def test_domainname_with_sysctl(): 69 | # Setting sysctl `kernel.domainname` and OCI field `domainname` must pass 70 | # when both have exact same value 71 | conf = base_config() 72 | conf['process']['args'] = ['/init', 'getdomainname'] 73 | conf['domainname'] = "foo" 74 | add_all_namespaces(conf) 75 | conf['linux']['sysctl'] = {'kernel.domainname' : 'foo'} 76 | cid = None 77 | try: 78 | out, cid = run_and_get_output(conf) 79 | if out == "(none)\n": 80 | return 0 81 | return 0 82 | except: 83 | return -1 84 | finally: 85 | if cid is not None: 86 | run_crun_command(["delete", "-f", cid]) 87 | return 0 88 | 89 | all_tests = { 90 | "domainname" : test_domainname, 91 | "domainname conflict with syctl" : test_domainname_conflict_sysctl, 92 | "domainname with syctl" : test_domainname_with_sysctl, 93 | } 94 | 95 | if __name__ == "__main__": 96 | tests_main(all_tests) 97 | -------------------------------------------------------------------------------- /src/libcrun/status.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #ifndef STATUS_H 20 | #define STATUS_H 21 | 22 | #include 23 | #include 24 | #include "error.h" 25 | #include "container.h" 26 | 27 | struct libcrun_container_list_s 28 | { 29 | struct libcrun_container_list_s *next; 30 | char *name; 31 | }; 32 | typedef struct libcrun_container_list_s libcrun_container_list_t; 33 | 34 | struct libcrun_container_status_s 35 | { 36 | pid_t pid; 37 | unsigned long long process_start_time; 38 | char *bundle; 39 | char *rootfs; 40 | char *cgroup_path; 41 | char *scope; 42 | int systemd_cgroup; 43 | char *created; 44 | int detached; 45 | char *external_descriptors; 46 | char *owner; 47 | }; 48 | typedef struct libcrun_container_status_s libcrun_container_status_t; 49 | 50 | LIBCRUN_PUBLIC void libcrun_free_container_status (libcrun_container_status_t *status); 51 | LIBCRUN_PUBLIC int libcrun_write_container_status (const char *state_root, const char *id, 52 | libcrun_container_status_t *status, libcrun_error_t *err); 53 | LIBCRUN_PUBLIC int libcrun_read_container_status (libcrun_container_status_t *status, const char *state_root, 54 | const char *id, libcrun_error_t *err); 55 | LIBCRUN_PUBLIC void libcrun_free_containers_list (libcrun_container_list_t *list); 56 | LIBCRUN_PUBLIC int libcrun_is_container_running (libcrun_container_status_t *status, libcrun_error_t *err); 57 | LIBCRUN_PUBLIC char *libcrun_get_state_directory (const char *state_root, const char *id); 58 | LIBCRUN_PUBLIC int libcrun_container_delete_status (const char *state_root, const char *id, libcrun_error_t *err); 59 | LIBCRUN_PUBLIC int libcrun_get_containers_list (libcrun_container_list_t **ret, const char *state_root, 60 | libcrun_error_t *err); 61 | 62 | int libcrun_status_check_directories (const char *state_root, const char *id, libcrun_error_t *err); 63 | int libcrun_status_create_exec_fifo (const char *state_root, const char *id, libcrun_error_t *err); 64 | int libcrun_status_write_exec_fifo (const char *state_root, const char *id, libcrun_error_t *err); 65 | int libcrun_status_has_read_exec_fifo (const char *state_root, const char *id, libcrun_error_t *err); 66 | int libcrun_check_pid_valid (libcrun_container_status_t *status, libcrun_error_t *err); 67 | 68 | static inline void 69 | libcrun_free_container_listp (void *p) 70 | { 71 | libcrun_container_list_t **l = (libcrun_container_list_t **) p; 72 | if (*l != NULL) 73 | libcrun_free_containers_list (*l); 74 | } 75 | 76 | #define cleanup_container_status __attribute__ ((cleanup (libcrun_free_container_status))) 77 | #define cleanup_container_list __attribute__ ((cleanup (libcrun_free_container_listp))) 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /src/libcrun/cgroup.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef CGROUP_H 19 | #define CGROUP_H 20 | 21 | #include "container.h" 22 | #include 23 | 24 | #ifndef CGROUP_ROOT 25 | # define CGROUP_ROOT "/sys/fs/cgroup" 26 | #endif 27 | 28 | enum 29 | { 30 | CGROUP_MODE_UNIFIED = 1, 31 | CGROUP_MODE_LEGACY, 32 | CGROUP_MODE_HYBRID 33 | }; 34 | 35 | enum 36 | { 37 | CGROUP_MANAGER_CGROUPFS = 1, 38 | CGROUP_MANAGER_SYSTEMD, 39 | CGROUP_MANAGER_DISABLED 40 | }; 41 | 42 | struct libcrun_cgroup_status; 43 | 44 | struct libcrun_cgroup_args 45 | { 46 | runtime_spec_schema_config_linux_resources *resources; 47 | json_map_string_string *annotations; 48 | const char *cgroup_path; 49 | int manager; 50 | pid_t pid; 51 | uid_t root_uid; 52 | gid_t root_gid; 53 | const char *id; 54 | bool joined; 55 | }; 56 | 57 | /* cgroup life-cycle management. */ 58 | int libcrun_cgroup_preenter (struct libcrun_cgroup_args *args, int *dirfd, libcrun_error_t *err); 59 | int libcrun_cgroup_enter (struct libcrun_cgroup_args *args, struct libcrun_cgroup_status **out, libcrun_error_t *err); 60 | int libcrun_cgroup_enter_finalize (struct libcrun_cgroup_args *args, struct libcrun_cgroup_status *cgroup_status, libcrun_error_t *err); 61 | int libcrun_cgroup_destroy (struct libcrun_cgroup_status *cgroup_status, libcrun_error_t *err); 62 | 63 | /* Handle the cgroup status. */ 64 | int libcrun_cgroup_get_status (struct libcrun_cgroup_status *cgroup_status, libcrun_container_status_t *status, 65 | libcrun_error_t *err); 66 | void libcrun_cgroup_status_free (struct libcrun_cgroup_status *cgroup_status); 67 | 68 | struct libcrun_cgroup_status *libcrun_cgroup_make_status (libcrun_container_status_t *status); 69 | 70 | static inline void 71 | cgroup_status_freep (struct libcrun_cgroup_status **p) 72 | { 73 | struct libcrun_cgroup_status *s = *p; 74 | if (s) 75 | libcrun_cgroup_status_free (s); 76 | } 77 | #define cleanup_cgroup_status __attribute__ ((cleanup (cgroup_status_freep))) 78 | 79 | /* Operations on the cgroup. */ 80 | 81 | int libcrun_cgroup_killall (struct libcrun_cgroup_status *cgroup_status, int signal, libcrun_error_t *err); 82 | 83 | int libcrun_cgroup_has_oom (struct libcrun_cgroup_status *status, libcrun_error_t *err); 84 | 85 | int libcrun_cgroup_read_pids (struct libcrun_cgroup_status *status, bool recurse, pid_t **pids, libcrun_error_t *err); 86 | 87 | int libcrun_update_cgroup_resources (struct libcrun_cgroup_status *status, 88 | runtime_spec_schema_config_linux_resources *resources, 89 | libcrun_error_t *err); 90 | 91 | int libcrun_cgroup_is_container_paused (struct libcrun_cgroup_status *status, bool *paused, libcrun_error_t *err); 92 | 93 | int libcrun_cgroup_pause_unpause (struct libcrun_cgroup_status *status, const bool pause, libcrun_error_t *err); 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /docs/wasm-wasi-on-kubernetes.md: -------------------------------------------------------------------------------- 1 | # Running wasi workload natively on kubernetes using crun 2 | 3 | Crun natively supports running wasm/wasi workload on using `wasmedge`, `wasmer` and `wasmtime`. 4 | Each one of them (`wasmedge`, `wasmer` and `wasmtime`) comes with their own set of unique features. 5 | For instance `wasmer` can compile your `.wat` on the fly. Similarly `wasmedge` has its own perks. 6 | Crun can support only one of them at a time. Please build crun with whatever runtime suits you the best. 7 | 8 | #### How does crun detects if is a wasm workload ? 9 | * Make sure oci config propagated by your CRI implementation contains annotations `run.oci.handler: wasm` or `module.wasm.image/variant=compat`. 10 | * Entrypoint must point to a valid **.wat** (webassembly text) `**wasmer-only**` or **.wasm** (webassembly binary). 11 | * If your kubernetes infrastructure is using service-mesh, proxy or in general side-cars pattern then in such cases recommended annotations would be 12 | `module.wasm.image/variant=compat-smart` or `run.oci.handler: wasm-smart`. 13 | 14 | 15 | So spec generated by CRI implementation must contain annotation something like. 16 | 17 | ```json 18 | ... 19 | "annotations": { 20 | "run.oci.handler": "wasm" 21 | }, 22 | ... 23 | ``` 24 | 25 | ### Building `wasm` images 26 | * Read here: https://github.com/containers/crun/blob/main/docs/wasm-wasi-example.md#running-oci-wasm-compat-images-with-buildah-and-podman 27 | 28 | ### Supported and tested CRI implementations 29 | 30 | ##### CRI-O 31 | 32 | * Following features works completely out if the box once `cri-o` is using `crun` built with `wasm` support. 33 | * Configure `cri-o` to use `crun` instead of `runc` by editing config at `/etc/crio/crio.conf` read more about it here https://docs.openshift.com/container-platform/3.11/crio/crio_runtime.html#configure-crio-use-crio-engine 34 | * Restart `cri-o` by `sudo systemctl restart crio` 35 | * `cri-o` automatically propagates pod annotations to container spec. So we don't need to do anything. 36 | 37 | ```yaml 38 | apiVersion: v1 39 | kind: Pod 40 | metadata: 41 | name: pod-with-wasm-workload 42 | namespace: mynamespace 43 | annotations: 44 | module.wasm.image/variant: compat 45 | spec: 46 | containers: 47 | - name: wasm-container 48 | image: myrepo/mywasmimage:latest 49 | ``` 50 | 51 | ##### Containerd 52 | * `Containerd` supports switching container runtime via custom config defined at `/etc/containerd/config.toml` 53 | * Configure `containerd` to use `crun` by making sure runtime binary points to `crun` read more about config here https://github.com/containerd/containerd/blob/main/docs/cri/config.md 54 | * Configure `containerd` to whilelist `wasm` annotations so they could propagated to OCI spec. By setting `pod_annotations` in the config. 55 | ```toml 56 | pod_annotations = ["*.wasm.*", "wasm.*", "module.wasm.image/*", "*.module.wasm.image", "module.wasm.image/variant.*"] 57 | ``` 58 | * Restart `containerd` by `sudo systemctl start containerd` 59 | * Now `containerd` should propagate `wasm` pod annotations to containers. 60 | 61 | ```yaml 62 | apiVersion: v1 63 | kind: Pod 64 | metadata: 65 | name: pod-with-wasm-workload 66 | namespace: mynamespace 67 | annotations: 68 | module.wasm.image/variant: compat 69 | spec: 70 | containers: 71 | - name: wasm-container 72 | image: myrepo/mywasmimage:latest 73 | ``` 74 | 75 | ### Known Issues: 76 | * ~~CRI implementations as of now propagates annotations to `side-car` as well so if `side-car` has a non `wasm` workload it can break. Read on going discussion here: https://github.com/containers/crun/issues/829~~, issue still exists with CRI but crun supports a workaround with feature added here: https://github.com/containers/crun/pull/886 77 | -------------------------------------------------------------------------------- /src/ps.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "crun.h" 28 | #include "libcrun/container.h" 29 | #include "libcrun/utils.h" 30 | #include "libcrun/cgroup.h" 31 | 32 | static char doc[] = "OCI runtime"; 33 | 34 | enum 35 | { 36 | OPTION_CONSOLE_SOCKET = 1000, 37 | OPTION_PID_FILE, 38 | OPTION_NO_SUBREAPER, 39 | OPTION_NO_NEW_KEYRING, 40 | OPTION_PRESERVE_FDS 41 | }; 42 | 43 | struct ps_options_s 44 | { 45 | int format; 46 | }; 47 | 48 | enum 49 | { 50 | PS_TABLE = 100, 51 | PS_JSON, 52 | }; 53 | 54 | static struct ps_options_s ps_options; 55 | 56 | static struct argp_option options[] = { { "format", 'f', "FORMAT", 0, "select the output format", 0 }, 57 | { 58 | 0, 59 | } }; 60 | 61 | static char args_doc[] = "ps"; 62 | 63 | static error_t 64 | parse_opt (int key, char *arg, struct argp_state *state arg_unused) 65 | { 66 | switch (key) 67 | { 68 | case 'f': 69 | if (strcmp (arg, "table") == 0) 70 | ps_options.format = PS_TABLE; 71 | else if (strcmp (arg, "json") == 0) 72 | ps_options.format = PS_JSON; 73 | else 74 | error (EXIT_FAILURE, 0, "invalid format `%s`", arg); 75 | break; 76 | 77 | default: 78 | return ARGP_ERR_UNKNOWN; 79 | } 80 | 81 | return 0; 82 | } 83 | 84 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 85 | 86 | int 87 | crun_command_ps (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 88 | { 89 | int first_arg; 90 | int ret; 91 | cleanup_free pid_t *pids = NULL; 92 | libcrun_context_t crun_context = { 93 | 0, 94 | }; 95 | size_t i; 96 | 97 | ps_options.format = PS_TABLE; 98 | 99 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &ps_options); 100 | crun_assert_n_args (argc - first_arg, 1, 1); 101 | 102 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 103 | if (UNLIKELY (ret < 0)) 104 | return ret; 105 | 106 | ret = libcrun_container_read_pids (&crun_context, argv[first_arg], true, &pids, err); 107 | if (UNLIKELY (ret < 0)) 108 | { 109 | libcrun_error_write_warning_and_release (stderr, &err); 110 | return ret; 111 | } 112 | 113 | switch (ps_options.format) 114 | { 115 | case PS_JSON: 116 | printf ("[\n"); 117 | for (i = 0; pids[i]; i++) 118 | printf (" %d%s\n", pids[i], pids[i + 1] ? "," : ""); 119 | printf ("]\n"); 120 | break; 121 | 122 | case PS_TABLE: 123 | printf ("PID\n"); 124 | for (i = 0; pids[i]; i++) 125 | printf ("%d\n", pids[i]); 126 | break; 127 | } 128 | 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /nix/default-arm64.nix: -------------------------------------------------------------------------------- 1 | { enableSystemd ? true }: 2 | let 3 | static = import ./static.nix; 4 | pkgs = (import ./nixpkgs.nix { 5 | crossSystem = { 6 | config = "aarch64-unknown-linux-gnu"; 7 | }; 8 | config = { 9 | packageOverrides = pkg: { 10 | gpgme = (static pkg.gpgme); 11 | libassuan = (static pkg.libassuan); 12 | libgpgerror = (static pkg.libgpgerror); 13 | libseccomp = (static pkg.libseccomp); 14 | protobufc = (static pkg.protobufc); 15 | glib = (static pkg.glib).overrideAttrs (x: { 16 | outputs = [ "bin" "out" "dev" ]; 17 | mesonFlags = [ 18 | "-Ddefault_library=static" 19 | "-Ddevbindir=${placeholder ''dev''}/bin" 20 | "-Dgtk_doc=false" 21 | "-Dnls=disabled" 22 | ]; 23 | postInstall = '' 24 | moveToOutput "share/glib-2.0" "$dev" 25 | substituteInPlace "$dev/bin/gdbus-codegen" --replace "$out" "$dev" 26 | sed -i "$dev/bin/glib-gettextize" -e "s|^gettext_dir=.*|gettext_dir=$dev/share/glib-2.0/gettext|" 27 | sed '1i#line 1 "${x.pname}-${x.version}/include/glib-2.0/gobject/gobjectnotifyqueue.c"' \ 28 | -i "$dev"/include/glib-2.0/gobject/gobjectnotifyqueue.c 29 | ''; 30 | }); 31 | libcap = (static pkg.libcap).overrideAttrs (x: { 32 | postInstall = '' 33 | mkdir -p "$doc/share/doc/${x.pname}-${x.version}" 34 | cp License "$doc/share/doc/${x.pname}-${x.version}/" 35 | mkdir -p "$pam/lib/security" 36 | mv "$lib"/lib/security "$pam/lib" 37 | ''; 38 | }); 39 | systemd = (static pkg.systemd).overrideAttrs (x: { 40 | outputs = [ "out" "dev" ]; 41 | mesonFlags = x.mesonFlags ++ [ 42 | "-Dglib=false" 43 | "-Dstatic-libsystemd=true" 44 | ]; 45 | }); 46 | yajl = (static pkg.yajl).overrideAttrs (x: { 47 | preConfigure = '' 48 | export CMAKE_STATIC_LINKER_FLAGS="-static" 49 | ''; 50 | }); 51 | zstd = pkg.zstd.overrideAttrs (x: { 52 | cmakeFlags = x.cmakeFlags ++ [ "-DZSTD_BUILD_CONTRIB:BOOL=OFF" ]; 53 | preInstall = ""; 54 | }); 55 | }; 56 | }; 57 | }); 58 | 59 | self = with pkgs; stdenv.mkDerivation rec { 60 | name = "crun"; 61 | src = ./..; 62 | vendorSha256 = null; 63 | doCheck = false; 64 | enableParallelBuilding = true; 65 | outputs = [ "out" ]; 66 | nativeBuildInputs = with buildPackages; [ 67 | autoreconfHook 68 | bash 69 | gitMinimal 70 | pkg-config 71 | python3 72 | which 73 | ]; 74 | buildInputs = [ 75 | glibc 76 | glibc.static 77 | libcap 78 | libseccomp 79 | protobufc 80 | systemd 81 | yajl 82 | ]; 83 | configureFlags = [ "--enable-static" ] 84 | ++ lib.optional (!enableSystemd) [ "--disable-systemd" ]; 85 | prePatch = '' 86 | export CFLAGS='-static -pthread' 87 | export LDFLAGS='-s -w -static-libgcc -static' 88 | export EXTRA_LDFLAGS='-s -w -linkmode external -extldflags "-static -lm"' 89 | export CRUN_LDFLAGS='-all-static' 90 | export LIBS='${glibc.static}/lib/libc.a ${glibc.static}/lib/libpthread.a ${glibc.static}/lib/librt.a ${lib.getLib libcap}/lib/libcap.a ${lib.getLib libseccomp}/lib/libseccomp.a ${protobufc}/lib/libprotobuf-c.a ${protobuf}/lib/libprotobuf.a ${lib.getLib systemd}/lib/libsystemd.a ${yajl}/lib/libyajl_s.a' 91 | ''; 92 | buildPhase = '' 93 | patchShebangs . 94 | make 95 | ''; 96 | installPhase = '' 97 | install -Dm755 crun $out/bin/crun 98 | ''; 99 | }; 100 | in 101 | self 102 | -------------------------------------------------------------------------------- /contrib/seccomp-notify-plugin-rust/src/seccompwatcher.rs: -------------------------------------------------------------------------------- 1 | extern crate nc; 2 | 3 | mod mknod; 4 | 5 | use std::os::raw::c_char; 6 | 7 | pub enum RunOciSeccompNotifyHandleRet { 8 | NotHandled, 9 | SendResponse, 10 | DelayedResponse, 11 | SendResponseAndContinue, 12 | } 13 | 14 | 15 | impl RunOciSeccompNotifyHandleRet { 16 | fn value(&self) -> i32 { 17 | match *self { 18 | RunOciSeccompNotifyHandleRet::NotHandled => 0, 19 | RunOciSeccompNotifyHandleRet::SendResponse => 1, 20 | RunOciSeccompNotifyHandleRet::DelayedResponse => 2, 21 | RunOciSeccompNotifyHandleRet::SendResponseAndContinue => 3, 22 | } 23 | } 24 | } 25 | type Errno = i32; 26 | 27 | type SyscallHandler = fn(req: &mut nc::seccomp_notif_t) -> Result; 28 | 29 | pub struct LibcrunLoadSeccompNotifyConf { 30 | _runtime_root_path: *const c_char, 31 | _name: *const c_char, 32 | _bundle_path: *const c_char, 33 | _oci_config_path: *const c_char, 34 | } 35 | 36 | #[no_mangle] 37 | pub extern "C" fn run_oci_seccomp_notify_plugin_version() -> i32 { 38 | 1 39 | } 40 | 41 | #[no_mangle] 42 | pub extern "C" fn run_oci_seccomp_notify_stop(opaque: *mut core::ffi::c_void) -> i32 { 43 | let ptr: *mut std::collections::HashMap = 44 | opaque as *mut std::collections::HashMap; 45 | unsafe { 46 | Box::from_raw(ptr); 47 | } 48 | 0 49 | } 50 | 51 | #[no_mangle] 52 | pub extern "C" fn run_oci_seccomp_notify_start( 53 | opaque: *mut *mut core::ffi::c_void, 54 | _conf: *mut LibcrunLoadSeccompNotifyConf, 55 | size_configuration: usize, 56 | ) -> i32 { 57 | if std::mem::size_of::() != size_configuration { 58 | return -libc::EINVAL; 59 | } 60 | let mut handlers = Box::new(std::collections::HashMap::new()); 61 | handlers.insert(nc::SYS_MKNOD, mknod::handle_mknod_request as SyscallHandler); 62 | handlers.insert( 63 | nc::SYS_MKNODAT, 64 | mknod::handle_mknodat_request as SyscallHandler, 65 | ); 66 | 67 | let ptr: *mut std::collections::HashMap = Box::into_raw(handlers); 68 | 69 | unsafe { 70 | *opaque = ptr as *mut libc::c_void; 71 | } 72 | 73 | 0 74 | } 75 | 76 | #[no_mangle] 77 | pub extern "C" fn run_oci_seccomp_notify_handle_request( 78 | opaque: *mut *mut core::ffi::c_void, 79 | _sizes: *mut nc::seccomp_notif_sizes_t, 80 | sreq: *mut nc::seccomp_notif_t, 81 | sresp: *mut nc::seccomp_notif_resp_t, 82 | _seccomp_fd: i32, 83 | shandled: *mut i32, 84 | ) -> i32 { 85 | let ptr: *mut std::collections::HashMap = 86 | opaque as *mut std::collections::HashMap; 87 | let handlers = *&ptr; 88 | let req = unsafe { &mut *sreq }; 89 | let resp = unsafe { &mut *sresp }; 90 | let handled = unsafe { &mut *shandled }; 91 | let handler_maybe = { unsafe { handlers.as_ref().unwrap().get(&(req.data.nr as usize)) } }; 92 | 93 | *handled = RunOciSeccompNotifyHandleRet::NotHandled.value(); 94 | 95 | if let Some(handler) = handler_maybe { 96 | *handled = RunOciSeccompNotifyHandleRet::SendResponse.value(); 97 | match handler(req) { 98 | Ok(notify_continue) => { 99 | if notify_continue { 100 | *handled = RunOciSeccompNotifyHandleRet::SendResponseAndContinue.value(); 101 | } 102 | resp.error = 0; 103 | } 104 | Err(errno) => { 105 | resp.error = -errno; 106 | } 107 | } 108 | resp.id = req.id; 109 | resp.val = 0; 110 | return 0; 111 | } 112 | 0 113 | } 114 | -------------------------------------------------------------------------------- /tests/test_seccomp.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2021 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import json 19 | import subprocess 20 | import os 21 | import socket 22 | import sys 23 | import array 24 | from tests_utils import * 25 | 26 | def is_seccomp_listener_supported(): 27 | r = subprocess.call(["./tests/init", "check-feature", "open_tree"]) 28 | return r == 0 29 | 30 | # taken from https://docs.python.org/3/library/socket.html#socket.socket.recvmsg 31 | def recv_fds(sock, msglen, maxfds): 32 | fds = array.array("i") # Array of ints 33 | msg, ancdata, flags, addr = sock.recvmsg(msglen, socket.CMSG_LEN(maxfds * fds.itemsize)) 34 | for cmsg_level, cmsg_type, cmsg_data in ancdata: 35 | if cmsg_level == socket.SOL_SOCKET and cmsg_type == socket.SCM_RIGHTS: 36 | # Append data, ignoring any truncated integers at the end. 37 | fds.frombytes(cmsg_data[:len(cmsg_data) - (len(cmsg_data) % fds.itemsize)]) 38 | return msg, list(fds) 39 | 40 | def test_seccomp_listener(): 41 | if not is_seccomp_listener_supported(): 42 | return 77 43 | 44 | listener_path = "%s/seccomp-listener" % get_tests_root() 45 | listener_metadata = "SOME-RANDOM-METADATA" 46 | 47 | sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 48 | sock.bind(listener_path) 49 | sock.listen(1) 50 | 51 | conf = base_config() 52 | add_all_namespaces(conf) 53 | conf['linux']['seccomp'] = { 54 | 'defaultAction': 'SCMP_ACT_ALLOW', 55 | 'listenerPath': listener_path, 56 | 'listenerMetadata': listener_metadata, 57 | } 58 | conf['process']['args'] = ['/init', 'true'] 59 | cid = None 60 | try: 61 | _, cid = run_and_get_output(conf, command='run', detach=True) 62 | conn = sock.accept() 63 | msg, fds = recv_fds(conn[0], 4096, 1) 64 | if len(fds) != 1: 65 | print("invalid number of FDs received", file=sys.stderr) 66 | return 1 67 | 68 | m = json.loads(msg) 69 | if m['ociVersion'] != '0.2.0': 70 | print("invalid OCI version", file=sys.stderr) 71 | return 1 72 | if len(m['fds']) != 1: 73 | print("invalid fds", file=sys.stderr) 74 | return 1 75 | if 'pid' not in m != 1: 76 | print("invalid pid", file=sys.stderr) 77 | return 1 78 | if m['metadata'] != listener_metadata: 79 | print("invalid metadata", file=sys.stderr) 80 | return 1 81 | state = m['state'] 82 | if state['status'] != 'creating': 83 | print("invalid status", file=sys.stderr) 84 | return 1 85 | if state['id'] != cid: 86 | print("invalid container id", file=sys.stderr) 87 | return 1 88 | return 0 89 | finally: 90 | if cid is not None: 91 | run_crun_command(["delete", "-f", cid]) 92 | os.unlink(listener_path) 93 | 94 | return -1 95 | 96 | all_tests = { 97 | "seccomp-listener" : test_seccomp_listener, 98 | } 99 | 100 | if __name__ == "__main__": 101 | tests_main(all_tests) 102 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | BasedOnStyle: GNU 3 | AccessModifierOffset: -2 4 | AlignAfterOpenBracket: Align 5 | AlignConsecutiveMacros: false 6 | AlignConsecutiveAssignments: false 7 | AlignConsecutiveDeclarations: false 8 | AlignEscapedNewlines: Left 9 | AlignOperands: true 10 | AlignTrailingComments: true 11 | AllowAllArgumentsOnNextLine: true 12 | AllowAllConstructorInitializersOnNextLine: true 13 | AllowAllParametersOfDeclarationOnNextLine: true 14 | AllowShortBlocksOnASingleLine: Never 15 | AllowShortCaseLabelsOnASingleLine: false 16 | AllowShortFunctionsOnASingleLine: All 17 | AllowShortLambdasOnASingleLine: All 18 | AllowShortIfStatementsOnASingleLine: Never 19 | AllowShortLoopsOnASingleLine: false 20 | AlwaysBreakAfterDefinitionReturnType: All 21 | AlwaysBreakAfterReturnType: AllDefinitions 22 | AlwaysBreakBeforeMultilineStrings: false 23 | AlwaysBreakTemplateDeclarations: MultiLine 24 | BinPackArguments: true 25 | BinPackParameters: true 26 | AllowShortIfStatementsOnASingleLine: false 27 | AllowShortLoopsOnASingleLine: false 28 | AllowShortCaseLabelsOnASingleLine: false 29 | AllowShortFunctionsOnASingleLine: false 30 | AllowShortBlocksOnASingleLine: false 31 | BreakBeforeBraces: Allman 32 | BraceWrapping: 33 | AfterCaseLabel: true 34 | AfterClass: true 35 | AfterControlStatement: true 36 | AfterEnum: true 37 | AfterFunction: true 38 | AfterNamespace: true 39 | AfterObjCDeclaration: true 40 | AfterStruct: true 41 | AfterUnion: true 42 | BeforeCatch: true 43 | BeforeElse: true 44 | IndentBraces: true 45 | SplitEmptyFunction: true 46 | SplitEmptyRecord: true 47 | SplitEmptyNamespace: true 48 | BreakBeforeBinaryOperators: All 49 | BreakBeforeBraces: Custom 50 | BreakBeforeInheritanceComma: false 51 | BreakInheritanceList: BeforeColon 52 | BreakBeforeTernaryOperators: true 53 | BreakConstructorInitializersBeforeComma: false 54 | BreakConstructorInitializers: BeforeColon 55 | BreakAfterJavaFieldAnnotations: false 56 | BreakStringLiterals: true 57 | ColumnLimit: 0 58 | ContinuationIndentWidth: 4 59 | DeriveLineEnding: true 60 | DerivePointerAlignment: false 61 | DisableFormat: false 62 | ExperimentalAutoDetectBinPacking: false 63 | FixNamespaceComments: false 64 | ForEachMacros: 65 | - foreach 66 | - Q_FOREACH 67 | - BOOST_FOREACH 68 | IncludeBlocks: Preserve 69 | IncludeIsMainRegex: '(Test)?$' 70 | IncludeIsMainSourceRegex: '' 71 | IndentCaseLabels: false 72 | IndentGotoLabels: true 73 | IndentPPDirectives: AfterHash 74 | IndentWidth: 2 75 | IndentWrappedFunctionNames: false 76 | JavaScriptQuotes: Leave 77 | JavaScriptWrapImports: true 78 | KeepEmptyLinesAtTheStartOfBlocks: true 79 | MacroBlockBegin: '' 80 | MacroBlockEnd: '' 81 | MaxEmptyLinesToKeep: 1 82 | NamespaceIndentation: None 83 | ObjCBinPackProtocolList: Auto 84 | ObjCBlockIndentWidth: 2 85 | ObjCSpaceAfterProperty: false 86 | ObjCSpaceBeforeProtocolList: true 87 | PenaltyBreakAssignment: 2 88 | PenaltyBreakBeforeFirstCallParameter: 19 89 | PenaltyBreakComment: 300 90 | PenaltyBreakFirstLessLess: 120 91 | PenaltyBreakString: 1000 92 | PenaltyBreakTemplateDeclaration: 10 93 | PenaltyExcessCharacter: 1000000 94 | PenaltyReturnTypeOnItsOwnLine: 60 95 | PointerAlignment: Right 96 | ReflowComments: true 97 | SortIncludes: false 98 | SortUsingDeclarations: true 99 | SpaceAfterCStyleCast: true 100 | SpaceAfterLogicalNot: true 101 | SpaceAfterTemplateKeyword: true 102 | SpaceBeforeAssignmentOperators: true 103 | SpaceBeforeParens: Always 104 | SpaceInEmptyBlock: false 105 | SpaceInEmptyParentheses: false 106 | SpacesBeforeTrailingComments: 1 107 | SpacesInAngles: false 108 | SpacesInConditionalStatement: false 109 | SpacesInContainerLiterals: true 110 | SpacesInCStyleCastParentheses: false 111 | SpacesInParentheses: false 112 | SpacesInSquareBrackets: false 113 | SpaceBeforeSquareBrackets: false 114 | TabWidth: 8 115 | UseCRLF: false 116 | UseTab: Never 117 | ... 118 | -------------------------------------------------------------------------------- /contrib/seccomp-receiver/seccomp-receiver.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2021 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #define _GNU_SOURCE 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define error(status, errno, fmt, ...) do { \ 34 | if (errno) \ 35 | fprintf (stderr, "crun: " fmt, ##__VA_ARGS__); \ 36 | else \ 37 | fprintf (stderr, "crun: %s:" fmt, strerror (errno), ##__VA_ARGS__); \ 38 | if (status) \ 39 | exit (status); \ 40 | } while(0) 41 | 42 | static int 43 | open_unix_domain_socket (const char *path) 44 | { 45 | struct sockaddr_un addr = {}; 46 | int ret; 47 | int fd = socket (AF_UNIX, SOCK_STREAM, 0); 48 | if (fd < 0) 49 | error (EXIT_FAILURE, errno, "error creating UNIX socket"); 50 | 51 | strcpy (addr.sun_path, path); 52 | addr.sun_family = AF_UNIX; 53 | ret = bind (fd, (struct sockaddr *) &addr, sizeof (addr)); 54 | if (ret < 0) 55 | error (EXIT_FAILURE, errno, "error binding UNIX socket"); 56 | 57 | ret = listen (fd, 1); 58 | if (ret < 0) 59 | error (EXIT_FAILURE, errno, "listen"); 60 | 61 | return fd; 62 | } 63 | 64 | static void 65 | print_payload (int from) 66 | { 67 | int fd = -1; 68 | struct iovec iov[1]; 69 | struct msghdr msg = {}; 70 | char ctrl_buf[2048] = {}; 71 | char data[2048]; 72 | int ret; 73 | struct cmsghdr *cmsg; 74 | 75 | iov[0].iov_base = data; 76 | iov[0].iov_len = sizeof (data) - 1; 77 | 78 | msg.msg_name = NULL; 79 | msg.msg_namelen = 0; 80 | msg.msg_iov = iov; 81 | msg.msg_iovlen = 1; 82 | msg.msg_controllen = CMSG_SPACE (sizeof (int)); 83 | msg.msg_control = ctrl_buf; 84 | 85 | do 86 | ret = recvmsg (from, &msg, 0); 87 | while (ret < 0 && errno == EINTR); 88 | if (ret < 0) 89 | { 90 | error (0, errno, "recvmsg"); 91 | return; 92 | } 93 | 94 | data[iov[0].iov_len] = '\0'; 95 | puts (data); 96 | 97 | cmsg = CMSG_FIRSTHDR (&msg); 98 | if (cmsg == NULL) 99 | { 100 | error (0, 0, "no msg received"); 101 | return; 102 | } 103 | memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd)); 104 | close (fd); 105 | } 106 | 107 | int 108 | main (int argc, char **argv) 109 | { 110 | char buf[8192]; 111 | int ret, fd, socket; 112 | if (argc < 2) 113 | error (EXIT_FAILURE, 0, "usage %s PATH\n", argv[0]); 114 | 115 | unlink (argv[1]); 116 | 117 | socket = open_unix_domain_socket (argv[1]); 118 | while (1) 119 | { 120 | struct termios tset; 121 | int conn; 122 | 123 | do 124 | conn = accept (socket, NULL, NULL); 125 | while (conn < 0 && errno == EINTR); 126 | if (conn < 0) 127 | error (EXIT_FAILURE, errno, "accept"); 128 | 129 | print_payload (conn); 130 | } 131 | 132 | return 0; 133 | } 134 | -------------------------------------------------------------------------------- /tests/test_uid_gid.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def test_userns_full_mapping(): 22 | if is_rootless(): 23 | return 77 24 | conf = base_config() 25 | add_all_namespaces(conf, userns=True) 26 | 27 | fullMapping = [ 28 | { 29 | "containerID": 0, 30 | "hostID": 0, 31 | "size": 4294967295 32 | } 33 | ] 34 | 35 | conf['linux']['uidMappings'] = fullMapping 36 | conf['linux']['gidMappings'] = fullMapping 37 | 38 | for filename in ['uid_map', 'gid_map']: 39 | conf['process']['args'] = ['/init', 'cat', '/proc/self/%s' % filename] 40 | out, _ = run_and_get_output(conf) 41 | proc_status = parse_proc_status(out) 42 | 43 | if "4294967295" not in out: 44 | return -1 45 | 46 | return 0 47 | 48 | def test_uid(): 49 | if is_rootless(): 50 | return 77 51 | conf = base_config() 52 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 53 | add_all_namespaces(conf) 54 | conf['process']['user']['uid'] = 1000 55 | out, _ = run_and_get_output(conf) 56 | proc_status = parse_proc_status(out) 57 | 58 | ids = proc_status['Uid'].split() 59 | for i in ids: 60 | if i != "1000": 61 | return -1 62 | return 0 63 | 64 | def test_gid(): 65 | if is_rootless(): 66 | return 77 67 | conf = base_config() 68 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 69 | add_all_namespaces(conf) 70 | conf['process']['user']['gid'] = 1000 71 | out, _ = run_and_get_output(conf) 72 | proc_status = parse_proc_status(out) 73 | 74 | ids = proc_status['Gid'].split() 75 | for i in ids: 76 | if i != "1000": 77 | return -1 78 | return 0 79 | 80 | def test_no_groups(): 81 | if is_rootless(): 82 | return 77 83 | conf = base_config() 84 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 85 | add_all_namespaces(conf) 86 | conf['process']['user']['gid'] = 1000 87 | out, _ = run_and_get_output(conf) 88 | proc_status = parse_proc_status(out) 89 | 90 | ids = proc_status['Groups'].split() 91 | if len(ids) > 0: 92 | return -1 93 | return 0 94 | 95 | def test_keep_groups(): 96 | if is_rootless(): 97 | return 77 98 | oldgroups = os.getgroups() 99 | out = "" 100 | try: 101 | os.setgroups([1,2,3,4,5]) 102 | conf = base_config() 103 | conf['process']['args'] = ['/init', 'cat', '/proc/self/status'] 104 | add_all_namespaces(conf) 105 | conf['annotations'] = {} 106 | conf['annotations']['run.oci.keep_original_groups'] = "1" 107 | out, _ = run_and_get_output(conf) 108 | finally: 109 | os.setgroups(oldgroups) 110 | 111 | proc_status = parse_proc_status(out) 112 | ids = proc_status['Groups'].split() 113 | if len(ids) == 0: 114 | return -1 115 | return 0 116 | 117 | all_tests = { 118 | "uid" : test_uid, 119 | "gid" : test_gid, 120 | "userns-full-mapping" : test_userns_full_mapping, 121 | "no-groups" : test_no_groups, 122 | "keep-groups" : test_keep_groups, 123 | } 124 | 125 | if __name__ == "__main__": 126 | tests_main(all_tests) 127 | -------------------------------------------------------------------------------- /src/delete.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | #include "crun.h" 29 | #include "libcrun/container.h" 30 | #include "libcrun/utils.h" 31 | #include "libcrun/status.h" 32 | 33 | static char doc[] = "OCI runtime"; 34 | 35 | enum 36 | { 37 | OPTION_CONSOLE_SOCKET = 1000, 38 | OPTION_PID_FILE, 39 | OPTION_NO_SUBREAPER, 40 | OPTION_NO_NEW_KEYRING, 41 | OPTION_PRESERVE_FDS 42 | }; 43 | 44 | struct delete_options_s 45 | { 46 | int regex; 47 | bool force; 48 | }; 49 | 50 | static struct delete_options_s delete_options; 51 | 52 | static struct argp_option options[] 53 | = { { "force", 'f', 0, 0, "delete the container even if it is still running", 0 }, 54 | { "regex", 'r', 0, 0, "the specified CONTAINER is a regular expression (delete multiple containers)", 0 }, 55 | { 56 | 0, 57 | } }; 58 | 59 | static char args_doc[] = "delete CONTAINER"; 60 | 61 | static error_t 62 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 63 | { 64 | switch (key) 65 | { 66 | case 'f': 67 | delete_options.force = true; 68 | break; 69 | 70 | case 'r': 71 | delete_options.regex = true; 72 | break; 73 | 74 | case ARGP_KEY_NO_ARGS: 75 | libcrun_fail_with_error (0, "please specify a ID for the container"); 76 | 77 | default: 78 | return ARGP_ERR_UNKNOWN; 79 | } 80 | 81 | return 0; 82 | } 83 | 84 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 85 | 86 | int 87 | crun_command_delete (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 88 | { 89 | int first_arg = 0, ret; 90 | 91 | libcrun_context_t crun_context = { 92 | 0, 93 | }; 94 | 95 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &delete_options); 96 | crun_assert_n_args (argc - first_arg, 1, 1); 97 | 98 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 99 | if (UNLIKELY (ret < 0)) 100 | return ret; 101 | 102 | if (delete_options.regex) 103 | { 104 | regex_t re; 105 | libcrun_container_list_t *list, *it; 106 | 107 | ret = regcomp (&re, argv[first_arg], REG_EXTENDED | REG_NOSUB); 108 | if (UNLIKELY (ret < 0)) 109 | libcrun_fail_with_error (0, "invalid regular expression %s", argv[first_arg]); 110 | 111 | ret = libcrun_get_containers_list (&list, crun_context.state_root, err); 112 | if (UNLIKELY (ret < 0)) 113 | libcrun_fail_with_error (0, "cannot read containers list"); 114 | 115 | for (it = list; it; it = it->next) 116 | if (regexec (&re, it->name, 0, NULL, 0) == 0) 117 | { 118 | ret = libcrun_container_delete (&crun_context, NULL, it->name, delete_options.force, err); 119 | if (UNLIKELY (ret < 0)) 120 | libcrun_error_write_warning_and_release (stderr, &err); 121 | } 122 | 123 | libcrun_free_containers_list (list); 124 | regfree (&re); 125 | return 0; 126 | } 127 | 128 | return libcrun_container_delete (&crun_context, NULL, argv[first_arg], delete_options.force, err); 129 | } 130 | -------------------------------------------------------------------------------- /tests/test_devices.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import os 19 | from tests_utils import * 20 | 21 | def test_deny_devices(): 22 | if is_rootless(): 23 | return 77 24 | 25 | try: 26 | os.stat("/dev/fuse") 27 | except: 28 | return 77 29 | 30 | conf = base_config() 31 | add_all_namespaces(conf) 32 | conf['process']['args'] = ['/init', 'open', '/dev/fuse'] 33 | conf['linux']['resources'] = {"devices": [{"allow": False, "access": "rwm"}]} 34 | dev = { 35 | "destination": "/dev", 36 | "type": "bind", 37 | "source": "/dev", 38 | "options": [ 39 | "rbind", 40 | "rw" 41 | ] 42 | } 43 | conf['mounts'].append(dev) 44 | try: 45 | run_and_get_output(conf) 46 | except Exception as e: 47 | if "Operation not permitted" in e.output.decode(): 48 | return 0 49 | return -1 50 | 51 | def test_allow_device(): 52 | if is_rootless(): 53 | return 77 54 | 55 | try: 56 | os.stat("/dev/fuse") 57 | except: 58 | return 77 59 | 60 | conf = base_config() 61 | add_all_namespaces(conf) 62 | conf['process']['args'] = ['/init', 'open', '/dev/fuse'] 63 | conf['linux']['resources'] = {"devices": [{"allow": False, "access": "rwm"}, 64 | {"allow": True, "type": "c", "major": 10, "minor": 229, "access": "r"}]} 65 | dev = { 66 | "destination": "/dev", 67 | "type": "bind", 68 | "source": "/dev", 69 | "options": [ 70 | "rbind", 71 | "rw" 72 | ] 73 | } 74 | conf['mounts'].append(dev) 75 | try: 76 | run_and_get_output(conf) 77 | except Exception as e: 78 | return -1 79 | return 0 80 | 81 | def test_allow_access(): 82 | if is_rootless(): 83 | return 77 84 | 85 | try: 86 | os.stat("/dev/fuse") 87 | except: 88 | return 77 89 | 90 | conf = base_config() 91 | add_all_namespaces(conf) 92 | conf['process']['args'] = ['/init', 'access', '/dev/fuse'] 93 | conf['linux']['resources'] = {"devices": [{"allow": False, "access": "rwm"}, 94 | {"allow": True, "type": "c", "major": 10, "minor": 229, "access": "rw"}]} 95 | dev = { 96 | "destination": "/dev", 97 | "type": "bind", 98 | "source": "/dev", 99 | "options": [ 100 | "rbind", 101 | "rw" 102 | ] 103 | } 104 | conf['mounts'].append(dev) 105 | try: 106 | run_and_get_output(conf) 107 | except Exception as e: 108 | return -1 109 | return 0 110 | 111 | def test_mknod_device(): 112 | if is_rootless(): 113 | return 77 114 | 115 | conf = base_config() 116 | add_all_namespaces(conf) 117 | conf['process']['args'] = ['/init', 'true'] 118 | conf['linux']['devices'] = [{"path": "/foo-dev", "type": "b", "major": 10, "minor": 229}, 119 | {"path": "/subdir/foo-dev", "type": "b", "major": 10, "minor": 229},] 120 | try: 121 | run_and_get_output(conf) 122 | except Exception as e: 123 | return -1 124 | return 0 125 | 126 | 127 | all_tests = { 128 | "deny-devices" : test_deny_devices, 129 | "allow-device" : test_allow_device, 130 | "allow-access" : test_allow_access, 131 | "mknod-device" : test_mknod_device, 132 | } 133 | 134 | if __name__ == "__main__": 135 | tests_main(all_tests) 136 | -------------------------------------------------------------------------------- /src/spec.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include "crun.h" 28 | #include "libcrun/container.h" 29 | #include "libcrun/utils.h" 30 | 31 | static char doc[] = "OCI runtime"; 32 | 33 | struct spec_options_s 34 | { 35 | bool rootless; 36 | }; 37 | 38 | enum 39 | { 40 | OPTION_ROOTLESS = 1000 41 | }; 42 | 43 | static const char *bundle; 44 | static const char *fname; 45 | 46 | static struct spec_options_s spec_options; 47 | 48 | static struct argp_option options[] = { { "bundle", 'b', "DIR", 0, "path to the root of the bundle dir (default \".\")", 0 }, 49 | { "file", 'f', "PATH", 0, "destination file", 0 }, 50 | { "rootless", OPTION_ROOTLESS, 0, 0, "spec for the rootless case", 0 }, 51 | { 52 | 0, 53 | } }; 54 | 55 | static char args_doc[] = "spec"; 56 | 57 | static error_t 58 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 59 | { 60 | switch (key) 61 | { 62 | case 'b': 63 | bundle = argp_mandatory_argument (arg, state); 64 | break; 65 | 66 | case 'f': 67 | fname = argp_mandatory_argument (arg, state); 68 | break; 69 | 70 | case OPTION_ROOTLESS: 71 | spec_options.rootless = true; 72 | break; 73 | 74 | default: 75 | return ARGP_ERR_UNKNOWN; 76 | } 77 | 78 | return 0; 79 | } 80 | 81 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 82 | 83 | int 84 | crun_command_spec (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 85 | { 86 | int first_arg; 87 | libcrun_context_t crun_context = { 88 | 0, 89 | }; 90 | cleanup_file FILE *f = NULL; 91 | cleanup_free char *bundle_cleanup = NULL; 92 | const char *where; 93 | int ret; 94 | 95 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &spec_options); 96 | crun_assert_n_args (argc - first_arg, 0, 0); 97 | 98 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 99 | if (UNLIKELY (ret < 0)) 100 | return ret; 101 | 102 | /* Change dir only if -b or --bundle is defined and make sure the bundle is an absolute path. */ 103 | if (bundle != NULL) 104 | { 105 | if (bundle[0] != '/') 106 | { 107 | bundle_cleanup = realpath (bundle, NULL); 108 | if (bundle_cleanup == NULL) 109 | libcrun_fail_with_error (errno, "realpath `%s` failed", bundle); 110 | bundle = bundle_cleanup; 111 | } 112 | 113 | if (chdir (bundle) < 0) 114 | libcrun_fail_with_error (errno, "chdir `%s` failed", bundle); 115 | } 116 | 117 | where = fname ? fname : "config.json"; 118 | 119 | if (fname == NULL) 120 | { 121 | ret = access (where, F_OK); 122 | if (ret == 0) 123 | return libcrun_make_error (err, 0, "`%s` already exists", where); 124 | } 125 | 126 | f = fopen (where, "w+"); 127 | if (f == NULL) 128 | return libcrun_make_error (err, errno, "cannot open `%s`", where); 129 | 130 | ret = libcrun_container_spec (! spec_options.rootless, f, err); 131 | 132 | return ret >= 0 ? 0 : ret; 133 | } 134 | -------------------------------------------------------------------------------- /contrib/notify-socket-server/notify-socket-server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2020 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #define _GNU_SOURCE 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #define error(status, errno, fmt, ...) do{ \ 34 | if (errno) \ 35 | fprintf (stderr, "crun: " fmt, ##__VA_ARGS__); \ 36 | else \ 37 | fprintf (stderr, "crun: %s:" fmt, strerror (errno), ##__VA_ARGS__); \ 38 | if (status) \ 39 | exit (status); \ 40 | } while(0) 41 | 42 | static int 43 | open_unix_domain_socket (const char *path) 44 | { 45 | struct sockaddr_un addr = {}; 46 | int ret, fd; 47 | const int one = 1; 48 | 49 | fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0); 50 | if (fd < 0) 51 | error (EXIT_FAILURE, errno, "socket"); 52 | 53 | if (strlen (path) >= sizeof (addr.sun_path)) 54 | error (EXIT_FAILURE, 0, "invalid path"); 55 | strcpy (addr.sun_path, path); 56 | addr.sun_family = AF_UNIX; 57 | ret = bind (fd, (struct sockaddr *) &addr, sizeof (addr)); 58 | if (ret < 0) 59 | error (EXIT_FAILURE, errno, "bind"); 60 | 61 | ret = setsockopt (fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof (one)); 62 | if (ret < 0) 63 | error (EXIT_FAILURE, errno, "setsockopt"); 64 | 65 | return fd; 66 | } 67 | 68 | int 69 | main (int argc, char **argv) 70 | { 71 | #define CTRL_SIZE (CMSG_SPACE (sizeof (struct ucred))) 72 | char buf[512]; 73 | int ret, fd; 74 | if (argc < 2) 75 | error (EXIT_FAILURE, 0, "usage %s PATH\n", argv[0]); 76 | 77 | unlink (argv[1]); 78 | 79 | fd = open_unix_domain_socket (argv[1]); 80 | 81 | while (1) 82 | { 83 | char ctrl_buf[CTRL_SIZE] = {}; 84 | struct cmsghdr *cmsg; 85 | char data[1]; 86 | struct iovec iov[1]; 87 | struct msghdr msg = {}; 88 | struct ucred *ucred = NULL; 89 | 90 | iov[0].iov_base = buf; 91 | iov[0].iov_len = sizeof (buf) - 1; 92 | 93 | msg.msg_name = NULL; 94 | msg.msg_namelen = 0; 95 | msg.msg_iov = iov; 96 | msg.msg_iovlen = 1; 97 | msg.msg_control = ctrl_buf; 98 | msg.msg_controllen = CTRL_SIZE; 99 | 100 | ret = recvmsg (fd, &msg, MSG_CMSG_CLOEXEC|MSG_TRUNC); 101 | if (ret < 0 && errno == EINTR) 102 | continue; 103 | if (ret < 0) 104 | error (EXIT_FAILURE, errno, "recvfrom"); 105 | 106 | buf[ret] = '\0'; 107 | 108 | for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg)) 109 | { 110 | if (cmsg 111 | && cmsg->cmsg_level == SOL_SOCKET 112 | && cmsg->cmsg_type == SCM_CREDENTIALS 113 | && cmsg->cmsg_len == CMSG_LEN (sizeof (struct ucred))) 114 | { 115 | ucred = (struct ucred *) CMSG_DATA (cmsg); 116 | break; 117 | } 118 | } 119 | 120 | if (ucred) 121 | printf ("RECEIVED (PID:%d UID:%d GID:%d): %s\n", ucred->pid, ucred->uid, ucred->gid, buf); 122 | else 123 | printf ("RECEIVED: %s\n", buf); 124 | } 125 | 126 | return 0; 127 | } 128 | -------------------------------------------------------------------------------- /src/kill.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU General Public License as published by 7 | * the Free Software Foundation; either version 2 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #include "crun.h" 30 | #include "libcrun/container.h" 31 | #include "libcrun/status.h" 32 | #include "libcrun/utils.h" 33 | 34 | static char doc[] = "OCI runtime"; 35 | 36 | enum 37 | { 38 | OPTION_CONSOLE_SOCKET = 1000, 39 | OPTION_PID_FILE, 40 | OPTION_NO_SUBREAPER, 41 | OPTION_NO_NEW_KEYRING, 42 | OPTION_PRESERVE_FDS 43 | }; 44 | 45 | struct kill_options_s 46 | { 47 | bool all; 48 | bool regex; 49 | }; 50 | 51 | static struct kill_options_s kill_options; 52 | 53 | static struct argp_option options[] 54 | = { { "all", 'a', 0, 0, "kill all the processes", 0 }, 55 | { "regex", 'r', 0, 0, "the specified CONTAINER is a regular expression (kill multiple containers)", 0 }, 56 | { 57 | 0, 58 | } }; 59 | 60 | static char args_doc[] = "kill CONTAINER [SIGNAL]"; 61 | 62 | static error_t 63 | parse_opt (int key, char *arg arg_unused, struct argp_state *state arg_unused) 64 | { 65 | switch (key) 66 | { 67 | case 'a': 68 | kill_options.all = true; 69 | break; 70 | 71 | case 'r': 72 | kill_options.regex = true; 73 | break; 74 | 75 | case ARGP_KEY_NO_ARGS: 76 | libcrun_fail_with_error (0, "please specify a ID for the container"); 77 | 78 | default: 79 | return ARGP_ERR_UNKNOWN; 80 | } 81 | 82 | return 0; 83 | } 84 | 85 | static struct argp run_argp = { options, parse_opt, args_doc, doc, NULL, NULL, NULL }; 86 | 87 | int 88 | crun_command_kill (struct crun_global_arguments *global_args, int argc, char **argv, libcrun_error_t *err) 89 | { 90 | int first_arg = 0, ret; 91 | const char *signal; 92 | 93 | libcrun_context_t crun_context = { 94 | 0, 95 | }; 96 | 97 | argp_parse (&run_argp, argc, argv, ARGP_IN_ORDER, &first_arg, &kill_options); 98 | crun_assert_n_args (argc - first_arg, 1, 2); 99 | 100 | ret = init_libcrun_context (&crun_context, argv[first_arg], global_args, err); 101 | if (UNLIKELY (ret < 0)) 102 | return ret; 103 | 104 | signal = "SIGTERM"; 105 | if (argc - first_arg > 1) 106 | signal = argv[first_arg + 1]; 107 | 108 | if (kill_options.regex) 109 | { 110 | regex_t re; 111 | libcrun_container_list_t *list, *it; 112 | 113 | ret = regcomp (&re, argv[first_arg], REG_EXTENDED | REG_NOSUB); 114 | if (UNLIKELY (ret < 0)) 115 | libcrun_fail_with_error (0, "invalid regular expression %s", argv[first_arg]); 116 | 117 | ret = libcrun_get_containers_list (&list, crun_context.state_root, err); 118 | if (UNLIKELY (ret < 0)) 119 | libcrun_fail_with_error (0, "cannot read containers list"); 120 | 121 | for (it = list; it; it = it->next) 122 | if (regexec (&re, it->name, 0, NULL, 0) == 0) 123 | { 124 | ret = libcrun_container_kill (&crun_context, it->name, signal, err); 125 | if (UNLIKELY (ret < 0)) 126 | libcrun_error_write_warning_and_release (stderr, &err); 127 | } 128 | 129 | libcrun_free_containers_list (list); 130 | regfree (&re); 131 | return 0; 132 | } 133 | 134 | if (kill_options.all) 135 | return libcrun_container_killall (&crun_context, argv[first_arg], signal, err); 136 | 137 | return libcrun_container_kill (&crun_context, argv[first_arg], signal, err); 138 | } 139 | -------------------------------------------------------------------------------- /tests/test_delete.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | # crun - OCI runtime written in C 3 | # 4 | # Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | # crun is free software; you can redistribute it and/or modify 6 | # it under the terms of the GNU General Public License as published by 7 | # the Free Software Foundation; either version 2 of the License, or 8 | # (at your option) any later version. 9 | # 10 | # crun is distributed in the hope that it will be useful, 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | # GNU General Public License for more details. 14 | # 15 | # You should have received a copy of the GNU General Public License 16 | # along with crun. If not, see . 17 | 18 | import json 19 | import subprocess 20 | import os 21 | from tests_utils import * 22 | 23 | def test_simple_delete(): 24 | conf = base_config() 25 | conf['process']['args'] = ['/init', 'pause'] 26 | add_all_namespaces(conf) 27 | 28 | out, container_id = run_and_get_output(conf, detach=True, hide_stderr=True) 29 | if out != "": 30 | return -1 31 | try: 32 | state = json.loads(run_crun_command(["state", container_id])) 33 | if state['status'] != "running": 34 | return -1 35 | if state['id'] != container_id: 36 | return -1 37 | finally: 38 | freezerCreated=False 39 | if not os.path.exists("/sys/fs/cgroup/cgroup.controllers") and os.access('/sys/fs/cgroup/freezer/', os.W_OK): 40 | # cgroupv1 freezer can easily simulate stuck or breaking `crun delete -f ` 41 | # this should be only done on cgroupv1 systems 42 | if not os.path.exists("/sys/fs/cgroup/freezer/frozen/"): 43 | freezerCreated=True 44 | os.makedirs("/sys/fs/cgroup/freezer/frozen/") 45 | with open('/sys/fs/cgroup/freezer/frozen/tasks', 'w') as f: 46 | f.write(str(state['pid'])) 47 | with open('/sys/fs/cgroup/freezer/frozen/freezer.state', 'w') as f: 48 | f.write('FROZEN') 49 | try: 50 | output = run_crun_command_raw(["delete", "-f", container_id]) 51 | except subprocess.CalledProcessError as exc: 52 | print("Status : FAIL", exc.returncode, exc.output) 53 | return -1 54 | else: 55 | # this is expected for cgroup v1 so ignore 56 | if not output or b'Device or resource busy' in output: 57 | # if output is empty or expected error pass 58 | pass 59 | else: 60 | # anything else is error 61 | print(output) 62 | return -1 63 | 64 | if freezerCreated: 65 | os.rmdir("/sys/fs/cgroup/freezer/frozen/") 66 | return 0 67 | 68 | def test_multiple_containers_delete(): 69 | """Delete multiple containers with a regular expression""" 70 | conf = base_config() 71 | conf['process']['args'] = ['/init', 'pause'] 72 | add_all_namespaces(conf) 73 | 74 | out_test1, container_id_test1 = run_and_get_output(conf, detach=True, hide_stderr=True) 75 | if out_test1 != "": 76 | return -1 77 | out_test2, container_id_test2 = run_and_get_output(conf, detach=True, hide_stderr=True) 78 | if out_test2 != "": 79 | return -1 80 | try: 81 | state_test1 = json.loads(run_crun_command(["state", container_id_test1])) 82 | if state_test1['status'] != "running": 83 | return -1 84 | if state_test1['id'] != container_id_test1: 85 | return -1 86 | state_test2 = json.loads(run_crun_command(["state", container_id_test2])) 87 | if state_test2['status'] != "running": 88 | return -1 89 | if state_test2['id'] != container_id_test2: 90 | return -1 91 | finally: 92 | try: 93 | output = run_crun_command_raw(["delete", "-f", "--regex", "test-*"]) 94 | except subprocess.CalledProcessError as exc: 95 | print("Status : FAIL", exc.returncode, exc.output) 96 | return -1 97 | return 0 98 | 99 | 100 | all_tests = { 101 | "test_simple_delete" : test_simple_delete, 102 | "test_multiple_containers_delete" : test_multiple_containers_delete, 103 | } 104 | 105 | if __name__ == "__main__": 106 | tests_main(all_tests) 107 | 108 | -------------------------------------------------------------------------------- /src/libcrun/cgroup-cgroupfs.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #define _GNU_SOURCE 20 | 21 | #include 22 | #include "cgroup.h" 23 | #include "cgroup-internal.h" 24 | #include "cgroup-systemd.h" 25 | #include "cgroup-setup.h" 26 | #include "cgroup-utils.h" 27 | #include "cgroup-cgroupfs.h" 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | static char * 41 | make_cgroup_path (const char *path, const char *id) 42 | { 43 | const char *cgroup_path = path; 44 | char *ret; 45 | 46 | if (cgroup_path == NULL) 47 | xasprintf (&ret, "/%s", id); 48 | else if (cgroup_path[0] == '/') 49 | ret = xstrdup (cgroup_path); 50 | else 51 | xasprintf (&ret, "/%s", cgroup_path); 52 | 53 | return ret; 54 | } 55 | 56 | static int 57 | libcrun_precreate_cgroup_cgroupfs (struct libcrun_cgroup_args *args, int *dirfd, libcrun_error_t *err) 58 | { 59 | cleanup_free char *sub_path = make_cgroup_path (args->cgroup_path, args->id); 60 | cleanup_free char *cgroup_path = NULL; 61 | int ret; 62 | 63 | /* No need to check the mode since this feature is supported only on cgroup v2, and 64 | libcrun_cgroup_preenter already performs this check. */ 65 | 66 | *dirfd = -1; 67 | 68 | ret = append_paths (&cgroup_path, err, CGROUP_ROOT, sub_path, NULL); 69 | if (UNLIKELY (ret < 0)) 70 | return ret; 71 | 72 | ret = crun_ensure_directory (cgroup_path, 0755, true, err); 73 | if (UNLIKELY (ret < 0)) 74 | { 75 | libcrun_error_release (err); 76 | return 0; 77 | } 78 | 79 | ret = enable_controllers (sub_path, err); 80 | if (UNLIKELY (ret < 0)) 81 | return ret; 82 | 83 | *dirfd = open (cgroup_path, O_CLOEXEC | O_NOFOLLOW | O_DIRECTORY | O_RDONLY); 84 | if (UNLIKELY (*dirfd < 0)) 85 | return crun_make_error (err, errno, "open `%s`", cgroup_path); 86 | 87 | return 0; 88 | } 89 | 90 | static int 91 | libcrun_cgroup_enter_cgroupfs (struct libcrun_cgroup_args *args, struct libcrun_cgroup_status *out, libcrun_error_t *err) 92 | { 93 | pid_t pid = args->pid; 94 | int cgroup_mode; 95 | 96 | /* The cgroup was already joined, nothing more left to do. */ 97 | if (args->joined) 98 | return 0; 99 | 100 | cgroup_mode = libcrun_get_cgroup_mode (err); 101 | if (UNLIKELY (cgroup_mode < 0)) 102 | return cgroup_mode; 103 | 104 | out->path = make_cgroup_path (args->cgroup_path, args->id); 105 | 106 | if (cgroup_mode == CGROUP_MODE_UNIFIED) 107 | { 108 | int ret; 109 | 110 | ret = enable_controllers (out->path, err); 111 | if (UNLIKELY (ret < 0)) 112 | return ret; 113 | } 114 | 115 | return enter_cgroup (cgroup_mode, pid, 0, out->path, true, err); 116 | } 117 | 118 | static int 119 | libcrun_destroy_cgroup_cgroupfs (struct libcrun_cgroup_status *cgroup_status, 120 | libcrun_error_t *err) 121 | { 122 | int mode; 123 | int ret; 124 | 125 | mode = libcrun_get_cgroup_mode (err); 126 | if (UNLIKELY (mode < 0)) 127 | return mode; 128 | 129 | ret = cgroup_killall_path (cgroup_status->path, SIGKILL, err); 130 | if (UNLIKELY (ret < 0)) 131 | crun_error_release (err); 132 | 133 | return destroy_cgroup_path (cgroup_status->path, mode, err); 134 | } 135 | 136 | struct libcrun_cgroup_manager cgroup_manager_cgroupfs = { 137 | .precreate_cgroup = libcrun_precreate_cgroup_cgroupfs, 138 | .create_cgroup = libcrun_cgroup_enter_cgroupfs, 139 | .destroy_cgroup = libcrun_destroy_cgroup_cgroupfs, 140 | }; 141 | -------------------------------------------------------------------------------- /src/libcrun/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | #ifndef ERROR_H 19 | #define ERROR_H 20 | #include 21 | #ifdef HAVE_ERROR_H 22 | # include 23 | #else 24 | # define error(status, errno, fmt, ...) \ 25 | do \ 26 | { \ 27 | if (errno == 0) \ 28 | fprintf (stderr, "crun: " fmt "\n", ##__VA_ARGS__); \ 29 | else \ 30 | { \ 31 | fprintf (stderr, "crun: " fmt, ##__VA_ARGS__); \ 32 | fprintf (stderr, ": %s\n", strerror (errno)); \ 33 | } \ 34 | if (status) \ 35 | exit (status); \ 36 | } while (0) 37 | #endif 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | 44 | struct libcrun_error_s 45 | { 46 | int status; 47 | char *msg; 48 | }; 49 | typedef struct libcrun_error_s *libcrun_error_t; 50 | 51 | #define OOM() \ 52 | do \ 53 | { \ 54 | fprintf (stderr, "out of memory"); \ 55 | _exit (EXIT_FAILURE); \ 56 | } while (0) 57 | 58 | typedef void (*crun_output_handler) (int errno_, const char *msg, bool warning, void *arg); 59 | 60 | void crun_set_output_handler (crun_output_handler handler, void *arg, bool log_to_stderr); 61 | 62 | void log_write_to_journald (int errno_, const char *msg, bool warning, void *arg); 63 | 64 | void log_write_to_syslog (int errno_, const char *msg, bool warning, void *arg); 65 | 66 | void log_write_to_stream (int errno_, const char *msg, bool warning, void *arg); 67 | 68 | void log_write_to_stderr (int errno_, const char *msg, bool warning, void *arg); 69 | 70 | int crun_make_error (libcrun_error_t *err, int status, const char *msg, ...) __attribute__ ((format (printf, 3, 4))); 71 | 72 | int crun_error_wrap (libcrun_error_t *err, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 73 | 74 | int crun_error_get_errno (libcrun_error_t *err); 75 | 76 | int crun_error_release (libcrun_error_t *err); 77 | 78 | void crun_error_write_warning_and_release (FILE *out, libcrun_error_t **err); 79 | 80 | LIBCRUN_PUBLIC void libcrun_warning (const char *msg, ...) __attribute__ ((format (printf, 1, 2))); 81 | 82 | LIBCRUN_PUBLIC void libcrun_error (int errno_, const char *msg, ...) __attribute__ ((format (printf, 2, 3))); 83 | 84 | LIBCRUN_PUBLIC int libcrun_make_error (libcrun_error_t *err, int status, const char *msg, ...) __attribute__ ((format (printf, 3, 4))); 85 | 86 | LIBCRUN_PUBLIC void libcrun_error_write_warning_and_release (FILE *out, libcrun_error_t **err); 87 | 88 | LIBCRUN_PUBLIC void libcrun_fail_with_error (int errno_, const char *msg, ...) __attribute__ ((noreturn)) __attribute__ ((format (printf, 2, 3))); 89 | 90 | LIBCRUN_PUBLIC int libcrun_set_log_format (const char *format, libcrun_error_t *err); 91 | 92 | LIBCRUN_PUBLIC int libcrun_init_logging (crun_output_handler *output_handler, void **output_handler_arg, const char *id, 93 | const char *log, libcrun_error_t *err); 94 | 95 | LIBCRUN_PUBLIC int libcrun_error_release (libcrun_error_t *err); 96 | 97 | int yajl_error_to_crun_error (int yajl_status, libcrun_error_t *err); 98 | 99 | enum 100 | { 101 | LIBCRUN_VERBOSITY_ERROR, 102 | LIBCRUN_VERBOSITY_WARNING, 103 | }; 104 | 105 | LIBCRUN_PUBLIC void libcrun_set_verbosity (int verbosity); 106 | LIBCRUN_PUBLIC int libcrun_get_verbosity (); 107 | 108 | #endif 109 | -------------------------------------------------------------------------------- /src/libcrun/terminal.c: -------------------------------------------------------------------------------- 1 | /* 2 | * crun - OCI runtime written in C 3 | * 4 | * Copyright (C) 2017, 2018, 2019 Giuseppe Scrivano 5 | * crun is free software; you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation; either version 2.1 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * crun is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with crun. If not, see . 17 | */ 18 | 19 | #define _XOPEN_SOURCE 20 | 21 | #define _GNU_SOURCE 22 | 23 | #include 24 | #include "linux.h" 25 | #include "utils.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | struct terminal_status_s 34 | { 35 | int fd; 36 | struct termios termios; 37 | }; 38 | 39 | int 40 | libcrun_new_terminal (char **pty, libcrun_error_t *err) 41 | { 42 | char buf[64]; 43 | int ret; 44 | cleanup_close int fd = open ("/dev/ptmx", O_RDWR | O_NOCTTY | O_CLOEXEC); 45 | if (UNLIKELY (fd < 0)) 46 | return crun_make_error (err, errno, "open /dev/ptmx"); 47 | 48 | ret = ptsname_r (fd, buf, sizeof (buf)); 49 | if (UNLIKELY (ret < 0)) 50 | return crun_make_error (err, errno, "ptsname"); 51 | 52 | ret = unlockpt (fd); 53 | if (UNLIKELY (ret < 0)) 54 | return crun_make_error (err, errno, "unlockpt"); 55 | 56 | *pty = xstrdup (buf); 57 | 58 | ret = fd; 59 | fd = -1; 60 | 61 | return ret; 62 | } 63 | 64 | static int 65 | set_raw (int fd, libcrun_error_t *err) 66 | { 67 | int ret; 68 | struct termios termios; 69 | 70 | ret = tcgetattr (fd, &termios); 71 | if (UNLIKELY (ret < 0)) 72 | return crun_make_error (err, errno, "tcgetattr"); 73 | 74 | cfmakeraw (&termios); 75 | 76 | termios.c_iflag &= OPOST; 77 | termios.c_oflag &= OPOST; 78 | 79 | ret = tcsetattr (fd, TCSANOW, &termios); 80 | if (UNLIKELY (ret < 0)) 81 | return crun_make_error (err, errno, "tcsetattr"); 82 | 83 | return 0; 84 | } 85 | 86 | int 87 | libcrun_set_stdio (char *pty, libcrun_error_t *err) 88 | { 89 | int ret, i; 90 | cleanup_close int fd = open (pty, O_RDWR); 91 | 92 | if (UNLIKELY (fd < 0)) 93 | return crun_make_error (err, errno, "open %s", pty); 94 | 95 | for (i = 0; i < 3; i++) 96 | { 97 | ret = dup3 (fd, i, 0); 98 | if (UNLIKELY (ret < 0)) 99 | return crun_make_error (err, errno, "dup terminal"); 100 | } 101 | 102 | ret = ioctl (0, TIOCSCTTY, 0); 103 | if (UNLIKELY (ret < 0)) 104 | return crun_make_error (err, errno, "ioctl TIOCSCTTY"); 105 | 106 | return 0; 107 | } 108 | 109 | int 110 | libcrun_setup_terminal_ptmx (int fd, void **current_status, libcrun_error_t *err) 111 | { 112 | int ret; 113 | struct termios termios; 114 | 115 | ret = tcgetattr (fd, &termios); 116 | if (UNLIKELY (ret < 0)) 117 | return crun_make_error (err, errno, "tcgetattr"); 118 | 119 | if (current_status) 120 | { 121 | struct terminal_status_s *s = xmalloc (sizeof (*s)); 122 | s->fd = 0; 123 | memcpy (&(s->termios), &termios, sizeof (termios)); 124 | *current_status = s; 125 | } 126 | 127 | ret = tcsetattr (fd, TCSANOW, &termios); 128 | if (UNLIKELY (ret < 0)) 129 | return crun_make_error (err, errno, "tcsetattr"); 130 | 131 | return set_raw (0, err); 132 | } 133 | 134 | void 135 | cleanup_terminalp (void *p) 136 | { 137 | struct terminal_status_s **s = (struct terminal_status_s **) p; 138 | if (*s) 139 | { 140 | tcsetattr ((*s)->fd, TCSANOW, &(*s)->termios); 141 | free (*s); 142 | } 143 | } 144 | 145 | int 146 | libcrun_terminal_setup_size (int fd, unsigned short rows, unsigned short cols, libcrun_error_t *err) 147 | { 148 | struct winsize ws = { .ws_row = rows, .ws_col = cols }; 149 | int ret; 150 | 151 | if (ws.ws_row == 0 || ws.ws_col == 0) 152 | { 153 | ret = ioctl (0, TIOCGWINSZ, &ws); 154 | if (UNLIKELY (ret < 0)) 155 | { 156 | if (errno == ENOTTY) 157 | return 0; 158 | return crun_make_error (err, errno, "ioctl TIOCGWINSZ"); 159 | } 160 | } 161 | 162 | ret = ioctl (fd, TIOCSWINSZ, &ws); 163 | if (UNLIKELY (ret < 0)) 164 | return crun_make_error (err, errno, "ioctl TIOCSWINSZ"); 165 | return 0; 166 | } 167 | --------------------------------------------------------------------------------