Compare commits
5
Commits
f2b68004ae
...
93cbf7ca47
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93cbf7ca47 | ||
|
|
c3b6a72d39 | ||
|
|
90de50dfed | ||
|
|
6111bbeb8d | ||
|
|
524ef3e793 |
+134
@@ -103,6 +103,136 @@ EOF
|
|||||||
rm -rf "$work"
|
rm -rf "$work"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_user() {
|
||||||
|
echo "=== Testing USER directive ==="
|
||||||
|
|
||||||
|
work="$(mktemp -d)"
|
||||||
|
img="slim-test-user"
|
||||||
|
|
||||||
|
cat > "$work/Containerfile" <<'EOF'
|
||||||
|
FROM alpine:latest
|
||||||
|
RUN adduser -D -u 1500 testuser
|
||||||
|
USER testuser
|
||||||
|
CMD ["/bin/sh", "-c", "echo USER_BUILD_OK:$(id -u):$(whoami); poweroff -f"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "-- Building container image with USER directive..."
|
||||||
|
if ! podman build --network=none -t "$img" -f "$work/Containerfile" >/dev/null 2>&1; then
|
||||||
|
report fail "USER directive (podman build failed)"
|
||||||
|
rm -rf "$work"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "-- Test 1: build-time CMD runs as USER"
|
||||||
|
"$SLIM_BIN" build qcow2 "$img" >/dev/null 2>&1
|
||||||
|
output=$(timeout "$TIMEOUT" "$SLIM_BIN" run "$img" 2>&1 || true)
|
||||||
|
check_output "$output" "USER_BUILD_OK:1500:testuser" "USER build-time CMD runs as testuser"
|
||||||
|
|
||||||
|
echo "-- Test 2: run --cmd override runs as USER"
|
||||||
|
output=$(timeout "$TIMEOUT" "$SLIM_BIN" run "$img" --cmd 'echo USER_RUN_OK:$(id -u):$(whoami); poweroff -f' 2>&1 || true)
|
||||||
|
check_output "$output" "USER_RUN_OK:1500:testuser" "USER run --cmd override runs as testuser"
|
||||||
|
|
||||||
|
cleanup "$img" "$img"
|
||||||
|
rm -rf "$work"
|
||||||
|
}
|
||||||
|
|
||||||
|
test_mount() {
|
||||||
|
echo "=== Testing --mount (9p shares) ==="
|
||||||
|
|
||||||
|
work="$(mktemp -d)"
|
||||||
|
|
||||||
|
# --- Image 1: no WORKINGDIR, test host:guest and multi-mount ---
|
||||||
|
img="slim-test-mount"
|
||||||
|
share_dir="$work/share"
|
||||||
|
share_dir2="$work/share2"
|
||||||
|
guest_dir="/mnt/guest"
|
||||||
|
guest_dir2="/mnt/guest2"
|
||||||
|
|
||||||
|
mkdir -p "$share_dir" "$share_dir2"
|
||||||
|
echo "hello from host" > "$share_dir/testfile.txt"
|
||||||
|
echo "second share" > "$share_dir2/testfile2.txt"
|
||||||
|
|
||||||
|
cat > "$work/Containerfile" <<'EOF'
|
||||||
|
FROM alpine:latest
|
||||||
|
CMD ["/bin/sh", "-c", "poweroff -f"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "-- Building container image (no WORKINGDIR)..."
|
||||||
|
if ! podman build --network=none -t "$img" -f "$work/Containerfile" >/dev/null 2>&1; then
|
||||||
|
report fail "--mount (podman build failed)"
|
||||||
|
rm -rf "$work"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "-- Building slim VM..."
|
||||||
|
if ! "$SLIM_BIN" build qcow2 "$img" >/dev/null 2>&1; then
|
||||||
|
report fail "--mount (slim build failed)"
|
||||||
|
cleanup "$img" "$img"
|
||||||
|
rm -rf "$work"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
share_canon=$(readlink -f "$share_dir")
|
||||||
|
share_canon2=$(readlink -f "$share_dir2")
|
||||||
|
|
||||||
|
echo "-- Test 1: --mount host:guest (absolute guest path, multi-mount)..."
|
||||||
|
output=$(timeout "$TIMEOUT" "$SLIM_BIN" run "$img" \
|
||||||
|
--mount "${share_dir}:${guest_dir}" \
|
||||||
|
--mount "${share_dir2}:${guest_dir2}" \
|
||||||
|
--cmd "for f in /sys/bus/virtio/drivers/9pnet_virtio/virtio*/mount_tag; do [ -f \"\$f\" ] && echo \"\$f: \$(tr -d '\\0' < \"\$f\")\"; done; mount -v; cat ${guest_dir}/testfile.txt 2>/dev/null || echo NO_FILE; cat ${guest_dir2}/testfile2.txt 2>/dev/null || echo NO_FILE2; echo MOUNT_VERIFY_DONE; poweroff -f" \
|
||||||
|
2>&1 || true)
|
||||||
|
|
||||||
|
check_output "$output" "mount_tag: slim0" "--mount 9p share detected"
|
||||||
|
check_output "$output" "mount_tag: slim1" "--mount second 9p share detected"
|
||||||
|
check_output "$output" "type 9p" "--mount 9p filesystem in mount list"
|
||||||
|
check_output "$output" "hello from host" "--mount file accessible at guest path"
|
||||||
|
check_output "$output" "second share" "--mount second file accessible at guest path"
|
||||||
|
check_output "$output" "MOUNT_VERIFY_DONE" "--mount VM ran to completion"
|
||||||
|
|
||||||
|
cleanup "$img" "$img"
|
||||||
|
|
||||||
|
# --- Image 2: with WORKINGDIR, test relative guest path ---
|
||||||
|
img="slim-test-mount-wd"
|
||||||
|
share_dir3="$work/share3"
|
||||||
|
|
||||||
|
mkdir -p "$share_dir3"
|
||||||
|
echo "relative share" > "$share_dir3/relfile.txt"
|
||||||
|
|
||||||
|
cat > "$work/Containerfile.wd" <<'EOF'
|
||||||
|
FROM alpine:latest
|
||||||
|
WORKDIR /app
|
||||||
|
CMD ["/bin/sh", "-c", "poweroff -f"]
|
||||||
|
EOF
|
||||||
|
|
||||||
|
echo "-- Building container image (WORKINGDIR /app)..."
|
||||||
|
if ! podman build --network=none -t "$img" -f "$work/Containerfile.wd" >/dev/null 2>&1; then
|
||||||
|
report fail "--mount relative (podman build failed)"
|
||||||
|
rm -rf "$work"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "-- Building slim VM..."
|
||||||
|
if ! "$SLIM_BIN" build qcow2 "$img" >/dev/null 2>&1; then
|
||||||
|
report fail "--mount relative (slim build failed)"
|
||||||
|
cleanup "$img" "$img"
|
||||||
|
rm -rf "$work"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "-- Test 2: --mount host:relative-guest (resolved against WORKINGDIR)..."
|
||||||
|
output=$(timeout "$TIMEOUT" "$SLIM_BIN" run "$img" \
|
||||||
|
--mount "${share_dir3}:data" \
|
||||||
|
--cmd "mount -v; cat /app/data/relfile.txt 2>/dev/null || echo NO_REL_FILE; echo REL_VERIFY_DONE; poweroff -f" \
|
||||||
|
2>&1 || true)
|
||||||
|
|
||||||
|
check_output "$output" "type 9p" "--mount relative 9p filesystem in mount list"
|
||||||
|
check_output "$output" "relative share" "--mount relative file accessible at WORKINGDIR/data"
|
||||||
|
check_output "$output" "REL_VERIFY_DONE" "--mount relative VM ran to completion"
|
||||||
|
|
||||||
|
cleanup "$img" "$img"
|
||||||
|
rm -rf "$work"
|
||||||
|
}
|
||||||
|
|
||||||
test_service() {
|
test_service() {
|
||||||
echo "=== Testing nextcloud service ==="
|
echo "=== Testing nextcloud service ==="
|
||||||
|
|
||||||
@@ -171,6 +301,10 @@ cargo build 2>&1
|
|||||||
test_distro "alpine" "alpine:latest" ""
|
test_distro "alpine" "alpine:latest" ""
|
||||||
test_distro "archlinux" "archlinux:latest" "RUN pacman -Sy --noconfirm iproute2 wget; pacman -Sc --noconfirm"
|
test_distro "archlinux" "archlinux:latest" "RUN pacman -Sy --noconfirm iproute2 wget; pacman -Sc --noconfirm"
|
||||||
|
|
||||||
|
test_user
|
||||||
|
|
||||||
|
test_mount
|
||||||
|
|
||||||
test_service
|
test_service
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|||||||
+6
-1
@@ -78,7 +78,12 @@ fn build_inner(
|
|||||||
let command = cmd.unwrap_or_else(|| inject::infer_command(&config));
|
let command = cmd.unwrap_or_else(|| inject::infer_command(&config));
|
||||||
let exec_script =
|
let exec_script =
|
||||||
inject::build_exec_script(&command, &config.env, config.working_dir.as_deref());
|
inject::build_exec_script(&command, &config.env, config.working_dir.as_deref());
|
||||||
inject::inject(mount_path, &exec_script)?;
|
inject::inject(
|
||||||
|
mount_path,
|
||||||
|
&exec_script,
|
||||||
|
config.user.as_deref(),
|
||||||
|
config.working_dir.as_deref(),
|
||||||
|
)?;
|
||||||
println!("Injected /slim/ (init + exec)");
|
println!("Injected /slim/ (init + exec)");
|
||||||
|
|
||||||
match kind {
|
match kind {
|
||||||
|
|||||||
+31
-23
@@ -22,6 +22,8 @@ pub struct Config {
|
|||||||
pub env: Vec<String>,
|
pub env: Vec<String>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub working_dir: Option<String>,
|
pub working_dir: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub user: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inspect_config(image: &str) -> Result<Config> {
|
pub fn inspect_config(image: &str) -> Result<Config> {
|
||||||
@@ -85,33 +87,39 @@ pub fn build_exec_script(command: &str, env: &[String], working_dir: Option<&str
|
|||||||
lines
|
lines
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inject /slim/init and /slim/exec into a mounted container image rootfs.
|
/// Install `content` into the mounted rootfs at `<mount>/slim/<name>` with
|
||||||
pub fn inject(mount_path: &Path, exec_script: &str) -> Result<()> {
|
/// the given mode.
|
||||||
|
fn install_into_rootfs(mount: &str, name: &str, mode: &str, content: &str) -> Result<()> {
|
||||||
|
let temp = tempfile::NamedTempFile::new()?;
|
||||||
|
fs::write(temp.path(), content)?;
|
||||||
|
let src = temp.path().to_str().context("temp path is not UTF-8")?;
|
||||||
|
let dest = format!("{mount}/slim/{name}");
|
||||||
|
cmd(&[
|
||||||
|
"podman", "unshare", "--", "install", "-D", "-m", mode, src, &dest,
|
||||||
|
])?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inject /slim/init, /slim/exec, and optionally /slim/user and /slim/workdir
|
||||||
|
/// into a mounted container image rootfs.
|
||||||
|
pub fn inject(
|
||||||
|
mount_path: &Path,
|
||||||
|
exec_script: &str,
|
||||||
|
user: Option<&str>,
|
||||||
|
working_dir: Option<&str>,
|
||||||
|
) -> Result<()> {
|
||||||
let mount_str = mount_path.to_str().context("mount path is not UTF-8")?;
|
let mount_str = mount_path.to_str().context("mount path is not UTF-8")?;
|
||||||
|
|
||||||
let init_temp = tempfile::NamedTempFile::new()?;
|
install_into_rootfs(mount_str, "init", "755", SLIM_INIT)?;
|
||||||
let exec_temp = tempfile::NamedTempFile::new()?;
|
install_into_rootfs(mount_str, "exec", "755", exec_script)?;
|
||||||
fs::write(init_temp.path(), SLIM_INIT)?;
|
|
||||||
fs::write(exec_temp.path(), exec_script)?;
|
|
||||||
|
|
||||||
let init_src = init_temp
|
if let Some(user) = user.filter(|u| !u.is_empty()) {
|
||||||
.path()
|
install_into_rootfs(mount_str, "user", "644", user)?;
|
||||||
.to_str()
|
}
|
||||||
.context("temp path is not UTF-8")?;
|
|
||||||
let exec_src = exec_temp
|
|
||||||
.path()
|
|
||||||
.to_str()
|
|
||||||
.context("temp path is not UTF-8")?;
|
|
||||||
|
|
||||||
let init_dest = format!("{mount_str}/slim/init");
|
if let Some(dir) = working_dir.filter(|d| !d.is_empty()) {
|
||||||
let exec_dest = format!("{mount_str}/slim/exec");
|
install_into_rootfs(mount_str, "workdir", "644", dir)?;
|
||||||
|
}
|
||||||
cmd(&[
|
|
||||||
"podman", "unshare", "--", "install", "-D", "-m", "755", init_src, &init_dest,
|
|
||||||
])?;
|
|
||||||
cmd(&[
|
|
||||||
"podman", "unshare", "--", "install", "-D", "-m", "755", exec_src, &exec_dest,
|
|
||||||
])?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
+38
@@ -32,6 +32,13 @@ pub struct RunCmd {
|
|||||||
/// cmdline as slim.cmd=<b64>). Overrides the CMD inferred at build time.
|
/// cmdline as slim.cmd=<b64>). Overrides the CMD inferred at build time.
|
||||||
#[clap(long)]
|
#[clap(long)]
|
||||||
cmd: Option<String>,
|
cmd: Option<String>,
|
||||||
|
|
||||||
|
/// Share a host directory into the VM via 9p. Format:
|
||||||
|
/// `<host-path>` or `<host-path>:<guest-path>`. When the guest path is
|
||||||
|
/// omitted, the host path is used. Non-absolute guest paths are
|
||||||
|
/// relative to the image's WORKINGDIR. Can be repeated.
|
||||||
|
#[clap(long)]
|
||||||
|
mount: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn run(
|
pub(crate) fn run(
|
||||||
@@ -40,6 +47,7 @@ pub(crate) fn run(
|
|||||||
memory,
|
memory,
|
||||||
forward,
|
forward,
|
||||||
cmd,
|
cmd,
|
||||||
|
mount,
|
||||||
}: RunCmd,
|
}: RunCmd,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let reg_dir = registry_dir(&name)?;
|
let reg_dir = registry_dir(&name)?;
|
||||||
@@ -81,6 +89,35 @@ pub(crate) fn run(
|
|||||||
cmdline.push(format!("slim.cmd={encoded}"));
|
cmdline.push(format!("slim.cmd={encoded}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Build 9p shares for each --mount. Tags are short (slim0, slim1, …)
|
||||||
|
// because 9p mount_tag has a ~31-byte limit. The guest destination path
|
||||||
|
// is passed on the kernel cmdline as slim.mount=<tag>:<base64(guest_path)>.
|
||||||
|
// If no guest path is specified, the host path is used as the guest path.
|
||||||
|
let mut virtfs_args: Vec<String> = Vec::new();
|
||||||
|
for (i, spec) in mount.iter().enumerate() {
|
||||||
|
let (host_path, guest_path) = match spec.split_once(':') {
|
||||||
|
Some((h, g)) => (h, g),
|
||||||
|
None => (spec.as_str(), spec.as_str()),
|
||||||
|
};
|
||||||
|
let canonical = std::path::Path::new(host_path)
|
||||||
|
.canonicalize()
|
||||||
|
.with_context(|| format!("Cannot resolve mount path '{host_path}'"))?;
|
||||||
|
let host_str = canonical
|
||||||
|
.to_str()
|
||||||
|
.context("Mount path is not valid UTF-8")?;
|
||||||
|
let tag = format!("slim{i}");
|
||||||
|
let dest_b64 = base64::engine::general_purpose::STANDARD.encode(guest_path.as_bytes());
|
||||||
|
|
||||||
|
// QEMU's QemuOpts splits on commas — escape literal commas in the
|
||||||
|
// path as ",," per QEMU convention.
|
||||||
|
let host_escaped = host_str.replace(',', ",,");
|
||||||
|
virtfs_args.push("-virtfs".into());
|
||||||
|
virtfs_args.push(format!(
|
||||||
|
"local,path={host_escaped},mount_tag={tag},security_model=mapped-xattr"
|
||||||
|
));
|
||||||
|
cmdline.push(format!("slim.mount={tag}:{dest_b64}"));
|
||||||
|
}
|
||||||
|
|
||||||
println!("Booting {name} from registry: {}", reg_dir.display());
|
println!("Booting {name} from registry: {}", reg_dir.display());
|
||||||
|
|
||||||
let cmdline = cmdline.join(" ");
|
let cmdline = cmdline.join(" ");
|
||||||
@@ -101,6 +138,7 @@ pub(crate) fn run(
|
|||||||
.arg("-kernel")
|
.arg("-kernel")
|
||||||
.arg(vmlinuz_path.as_os_str())
|
.arg(vmlinuz_path.as_os_str())
|
||||||
.args(&fs_args)
|
.args(&fs_args)
|
||||||
|
.args(&virtfs_args)
|
||||||
.args(["-snapshot"])
|
.args(["-snapshot"])
|
||||||
.args(["-no-reboot"])
|
.args(["-no-reboot"])
|
||||||
.args(["-append", &cmdline])
|
.args(["-append", &cmdline])
|
||||||
|
|||||||
@@ -2,6 +2,11 @@
|
|||||||
# slim universal init - distro-agnostic VM bootstrap.
|
# slim universal init - distro-agnostic VM bootstrap.
|
||||||
# Injected by `slim build` at /slim/init and invoked via init=/slim/init.
|
# Injected by `slim build` at /slim/init and invoked via init=/slim/init.
|
||||||
|
|
||||||
|
# === Helpers ===
|
||||||
|
b64dec() {
|
||||||
|
printf '%s' "$1" | base64 -d 2>/dev/null || printf '%s' "$1" | openssl base64 -d 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
# === Devices & special filesystems ===
|
# === Devices & special filesystems ===
|
||||||
[ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
|
[ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
|
||||||
mkdir -p /proc /sys /dev/pts /dev/shm
|
mkdir -p /proc /sys /dev/pts /dev/shm
|
||||||
@@ -34,6 +39,70 @@ ip addr add 10.0.2.15/24 dev eth0 2>/dev/null || echo "ip addr add eth0 failed"
|
|||||||
ip route add default via 10.0.2.2 2>/dev/null || echo "ip route add default failed"
|
ip route add default via 10.0.2.2 2>/dev/null || echo "ip route add default failed"
|
||||||
echo nameserver 10.0.2.3 > /etc/resolv.conf
|
echo nameserver 10.0.2.3 > /etc/resolv.conf
|
||||||
|
|
||||||
|
# === 9p shares (host directories shared via --mount) ===
|
||||||
|
# Each share is passed as slim.mount=<tag>:<base64(guest_path)> on the
|
||||||
|
# kernel cmdline. The 9p tag is short (e.g. slim0) because mount_tag
|
||||||
|
# has a ~31-byte limit; the guest path is base64-encoded.
|
||||||
|
# Non-absolute guest paths are resolved against /slim/workdir (the
|
||||||
|
# image's WORKINGDIR).
|
||||||
|
SLIM_WORKDIR=""
|
||||||
|
[ -f /slim/workdir ] && SLIM_WORKDIR=$(cat /slim/workdir 2>/dev/null)
|
||||||
|
# shellcheck disable=SC2013 # word-splitting is intentional: cmdline tokens are space-separated
|
||||||
|
for tok in $(cat /proc/cmdline 2>/dev/null); do
|
||||||
|
case "$tok" in
|
||||||
|
slim.mount=*)
|
||||||
|
v=${tok#slim.mount=}
|
||||||
|
tag=${v%%:*}
|
||||||
|
dest_b64=${v#*:}
|
||||||
|
dest=$(b64dec "$dest_b64") || echo "base64 decode failed"
|
||||||
|
if [ -n "$tag" ] && [ -n "$dest" ]; then
|
||||||
|
# Resolve relative paths against the image's WORKINGDIR
|
||||||
|
case "$dest" in
|
||||||
|
/*) ;;
|
||||||
|
*) dest="${SLIM_WORKDIR:-/}/${dest}" ;;
|
||||||
|
esac
|
||||||
|
mkdir -p "$dest"
|
||||||
|
mount -t 9p "$tag" "$dest" -o trans=virtio,version=9p2000.L 2>/dev/null \
|
||||||
|
&& echo "mounted 9p '$tag' -> '$dest'" \
|
||||||
|
|| echo "failed to mount 9p '$tag' -> '$dest'"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# === Drop privileges (respect USER directive from image config) ===
|
||||||
|
# /slim/user may contain a username, uid, or uid:gid (OCI image spec).
|
||||||
|
# Numeric uids are resolved to a username via /etc/passwd because BusyBox
|
||||||
|
# su does not accept numeric arguments.
|
||||||
|
SLIM_USER=""
|
||||||
|
[ -f /slim/user ] && SLIM_USER=$(cat /slim/user 2>/dev/null)
|
||||||
|
|
||||||
|
# Resolve a numeric uid to a username from /etc/passwd.
|
||||||
|
slim_resolve_user() {
|
||||||
|
_u="$1"
|
||||||
|
case "$_u" in
|
||||||
|
*[!0-9]*) printf '%s' "$_u" ;;
|
||||||
|
*)
|
||||||
|
_resolved=$(awk -F: -v uid="$_u" '$3==uid{print $1; exit}' /etc/passwd 2>/dev/null)
|
||||||
|
[ -n "$_resolved" ] && printf '%s' "$_resolved" || printf '%s' "$_u"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Exec a command, dropping privileges if SLIM_USER is set.
|
||||||
|
# When dropping privileges, run as a child (not exec) so PID 1 stays root
|
||||||
|
# and can poweroff after the command exits — non-root cannot call poweroff.
|
||||||
|
slim_exec() {
|
||||||
|
_cmd="$1"
|
||||||
|
if [ -z "$SLIM_USER" ]; then
|
||||||
|
exec /bin/sh -c "$_cmd"
|
||||||
|
fi
|
||||||
|
_user="${SLIM_USER%%:*}"
|
||||||
|
_user=$(slim_resolve_user "$_user")
|
||||||
|
su "$_user" -c "$_cmd"
|
||||||
|
poweroff -f
|
||||||
|
}
|
||||||
|
|
||||||
# === Execute the configured command ===
|
# === Execute the configured command ===
|
||||||
# If slim.cmd=<base64> is on the kernel cmdline, decode and exec it.
|
# If slim.cmd=<base64> is on the kernel cmdline, decode and exec it.
|
||||||
# Otherwise, exec /slim/exec (generated from the image's CMD/ENTRYPOINT).
|
# Otherwise, exec /slim/exec (generated from the image's CMD/ENTRYPOINT).
|
||||||
@@ -42,13 +111,11 @@ for tok in $(cat /proc/cmdline 2>/dev/null); do
|
|||||||
case "$tok" in
|
case "$tok" in
|
||||||
slim.cmd=*)
|
slim.cmd=*)
|
||||||
v=${tok#slim.cmd=}
|
v=${tok#slim.cmd=}
|
||||||
decoded=$(printf '%s' "$v" | base64 -d 2>/dev/null) \
|
decoded=$(b64dec "$v") || echo "base64 decode failed"
|
||||||
|| decoded=$(printf '%s' "$v" | openssl base64 -d 2>/dev/null) \
|
|
||||||
|| echo "base64 decode failed"
|
|
||||||
if [ -n "$decoded" ]; then
|
if [ -n "$decoded" ]; then
|
||||||
exec /bin/sh -c "$decoded"
|
slim_exec "$decoded"
|
||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
exec /slim/exec
|
slim_exec "/slim/exec"
|
||||||
|
|||||||
Reference in New Issue
Block a user