This commit is contained in:
tangweicheng 2020-10-31 17:24:35 +08:00
parent 57dc106f2a
commit ac80c891ed
22 changed files with 2277 additions and 163 deletions

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

8
.idea/modules.xml Normal file
View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/rustime.iml" filepath="$PROJECT_DIR$/.idea/rustime.iml" />
</modules>
</component>
</project>

13
.idea/rustime.iml Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/cmd/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

63
.idea/workspace.xml Normal file
View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CargoProjects">
<cargoProject FILE="$PROJECT_DIR$/Cargo.toml" />
</component>
<component name="ChangeListManager">
<list default="true" id="0c97c045-ef1e-4c00-a325-9a023e092dd8" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/src/spec/spec.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/spec/spec.rs" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="CodeStyleSettingsInfer">
<option name="done" value="true" />
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="MacroExpansionManager">
<option name="directoryName" value="gmltrzoy" />
</component>
<component name="ProjectCodeStyleSettingsMigration">
<option name="version" value="1" />
</component>
<component name="ProjectId" id="1jRrX8dN97Qg42QBfnPcRVCPZQl" />
<component name="ProjectViewState">
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="aspect.path.notification.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/../rust-runc" />
<property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" />
<property name="settings.editor.selected.configurable" value="MavenSettings" />
</component>
<component name="RustProjectSettings">
<option name="toolchainHomeDirectory" value="$USER_HOME$/.cargo/bin" />
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="0c97c045-ef1e-4c00-a325-9a023e092dd8" name="Default Changelist" comment="" />
<created>1603777782342</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1603777782342</updated>
<workItem from="1603777783511" duration="16662000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="WindowStateProjectService">
<state x="709" y="294" key="FileChooserDialogImpl" timestamp="1603869939062">
<screen x="0" y="0" width="1858" height="1080" />
</state>
<state x="709" y="294" key="FileChooserDialogImpl/0.0.1858.1080@0.0.1858.1080" timestamp="1603869939062" />
</component>
</project>

392
Cargo.lock generated
View File

@ -4,402 +4,482 @@
name = "ansi_term"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi",
]
[[package]]
name = "atty"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
dependencies = [
"hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"hermit-abi",
"libc",
"winapi",
]
[[package]]
name = "bitflags"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "caps"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "638fc723ed85617d1fbff518d34e6f6481b88b9b661add18cb2d8f20ff29da41"
dependencies = [
"errno",
"error-chain 0.11.0",
"libc",
]
[[package]]
name = "cc"
version = "1.0.58"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "clap"
version = "2.33.1"
version = "2.33.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002"
dependencies = [
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ansi_term",
"atty",
"bitflags",
"strsim",
"textwrap",
"unicode-width",
"vec_map",
]
[[package]]
name = "cmd"
version = "0.1.0"
dependencies = [
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prctl 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"runtime 0.1.0",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syslog 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
"libc",
"log",
"nix 0.17.0",
"prctl",
"runtime",
"serde",
"serde_derive",
"serde_json",
"structopt",
"syslog",
"thiserror",
]
[[package]]
name = "errno"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe"
dependencies = [
"errno-dragonfly",
"libc",
"winapi",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "14ca354e36190500e1e1fb267c647932382b54053c50b14970856c0b00a35067"
dependencies = [
"gcc",
"libc",
]
[[package]]
name = "error-chain"
version = "0.12.2"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check",
]
[[package]]
name = "gcc"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
[[package]]
name = "heck"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
dependencies = [
"unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation",
]
[[package]]
name = "hermit-abi"
version = "0.1.15"
version = "0.1.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8"
dependencies = [
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"libc",
]
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.73"
version = "0.2.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if",
]
[[package]]
name = "nix"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "becb657d662f1cd2ef38c7ad480ec6b8cf9e96b27adb543e594f9cf0f2e6065c"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
"void",
]
[[package]]
name = "nix"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
dependencies = [
"bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)",
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"bitflags",
"cc",
"cfg-if",
"libc",
"void",
]
[[package]]
name = "nix"
version = "0.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85db2feff6bf70ebc3a4793191517d5f0331100a2f10f9bf93b5e5214f32b7b7"
dependencies = [
"bitflags",
"cc",
"cfg-if",
"libc",
]
[[package]]
name = "prctl"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52"
dependencies = [
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libc",
"nix 0.19.0",
]
[[package]]
name = "proc-macro-error"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.19"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid",
]
[[package]]
name = "quote"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
]
[[package]]
name = "runtime"
version = "0.1.0"
dependencies = [
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)",
"prctl 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)",
"syslog 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
"caps",
"lazy_static",
"libc",
"log",
"nix 0.11.1",
"prctl",
"scopeguard",
"seccomp-sys",
"serde",
"serde_derive",
"serde_json",
"structopt",
"syslog",
"thiserror",
]
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "scopeguard"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
[[package]]
name = "seccomp-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5bcf74ba0708aeaf8d702e4f84f7458ae1de42d80e2c20963a395b6038e6be6"
dependencies = [
"libc",
]
[[package]]
name = "serde"
version = "1.0.114"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a"
[[package]]
name = "serde_derive"
version = "1.0.114"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.56"
version = "1.0.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95"
dependencies = [
"itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)",
"itoa",
"ryu",
"serde",
]
[[package]]
name = "strsim"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "structopt"
version = "0.3.15"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8"
dependencies = [
"clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"clap",
"lazy_static",
"structopt-derive",
]
[[package]]
name = "structopt-derive"
version = "0.4.8"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8"
dependencies = [
"heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"heck",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.34"
version = "1.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "syn-mid"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "syslog"
version = "5.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a5d8ef1b679c07976f3ee336a436453760c470f54b5e7237556728b8589515d"
dependencies = [
"error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.12.4",
"libc",
"log",
"time",
]
[[package]]
name = "textwrap"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
dependencies = [
"unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-width",
]
[[package]]
name = "thiserror"
version = "1.0.20"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
dependencies = [
"thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)",
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.20"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
dependencies = [
"proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
"quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
"syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.1.43"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
dependencies = [
"libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"libc",
"wasi",
"winapi",
]
[[package]]
name = "unicode-segmentation"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
[[package]]
name = "unicode-width"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
[[package]]
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "vec_map"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b"
"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
"checksum cc 1.0.58 (registry+https://github.com/rust-lang/crates.io-index)" = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum clap 2.33.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bdfa80d47f954d53a35a64987ca1422f495b8d6483c0fe9f7117b36c2a792129"
"checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd"
"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205"
"checksum hermit-abi 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "3deed196b6e7f9e44a2ae8d94225d80302d81208b1bb673fd21fe634645c85a9"
"checksum itoa 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.73 (registry+https://github.com/rust-lang/crates.io-index)" = "bd7d4bd64732af4bf3a67f367c27df8520ad7e230c5817b8ff485864d80242b9"
"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
"checksum nix 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50e4785f2c3b7589a0d0c1dd60285e1188adac4006e8abd6dd578e1567027363"
"checksum prctl 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "059a34f111a9dee2ce1ac2826a68b24601c4298cfeb1a587c3cb493d5ab46f52"
"checksum proc-macro-error 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fc175e9777c3116627248584e8f8b3e2987405cabe1c0adf7d1dd28f09dc7880"
"checksum proc-macro-error-attr 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3cc9795ca17eb581285ec44936da7fc2335a3f34f2ddd13118b6f4d515435c50"
"checksum proc-macro2 1.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
"checksum quote 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37"
"checksum ryu 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
"checksum serde 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "5317f7588f0a5078ee60ef675ef96735a1442132dc645eb1d12c018620ed8cd3"
"checksum serde_derive 1.0.114 (registry+https://github.com/rust-lang/crates.io-index)" = "2a0be94b04690fbaed37cddffc5c134bf537c8e3329d53e982fe04c374978f8e"
"checksum serde_json 1.0.56 (registry+https://github.com/rust-lang/crates.io-index)" = "3433e879a558dde8b5e8feb2a04899cf34fdde1fafb894687e52105fc1162ac3"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
"checksum structopt 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "de2f5e239ee807089b62adce73e48c625e0ed80df02c7ab3f068f5db5281065c"
"checksum structopt-derive 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "510413f9de616762a4fbeab62509bf15c729603b72d7cd71280fbca431b1c118"
"checksum syn 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "936cae2873c940d92e697597c5eee105fb570cd5689c695806f672883653349b"
"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a"
"checksum syslog 5.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9a5d8ef1b679c07976f3ee336a436453760c470f54b5e7237556728b8589515d"
"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
"checksum thiserror 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "7dfdd070ccd8ccb78f4ad66bf1982dc37f620ef696c6b5028fe2ed83dd3d0d08"
"checksum thiserror-impl 1.0.20 (registry+https://github.com/rust-lang/crates.io-index)" = "bd80fc12f73063ac132ac92aceea36734f04a1d93c1240c6944e23a3b8841793"
"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0"
"checksum unicode-width 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3"
"checksum unicode-xid 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
"checksum vec_map 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
"checksum version_check 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View File

@ -18,9 +18,13 @@ serde_derive = "1.0"
log = "0.4"
syslog = "5.0"
structopt = "0.3.15"
nix = "0.17.0"
nix = "0.11.0"
libc = "0.2"
prctl = "1.0.0"
lazy_static = "1.4.0"
scopeguard = "^0.3.3"
caps = "0.2.0"
seccomp-sys = "0.1.3"
[workspace]
members = [

View File

@ -1,3 +1,2 @@
# 说明
目前容器运行时以OCI runtime spec为标准runc是该标准下应用最为广泛的运行时之一。runc基于golang实现由于golang自带语言运行时开销为了进一步减少容器运行时的额外开销提升容器启动性能本仓库基于rust编程语言实现OCI运行时命令行接口兼容OCI规范。
# rustime
308a

180
config.json Normal file
View File

@ -0,0 +1,180 @@
{
"ociVersion": "1.0.1-dev",
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": "/",
"capabilities": {
"bounding": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"effective": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"inheritable": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"permitted": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"ambient": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
]
},
"rlimits": [
{
"type": "RLIMIT_NOFILE",
"hard": 1024,
"soft": 1024
}
],
"noNewPrivileges": true
},
"root": {
"path": "rootfs",
"readonly": true
},
"hostname": "runc",
"mounts": [
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
{
"destination": "/dev",
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"strictatime",
"mode=755",
"size=65536k"
]
},
{
"destination": "/dev/pts",
"type": "devpts",
"source": "devpts",
"options": [
"nosuid",
"noexec",
"newinstance",
"ptmxmode=0666",
"mode=0620",
"gid=5"
]
},
{
"destination": "/dev/shm",
"type": "tmpfs",
"source": "shm",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
{
"destination": "/dev/mqueue",
"type": "mqueue",
"source": "mqueue",
"options": [
"nosuid",
"noexec",
"nodev"
]
},
{
"destination": "/sys",
"type": "sysfs",
"source": "sysfs",
"options": [
"nosuid",
"noexec",
"nodev",
"ro"
]
},
{
"destination": "/sys/fs/cgroup",
"type": "cgroup",
"source": "cgroup",
"options": [
"nosuid",
"noexec",
"nodev",
"relatime",
"ro"
]
}
],
"linux": {
"resources": {
"devices": [
{
"allow": false,
"access": "rwm"
}
]
},
"namespaces": [
{
"type": "pid"
},
{
"type": "network"
},
{
"type": "ipc"
},
{
"type": "uts"
},
{
"type": "mount"
}
],
"maskedPaths": [
"/proc/acpi",
"/proc/asound",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/sys/firmware",
"/proc/scsi"
],
"readonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
}
}

20
config.json.bak Normal file
View File

@ -0,0 +1,20 @@
{
"ociVersion": "1.0.1",
"id": "oci-container1",
"status": "running",
"pid": 4422,
"bundlePath": "/containers/redis",
"annotations": {
"myKey": "myValue"
},
"version":"",
"platform":{},
"process":{
"user":{},
"args":[]
},
"root":{
"path":"",
"readonly":false
}
}

180
config.json.bak2 Normal file
View File

@ -0,0 +1,180 @@
{
"ociVersion": "1.0.2-dev",
"process": {
"terminal": true,
"user": {
"uid": 0,
"gid": 0
},
"args": [
"sh"
],
"env": [
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"TERM=xterm"
],
"cwd": "/",
"capabilities": {
"bounding": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"effective": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"inheritable": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"permitted": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
],
"ambient": [
"CAP_AUDIT_WRITE",
"CAP_KILL",
"CAP_NET_BIND_SERVICE"
]
},
"rlimits": [
{
"type": "RLIMIT_NOFILE",
"hard": 1024,
"soft": 1024
}
],
"noNewPrivileges": true
},
"root": {
"path": "rootfs",
"readonly": true
},
"hostname": "runc",
"mounts": [
{
"destination": "/proc",
"type": "proc",
"source": "proc"
},
{
"destination": "/dev",
"type": "tmpfs",
"source": "tmpfs",
"options": [
"nosuid",
"strictatime",
"mode=755",
"size=65536k"
]
},
{
"destination": "/dev/pts",
"type": "devpts",
"source": "devpts",
"options": [
"nosuid",
"noexec",
"newinstance",
"ptmxmode=0666",
"mode=0620",
"gid=5"
]
},
{
"destination": "/dev/shm",
"type": "tmpfs",
"source": "shm",
"options": [
"nosuid",
"noexec",
"nodev",
"mode=1777",
"size=65536k"
]
},
{
"destination": "/dev/mqueue",
"type": "mqueue",
"source": "mqueue",
"options": [
"nosuid",
"noexec",
"nodev"
]
},
{
"destination": "/sys",
"type": "sysfs",
"source": "sysfs",
"options": [
"nosuid",
"noexec",
"nodev",
"ro"
]
},
{
"destination": "/sys/fs/cgroup",
"type": "cgroup",
"source": "cgroup",
"options": [
"nosuid",
"noexec",
"nodev",
"relatime",
"ro"
]
}
],
"linux": {
"resources": {
"devices": [
{
"allow": false,
"access": "rwm"
}
]
},
"namespaces": [
{
"type": "pid"
},
{
"type": "network"
},
{
"type": "ipc"
},
{
"type": "uts"
},
{
"type": "mount"
}
],
"maskedPaths": [
"/proc/acpi",
"/proc/asound",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/sys/firmware",
"/proc/scsi"
],
"readonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
}
}

View File

@ -3,6 +3,20 @@ use structopt::StructOpt;
use crate::errors::Error;
use crate::spec;
use std::fs::File;
use std::fs;
use nix::unistd::Pid;
use nix::unistd::chdir;
use nix::sys::signal::{SaFlags, Signal};
use nix::sys::signal::kill;
use crate::namespace;
use std::io::Read;
const INIT_PID: &'static str = "init.pid";
const PROCESS_PID: &'static str = "process.pid";
// structopt可以方便的将命令行参数解析为一个struct。
#[derive(StructOpt, Debug)]
#[structopt(name = "rustime", about = "container runtime by rust")]
pub struct Opt {
@ -37,6 +51,12 @@ impl Opt {
}
}
pub struct State {
pub id: String,
pub status: String,
pub pid: String,
}
#[derive(StructOpt, Debug)]
#[structopt(about = "container runtime by rust")]
pub enum Commands {
@ -64,9 +84,12 @@ pub enum Commands {
#[derive(StructOpt, Debug)]
pub struct CreateArgs {
/// bundle path
#[structopt(short, long, default_value = ".")]
#[structopt(short("b"), long, default_value = ".")]
pub bundle: String,
#[structopt(short("d"), long, default_value = "/run/rustime")]
pub dir:String,
/// file to write pid
#[structopt(long, default_value = "")]
pub pid_file: String,
@ -119,6 +142,8 @@ pub fn handle(opt: &Opt) -> Result<(), Error> {
pub fn do_create(_opt: &Opt, args: &CreateArgs) -> Result<(), Error> {
let fcfg = [&args.bundle, "config.json"].join("/");
let _spec = spec::load_spec(&fcfg)?;
namespace::init_spec(&_spec, &args);
Ok(())
}
@ -127,14 +152,95 @@ pub fn do_init(_opt: &Opt, _args: &InitArgs) -> Result<(), Error> {
}
pub fn do_start(_opt: &Opt, _args: &StartArgs) -> Result<(), Error> {
println!("");
Ok(())
}
fn do_state(_opt: &Opt, _args: &StateArgs) -> Result<(), Error> {
let sdir= "/run/rustime";
let st = state_dir(&_args.id, sdir)?;
Ok(())
}
fn do_delete(_opt: &Opt, _args: &DeleteArgs) -> Result<(), Error> {
println!("{:?}", _args);
let mut result = &_args.id;
if let Ok(process_pid) = result.parse::<i32>() {
let process_pid = Pid::from_raw(process_pid);
println!("{}",process_pid);
if sign_process(process_pid,None).is_ok(){
if let Err(e)=sign_process(process_pid, Signal::SIGKILL){
println!("can not sigkill");
}else{
println!("kill process_pid");
}
}else{
println!("do nothing");
}
}else{
println!("processpid no in");
}
Ok(())
}
pub fn sign_process<T: Into<Option<Signal>>> (
pid:Pid,
signal:T,
)-> Result<(), Error> {
kill(pid, signal)?;
Ok(())
}
fn state_dir(id: &str, state_dir: &str) -> Result<(self::State),Error> {
let id_dir=format!("{}/{}",state_dir,id);
if let Err(e)=chdir(&*id_dir){
println!("not exist");
}
let mut status = "creating";
/*if let Ok(process_pid) = id.parse::<i32>() {
let process_pid=Pid::from_raw(process_pid);
status = "running";
if sign_process(process_pid,None).is_err(){
status = "stopped";
}
}else{
println!("");
} */
if let Ok(mut f) = std::fs::File::open(PROCESS_PID) {
status = "running";
let mut result = String::new();
f.read_to_string(&mut result)?;
if let Ok(process_pid_now) = result.parse::<i32>() {
if let Err(e)=sign_process(Pid::from_raw(process_pid_now), None) {
status = "stopped";
}else{
}
}
}
//let process_pid_temp = id;
//let process_pid_temp=Pid::from_raw(process_pid_temp);
let process_pid_temp=get_initpid();
let st = state(id, status, &process_pid_temp);
Ok(st)
}
fn state(id: &str, status: &str, pid: &str) -> self::State {
self::State {
id: id.to_string(),
status: status.to_string(),
pid: pid.to_string(),
}
}
fn get_initpid()-> std::string::String{
// let result = fs::read_to_string(INIT_PID);
// let resultt=String::from("-1");
if let Ok(mut f) = std::fs::File::open(INIT_PID) {
let mut result = String::new();
f.read_to_string(&mut result);
return result
}else{
let resultt=String::from("-1");
return resultt ;
}
}

View File

@ -2,3 +2,4 @@ pub mod commands;
pub use self::commands::handle;
pub use self::commands::Opt;
pub use self::commands::CreateArgs;

37
src/erroe_chain.rs Normal file
View File

@ -0,0 +1,37 @@
error_chain! {
types {
Error, ErrorKind, ResultExt, Result;
}
foreign_links {
Nix(::nix::Error);
Io(::std::io::Error);
Ffi(::std::ffi::NulError);
Caps(::caps::errors::Error);
}
errors {
InvalidSpec(t: String) {
description("invalid spec")
display("invalid spec: '{}'", t)
}
SeccompError(t: String) {
description("seccomp error")
display("seccomp error: '{}'", t)
}
Timeout(timeout: i32) {
description("timeout")
display("timeout after {} milliseconds", timeout)
}
PipeClosed(t: String) {
description("pipe closed")
display("pipe closed: '{}'", t)
}
InvalidValue(t: String) {
description("invalid value")
display("invalid value: '{}'", t)
}
InvalidHook(t: String) {
description("invalid hook")
display("invalid hook: '{}'", t)
}
}
}

View File

@ -1,4 +1,5 @@
extern crate nix;
extern crate caps;
use log;
use std;

View File

@ -1,7 +1,15 @@
#[macro_use]
extern crate serde_derive;
extern crate nix;
extern crate caps;
extern crate libc;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate scopeguard;
pub mod commands;
pub mod errors;
pub mod logger;
pub mod spec;
pub mod namespace;

4
src/namespace/mod.rs Normal file
View File

@ -0,0 +1,4 @@
pub mod namespace;
pub mod utilities;
pub mod mounts;
pub use self::namespace::init_spec;

687
src/namespace/mounts.rs Normal file
View File

@ -0,0 +1,687 @@
use crate::errors::Error;
use nix::errno::Errno;
use nix::fcntl::{open, OFlag};
use nix::mount::MsFlags;
use nix::mount::*;
use nix::sys::stat::{mknod, umask};
use nix::sys::stat::{Mode, SFlag};
use nix::unistd::{chdir, chown, close, getcwd, pivot_root};
use nix::unistd::{Gid, Uid};
use nix::NixPath;
use std::fs::{create_dir_all, remove_dir, File};
use crate::spec::{LinuxDevice, LinuxDeviceType, Mount, Spec};
use std::collections::HashMap;
use std::fs::OpenOptions;
use std::fs::{canonicalize};
use std::os::unix::fs::symlink;
use std::path::{Path, PathBuf};
use std::io::{BufRead, BufReader};
use crate::namespace::utilities::{setfilecon, setexeccon};
use std::os::unix::io::RawFd;
lazy_static! {
pub static ref PATHS: HashMap<String, String> = {
let mut result = HashMap::new();
let f = match File::open("/proc/self/cgroup") {
Ok(f) => f,
Err(e) => {
return result;
}
};
for line in BufReader::new(f).lines() {
let l = match line {
Ok(l) => l,
Err(e) => {
return result;
}
};
let fields: Vec<&str> = l.split(':').collect();
if fields.len() != 3 {
continue;
}
result.insert(fields[1].to_string(), fields[2].to_string());
}
result
};
}
lazy_static! {
pub static ref MOUNTS: HashMap<String, String> = {
let mut result = HashMap::new();
let f = match File::open("/proc/self/mountinfo") {
Ok(f) => f,
Err(e) => {
return result;
}
};
for line in BufReader::new(f).lines() {
let l = match line {
Ok(l) => l,
Err(e) => {
return result;
}
};
if let Some(sep) = l.find(" - ") {
if l.len() < sep + 10 {
continue;
}
let key = &l[sep + 3..sep + 10];
if key != "cgroup " && key != "cgroup2" {
continue;
}
let pre: Vec<&str> = l[..sep].split(' ').collect();
if pre.len() != 7 {
continue;
}
let post: Vec<&str> = l[sep + 3..].split(' ').collect();
if post.len() != 3 {
continue;
}
let mut offset = post[2].len();
while let Some(o) = post[2][..offset].rfind(',') {
let name = &post[2][o + 1..];
if PATHS.contains_key(name) {
result.insert(name.to_string(), pre[4].to_string());
break;
}
offset = o;
}
}
}
result
};
}
lazy_static! {
static ref DEFAULT_DEVICES: Vec<LinuxDevice> = {
let mut v = Vec::new();
v.push(LinuxDevice {
path: "/dev/null".to_string(),
typ: LinuxDeviceType::c,
major: 1,
minor: 3,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v.push(LinuxDevice {
path: "/dev/zero".to_string(),
typ: LinuxDeviceType::c,
major: 1,
minor: 5,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v.push(LinuxDevice {
path: "/dev/full".to_string(),
typ: LinuxDeviceType::c,
major: 1,
minor: 7,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v.push(LinuxDevice {
path: "/dev/tty".to_string(),
typ: LinuxDeviceType::c,
major: 5,
minor: 0,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v.push(LinuxDevice {
path: "/dev/urandom".to_string(),
typ: LinuxDeviceType::c,
major: 1,
minor: 9,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v.push(LinuxDevice {
path: "/dev/random".to_string(),
typ: LinuxDeviceType::c,
major: 1,
minor: 8,
file_mode: Some(0o066),
uid: None,
gid: None,
});
v
};
}
pub fn init_rootfs(
spec: &Spec,
rootfs: &str,
cpath: &str,
bind_devices: bool,
) -> Result<(), Error> {
// set namespace propagation
// 设置命名空间传播
let mut flags = MsFlags::MS_REC;
match spec.linux {
Some(ref linux) => match linux.rootfs_propagation.as_ref() {
"shared" => {
flags |= MsFlags::MS_SHARED;
Ok(())
}
"private" => {
flags |= MsFlags::MS_PRIVATE;
Ok(())
}
"slave" | "" => {
flags |= MsFlags::MS_SLAVE;
Ok(())
}
_ => {
let msg = format!(
"invalid propogation value: {}",
linux.rootfs_propagation
);
Err(Error::from(Error::Unsupported(msg)))
}
},
None => {
flags |= MsFlags::MS_SLAVE;
Ok(())
}
}?;
let linux = spec.linux.as_ref().unwrap();
mount(None::<&str>, "/", None::<&str>, flags, None::<&str>)?;
// mount root dir
// 挂载根目录
mount(
Some(rootfs),
rootfs,
None::<&str>,
MsFlags::MS_BIND | MsFlags::MS_REC,
None::<&str>,
)?;
for m in &spec.mounts {
// 注意:严格地说这比runc更宽松只要结果路径保留在rootfs中就可以。没有好的理由允许这样做所以我们只是禁止它
if !m.destination.starts_with('/') || m.destination.contains("..") {
let msg = format!("invalid mount destination: {}", m.destination);
return Err(Error::Unsupported(msg));
}
let (flags, data) = parse_mount(m);
if m.typ == "cgroup" {
mount_cgroups(m, rootfs, flags, &data, &linux.mount_label, cpath)?;
} else if m.destination == "/dev" {
mount_from(
m,
rootfs,
flags & !MsFlags::MS_RDONLY,
&data,
&linux.mount_label,
)?;
} else {
mount_from(m, rootfs, flags, &data, &linux.mount_label)?;
}
}
// chdir into the rootfs so we can make devices with simpler paths
let olddir = getcwd()?;
chdir(rootfs)?;
default_symlinks()?;
create_devices(&linux.devices, bind_devices)?;
ensure_ptmx()?;
chdir(&olddir)?;
Ok(())
}
pub fn pivot_rootfs<P: ?Sized + NixPath>(path: &P) -> Result<(), Error> {
let oldroot =
open("/", OFlag::O_DIRECTORY | OFlag::O_RDONLY, Mode::empty())?;
defer!(close(oldroot).unwrap());
let newroot =
open(path, OFlag::O_DIRECTORY | OFlag::O_RDONLY, Mode::empty())?;
defer!(close(newroot).unwrap());
pivot_root(path, path)?;
umount2("/", MntFlags::MNT_DETACH)?;
fchdir(newroot);
Ok(())
}
pub fn finish_rootfs(spec: &Spec) -> Result<(), Error> {
if let Some(ref linux) = spec.linux {
for path in &linux.masked_paths {
mask_path(path)?;
}
for path in &linux.readonly_paths {
readonly_path(path)?;
}
}
// remount dev ro if necessary
for m in &spec.mounts {
if m.destination == "/dev" {
let (flags, _) = parse_mount(m);
if flags.contains(MsFlags::MS_RDONLY) {
mount(
Some("/dev"),
"/dev",
None::<&str>,
flags | MsFlags::MS_REMOUNT,
None::<&str>,
)?;
}
}
}
if spec.root.readonly {
let flags = MsFlags::MS_BIND
| MsFlags::MS_RDONLY
| MsFlags::MS_NODEV
| MsFlags::MS_REMOUNT;
mount(Some("/"), "/", None::<&str>, flags, None::<&str>)?;
}
umask(Mode::from_bits_truncate(0o022));
Ok(())
}
#[cfg_attr(rustfmt, rustfmt_skip)]
lazy_static! {
static ref OPTIONS: HashMap<&'static str, (bool, MsFlags)> = {
let mut m = HashMap::new();
m.insert("defaults", (false, MsFlags::empty()));
m.insert("ro", (false, MsFlags::MS_RDONLY));
m.insert("rw", (true, MsFlags::MS_RDONLY));
m.insert("suid", (true, MsFlags::MS_NOSUID));
m.insert("nosuid", (false, MsFlags::MS_NOSUID));
m.insert("dev", (true, MsFlags::MS_NODEV));
m.insert("nodev", (false, MsFlags::MS_NODEV));
m.insert("exec", (true, MsFlags::MS_NOEXEC));
m.insert("noexec", (false, MsFlags::MS_NOEXEC));
m.insert("sync", (false, MsFlags::MS_SYNCHRONOUS));
m.insert("async", (true, MsFlags::MS_SYNCHRONOUS));
m.insert("dirsync", (false, MsFlags::MS_DIRSYNC));
m.insert("remount", (false, MsFlags::MS_REMOUNT));
m.insert("mand", (false, MsFlags::MS_MANDLOCK));
m.insert("nomand", (true, MsFlags::MS_MANDLOCK));
m.insert("atime", (true, MsFlags::MS_NOATIME));
m.insert("noatime", (false, MsFlags::MS_NOATIME));
m.insert("diratime", (true, MsFlags::MS_NODIRATIME));
m.insert("nodiratime", (false, MsFlags::MS_NODIRATIME));
m.insert("bind", (false, MsFlags::MS_BIND));
m.insert("rbind", (false, MsFlags::MS_BIND | MsFlags::MS_REC));
m.insert("unbindable", (false, MsFlags::MS_UNBINDABLE));
m.insert("runbindable", (false, MsFlags::MS_UNBINDABLE | MsFlags::MS_REC));
m.insert("private", (false, MsFlags::MS_PRIVATE));
m.insert("rprivate", (false, MsFlags::MS_PRIVATE | MsFlags::MS_REC));
m.insert("shared", (false, MsFlags::MS_SHARED));
m.insert("rshared", (false, MsFlags::MS_SHARED | MsFlags::MS_REC));
m.insert("slave", (false, MsFlags::MS_SLAVE));
m.insert("rslave", (false, MsFlags::MS_SLAVE | MsFlags::MS_REC));
m.insert("relatime", (false, MsFlags::MS_RELATIME));
m.insert("norelatime", (true, MsFlags::MS_RELATIME));
m.insert("strictatime", (false, MsFlags::MS_STRICTATIME));
m.insert("nostrictatime", (true, MsFlags::MS_STRICTATIME));
m
};
}
pub fn path(key: &str, cgroups_path: &str) -> Option<String> {
let mount = MOUNTS.get(key);
let rel = PATHS.get(key);
if mount.is_none() || rel.is_none() {
None
} else if rel.unwrap() == "/" {
Some(format!{"{}{}", &mount.unwrap(), cgroups_path})
} else {
Some(format!{"{}{}{}", &mount.unwrap(), &rel.unwrap(), cgroups_path})
}
}
fn mount_cgroups(
m: &Mount,
rootfs: &str,
flags: MsFlags,
data: &str,
label: &str,
cpath: &str,
) -> Result<(), Error> {
let cm = Mount {
source: "tmpfs".to_string(),
typ: "tmpfs".to_string(),
destination: m.destination.clone(),
options: Vec::new(),
};
let cflags = MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID | MsFlags::MS_NODEV;
// mount tmpfs for mounts
mount_from(&cm, rootfs, cflags, "", label)?;
for (key, mount_path) in MOUNTS.iter() {
let source = if let Some(s) = path(key, cpath) {
s
} else {
continue;
};
// NOTE: this will bind mount over the same location if two
// cgroups are mounted to directories with the same
// value at the end of the path, for example:
// /path/to/a/cgroup /path/to/b/cgroup
// runc mounts by using the final path component, so
// we do the same thing here.
let base = if let Some(o) = mount_path.rfind('/') {
&mount_path[o + 1..]
} else {
&mount_path[..]
};
let dest = format!{"{}/{}", &m.destination, &base};
let bm = Mount {
source: source,
typ: "bind".to_string(),
destination: dest,
options: Vec::new(),
};
mount_from(
&bm,
rootfs,
flags | MsFlags::MS_BIND | MsFlags::MS_REC,
data,
label,
)?;
for k in key.split(',') {
if k != key {
// try to create a symlink for combined strings
let dest = format!{"{}{}/{}", rootfs, &m.destination, &k};
symlink(key, &dest)?;
}
}
}
// remount readonly if necessary
if flags.contains(MsFlags::MS_RDONLY) {
let dest = format!{"{}{}", rootfs, &m.destination};
mount(
Some(&*dest),
&*dest,
None::<&str>,
cflags | MsFlags::MS_BIND | MsFlags::MS_REMOUNT,
None::<&str>,
)?;
}
Ok(())
}
fn parse_mount(m: &Mount) -> (MsFlags, String) {
let mut flags = MsFlags::empty();
let mut data = Vec::new();
for s in &m.options {
match OPTIONS.get(s.as_str()) {
Some(x) => {
let (clear, f) = *x;
if clear {
flags &= !f;
} else {
flags |= f;
}
}
None => {
data.push(s.as_str());
}
};
}
(flags, data.join(","))
}
fn mount_from(
m: &Mount,
rootfs: &str,
flags: MsFlags,
data: &str,
label: &str,
) -> Result<(), Error> {
let d;
if !label.is_empty() && m.typ != "proc" && m.typ != "sysfs" {
if data.is_empty() {
d = format!{"context=\"{}\"", label};
} else {
d = format!{"{},context=\"{}\"", data, label};
}
} else {
d = data.to_string();
}
let dest = format!{"{}{}", rootfs, &m.destination};
let src = if m.typ == "bind" {
let src = canonicalize(&m.source)?;
let dir = if src.is_file() {
Path::new(&dest).parent().unwrap()
} else {
Path::new(&dest)
};
if let Err(e) = create_dir_all(&dir) {
}
// make sure file exists so we can bind over it
if src.is_file() {
if let Err(e) =
OpenOptions::new().create(true).write(true).open(&dest)
{
}
}
src
} else {
if let Err(e) = create_dir_all(&dest) {
}
PathBuf::from(&m.source)
};
if let Err(::nix::Error::Sys(errno)) =
mount(Some(&*src), &*dest, Some(&*m.typ), flags, Some(&*d))
{
if errno != Errno::EINVAL {
let chain = || format!("mount of {} failed", &m.destination);
return Err(::nix::Error::Sys(errno))?;
}
// try again without mount label
mount(Some(&*src), &*dest, Some(&*m.typ), flags, Some(data))?;
// warn if label cannot be set
if let Err(e) = setfilecon(&dest, label) {
println!{"could not set mount label of {} to {}: {}",
&m.destination, &label, e};
}
}
// remount bind mounts if they have other flags (like MsFlags::MS_RDONLY)
if flags.contains(MsFlags::MS_BIND)
&& flags.intersects(
!(MsFlags::MS_REC
| MsFlags::MS_REMOUNT
| MsFlags::MS_BIND
| MsFlags::MS_PRIVATE
| MsFlags::MS_SHARED
| MsFlags::MS_SLAVE),
) {
let chain = || format!("remount of {} failed", &dest);
mount(
Some(&*dest),
&*dest,
None::<&str>,
flags | MsFlags::MS_REMOUNT,
None::<&str>,
)?;
}
Ok(())
}
static SYMLINKS: &'static [(&'static str, &'static str)] = &[
("/proc/self/fd", "dev/fd"),
("/proc/self/fd/0", "dev/stdin"),
("/proc/self/fd/1", "dev/stdout"),
("/proc/self/fd/2", "dev/stderr"),
];
fn default_symlinks() -> Result<(), Error> {
if Path::new("/proc/kcore").exists() {
symlink("/proc/kcore", "dev/kcore")?;
}
for &(src, dst) in SYMLINKS {
symlink(src, dst)?;
}
Ok(())
}
fn create_devices(devices: &[LinuxDevice], bind: bool) -> Result<(), Error> {
let op: fn(&LinuxDevice) -> Result<(), Error> =
if bind { bind_dev } else { mknod_dev };
let old = umask(Mode::from_bits_truncate(0o000));
for dev in DEFAULT_DEVICES.iter() {
op(dev)?;
}
for dev in devices {
if !dev.path.starts_with("/dev") || dev.path.contains("..") {
let msg = format!("{} is not a valid device path", dev.path);
}
op(dev)?;
}
umask(old);
Ok(())
}
fn ensure_ptmx() -> Result<(), Error> {
if let Err(e) = std::fs::remove_file("dev/ptmx") {
if e.kind() != ::std::io::ErrorKind::NotFound {
let msg = "could not delete /dev/ptmx".to_string();
Err(e)?;
}
}
symlink("pts/ptmx", "dev/ptmx")?;
Ok(())
}
fn makedev(major: u64, minor: u64) -> u64 {
(minor & 0xff)
| ((major & 0xfff) << 8)
| ((minor & !0xff) << 12)
| ((major & !0xfff) << 32)
}
fn to_sflag(t: LinuxDeviceType) -> Result<SFlag, Error> {
match t {
LinuxDeviceType::b => Ok(SFlag::S_IFBLK),
LinuxDeviceType::c | LinuxDeviceType::u => Ok(SFlag::S_IFCHR),
LinuxDeviceType::p => Ok(SFlag::S_IFIFO),
LinuxDeviceType::a => {let msg = "type a is not allowed for linux device".to_string();Err(Error::Unsupported(msg))}
}
}
fn mknod_dev(dev: &LinuxDevice) -> Result<(), Error> {
let f = to_sflag(dev.typ)?;
mknod(
&dev.path[1..],
f,
Mode::from_bits_truncate(dev.file_mode.unwrap_or(0)),
makedev(dev.major, dev.minor),
)?;
chown(
&dev.path[1..],
dev.uid.map(|n| Uid::from_raw(n)),
dev.gid.map(|n| Gid::from_raw(n)),
)?;
Ok(())
}
fn bind_dev(dev: &LinuxDevice) -> Result<(), Error> {
let fd = open(
&dev.path[1..],
OFlag::O_RDWR | OFlag::O_CREAT,
Mode::from_bits_truncate(0o644),
)?;
close(fd)?;
mount(
Some(&*dev.path),
&dev.path[1..],
None::<&str>,
MsFlags::MS_BIND,
None::<&str>,
)?;
Ok(())
}
fn mask_path(path: &str) -> Result<(), Error> {
if !path.starts_with('/') || path.contains("..") {
let msg = format!("invalid maskedPath: {}", path);
return Err(Error::Unsupported(msg));
}
if let Err(::nix::Error::Sys(errno)) = mount(
Some("/dev/null"),
path,
None::<&str>,
MsFlags::MS_BIND,
None::<&str>,
) {
// ignore ENOENT and ENOTDIR: path to mask doesn't exist
if errno != Errno::ENOENT && errno != Errno::ENOTDIR {
let msg = format!("could not mask {}", path);
Err(::nix::Error::Sys(errno))?;
} else {
}
}
Ok(())
}
fn readonly_path(path: &str) -> Result<(), Error> {
if !path.starts_with('/') || path.contains("..") {
let msg = format!("invalid readonlyPath: {}", path);
return Err(Error::Unsupported(msg));
}
if let Err(e) = mount(
Some(&path[1..]),
path,
None::<&str>,
MsFlags::MS_BIND | MsFlags::MS_REC,
None::<&str>,
) {
match e {
::nix::Error::Sys(errno) => {
// ignore ENOENT: path to make read only doesn't exist
if errno != Errno::ENOENT {
let msg = format!("could not readonly {}", path);
Err(e)?;
}
return Ok(());
}
_ => {
unreachable!("Supposedly unreachable error {:?}", e);
}
}
}
mount(
Some(&path[1..]),
&path[1..],
None::<&str>,
MsFlags::MS_BIND
| MsFlags::MS_REC
| MsFlags::MS_RDONLY
| MsFlags::MS_REMOUNT,
None::<&str>,
)?;
Ok(())
}
#[inline]
pub fn fchdir(fd: RawFd){
let res = unsafe { libc::fchdir(fd) };
}

359
src/namespace/namespace.rs Normal file
View File

@ -0,0 +1,359 @@
use nix;
use lazy_static;
use scopeguard;
use std::collections::HashMap;
use std::ffi::CString;
use std::{thread, time};
use std::fs::{canonicalize, create_dir, create_dir_all, remove_dir_all, File};
use std::io::{Read, Write};
use nix::sched::{setns, unshare, CloneFlags};
use nix::sys::stat::{Mode};
use nix::fcntl::{OFlag,open};
use nix::sys::wait::{waitpid, WaitStatus};
use nix::unistd::{chdir,pipe2,read,close,write, execvp, execv,getpid, sethostname, setresgid, setresuid};
use nix::sched::{clone};
use nix::sys::signal::{SigSet,kill, Signal,SigHandler};
use nix::unistd::{fork,ForkResult,Gid, Pid, Uid};
use std::os::unix::io::RawFd;
use nix::errno::Errno;
use crate::namespace::mounts;
use crate::errors::Error;
use crate::spec::Spec;
use crate::spec::Linux;
use crate::spec::LinuxRlimit;
use crate::spec::LinuxIDMapping;
use crate::namespace::utilities;
use crate::commands::CreateArgs;
lazy_static! {
#[derive(Debug)]
static ref NAMESPACES: HashMap<CloneFlags, &'static str> = {
let mut result = HashMap::new();
result.insert(CloneFlags::CLONE_NEWIPC, "ipc");
result.insert(CloneFlags::CLONE_NEWUTS, "uts");
result.insert(CloneFlags::CLONE_NEWNET, "net");
result.insert(CloneFlags::CLONE_NEWPID, "pid");
result.insert(CloneFlags::CLONE_NEWNS, "mnt");
result.insert(CloneFlags::CLONE_NEWCGROUP, "cgroup");
result.insert(CloneFlags::CLONE_NEWUSER, "user");
result
};
}
static mut CHILD_PID: Option<Pid> = None;
pub fn init_spec(spec: &Spec, args: &CreateArgs) -> Result<Pid,Error>{
lazy_static::initialize(&NAMESPACES);
//println!("{:?}",*NAMESPACES);
// CreateArgs { bundle: ".", pid_file: "", console_socket: "", id: "123" }
//println!("{:?}", args);
// 实参
let rootfs = canonicalize(&spec.root.path)?.to_string_lossy().into_owned();;
let init_pid = Pid::from_raw(-1);
let mut userns = false;
let rlimits = &spec.process.rlimits;
// 收集命名空间
let mut cf = CloneFlags::empty();
let mut to_enter = Vec::new();
let mut enter_pid = false;
let linux = spec.linux.as_ref().unwrap();
for ns in &linux.namespaces {
println!("\n ns output: {:?} \n",ns);
let space = CloneFlags::from_bits_truncate(ns.typ as i32);
if space == CloneFlags::CLONE_NEWPID {
enter_pid = true;
}
if ns.path.is_empty() {
cf |= space;
} else {
let fd = open(&*ns.path, OFlag::empty(), Mode::empty())?;
to_enter.push((space, fd));
}
}
let mut bind_devices = false;
let mut userns = false;
let rlimits = &spec.process.rlimits;
if cf.contains(CloneFlags::CLONE_NEWUSER) {
bind_devices = true;
userns = true;
}
// 设置PID为1的init进程
// if !daemonize {
// if let Err(e) = prctl::set_child_subreaper(true) {
// // bail!(format!("set subreaper returned {}", e));
// };
// }
let id = &args.id;
let cpath = if linux.cgroups_path == "" {
format!{"/{}", id}
} else {
linux.cgroups_path.clone()
};
let process_result= create_child(id, init_pid , enter_pid, userns, linux, rlimits , &cpath, spec);
println!("process_result:{:?}", process_result);
let mut wfd: RawFd = -1;
match process_result {
Ok(v) => if v.0 != Pid::from_raw(-1){ return Ok(v.0) }else{wfd = v.1;},
Err(e) => println!("error because {:?}",e)
}
let mut mount_fd = -1;
// enter path namespaces
for &(space, fd) in &to_enter {
if space == CloneFlags::CLONE_NEWNS {
// enter mount ns last
mount_fd = fd;
continue;
}
setns(fd, space)?;
close(fd)?;
if space == CloneFlags::CLONE_NEWUSER {
utilities::setid(Uid::from_raw(0), Gid::from_raw(0))?;
bind_devices = true;
}
}
unshare(cf & !CloneFlags::CLONE_NEWUSER)?;
if enter_pid {
create_grandchild()?;
};
// 设置主机名
if cf.contains(CloneFlags::CLONE_NEWUTS) {
sethostname(&spec.hostname)?;
}
// 初始化rootfs
if cf.contains(CloneFlags::CLONE_NEWNS) {
mounts::init_rootfs(spec, &rootfs, &cpath, bind_devices)?;
}
if !enter_pid {
//通知父亲继续运行
println!("writing zero to pipe to trigger prestart");
let data: &[u8] = &[0];
write(wfd, data)?;
}
if mount_fd != -1 {
setns(mount_fd, CloneFlags::CLONE_NEWNS)?;
close(mount_fd)?;
}
if cf.contains(CloneFlags::CLONE_NEWNS) {
mounts::pivot_rootfs(&*rootfs)?;
// only set sysctls in newns
for (key, value) in &linux.sysctl {
utilities::set_sysctl(key, value)?;
}
// NOTE: apparently criu has problems if pointing to an fd outside
// the filesystem namespace.
utilities::reopen_dev_null()?;
}
if cf.contains(CloneFlags::CLONE_NEWNS) {
mounts::finish_rootfs(spec)?;
}
let uid = Uid::from_raw(spec.process.user.uid);
let gid = Gid::from_raw(spec.process.user.gid);
utilities::setid(uid, gid)?;
if !spec.process.user.additional_gids.is_empty() {
let gids = &spec.process.user.additional_gids;
unsafe { libc::setgroups(gids.len(), gids.as_ptr()) };
}
if spec.process.no_new_privileges {
if let Err(e) = prctl::set_no_new_privileges(true) {
};
// drop privileges
if let Some(ref c) = spec.process.capabilities {
utilities::drop_privileges(c)?;
}
if let Some(ref seccomp) = linux.seccomp {
utilities::initialize_seccomp(seccomp)?;
}
} else {
// NOTE: if we have not set no new priviliges, we must set up seccomp
// before capset, which will error if seccomp blocks it
if let Some(ref seccomp) = linux.seccomp {
utilities::initialize_seccomp(seccomp)?;
}
// drop privileges
if let Some(ref c) = spec.process.capabilities {
utilities::drop_privileges(c)?;
}
}
let data: &[u8] = &[0];
write(wfd, data)?;
if enter_pid {
do_init(wfd)?;
}
close(wfd);
Ok(Pid::from_raw(-1))
}
fn do_init(wfd: RawFd) -> Result<(),Error> {
let s = SigSet::all();
s.thread_block()?;
loop {
let signal = s.wait()?;
if signal == Signal::SIGCHLD {
let mut sig = None;
let code;
match wait_children()? {
WaitStatus::Exited(_, c) => code = c as i32,
WaitStatus::Signaled(_, s, _) => {
sig = Some(s);
code = 128 + s as libc::c_int;
}
_ => continue,
};
if let Some(s) = sig {
// raising from pid 1 doesn't work as you would
// expect, so write signal to pipe.
let data: &[u8] = &[s as u8];
write(wfd, data)?;
}
close(wfd)?;
std::process::exit(code)
}
if let Err(e) = nix::sys::signal::kill(Pid::from_raw(-1), signal) {
println!("failed to signal children, {}", e);
}
}
}
pub fn wait_children() -> Result<(WaitStatus),Error> {
let mut result = WaitStatus::Exited(Pid::from_raw(0), 0);
loop {
//监听所有进程的状态改变
match waitpid(Pid::from_raw(-1), Some(nix::sys::wait::WaitPidFlag::WNOHANG)) {
Err(e) => {
if e != ::nix::Error::Sys(Errno::ECHILD) {
return Err(e)?;
}
// ECHILD means no processes are left
break;
}
Ok(s) => {
result = s;
if result == WaitStatus::StillAlive {
break;
}
}
}
}
Ok(result)
}
pub fn create_grandchild() -> Result<(),Error>{
match fork()? {
ForkResult::Child => {
}
ForkResult::Parent { .. } => {
println!("second parent exiting");
utilities::exit(0, None)?;
}
};
Ok(())
}
pub fn create_child(id: &str, init_pid: Pid, enter_pid:bool,
userns:bool, linux: &Linux, rlimits:&[LinuxRlimit] , cpath:&str, spec:&Spec) -> Result<(Pid, RawFd),Error>
{
//println!("{:?}",linux);
let ccond = utilities::Cond::new()?;
let pcond = utilities::Cond::new()?;
let (rfd, wfd) = pipe2(OFlag::O_CLOEXEC)?;
match fork()? {
ForkResult::Child => {
println!("this is child progress");
//关闭读通道
close(rfd)?;
//设置进程名
prctl::set_name("run-user");
// 记录内存缓冲溢出评价值
if let Some(ref r) = linux.resources {
if let Some(adj) = r.oom_score_adj {
let mut f = File::create("/proc/self/oom_score_adj")?;
f.write_all(adj.to_string().as_bytes())?;
}
}
// 设置限制配额
for rlimit in rlimits.iter() {
//setrlimit(rlimit.typ as i32, rlimit.soft, rlimit.hard)?;
}
// 把子进程从当前命名空间移出, 创建新的命名空间
if userns {
unshare(CloneFlags::CLONE_NEWUSER)?;
}
println!("notify parent");
ccond.notify()?;
pcond.wait()?;
// create_shell(&spec.process.args);
println!("get parent notify");
if userns {
utilities::setid(Uid::from_raw(0), Gid::from_raw(0))?;
}
}
ForkResult::Parent { child } => {
println!("this is parent progress,child {}",child);
//关闭写通道
close(wfd)?;
ccond.wait()?;
println!("get child {} notify",child);
if userns {
// 将容器用户与系统用户作映射
write_mappings(
&format!("/proc/{}/uid_map", child),
&linux.uid_mappings,
)?;
write_mappings(
&format!("/proc/{}/gid_map", child),
&linux.gid_mappings,
)?;
}
// setup cgroups
let schild = child.to_string();
// notify child
pcond.notify()?;
utilities::exit(0,Some(Signal::SIGQUIT))?;
}
};
Ok((Pid::from_raw(-1), wfd))
}
fn create_shell(args:&[String]) -> Result<(),Error> {
let file_name = CString::new("sh".to_string()).unwrap();
let a : Vec<CString> = args.iter().map(|s| CString::new(s.to_string()).unwrap_or_default()).collect();
execvp(&file_name, &a)?;
Ok(())
}
fn write_mappings(path: &str, maps: &[LinuxIDMapping]) -> Result<(),Error> {
let mut data = String::new();
for m in maps {
let val = format!("{} {} {}\n", m.container_id, m.host_id, m.size);
data = data + &val;
}
if !data.is_empty() {
let fd = open(path, OFlag::O_WRONLY, Mode::empty())?;
defer!(close(fd).unwrap());
write(fd, data.as_bytes())?;
}
Ok(())
}

341
src/namespace/utilities.rs Normal file
View File

@ -0,0 +1,341 @@
use nix::fcntl::OFlag;
use nix::unistd::{Uid,Gid,close, pipe2, read,sethostname, setresgid, setresuid,chdir};
use nix::sys::signal::{kill, raise, sigaction};
use nix::sys::signal::{SaFlags, SigAction, SigHandler, SigSet, Signal};
use nix::unistd::Pid;
use std::os::unix::io::RawFd;
use crate::errors::Error;
use caps::*;
use crate::spec::Spec;
use nix::mount::MsFlags;
use nix::mount::*;
use crate::spec::Mount;
use crate::spec::LinuxCapabilities;
use crate::spec::LinuxCapabilityType;
use crate::namespace::mounts;
use crate::spec::{Arch, LinuxSeccomp, LinuxSeccompOperator};
use seccomp_sys::*;
use nix::fcntl::{open};
use nix::sys::stat::Mode;
use nix::unistd::{write};
use std::ffi::CString;
use nix::errno::Errno;
#[inline]
pub fn lsetxattr(
path: &CString,
name: &CString,
value: &CString,
len: usize,
flags: i32,
){
let res = unsafe {
libc::lsetxattr(
path.as_ptr(),
name.as_ptr(),
value.as_ptr() as *const libc::c_void,
len,
flags,
)
};
}
const EXEC_PATH: &'static str = "/proc/self/attr/exec";
pub fn setexeccon(label: &str) -> Result<(),Error> {
let fd = open(EXEC_PATH, OFlag::O_RDWR, Mode::empty())?;
defer!(close(fd).unwrap());
write(fd, label.as_bytes())?;
Ok(())
}
const XATTR_NAME: &'static str = "security.selinux";
pub fn setfilecon(file: &str, label: &str) -> Result<(), Error> {
let path = CString::new(file)?;
let name = CString::new(XATTR_NAME)?;
let value = CString::new(label)?;
lsetxattr(&path, &name, &value, label.len(), 0);
Ok(())
}
pub struct Cond {
rfd: RawFd,
wfd: RawFd,
}
impl Cond {
pub fn new() -> Result<Cond,Error> {
let (rfd, wfd) = pipe2(OFlag::O_CLOEXEC)?;
Ok(Cond { rfd: rfd, wfd: wfd })
}
pub fn wait(&self) -> Result<(),Error> {
close(self.wfd)?;
let data: &mut [u8] = &mut [0];
while read(self.rfd, data)? != 0 {}
close(self.rfd)?;
Ok(())
}
pub fn notify(&self) -> Result<(),Error> {
close(self.rfd)?;
close(self.wfd)?;
Ok(())
}
}
pub fn setid(uid: Uid, gid: Gid) -> Result<(),Error> {
if let Err(e) = prctl::set_keep_capabilities(true) {
println!("set keep capabilities returned {}", e);
};
{
setresgid(gid, gid, gid)?;
}
{
setresuid(uid, uid, uid)?;
}
if uid != Uid::from_raw(0) {
set(None, CapSet::Effective, ::caps::all());
}
if let Err(e) = prctl::set_keep_capabilities(false) {
println!("set keep capabilities returned {}", e);
};
Ok(())
}
fn to_set(caps: &[LinuxCapabilityType]) -> CapsHashSet {
let mut capabilities = CapsHashSet::new();
for c in caps {
capabilities.insert(unsafe { ::std::mem::transmute(*c) });
}
capabilities
}
pub fn drop_privileges(cs: &LinuxCapabilities) -> Result<(),Error> {
let all = ::caps::all();
// drop excluded caps from the bounding set
for c in all.difference(&to_set(&cs.bounding)) {
drop(None, CapSet::Bounding, *c);
}
// set other sets for current process
set(None, CapSet::Effective, to_set(&cs.effective));
set(None, CapSet::Permitted, to_set(&cs.permitted));
set(None, CapSet::Inheritable, to_set(&cs.inheritable));
if let Err(e) = set(None, CapSet::Ambient, to_set(&cs.ambient)) {
}
Ok(())
}
fn raise_for_parent(signal: Signal) -> Result<(),Error> {
if signal != Signal::SIGKILL && signal != Signal::SIGSTOP {
let a =
SigAction::new(SigHandler::SigDfl, SaFlags::empty(), SigSet::all());
unsafe {
sigaction(signal, &a)?;
}
}
let mut s = SigSet::empty();
s.add(signal);
s.thread_unblock()?;
raise(signal)?;
Ok(())
}
fn wait_for_signal() -> Result<Signal,Error> {
let s = SigSet::all();
s.thread_block()?;
let result = s.wait()?;
s.thread_unblock()?;
Ok(result)
}
pub fn exit(exit_code: i8, sig: Option<Signal>) -> Result<(),Error> {
match sig {
Some(signal) => {
println!("child exited with signal {:?}", signal);
raise_for_parent(signal)?;
loop {
wait_for_signal()?;
}
}
None => {
println!("child exited with code {:?}", exit_code);
std::process::exit(exit_code as i32);
}
}
}
pub unsafe fn set_handler(handler: SigHandler) -> Result<(),Error> {
let a = SigAction::new(handler, SaFlags::empty(), SigSet::all());
sigaction(Signal::SIGTERM, &a)?;
sigaction(Signal::SIGQUIT, &a)?;
sigaction(Signal::SIGINT, &a)?;
sigaction(Signal::SIGHUP, &a)?;
sigaction(Signal::SIGUSR1, &a)?;
sigaction(Signal::SIGUSR2, &a)?;
Ok(())
}
pub fn set_sysctl(key: &str, value: &str) -> Result<(),Error> {
let path = format!{"/proc/sys/{}", key.replace(".", "/")};
let fd = match open(&*path, OFlag::O_RDWR, Mode::empty()) {
Err(::nix::Error::Sys(errno)) => {
if errno != Errno::ENOENT {
let msg = format!("could not set sysctl {} to {}", key, value);
Err(::nix::Error::Sys(errno))?;
}
println!("could not set {} because it doesn't exist", key);
return Ok(());
}
Err(e) => Err(e)?,
Ok(fd) => fd,
};
defer!(close(fd).unwrap());
write(fd, value.as_bytes())?;
Ok(())
}
pub fn reopen_dev_null() -> Result<(),Error> {
let null_fd = open("/dev/null", OFlag::O_WRONLY, Mode::empty())?;
let null_stat = nix::sys::stat::fstat(null_fd)?;
defer!(close(null_fd).unwrap());
for fd in 0..3 {
if let Ok(stat) = nix::sys::stat::fstat(fd) {
if stat.st_rdev == null_stat.st_rdev {
if fd == 0 {
// close and reopen to get RDONLY
close(fd)?;
open("/dev/null", OFlag::O_RDONLY, Mode::empty())?;
} else {
// we already have wronly fd, so duplicate it
nix::unistd::dup2(null_fd, fd)?;
}
}
}
}
Ok(())
}
fn init(act: u32) -> Result<*mut scmp_filter_ctx, Error> {
let filter_ctx = unsafe { seccomp_init(act) };
if filter_ctx.is_null() {
let msg = "initialization failed".to_string();
Err(Error::Unsupported(msg))
} else {
Ok(filter_ctx)
}
}
fn arch_add(ctx: *mut scmp_filter_ctx, arch: scmp_arch) -> Result<i32,Error> {
let id = unsafe { seccomp_arch_add(ctx, arch as u32) };
if id == __NR_SCMP_ERROR {
let msg = format!("could not add arch {:?}", arch);
Err(Error::Unsupported(msg))
} else {
Ok(id)
}
}
fn attr_set(
ctx: *mut scmp_filter_ctx,
attr: scmp_filter_attr,
value: u32,
) -> Result<(),Error> {
let res = unsafe { seccomp_attr_set(ctx, attr, value) };
if res != 0 {
let msg = "failed to set_attr".to_string();
Err(Error::Unsupported(msg))
} else {
Ok(())
}
}
fn syscall_resolve_name(name: &str) -> Result<i32,Error> {
let s = ::std::ffi::CString::new(name)?;
let id = unsafe { seccomp_syscall_resolve_name(s.as_ptr()) };
if id == __NR_SCMP_ERROR {
let msg = format!("could not resolve {}", name);
Err(Error::Unsupported(msg))
} else {
Ok(id)
}
}
fn rule_add(
ctx: *mut scmp_filter_ctx,
act: u32,
id: i32,
cmps: &[scmp_arg_cmp],
) -> Result<(),Error> {
let res = unsafe {
let ptr = if cmps.is_empty() {
::std::ptr::null()
} else {
cmps.as_ptr()
};
seccomp_rule_add_array(ctx, act, id, cmps.len() as u32, ptr)
};
if res != 0 {
let msg = format!("failed to add rule for {}", id);
Err(Error::Unsupported(msg))
} else {
Ok(())
}
}
fn load(ctx: *mut scmp_filter_ctx) -> Result<(),Error> {
let res = unsafe { seccomp_load(ctx) };
if res != 0 {
let msg = "failed to load filter".to_string();
Err(Error::Unsupported(msg))
} else {
Ok(())
}
}
pub fn initialize_seccomp(seccomp: &LinuxSeccomp) -> Result<(), Error> {
let ctx = init(seccomp.default_action as u32)?;
// set control NoNewPrivs to false, as we deal with it separately
attr_set(ctx, scmp_filter_attr::SCMP_FLTATR_CTL_NNP, false as u32)?;
// set up architectures
for arch in &seccomp.architectures {
arch_add(ctx, unsafe { ::std::mem::transmute(*arch) })?;
}
// add actions for syscalls
for syscall in &seccomp.syscalls {
let mut names = syscall.names.clone();
if names.is_empty() {
names.push(syscall.name.clone())
};
for name in names {
let id = match syscall_resolve_name(&name) {
Ok(result) => result,
Err(e) => {
continue;
}
};
let mut cmps = Vec::new();
for arg in &syscall.args {
cmps.push(scmp_arg_cmp {
arg: arg.index as u32,
op: unsafe { ::std::mem::transmute(arg.op) },
datum_a: arg.value as scmp_datum_t,
datum_b: arg.value_two as scmp_datum_t,
});
}
rule_add(ctx, syscall.action as u32, id, &cmps)?;
}
}
load(ctx)?;
Ok(())
}

View File

@ -1,2 +1,14 @@
pub mod spec;
pub use self::spec::load_spec;
pub use self::spec::Spec;
pub use self::spec::Linux;
pub use self::spec::LinuxRlimit;
pub use self::spec::LinuxIDMapping;
pub use self::spec::Mount;
pub use self::spec::LinuxDevice;
pub use self::spec::LinuxDeviceType;
pub use self::spec::LinuxCapabilityType;
pub use self::spec::LinuxCapabilities;
pub use self::spec::Arch;
pub use self::spec::LinuxSeccomp;
pub use self::spec::LinuxSeccompOperator;

View File

@ -11,7 +11,7 @@ const OCI_VERSION: &str = "1.0.1";
fn is_false(b: &bool) -> bool {
!b
}
///
#[derive(Serialize, Deserialize, Debug)]
pub struct Platform {
#[serde(default, skip_serializing_if = "String::is_empty")]