mirror of
https://github.com/michael-yuji/xc.git
synced 2026-03-25 02:05:49 +01:00
add ALLOW, NOINIT, NODEINIT, SYSVIPC, MOUNT directives
This commit is contained in:
@@ -103,7 +103,7 @@ pub(crate) enum PatchActions {
|
||||
},
|
||||
}
|
||||
|
||||
fn patch_image<F>(
|
||||
pub(crate) fn patch_image<F>(
|
||||
conn: &mut UnixStream,
|
||||
image_reference: &ImageReference,
|
||||
f: F,
|
||||
|
||||
@@ -28,7 +28,109 @@ pub mod run;
|
||||
use super::JailContext;
|
||||
use crate::jailfile::parse::Action;
|
||||
|
||||
use anyhow::Context;
|
||||
use xc::models::jail_image::{JailConfig, SpecialMount};
|
||||
use xc::models::SystemVPropValue;
|
||||
|
||||
pub(crate) trait Directive: Sized {
|
||||
fn from_action(action: &Action) -> Result<Self, anyhow::Error>;
|
||||
fn run_in_context(&self, context: &mut JailContext) -> Result<(), anyhow::Error>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum ConfigMod {
|
||||
Allow(Vec<String>),
|
||||
ReplaceAllow(Vec<String>),
|
||||
WorkDir,
|
||||
Init,
|
||||
NoInit,
|
||||
Deinit,
|
||||
NoDeinit,
|
||||
Cmd,
|
||||
Expose,
|
||||
Volume,
|
||||
Mount(String, String),
|
||||
SysV(Vec<String>),
|
||||
}
|
||||
|
||||
impl ConfigMod {
|
||||
pub(crate) fn apply_config(&self, config: &mut JailConfig) {
|
||||
match self {
|
||||
Self::NoInit => config.init = Vec::new(),
|
||||
Self::NoDeinit => config.deinit = Vec::new(),
|
||||
Self::Allow(allows) => {
|
||||
for allow in allows.iter() {
|
||||
if let Some(param) = allow.strip_prefix('-') {
|
||||
for i in (0..config.allow.len()).rev() {
|
||||
if config.allow[i] == param {
|
||||
config.allow.remove(i);
|
||||
}
|
||||
}
|
||||
} else if !config.allow.contains(allow) {
|
||||
config.allow.push(allow.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::ReplaceAllow(allows) => {
|
||||
for allow in allows.iter() {
|
||||
if allow.strip_prefix('-').is_none() {
|
||||
config.allow.push(allow.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Mount(mount_type, mount_point) => {
|
||||
let special_mount = SpecialMount {
|
||||
mount_type: mount_type.to_string(),
|
||||
mount_point: mount_point.to_string(),
|
||||
};
|
||||
if !config.special_mounts.contains(&special_mount) {
|
||||
config.special_mounts.push(special_mount)
|
||||
}
|
||||
}
|
||||
Self::SysV(sysvattrs) => {
|
||||
for attr in sysvattrs.iter() {
|
||||
match attr.as_str() {
|
||||
"shm" => config.sysv_shm = SystemVPropValue::New,
|
||||
"-shm" => config.sysv_shm = SystemVPropValue::Disable,
|
||||
"msg" => config.sysv_msg = SystemVPropValue::New,
|
||||
"-msg" => config.sysv_msg = SystemVPropValue::Disable,
|
||||
"sem" => config.sysv_sem = SystemVPropValue::New,
|
||||
"-sem" => config.sysv_sem = SystemVPropValue::Disable,
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn implemented_directives() -> &'static [&'static str] {
|
||||
&["ALLOW", "NOINIT", "NODEINIT", "SYSVIPC", "MOUNT"]
|
||||
}
|
||||
}
|
||||
|
||||
impl Directive for ConfigMod {
|
||||
fn from_action(action: &Action) -> Result<Self, anyhow::Error> {
|
||||
match action.directive_name.as_str() {
|
||||
"ALLOW" => match action.directive_args.get("replace") {
|
||||
Some(value) if value.as_str() == "true" => {
|
||||
Ok(ConfigMod::ReplaceAllow(action.args.clone()))
|
||||
}
|
||||
_ => Ok(ConfigMod::Allow(action.args.clone())),
|
||||
},
|
||||
"NOINIT" => Ok(ConfigMod::NoInit),
|
||||
"NODEINIT" => Ok(ConfigMod::NoDeinit),
|
||||
"SYSVIPC" => Ok(ConfigMod::SysV(action.args.clone())),
|
||||
"MOUNT" => {
|
||||
let fstype = action.args.get(0).context("cannot get fstype")?;
|
||||
let mountpoint = action.args.get(1).context("cannot get mountpoint")?;
|
||||
Ok(ConfigMod::Mount(fstype.to_string(), mountpoint.to_string()))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn run_in_context(&self, context: &mut JailContext) -> Result<(), anyhow::Error> {
|
||||
context.config_mods.push(self.clone());
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,12 @@
|
||||
pub mod directives;
|
||||
pub mod parse;
|
||||
|
||||
use oci_util::image_reference::ImageReference;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::os::unix::net::UnixStream;
|
||||
use tracing::error;
|
||||
use xc::container::request::NetworkAllocRequest;
|
||||
use xc::models::jail_image::JailConfig;
|
||||
use xc::models::network::DnsSetting;
|
||||
use xcd::ipc::*;
|
||||
|
||||
@@ -42,6 +44,8 @@ pub(crate) struct JailContext {
|
||||
pub(crate) dns: DnsSetting,
|
||||
|
||||
pub(crate) network: Vec<NetworkAllocRequest>,
|
||||
|
||||
pub(crate) config_mods: Vec<self::directives::ConfigMod>,
|
||||
}
|
||||
|
||||
impl JailContext {
|
||||
@@ -56,10 +60,34 @@ impl JailContext {
|
||||
containers: HashMap::new(),
|
||||
dns,
|
||||
network,
|
||||
config_mods: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn release(mut self) -> anyhow::Result<()> {
|
||||
pub(crate) fn apply_config(&self, config: &mut JailConfig) {
|
||||
for config_mod in self.config_mods.iter() {
|
||||
config_mod.apply_config(config);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn release(self, image_reference: ImageReference) -> anyhow::Result<()> {
|
||||
let mut conn = self.conn;
|
||||
let config_mods = self.config_mods;
|
||||
let req = CommitRequest {
|
||||
name: image_reference.name.to_string(),
|
||||
tag: image_reference.tag.to_string(),
|
||||
container_name: self.container_id.clone().unwrap(),
|
||||
};
|
||||
|
||||
let _response = do_commit_container(&mut conn, req)?.unwrap();
|
||||
|
||||
crate::image::patch_image(&mut conn, &image_reference, |config| {
|
||||
for config_mod in config_mods.iter() {
|
||||
config_mod.apply_config(config);
|
||||
}
|
||||
// self.apply_config(config);
|
||||
})?;
|
||||
|
||||
let mut containers = HashSet::new();
|
||||
if let Some(container) = self.container_id {
|
||||
containers.insert(container);
|
||||
@@ -71,7 +99,7 @@ impl JailContext {
|
||||
let kill = KillContainerRequest {
|
||||
name: name.to_string(),
|
||||
};
|
||||
match do_kill_container(&mut self.conn, kill)? {
|
||||
match do_kill_container(&mut conn, kill)? {
|
||||
Ok(_) => {}
|
||||
Err(error) => {
|
||||
error!("cannot kill container {name}: {error:?}");
|
||||
|
||||
@@ -314,19 +314,30 @@ fn main() -> Result<(), ActionError> {
|
||||
} else if action.directive_name == "COPY" {
|
||||
let directive = CopyDirective::from_action(action)?;
|
||||
directive.run_in_context(&mut context)?;
|
||||
} else if ConfigMod::implemented_directives()
|
||||
.contains(&action.directive_name.as_str())
|
||||
{
|
||||
let directive = ConfigMod::from_action(action)?;
|
||||
directive.run_in_context(&mut context)?;
|
||||
}
|
||||
}
|
||||
|
||||
debug!("before commit");
|
||||
/*
|
||||
let req = CommitRequest {
|
||||
name: image_reference.name,
|
||||
name: image_reference.name.to_string(),
|
||||
tag: image_reference.tag.to_string(),
|
||||
container_name: context.container_id.clone().unwrap(),
|
||||
};
|
||||
let response = do_commit_container(&mut context.conn, req)?.unwrap();
|
||||
eprintln!("{response:#?}");
|
||||
|
||||
context.release()?;
|
||||
crate::image::patch_image(&mut context.conn, &image_reference, |config| {
|
||||
context.apply_config(config);
|
||||
})?;
|
||||
*/
|
||||
|
||||
context.release(image_reference)?;
|
||||
// let response: CommitResponse = request(&mut conn, "commit", req)?;
|
||||
}
|
||||
Action::Channel(action) => {
|
||||
|
||||
@@ -260,8 +260,10 @@ impl ImageStore for SqliteImageStore {
|
||||
|
||||
fn register_manifest(&self, manifest: &JailImage) -> Result<OciDigest, ImageStoreError> {
|
||||
let db = &self.db;
|
||||
let mut stmt =
|
||||
db.prepare_cached("insert into image_manifests (digest, manifest) values (?, ?)")?;
|
||||
let mut stmt = db.prepare_cached(
|
||||
"insert into image_manifests (digest, manifest) values (?, ?)
|
||||
on conflict(digest) do nothing",
|
||||
)?;
|
||||
let manifest_json = serde_json::to_string(manifest)?;
|
||||
let digest = manifest.digest();
|
||||
stmt.execute([digest.as_str(), manifest_json.as_str()])?;
|
||||
|
||||
Reference in New Issue
Block a user