From 4936f1193b7f2c19c4755112e279b0f5583ae29e Mon Sep 17 00:00:00 2001 From: Steffen Beyer Date: Fri, 10 Apr 2026 16:57:25 +0200 Subject: [PATCH] Define assembly privileged builder policy --- docs/plan.md | 16 +++- modules/fruix/system/freebsd/media.scm | 114 ++++++++++++++++++----- modules/fruix/system/freebsd/storage.scm | 53 +++++++---- modules/fruix/system/freebsd/utils.scm | 90 ++++++++++++++++++ scripts/fruix.scm | 6 ++ 5 files changed, 234 insertions(+), 45 deletions(-) diff --git a/docs/plan.md b/docs/plan.md index b9f6ca8..9d6c7a6 100644 --- a/docs/plan.md +++ b/docs/plan.md @@ -295,14 +295,19 @@ Current progress: - package profile materialization uses jailed merge policy - system closure profile/development-profile/build-profile assembly uses jailed union-tree policy +- rootfs population helpers now run through the jailed helper path too +- image/installer/ISO assembly now records staged jail metadata and uses a + dedicated assembly privileged policy surface - network is disabled by default in these jailed paths - union assembly mounts are now much smaller and omit host `/etc` and `devfs` +- direct block-device `system install` is now an explicit opt-in under the + assembly policy instead of the default path Next likely steps: -- tighten rootfs population helpers similarly -- then define a stricter privileged builder policy for image / installer / ISO - assembly +- keep shrinking the privileged surface for image / installer / ISO assembly +- decide whether some remaining host-side image construction steps should move + behind a more explicit dedicated privileged helper or runner ## Runtime / development / build separation @@ -487,11 +492,14 @@ This is useful and should continue: Recent work reduced union/closure/profile assembly jail mounts to a much smaller runtime surface. -That direction should continue into: +That direction has now continued into: - rootfs population helpers - image/installer/ISO assembly under a dedicated privileged builder policy +The next refinement is to reduce the remaining privileged host-side surface +further, especially around final image/device manipulation. + ## Summary Short version: diff --git a/modules/fruix/system/freebsd/media.scm b/modules/fruix/system/freebsd/media.scm index 0287ca6..68df84f 100644 --- a/modules/fruix/system/freebsd/media.scm +++ b/modules/fruix/system/freebsd/media.scm @@ -374,6 +374,12 @@ (call-with-input-file metadata-file read))))) (chmod metadata-file #o644))) +(define (write-assembly-privileged-policy-file metadata-file policy) + (when metadata-file + (mkdir-p (dirname metadata-file)) + (write-file metadata-file (object->string policy)) + (chmod metadata-file #o644))) + (define (rootfs-helper-read-only-mounts extra-paths) (map (lambda (path) (cons path path)) @@ -1059,10 +1065,10 @@ (installer-root-partition-label . ,installer-root-partition-label) (target-install . ,target-install-spec)))) -(define image-builder-version "4") -(define install-builder-version "4") -(define installer-image-builder-version "5") -(define installer-iso-builder-version "6") +(define image-builder-version "5") +(define install-builder-version "5") +(define installer-image-builder-version "6") +(define installer-iso-builder-version "7") (define* (operating-system-install-storage-layout os #:key @@ -1108,10 +1114,14 @@ (object->string realized-storage-layout)) (chmod (string-append install-root "/realized-storage-layout.scm") #o644)))) -(define (install-metadata-file-into-mounted-root source-path mounted-target-path) +(define (install-metadata-file-into-mounted-root privileged-policy source-path mounted-target-path) (when (file-exists? source-path) - (run-privileged-command "mkdir" "-p" (dirname mounted-target-path)) - (run-privileged-command "cp" "-p" source-path mounted-target-path))) + (run-assembly-privileged-command privileged-policy + 'copy-into-mounted-root + "mkdir" "-p" (dirname mounted-target-path)) + (run-assembly-privileged-command privileged-policy + 'copy-into-mounted-root + "cp" "-p" source-path mounted-target-path))) (define (render-installer-apply-script store-dir plan-directory) (let ((target-rootfs (string-append plan-directory "/target-rootfs")) @@ -1419,16 +1429,24 @@ "load_rc_config $name\n" "run_rc_command \"$1\"\n")) -(define (resize-gpt-image image disk-capacity) +(define* (resize-gpt-image image disk-capacity + #:key + (privileged-policy (default-assembly-privileged-policy))) (when disk-capacity (run-command "truncate" "-s" disk-capacity image) - (let ((md (privileged-command-output "mdconfig" "-a" "-t" "vnode" "-f" image))) + (let ((md (assembly-privileged-command-output privileged-policy + 'mdconfig-attach + "mdconfig" "-a" "-t" "vnode" "-f" image))) (dynamic-wind (lambda () #t) (lambda () - (run-privileged-command "gpart" "recover" (string-append "/dev/" md))) + (run-assembly-privileged-command privileged-policy + 'gpart-recover + "gpart" "recover" (string-append "/dev/" md))) (lambda () - (run-privileged-command "mdconfig" "-d" "-u" (string-drop md 2))))))) + (run-assembly-privileged-command privileged-policy + 'mdconfig-detach + "mdconfig" "-d" "-u" (string-drop md 2))))))) (define* (install-operating-system os #:key @@ -1448,7 +1466,16 @@ (serial-console "comconsole")) (unless (and (string? target) (not (string-null? target))) (error "install target must be a non-empty path" target)) - (let* ((closure (materialize-operating-system os + (let* ((target-kind (if (string-prefix? "/dev/" target) + 'block-device + 'raw-file)) + (privileged-policy (default-assembly-privileged-policy)) + (_policy-check (or (assembly-privileged-policy-allows-install-target-kind? privileged-policy + target-kind) + (error "assembly privileged policy forbids install target kind; set FRUIX_ASSEMBLY_ALLOW_BLOCK_DEVICE_TARGETS=1 to allow block-device targets" + target-kind + privileged-policy))) + (closure (materialize-operating-system os #:store-dir store-dir #:guile-prefix guile-prefix #:guile-extra-prefix guile-extra-prefix @@ -1458,9 +1485,6 @@ #:declaration-system-symbol declaration-system-symbol)) (closure-path (assoc-ref closure 'closure-path)) (store-items (store-reference-closure (list closure-path))) - (target-kind (if (string-prefix? "/dev/" target) - 'block-device - 'raw-file)) (declared-storage-layout (operating-system-install-storage-layout os #:efi-size efi-size #:root-size root-size @@ -1480,9 +1504,12 @@ (mnt-root (string-append build-root "/mnt-root")) (install-metadata-relative-path "/var/lib/fruix/install.scm") (staging-metadata-relative-root "/var/lib/fruix/system/install/metadata") + (assembly-privileged-policy-path + (string-append staging-metadata-relative-root "/assembly-privileged-policy.scm")) (rootfs-populate-metadata-path (string-append staging-metadata-relative-root "/rootfs-populate.scm")) (rootfs-copy-metadata-path (string-append staging-metadata-relative-root "/rootfs-copy.scm")) (store-copy-metadata-path (string-append staging-metadata-relative-root "/store-copy.scm")) + (assembly-privileged-policy-file (string-append rootfs assembly-privileged-policy-path)) (rootfs-populate-metadata-file (string-append rootfs rootfs-populate-metadata-path)) (rootfs-copy-metadata-temp-file (string-append build-root "/rootfs-copy.scm")) (store-copy-metadata-temp-file (string-append build-root "/store-copy.scm")) @@ -1500,6 +1527,8 @@ #:install-spec install-spec #:install-metadata-path install-metadata-relative-path #:metadata-file rootfs-populate-metadata-file) + (write-assembly-privileged-policy-file assembly-privileged-policy-file + privileged-policy) (mkdir-p mnt-root) (case target-kind ((raw-file) @@ -1508,7 +1537,9 @@ (mkdir-p (dirname target)) (delete-path-if-exists target) (run-command "truncate" "-s" disk-capacity target) - (let ((md (privileged-command-output "mdconfig" "-a" "-t" "vnode" "-f" target))) + (let ((md (assembly-privileged-command-output privileged-policy + 'mdconfig-attach + "mdconfig" "-a" "-t" "vnode" "-f" target))) (set! target-md md) (set! target-device (string-append "/dev/" md)))) ((block-device) @@ -1517,7 +1548,8 @@ (storage-layout-with-device declared-storage-layout target-device)) (set! storage-plan (assoc-ref (apply-freebsd-storage-layout effective-storage-layout - #:root-mount-point mnt-root) + #:root-mount-point mnt-root + #:privileged-policy privileged-policy) 'plan)) (set! mounted-targets (freebsd-storage-plan-mount-targets storage-plan)) (let ((esp-entry (freebsd-storage-plan-partition-by-role storage-plan 'efi)) @@ -1551,12 +1583,14 @@ #:name "fruix-install-rootfs-copy" #:metadata-file rootfs-copy-metadata-temp-file #:user "root") - (install-metadata-file-into-mounted-root rootfs-copy-metadata-temp-file + (install-metadata-file-into-mounted-root privileged-policy + rootfs-copy-metadata-temp-file (string-append mnt-root rootfs-copy-metadata-path)) (copy-store-items-into-rootfs/isolated mnt-root store-dir store-items #:metadata-file store-copy-metadata-temp-file #:user "root") - (install-metadata-file-into-mounted-root store-copy-metadata-temp-file + (install-metadata-file-into-mounted-root privileged-policy + store-copy-metadata-temp-file (string-append mnt-root store-copy-metadata-path)) (run-command "sync") `((target . ,target) @@ -1568,6 +1602,7 @@ (declared-storage-layout . ,(storage-layout-spec declared-storage-layout)) (realized-storage-layout . ,(realized-freebsd-storage-layout storage-plan)) (install-metadata-path . ,install-metadata-relative-path) + (assembly-privileged-policy-path . ,assembly-privileged-policy-path) (rootfs-populate-metadata-path . ,rootfs-populate-metadata-path) (rootfs-copy-metadata-path . ,rootfs-copy-metadata-path) (store-copy-metadata-path . ,store-copy-metadata-path) @@ -1584,13 +1619,17 @@ (store-items . ,store-items))) (lambda () (for-each (lambda (mount-target) - (run-privileged-shell-command + (run-assembly-privileged-shell-command + privileged-policy + 'unmount-file-system (string-append "umount " (shell-quote mount-target) " >/dev/null 2>&1 || true"))) mounted-targets) (when target-md - (run-privileged-shell-command + (run-assembly-privileged-shell-command + privileged-policy + 'mdconfig-detach (string-append "mdconfig -d -u " (shell-quote (string-drop target-md 2)) " >/dev/null 2>&1 || true")) @@ -1630,6 +1669,7 @@ #:root-partition-label root-partition-label #:serial-console serial-console)) (store-items (store-reference-closure (list closure-path))) + (privileged-policy (default-assembly-privileged-policy)) (manifest (string-append "image-builder-version=\n" image-builder-version @@ -1647,6 +1687,8 @@ (disk-image (string-append image-store-path "/disk.img")) (esp-image (string-append image-store-path "/esp.img")) (root-image (string-append image-store-path "/root.ufs")) + (assembly-privileged-policy-file + (string-append image-store-path "/metadata/assembly-privileged-policy.scm")) (rootfs-populate-metadata-file (string-append image-store-path "/metadata/rootfs-populate.scm")) (image-rootfs-copy-metadata-file (string-append image-store-path "/metadata/image-rootfs-copy.scm")) (store-copy-metadata-file (string-append image-store-path "/metadata/store-copy.scm"))) @@ -1659,6 +1701,8 @@ (temp-disk (string-append build-root "/disk.img")) (temp-esp (string-append build-root "/esp.img")) (temp-root (string-append build-root "/root.ufs")) + (assembly-privileged-policy-temp-file + (string-append temp-output "/metadata/assembly-privileged-policy.scm")) (rootfs-populate-metadata-temp-file (string-append temp-output "/metadata/rootfs-populate.scm")) (image-rootfs-copy-metadata-temp-file (string-append temp-output "/metadata/image-rootfs-copy.scm")) (store-copy-metadata-temp-file (string-append temp-output "/metadata/store-copy.scm"))) @@ -1697,8 +1741,11 @@ "-p" (string-append "efi/" efi-partition-label ":=" temp-esp) "-p" (string-append "freebsd-ufs/" root-partition-label ":=" temp-root) "-o" temp-disk) - (resize-gpt-image temp-disk disk-capacity) + (resize-gpt-image temp-disk disk-capacity + #:privileged-policy privileged-policy) (mkdir-p temp-output) + (write-assembly-privileged-policy-file assembly-privileged-policy-temp-file + privileged-policy) (copy-regular-file temp-disk (string-append temp-output "/disk.img")) (copy-regular-file temp-esp (string-append temp-output "/esp.img")) (copy-regular-file temp-root (string-append temp-output "/root.ufs")) @@ -1717,6 +1764,7 @@ (string-append temp-output "/closure-path") (string-append temp-output "/.references") (string-append temp-output "/.fruix-package") + assembly-privileged-policy-temp-file rootfs-populate-metadata-temp-file image-rootfs-copy-metadata-temp-file store-copy-metadata-temp-file))) @@ -1728,6 +1776,7 @@ (disk-image . ,disk-image) (esp-image . ,esp-image) (root-image . ,root-image) + (assembly-privileged-policy-file . ,assembly-privileged-policy-file) (rootfs-populate-metadata-file . ,rootfs-populate-metadata-file) (image-rootfs-copy-metadata-file . ,image-rootfs-copy-metadata-file) (store-copy-metadata-file . ,store-copy-metadata-file) @@ -1788,6 +1837,7 @@ (target-store-items (store-reference-closure (list target-closure-path))) (installer-store-items (store-reference-closure (list installer-closure-path))) (combined-store-items (delete-duplicates (append installer-store-items target-store-items))) + (privileged-policy (default-assembly-privileged-policy)) (installer-image-spec (operating-system-installer-image-spec os #:install-target-device install-target-device #:installer-host-name installer-host-name @@ -1841,6 +1891,8 @@ (disk-image (string-append image-store-path "/disk.img")) (esp-image (string-append image-store-path "/esp.img")) (root-image (string-append image-store-path "/root.ufs")) + (assembly-privileged-policy-file + (string-append image-store-path "/metadata/assembly-privileged-policy.scm")) (installer-rootfs-populate-metadata-file (string-append image-store-path "/metadata/installer-rootfs-populate.scm")) (target-rootfs-populate-metadata-file @@ -1862,6 +1914,8 @@ (temp-esp (string-append build-root "/esp.img")) (temp-root (string-append build-root "/root.ufs")) (plan-root (string-append image-rootfs installer-plan-directory)) + (assembly-privileged-policy-temp-file + (string-append temp-output "/metadata/assembly-privileged-policy.scm")) (installer-rootfs-populate-metadata-temp-file (string-append temp-output "/metadata/installer-rootfs-populate.scm")) (target-rootfs-populate-metadata-temp-file @@ -1938,8 +1992,11 @@ "-p" (string-append "efi/" installer-efi-partition-label ":=" temp-esp) "-p" (string-append "freebsd-ufs/" installer-root-partition-label ":=" temp-root) "-o" temp-disk) - (resize-gpt-image temp-disk disk-capacity) + (resize-gpt-image temp-disk disk-capacity + #:privileged-policy privileged-policy) (mkdir-p temp-output) + (write-assembly-privileged-policy-file assembly-privileged-policy-temp-file + privileged-policy) (copy-regular-file temp-disk (string-append temp-output "/disk.img")) (copy-regular-file temp-esp (string-append temp-output "/esp.img")) (copy-regular-file temp-root (string-append temp-output "/root.ufs")) @@ -1962,6 +2019,7 @@ (string-append temp-output "/target-closure-path") (string-append temp-output "/.references") (string-append temp-output "/.fruix-package") + assembly-privileged-policy-temp-file installer-rootfs-populate-metadata-temp-file target-rootfs-populate-metadata-temp-file installer-rootfs-copy-metadata-temp-file @@ -1975,6 +2033,7 @@ (disk-image . ,disk-image) (esp-image . ,esp-image) (root-image . ,root-image) + (assembly-privileged-policy-file . ,assembly-privileged-policy-file) (installer-rootfs-populate-metadata-file . ,installer-rootfs-populate-metadata-file) (target-rootfs-populate-metadata-file . ,target-rootfs-populate-metadata-file) (installer-rootfs-copy-metadata-file . ,installer-rootfs-copy-metadata-file) @@ -2159,6 +2218,7 @@ (installer-store-items (runtime-store-items (store-reference-closure (list installer-closure-path)))) (combined-store-items (delete-duplicates (append installer-store-items target-runtime-store-items))) + (privileged-policy (default-assembly-privileged-policy)) (sanitized-iso-volume-label (sanitize-iso-volume-label iso-volume-label)) (installer-iso-spec (operating-system-installer-iso-spec os #:install-target-device install-target-device @@ -2210,6 +2270,8 @@ (iso-image (string-append iso-store-path "/installer.iso")) (boot-efi-image (string-append iso-store-path "/efiboot.img")) (root-image (string-append iso-store-path "/root.img")) + (assembly-privileged-policy-file + (string-append iso-store-path "/metadata/assembly-privileged-policy.scm")) (installer-rootfs-populate-metadata-file (string-append iso-store-path "/metadata/installer-rootfs-populate.scm")) (target-rootfs-populate-metadata-file @@ -2231,6 +2293,8 @@ (temp-esp (string-append build-root "/efiboot.img")) (temp-root (string-append build-root "/root.img")) (plan-root (string-append image-rootfs installer-plan-directory)) + (assembly-privileged-policy-temp-file + (string-append temp-output "/metadata/assembly-privileged-policy.scm")) (installer-rootfs-populate-metadata-temp-file (string-append temp-output "/metadata/installer-rootfs-populate.scm")) (target-rootfs-populate-metadata-temp-file @@ -2300,6 +2364,8 @@ "-o" (string-append "label=" sanitized-iso-volume-label) temp-iso iso-root) (mkdir-p temp-output) + (write-assembly-privileged-policy-file assembly-privileged-policy-temp-file + privileged-policy) (copy-regular-file temp-iso (string-append temp-output "/installer.iso")) (copy-regular-file temp-esp (string-append temp-output "/efiboot.img")) (copy-regular-file temp-root (string-append temp-output "/root.img")) @@ -2322,6 +2388,7 @@ (string-append temp-output "/target-closure-path") (string-append temp-output "/.references") (string-append temp-output "/.fruix-package") + assembly-privileged-policy-temp-file installer-rootfs-populate-metadata-temp-file target-rootfs-populate-metadata-temp-file installer-rootfs-copy-metadata-temp-file @@ -2335,6 +2402,7 @@ (iso-image . ,iso-image) (boot-efi-image . ,boot-efi-image) (root-image . ,root-image) + (assembly-privileged-policy-file . ,assembly-privileged-policy-file) (installer-rootfs-populate-metadata-file . ,installer-rootfs-populate-metadata-file) (target-rootfs-populate-metadata-file . ,target-rootfs-populate-metadata-file) (installer-rootfs-copy-metadata-file . ,installer-rootfs-copy-metadata-file) diff --git a/modules/fruix/system/freebsd/storage.scm b/modules/fruix/system/freebsd/storage.scm index 99f89c7..3163aff 100644 --- a/modules/fruix/system/freebsd/storage.scm +++ b/modules/fruix/system/freebsd/storage.scm @@ -372,55 +372,72 @@ actions) "\n"))) -(define (run-format-action entry) +(define (run-format-action entry privileged-policy) (let ((format-name (action-ref entry 'format #f)) (partition-device (action-ref entry 'partition-device #f)) (label (action-ref entry 'file-system-label #f))) (cond ((string=? format-name "msdosfs") - (run-privileged-command "newfs_msdos" "-L" "EFISYS" partition-device)) + (run-assembly-privileged-command privileged-policy + 'format-msdosfs + "newfs_msdos" "-L" "EFISYS" partition-device)) ((string=? format-name "ufs") - (run-privileged-command "newfs" "-U" "-L" label partition-device)) + (run-assembly-privileged-command privileged-policy + 'format-ufs + "newfs" "-U" "-L" label partition-device)) (else (error "unsupported filesystem format in FreeBSD storage backend" format-name entry))))) -(define (run-action entry) +(define (run-action entry privileged-policy) (case (action-ref entry 'kind #f) ((destroy-device) - (run-privileged-shell-command + (run-assembly-privileged-shell-command + privileged-policy + 'destroy-device (string-append "gpart destroy -F " (action-ref entry 'device #f) " >/dev/null 2>&1 || true")) #t) ((create-partition-table) - (run-privileged-command "gpart" "create" "-s" - (symbol->string (action-ref entry 'partition-table #f)) - (action-ref entry 'device #f))) + (run-assembly-privileged-command privileged-policy + 'create-partition-table + "gpart" "create" "-s" + (symbol->string (action-ref entry 'partition-table #f)) + (action-ref entry 'device #f))) ((add-partition) (let* ((size (action-ref entry 'size #f)) - (argv (append (list "gpart" "add" "-a" "1m") + (argv (append (list privileged-policy + 'add-partition + "gpart" "add" "-a" "1m") (if size (list "-s" size) '()) (list "-t" (action-ref entry 'gpart-type #f) "-l" (action-ref entry 'partition-label #f) (action-ref entry 'device #f))))) - (apply run-privileged-command argv))) + (apply run-assembly-privileged-command argv))) ((format-file-system) - (run-format-action entry)) + (run-format-action entry privileged-policy)) ((mkdir) - (run-privileged-command "mkdir" "-p" (action-ref entry 'path #f))) + (run-assembly-privileged-command privileged-policy + 'create-mount-target + "mkdir" "-p" (action-ref entry 'path #f))) ((mount-file-system) - (run-privileged-command "mount" "-t" - (action-ref entry 'format #f) - (action-ref entry 'partition-device #f) - (action-ref entry 'mount-target #f))) + (run-assembly-privileged-command privileged-policy + 'mount-file-system + "mount" "-t" + (action-ref entry 'format #f) + (action-ref entry 'partition-device #f) + (action-ref entry 'mount-target #f))) (else (error "unknown FreeBSD storage backend action" entry)))) -(define* (apply-freebsd-storage-layout layout #:key (root-mount-point "/mnt")) +(define* (apply-freebsd-storage-layout layout #:key (root-mount-point "/mnt") + (privileged-policy (default-assembly-privileged-policy))) (let ((plan (freebsd-storage-layout-plan layout #:root-mount-point root-mount-point))) - (for-each run-action (action-ref plan 'actions '())) + (for-each (lambda (entry) + (run-action entry privileged-policy)) + (action-ref plan 'actions '())) `((plan . ,plan) (disk-device . ,(action-ref plan 'disk-device #f)) (root-mount-point . ,(action-ref plan 'root-mount-point #f)) diff --git a/modules/fruix/system/freebsd/utils.scm b/modules/fruix/system/freebsd/utils.scm index 7f2afb3..35bbde4 100644 --- a/modules/fruix/system/freebsd/utils.scm +++ b/modules/fruix/system/freebsd/utils.scm @@ -37,6 +37,11 @@ run-privileged-command run-privileged-shell-command privileged-command-output + default-assembly-privileged-policy + assembly-privileged-policy-allows-install-target-kind? + run-assembly-privileged-command + run-assembly-privileged-shell-command + assembly-privileged-command-output store-reference-closure copy-store-items-into-rootfs copy-rootfs-for-image @@ -314,6 +319,91 @@ " " (command->shell-fragment program args)))) +(define assembly-privileged-policy-version "1") +(define assembly-privileged-policy-name "assembly") +(define assembly-privileged-policy-operations + '(destroy-device + create-partition-table + add-partition + format-msdosfs + format-ufs + create-mount-target + mount-file-system + unmount-file-system + mdconfig-attach + mdconfig-detach + gpart-recover + copy-into-mounted-root)) + +(define (env-boolean name default) + (match (and (getenv name) + (string-downcase (string-trim-both (getenv name)))) + ((or #f "") default) + ((or "1" "true" "yes" "on") #t) + ((or "0" "false" "no" "off") #f) + (_ default))) + +(define (assembly-privileged-command-prefix) + (or (getenv "FRUIX_ASSEMBLY_PRIVILEGED_COMMAND") + (getenv "FRUIX_PRIVILEGED_COMMAND") + "sudo -n")) + +(define (default-assembly-privileged-policy) + `((assembly-privileged-policy-version . ,assembly-privileged-policy-version) + (name . ,assembly-privileged-policy-name) + (command-prefix . ,(assembly-privileged-command-prefix)) + (allowed-operations . ,assembly-privileged-policy-operations) + (allowed-install-target-kinds + . ,(if (env-boolean "FRUIX_ASSEMBLY_ALLOW_BLOCK_DEVICE_TARGETS" #f) + '(raw-file block-device) + '(raw-file))) + (environment + (command-prefix . "FRUIX_ASSEMBLY_PRIVILEGED_COMMAND") + (fallback-command-prefix . "FRUIX_PRIVILEGED_COMMAND") + (allow-block-device-targets . "FRUIX_ASSEMBLY_ALLOW_BLOCK_DEVICE_TARGETS")))) + +(define (assembly-privileged-policy-ref policy key default) + (match (assoc key policy) + ((_ . value) value) + (#f default))) + +(define (assembly-privileged-policy-command-prefix policy) + (assembly-privileged-policy-ref policy 'command-prefix + (assembly-privileged-command-prefix))) + +(define (assembly-privileged-policy-allows-operation? policy operation) + (member operation + (assembly-privileged-policy-ref policy 'allowed-operations '()))) + +(define (assembly-privileged-policy-allows-install-target-kind? policy kind) + (member kind + (assembly-privileged-policy-ref policy 'allowed-install-target-kinds '()))) + +(define (ensure-assembly-privileged-policy-allows-operation policy operation) + (unless (assembly-privileged-policy-allows-operation? policy operation) + (error "assembly privileged policy forbids operation" operation policy))) + +(define (run-assembly-privileged-command policy operation program . args) + (ensure-assembly-privileged-policy-allows-operation policy operation) + (run-command "sh" "-c" + (string-append (assembly-privileged-policy-command-prefix policy) + " " + (command->shell-fragment program args)))) + +(define (run-assembly-privileged-shell-command policy operation command) + (ensure-assembly-privileged-policy-allows-operation policy operation) + (run-command "sh" "-c" + (string-append (assembly-privileged-policy-command-prefix policy) + " sh -c " + (shell-quote command)))) + +(define (assembly-privileged-command-output policy operation program . args) + (ensure-assembly-privileged-policy-allows-operation policy operation) + (command-output "sh" "-c" + (string-append (assembly-privileged-policy-command-prefix policy) + " " + (command->shell-fragment program args)))) + (define (store-reference-closure roots) (let ((seen (make-hash-table)) (result '())) diff --git a/scripts/fruix.scm b/scripts/fruix.scm index 2ceddc8..adff85d 100644 --- a/scripts/fruix.scm +++ b/scripts/fruix.scm @@ -41,6 +41,8 @@ System options:\n\ --disk-capacity SIZE Disk capacity for 'image', 'installer', or raw-file 'install' targets.\n\ --root-size SIZE Root filesystem size for 'image', 'installer', 'installer-iso', or 'install' (example: 6g).\n\ --target PATH Install target for 'install' (raw image file or /dev/... device).\n\ + Direct /dev/... install targets require\n\ + FRUIX_ASSEMBLY_ALLOW_BLOCK_DEVICE_TARGETS=1.\n\ --install-target-device DEVICE\n\ Target block device used by the booted 'installer' environment.\n\ --self-test Use the Newt self-test path for 'installer-tui'.\n\ @@ -449,6 +451,7 @@ Common options:\n\ (esp_device . ,(assoc-ref result 'esp-device)) (root_device . ,(assoc-ref result 'root-device)) (install_metadata_path . ,(assoc-ref result 'install-metadata-path)) + (assembly_privileged_policy_path . ,(assoc-ref result 'assembly-privileged-policy-path)) (rootfs_populate_metadata_path . ,(assoc-ref result 'rootfs-populate-metadata-path)) (rootfs_copy_metadata_path . ,(assoc-ref result 'rootfs-copy-metadata-path)) (store_copy_metadata_path . ,(assoc-ref result 'store-copy-metadata-path)) @@ -531,6 +534,7 @@ Common options:\n\ (disk_image . ,(assoc-ref result 'disk-image)) (esp_image . ,(assoc-ref result 'esp-image)) (root_image . ,(assoc-ref result 'root-image)) + (assembly_privileged_policy_file . ,(assoc-ref result 'assembly-privileged-policy-file)) (rootfs_populate_metadata_file . ,(assoc-ref result 'rootfs-populate-metadata-file)) (image_rootfs_copy_metadata_file . ,(assoc-ref result 'image-rootfs-copy-metadata-file)) (store_copy_metadata_file . ,(assoc-ref result 'store-copy-metadata-file)) @@ -597,6 +601,7 @@ Common options:\n\ (disk_image . ,(assoc-ref result 'disk-image)) (esp_image . ,(assoc-ref result 'esp-image)) (root_image . ,(assoc-ref result 'root-image)) + (assembly_privileged_policy_file . ,(assoc-ref result 'assembly-privileged-policy-file)) (installer_rootfs_populate_metadata_file . ,(assoc-ref result 'installer-rootfs-populate-metadata-file)) (target_rootfs_populate_metadata_file . ,(assoc-ref result 'target-rootfs-populate-metadata-file)) (installer_rootfs_copy_metadata_file . ,(assoc-ref result 'installer-rootfs-copy-metadata-file)) @@ -667,6 +672,7 @@ Common options:\n\ (iso_image . ,(assoc-ref result 'iso-image)) (boot_efi_image . ,(assoc-ref result 'boot-efi-image)) (root_image . ,(assoc-ref result 'root-image)) + (assembly_privileged_policy_file . ,(assoc-ref result 'assembly-privileged-policy-file)) (installer_rootfs_populate_metadata_file . ,(assoc-ref result 'installer-rootfs-populate-metadata-file)) (target_rootfs_populate_metadata_file . ,(assoc-ref result 'target-rootfs-populate-metadata-file)) (installer_rootfs_copy_metadata_file . ,(assoc-ref result 'installer-rootfs-copy-metadata-file))