commit 03da1036befa8cd86cb320563b04eec9cd57dd1d
parent ba602ab35261343c82e74d654e8624144fb13b56
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Wed, 30 Apr 2025 00:14:46 +0000
Split pthbs-setup generator out of pthbs-build, use syd-lock in favour of syd
Diffstat:
2 files changed, 263 insertions(+), 171 deletions(-)
diff --git a/command/pthbs-build b/command/pthbs-build
@@ -81,14 +81,45 @@ fi
mkdir -p "$workdir"
case $(id -u) in
(0)
- sandbox_mode=root
export pthbs_uid=$(id -u pthbs) || exit $?
export pthbs_gid=$(id -g pthbs) || exit $?
export pthbs_install_uid=0 || exit $?
export pthbs_install_gid=$pthbs_gid || exit $?
+ sandbox_mode=rootns
;;
(*)
- sandbox_mode=userns
+ if which syd-lock 2>/dev/null 1>&2; then
+ sandbox_mode=landlock
+ else
+ sandbox_mode=userns
+ fi
+ ;;
+esac
+case "$pthbs_sandbox" in
+ (*:*)
+ sandbox_cmd=${pthbs_sandbox#*:}
+ pthbs_sandbox=${pthbs_sandbox%%:*}
+ ;;
+esac
+case "$pthbs_sandbox" in
+ (syd-lock)
+ (landlock)
+ sandbox_mode=landlock;;
+ (root)
+ (rootns)
+ sandbox_mode=rootns;;
+ (user)
+ (userns)
+ sandbox_mode=userns;;
+ ()
+ if test -n "$sandbox_cmd"; then
+ printf '%s\n' >&2 "$0: fatal: pthbs_sandbox defines command but no mode"
+ exit 100
+ fi
+ ;;
+ (*)
+ printf '%s\n' >&2 "$0: fatal: unrecognized sandbox mode in pthbs_sandbox: '$pthbs_sandbox'"
+ exit 100
;;
esac
@@ -96,175 +127,8 @@ env \
workdir="$workdir" \
script="$script" \
envdir="$pthbs_build_environment" \
- awk -v single_quote="'" -v sandbox_mode="$sandbox_mode" >"$workdir/pthbs-setup" '
-BEGIN {
- settings["sandbox"] = 1
- settings["set_path"] = 1
- FS=":"
- print "#!/bin/sh -e"
- print "if test -n \"$pthbs_xtrace\"; then"
- print " set -x"
- print " if test -n \"$BB_ASH_VERSION\"; then PS4=\"+${0##*/}\"" single_quote ":${FUNCNAME}:${LINENO} " single_quote "; fi"
- print "fi"
- print "cd "q(ENVIRON["workdir"])
- if(ENVIRON["pthbs_uid"]) {
- print "export pthbs_uid=" ENVIRON["pthbs_uid"]
- }
- if(ENVIRON["pthbs_gid"]) {
- print "export pthbs_gid=" ENVIRON["pthbs_gid"]
- }
-}
-
-function q(s) { # quote string for sh
- gsub(single_quote, single_quote "\\" single_quote single_quote, s)
- return single_quote s single_quote
-}
-
-function dirname(s) { # strip the last path component
- sub("/[^/]*$", "", s)
- return s
-}
-
-function basename(s) { # strip the last path component
- sub("^.*/$", "", s)
- return s
-}
-
-function fatal(msg) {
- printf "FATAL: pthbs-build: %s %s:%d: \"%s\"\n", msg, FILENAME, FNR, $0 >"/dev/stderr"
- exit 1
-}
-
-function qlink(rel) {
- return q(ENVIRON["pthbs_cache"] "/link/" rel)
-}
-
-function at_git(commit_id, dstdir){
- print "mkdir -p "q(dstdir)
- print "(cd "qlink("git-commit-sha1/"commit_id)" && git archive --format=tar "q(commit_id)" ) | tar --no-same-owner --no-same-permissions -xC "q(dstdir)
-}
-
-function at_untar(extra_opts, hash_type, file_hash, dstdir){
- print "mkdir -p "q(dstdir)
- print "tar -x "extra_opts" -C "q(dstdir)" -f "qlink("file-"hash_type"/"file_hash)
-}
-
-function at_filehash(hash_type, file_hash, dst, dstdir){
- if(dst ~ /\//) {
- dstdir = dst
- sub("/[^/]*$", "", dstdir)
- print "mkdir -p "q(dstdir)
- }
- print "cp -Lp "qlink("file-"hash_type"/"file_hash)" "q(dst)
-}
-
-/^#!/ { next }
-/^#\+/ {
- if($0 == "#+*") {
- settings["sandbox"] = 0
- } else if(!length(ENVIRON["envdir"])) {
- fatal("dependency specified but no envfile:")
- }
- next
-}
-/^#@/ {
- if($1 == "#@git") {
- if(match($0, "^#@git:[0-9a-f]+:") == 0) {
- fatal("invalid syntax for @git:")
- }
- at_git($2, substr($0, RLENGTH+1))
- } else if($1 == "#@sha256") {
- if(match($0, "^#@sha256:[0-9a-f]+:") == 0) {
- fatal("invalid syntax for @sha256:")
- }
- at_filehash("sha256", $2, substr($0, RLENGTH+1))
- } else if($1 == "#@untar") {
- if(match($0, "^#@untar:[^:]*:sha256:[0-9a-f]+:") == 0) {
- fatal("invalid syntax for @untar:")
- }
- at_untar($2, $3, $4, substr($0, RLENGTH+1))
- } else if($1 == "#@pragma") {
- if($2 == "nosandbox") {
- settings["sandbox"] = 0
- } else if($2 == "nopath") {
- settings["set_path"] = 0
- } else {
- fatal("unrecognized @pragma:")
- }
- } else {
- fatal("unrecognized @command:")
- }
- next
-}
-/^$/ {
- if(settings["sandbox"]) {
- if(length(ENVIRON["PTHBS_SYD"])) {
- sandbox_cmd=" SYD_NO_SYSLOG=1 SYD_LOG_FD=3 3>syd.log"
- sandbox_cmd=sandbox_cmd " " ENVIRON["PTHBS_SYD"] " -m sandbox/stat:off -m sandbox/exec:off"
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+"ENVIRON["workdir"]"/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/write+"ENVIRON["workdir"]"/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/proc/loadavg")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/passwd")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/group")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/tmp/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/write+/tmp/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/dev/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/write+/dev/***")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+"ENVIRON["script"])
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+"dirname(ENVIRON["envdir"])"/***")
- sandbox_cmd=sandbox_cmd " -munshare/user:1"
- sandbox_cmd=sandbox_cmd " -munshare/mount:1"
- sandbox_cmd=sandbox_cmd " -mbind+" q(ENVIRON["pthbs_workdir"]"/bin:/bin:ro,nosuid,nodev")
- sandbox_cmd=sandbox_cmd " -m " q("allow/read+/bin/***")
- sandbox_cmd=sandbox_cmd " -munshare/net:1 -munshare/ipc:1"
- } else if(sandbox_mode == "userns") {
- sandbox_cmd=" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=userns"
- sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"])
- sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp")
- sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root")
- printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root")
- } else if(sandbox_mode == "root") {
- sandbox_cmd=" "q(ENVIRON["pthbs_cache"]"/venv/bin/python")" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=root"
- sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"])
- sandbox_cmd=sandbox_cmd" --untar="q(ENVIRON["pthbs_source"]"/sandbox/root.tar")
- sandbox_cmd=sandbox_cmd" --chdir="q(ENVIRON["workdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"])
- sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp")
- sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root")
- printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root")
- } else {
- fatal("unrecognized sanbox_mode " sandbox_mode)
- }
- } else if(ENVIRON["pthbs_uid"]){
- sandbox_cmd="busybox chpst -u \"$pthbs_uid:$pthbs_gid\" --"
- } else {
- sandbox_cmd=""
- }
- if(ENVIRON["pthbs_uid"]) {
- printf "%s\n", "chown -R \"$pthbs_uid:$pthbs_gid\" "q(ENVIRON["workdir"])
- }
- if(length(ENVIRON["envdir"])){
- cmd="env pthbs_build_environment="q(ENVIRON["envdir"])
- cmd=cmd" "sandbox_cmd
- if(settings["set_path"]) {
- cmd=cmd" "q(ENVIRON["envdir"]"/command/pthbs-enter")
- }
- cmd=cmd" sh -xe "q(ENVIRON["script"])
- } else {
- cmd=sandbox_cmd" sh -xe "q(ENVIRON["script"])
- }
- print "exec >build.log 2>&1 " cmd
- exit 0
-}
-{
- fatal("unexpected line")
-}
-' "$1" || exit $?
+ sandbox_cmd="$sandbox_cmd"
+ awk -v sandbox_mode="$sandbox_mode" -f "$pthbs_source/command/pthbs-setup-gen.awk" >"$workdir/pthbs-setup" "$1" || exit $?
if test -z "$JOBS"; then
JOBS=$(nproc)
diff --git a/command/pthbs-setup-gen.awk b/command/pthbs-setup-gen.awk
@@ -0,0 +1,228 @@
+BEGIN {
+ settings["sandbox"] = 1
+ settings["set_path"] = 1
+ FS=":"
+ single_quote="'"
+ print "#!/bin/sh -e"
+ print "if test -n \"$pthbs_xtrace\"; then"
+ print " set -x"
+ print " if test -n \"$BB_ASH_VERSION\"; then PS4=\"+${0##*/}\"" single_quote ":${FUNCNAME}:${LINENO} " single_quote "; fi"
+ print "fi"
+ print "cd "q(ENVIRON["workdir"])
+ if(ENVIRON["pthbs_uid"]) {
+ print "export pthbs_uid=" ENVIRON["pthbs_uid"]
+ }
+ if(ENVIRON["pthbs_gid"]) {
+ print "export pthbs_gid=" ENVIRON["pthbs_gid"]
+ }
+}
+
+function q(s) { # quote string for sh
+ gsub(single_quote, single_quote "\\" single_quote single_quote, s)
+ return single_quote s single_quote
+}
+
+function dirname(s) { # strip the last path component
+ sub("/[^/]*$", "", s)
+ return s
+}
+
+function basename(s) { # strip the last path component
+ sub("^.*/$", "", s)
+ return s
+}
+
+function fatal(msg) {
+ printf "FATAL: pthbs-build: %s %s:%d: \"%s\"\n", msg, FILENAME, FNR, $0 >"/dev/stderr"
+ exit 1
+}
+
+function qlink(rel) {
+ return q(ENVIRON["pthbs_cache"] "/link/" rel)
+}
+
+function at_git(commit_id, dstdir){
+ print "mkdir -p "q(dstdir)
+ print "(cd "qlink("git-commit-sha1/"commit_id)" && git archive --format=tar "q(commit_id)" ) | tar --no-same-owner --no-same-permissions -xC "q(dstdir)
+}
+
+function at_untar(extra_opts, hash_type, file_hash, dstdir){
+ print "mkdir -p "q(dstdir)
+ print "tar -x "extra_opts" -C "q(dstdir)" -f "qlink("file-"hash_type"/"file_hash)
+}
+
+function at_filehash(hash_type, file_hash, dst, dstdir){
+ if(dst ~ /\//) {
+ dstdir = dst
+ sub("/[^/]*$", "", dstdir)
+ print "mkdir -p "q(dstdir)
+ }
+ print "cp -Lp "qlink("file-"hash_type"/"file_hash)" "q(dst)
+}
+function sydbox_ro_tree(dirpath) {
+ sandbox_cmd=sandbox_cmd " -m " q("allow/read,readdir,chdir+"dirpath"/***")
+}
+function sydbox_rw_tree(dirpath) {
+ sydbox_ro_tree(dirpath)
+ sandbox_cmd=sandbox_cmd " -m " q("allow/write,create,delete,rename,symlink,mkdir,chmod,mkfifo+"dirpath"/***")
+}
+
+function sandbox_ns_common(args, s) {
+ if(length(ENVIRON["sandbox_cmd"])) {
+ s = ENVIRON["sandbox_cmd"]
+ } else {
+ s = q(ENVIRON["pthbs_cache"]"/venv/bin/python")" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")
+ }
+ s = s" --versions="q(ENVIRON["pthbs_versions"])
+ s = s" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"])
+ s = s" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"])
+ s = s" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"])
+ s = s" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp")
+ s = s" -- "q(ENVIRON["pthbs_workdir"]"/root")
+ printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root")
+ return s
+}
+function sandbox( s) {
+ if(!settings["sandbox"]) {
+ if(ENVIRON["pthbs_uid"]){
+ return "busybox chpst -u \"$pthbs_uid:$pthbs_gid\" --"
+ }
+ return ""
+ }
+ if(sandbox_mode == "rootns") {
+ s = " --mode=root"
+ s = s" --untar="q(ENVIRON["pthbs_source"]"/sandbox/root.tar")
+ s = s" --chdir="q(ENVIRON["workdir"])
+ return sandbox_ns_common(s)
+ } else if(sandbox_mode == "userns") {
+ return sandbox_ns_common("--mode=userns")
+ } else if(sandbox_mode == "landlock") {
+ s = length(ENVIRON["sandbox_cmd"]) ? ENVIRON["sandbox_cmd"] : "syd-lock"
+ # R/O dirs
+ s = s" -r "q("/bin")
+ s = s" -r "q(dirname(ENVIRON["envdir"]))
+ # R/O files
+ s = s" -r "q("/proc/loadavg")
+ s = s" -r "q("/proc/loadavg")
+ s = s" -r "q("/etc/passwd")
+ s = s" -r "q("/etc/group")
+ s = s" -r "q(""ENVIRON["script"])
+ # R/W dirs
+ s = s" -w "q(ENVIRON["workdir"])
+ s = s" -w "q("/tmp")
+ s = s" -w "q("/dev")
+ s = s" -w "q("/proc")
+ return s
+ }
+ fatal("unrecognized sanbox_mode " sandbox_mode)
+}
+
+/^#!/ { next }
+/^#\+/ {
+ if($0 == "#+*") {
+ settings["sandbox"] = 0
+ } else if(!length(ENVIRON["envdir"])) {
+ fatal("dependency specified but no envfile:")
+ }
+ next
+}
+/^#@/ {
+ if($1 == "#@git") {
+ if(match($0, "^#@git:[0-9a-f]+:") == 0) {
+ fatal("invalid syntax for @git:")
+ }
+ at_git($2, substr($0, RLENGTH+1))
+ } else if($1 == "#@sha256") {
+ if(match($0, "^#@sha256:[0-9a-f]+:") == 0) {
+ fatal("invalid syntax for @sha256:")
+ }
+ at_filehash("sha256", $2, substr($0, RLENGTH+1))
+ } else if($1 == "#@untar") {
+ if(match($0, "^#@untar:[^:]*:sha256:[0-9a-f]+:") == 0) {
+ fatal("invalid syntax for @untar:")
+ }
+ at_untar($2, $3, $4, substr($0, RLENGTH+1))
+ } else if($1 == "#@pragma") {
+ if($2 == "nosandbox") {
+ settings["sandbox"] = 0
+ } else if($2 == "nopath") {
+ settings["set_path"] = 0
+ } else {
+ fatal("unrecognized @pragma:")
+ }
+ } else {
+ fatal("unrecognized @command:")
+ }
+ next
+}
+/^$/ {
+ sandbox_cmd = sandbox()
+ if(settings["sandbox"]) {
+ if(length(ENVIRON["PTHBS_SYD"])) {
+ sandbox_cmd=" SYD_NO_SYSLOG=1 SYD_LOG_FD=3 3>syd.log"
+ sandbox_cmd=sandbox_cmd " " ENVIRON["PTHBS_SYD"]
+ sandbox_cmd=sandbox_cmd " -m sandbox/force:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/stat:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/exec:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/truncate:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/utime:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/chown:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/chgrp:off"
+ sandbox_cmd=sandbox_cmd " -m sandbox/ioctl:off"
+ sandbox_cmd=sandbox_cmd " -m " q("allow/read+/proc/loadavg")
+ sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/passwd")
+ sandbox_cmd=sandbox_cmd " -m " q("allow/read+/etc/group")
+ sandbox_cmd=sandbox_cmd " -m " q("allow/read+"ENVIRON["script"])
+ sydbox_rw_tree(ENVIRON["workdir"])
+ sydbox_rw_tree("/tmp")
+ sydbox_rw_tree("/dev")
+ sydbox_rw_tree("/proc")
+ sydbox_ro_tree(dirname(ENVIRON["envdir"]))
+ sandbox_cmd=sandbox_cmd " -munshare/user:1"
+ sandbox_cmd=sandbox_cmd " -munshare/mount:1"
+ sandbox_cmd=sandbox_cmd " -mbind+" q(ENVIRON["pthbs_workdir"]"/bin:/bin:ro,nosuid,nodev")
+ sydbox_ro_tree("/bin")
+ sandbox_cmd=sandbox_cmd " -munshare/net:1 -munshare/ipc:1"
+ } else if(sandbox_mode == "userns") {
+ sandbox_cmd=" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=userns"
+ sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp")
+ sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root")
+ printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root")
+ } else if(sandbox_mode == "root") {
+ sandbox_cmd=" "q(ENVIRON["pthbs_cache"]"/venv/bin/python")" "q(ENVIRON["pthbs_source"]"/sandbox/ns_sandbox.py")" --mode=root"
+ sandbox_cmd=sandbox_cmd" --versions="q(ENVIRON["pthbs_versions"])
+ sandbox_cmd=sandbox_cmd" --untar="q(ENVIRON["pthbs_source"]"/sandbox/root.tar")
+ sandbox_cmd=sandbox_cmd" --chdir="q(ENVIRON["workdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=tmpfs:"q(ENVIRON["pthbs_workdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=ro_bind:"q(ENVIRON["pthbs_pkgdir"]":"ENVIRON["pthbs_pkgdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]":"ENVIRON["workdir"])
+ sandbox_cmd=sandbox_cmd" --extra-mount=rw_bind:"q(ENVIRON["workdir"]"/.tmp:/tmp")
+ sandbox_cmd=sandbox_cmd" -- "q(ENVIRON["pthbs_workdir"]"/root")
+ printf "%s\n", "mkdir -p "q(ENVIRON["workdir"]"/.tmp")" "q(ENVIRON["pthbs_workdir"]"/root")
+ } else {
+ fatal("unrecognized sanbox_mode " sandbox_mode)
+ }
+ }
+ if(ENVIRON["pthbs_uid"]) {
+ printf "%s\n", "chown -R \"$pthbs_uid:$pthbs_gid\" "q(ENVIRON["workdir"])
+ }
+ if(length(ENVIRON["envdir"])){
+ cmd="env pthbs_build_environment="q(ENVIRON["envdir"])
+ cmd=cmd" "sandbox_cmd
+ if(settings["set_path"]) {
+ cmd=cmd" "q(ENVIRON["envdir"]"/command/pthbs-enter")
+ }
+ cmd=cmd" sh -xe "q(ENVIRON["script"])
+ } else {
+ cmd=sandbox_cmd" sh -xe "q(ENVIRON["script"])
+ }
+ print "exec >build.log 2>&1 " cmd
+ exit 0
+}
+{
+ fatal("unexpected line")
+}