Reduce host-side privileged assembly surface
This commit is contained in:
@@ -298,6 +298,9 @@ Current progress:
|
||||
- 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
|
||||
- install-time storage layout application is now executed as a rendered
|
||||
privileged helper script under that policy instead of many scattered host-side
|
||||
privileged calls
|
||||
- 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
|
||||
|
||||
@@ -1507,10 +1507,12 @@
|
||||
(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"))
|
||||
(storage-apply-metadata-path (string-append staging-metadata-relative-root "/storage-apply.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))
|
||||
(storage-apply-metadata-temp-file (string-append build-root "/storage-apply.scm"))
|
||||
(rootfs-copy-metadata-temp-file (string-append build-root "/rootfs-copy.scm"))
|
||||
(store-copy-metadata-temp-file (string-append build-root "/store-copy.scm"))
|
||||
(target-device #f)
|
||||
@@ -1549,8 +1551,12 @@
|
||||
(set! storage-plan
|
||||
(assoc-ref (apply-freebsd-storage-layout effective-storage-layout
|
||||
#:root-mount-point mnt-root
|
||||
#:privileged-policy privileged-policy)
|
||||
#:privileged-policy privileged-policy
|
||||
#:metadata-file storage-apply-metadata-temp-file)
|
||||
'plan))
|
||||
(install-metadata-file-into-mounted-root privileged-policy
|
||||
storage-apply-metadata-temp-file
|
||||
(string-append mnt-root storage-apply-metadata-path))
|
||||
(set! mounted-targets (freebsd-storage-plan-mount-targets storage-plan))
|
||||
(let ((esp-entry (freebsd-storage-plan-partition-by-role storage-plan 'efi))
|
||||
(root-entry (or (freebsd-storage-plan-partition-by-role storage-plan 'root)
|
||||
@@ -1604,6 +1610,7 @@
|
||||
(install-metadata-path . ,install-metadata-relative-path)
|
||||
(assembly-privileged-policy-path . ,assembly-privileged-policy-path)
|
||||
(rootfs-populate-metadata-path . ,rootfs-populate-metadata-path)
|
||||
(storage-apply-metadata-path . ,storage-apply-metadata-path)
|
||||
(rootfs-copy-metadata-path . ,rootfs-copy-metadata-path)
|
||||
(store-copy-metadata-path . ,store-copy-metadata-path)
|
||||
(closure-path . ,closure-path)
|
||||
@@ -1618,22 +1625,32 @@
|
||||
(store-layout-file . ,(assoc-ref closure 'store-layout-file))
|
||||
(store-items . ,store-items)))
|
||||
(lambda ()
|
||||
(for-each (lambda (mount-target)
|
||||
(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-assembly-privileged-shell-command
|
||||
(when (or (pair? mounted-targets) target-md)
|
||||
(run-assembly-privileged-script
|
||||
privileged-policy
|
||||
'mdconfig-detach
|
||||
(string-append "mdconfig -d -u "
|
||||
(shell-quote (string-drop target-md 2))
|
||||
" >/dev/null 2>&1 || true"))
|
||||
(set! target-md #f))
|
||||
"fruix-install-cleanup"
|
||||
(string-append
|
||||
"#!/bin/sh\n"
|
||||
"set +e\n"
|
||||
(string-concatenate
|
||||
(map (lambda (mount-target)
|
||||
(string-append "umount "
|
||||
(shell-quote mount-target)
|
||||
" >/dev/null 2>&1 || true\n"))
|
||||
mounted-targets))
|
||||
(if target-md
|
||||
(string-append "mdconfig -d -u "
|
||||
(shell-quote (string-drop target-md 2))
|
||||
" >/dev/null 2>&1 || true\n")
|
||||
""))
|
||||
#:operations (delete-duplicates
|
||||
(append (if (pair? mounted-targets)
|
||||
'(unmount-file-system)
|
||||
'())
|
||||
(if target-md
|
||||
'(mdconfig-detach)
|
||||
'())))))
|
||||
(set! target-md #f)
|
||||
(when (file-exists? build-root)
|
||||
(delete-file-recursively build-root))))))
|
||||
|
||||
|
||||
@@ -324,6 +324,12 @@
|
||||
(mount-targets . ,(freebsd-storage-plan-mount-targets plan))
|
||||
(partitions . ,(action-ref plan 'partitions '()))))
|
||||
|
||||
(define (storage-shell-quote text)
|
||||
(string-append "'" (string-replace-all text "'" "'\"'\"'") "'"))
|
||||
|
||||
(define (render-shell-command argv)
|
||||
(string-join (map storage-shell-quote argv) " "))
|
||||
|
||||
(define (render-add-partition-action entry)
|
||||
(let* ((argv (append (list "gpart" "add" "-a" "1m")
|
||||
(let ((size (action-ref entry 'size #f)))
|
||||
@@ -333,7 +339,7 @@
|
||||
(list "-t" (action-ref entry 'gpart-type #f)
|
||||
"-l" (action-ref entry 'partition-label #f)
|
||||
(action-ref entry 'device #f)))))
|
||||
(string-join argv " ")))
|
||||
(render-shell-command argv)))
|
||||
|
||||
(define (render-freebsd-storage-layout-plan plan)
|
||||
(let ((actions (action-ref plan 'actions '())))
|
||||
@@ -341,12 +347,15 @@
|
||||
(map (lambda (entry)
|
||||
(case (action-ref entry 'kind #f)
|
||||
((destroy-device)
|
||||
(format #f "gpart destroy -F ~a >/dev/null 2>&1 || true"
|
||||
(action-ref entry 'device #f)))
|
||||
(string-append
|
||||
(render-shell-command
|
||||
(list "gpart" "destroy" "-F" (action-ref entry 'device #f)))
|
||||
" >/dev/null 2>&1 || true"))
|
||||
((create-partition-table)
|
||||
(format #f "gpart create -s ~a ~a"
|
||||
(symbol->string (action-ref entry 'partition-table #f))
|
||||
(action-ref entry 'device #f)))
|
||||
(render-shell-command
|
||||
(list "gpart" "create" "-s"
|
||||
(symbol->string (action-ref entry 'partition-table #f))
|
||||
(action-ref entry 'device #f))))
|
||||
((add-partition)
|
||||
(render-add-partition-action entry))
|
||||
((format-file-system)
|
||||
@@ -355,89 +364,64 @@
|
||||
(label (action-ref entry 'file-system-label #f)))
|
||||
(cond
|
||||
((string=? format-name "msdosfs")
|
||||
(format #f "newfs_msdos -L EFISYS ~a" partition-device))
|
||||
(render-shell-command
|
||||
(list "newfs_msdos" "-L" "EFISYS" partition-device)))
|
||||
((string=? format-name "ufs")
|
||||
(format #f "newfs -U -L ~a ~a" label partition-device))
|
||||
(render-shell-command
|
||||
(list "newfs" "-U" "-L" label partition-device)))
|
||||
(else
|
||||
(format #f "# unsupported filesystem format ~a on ~a" format-name partition-device)))))
|
||||
((mkdir)
|
||||
(format #f "mkdir -p ~a" (action-ref entry 'path #f)))
|
||||
(render-shell-command
|
||||
(list "mkdir" "-p" (action-ref entry 'path #f))))
|
||||
((mount-file-system)
|
||||
(format #f "mount -t ~a ~a ~a"
|
||||
(action-ref entry 'format #f)
|
||||
(action-ref entry 'partition-device #f)
|
||||
(action-ref entry 'mount-target #f)))
|
||||
(render-shell-command
|
||||
(list "mount" "-t"
|
||||
(action-ref entry 'format #f)
|
||||
(action-ref entry 'partition-device #f)
|
||||
(action-ref entry 'mount-target #f))))
|
||||
(else
|
||||
(format #f "# unknown storage action ~s" entry))))
|
||||
actions)
|
||||
"\n")))
|
||||
|
||||
(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-assembly-privileged-command privileged-policy
|
||||
'format-msdosfs
|
||||
"newfs_msdos" "-L" "EFISYS" partition-device))
|
||||
((string=? format-name "ufs")
|
||||
(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 privileged-policy)
|
||||
(define (storage-action->assembly-operations entry)
|
||||
(case (action-ref entry 'kind #f)
|
||||
((destroy-device)
|
||||
(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-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 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-assembly-privileged-command argv)))
|
||||
((destroy-device) '(destroy-device))
|
||||
((create-partition-table) '(create-partition-table))
|
||||
((add-partition) '(add-partition))
|
||||
((format-file-system)
|
||||
(run-format-action entry privileged-policy))
|
||||
((mkdir)
|
||||
(run-assembly-privileged-command privileged-policy
|
||||
'create-mount-target
|
||||
"mkdir" "-p" (action-ref entry 'path #f)))
|
||||
((mount-file-system)
|
||||
(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)))
|
||||
(let ((format-name (action-ref entry 'format #f)))
|
||||
(cond
|
||||
((string=? format-name "msdosfs") '(format-msdosfs))
|
||||
((string=? format-name "ufs") '(format-ufs))
|
||||
(else
|
||||
(error "unsupported filesystem format in FreeBSD storage backend" format-name entry)))))
|
||||
((mkdir) '(create-mount-target))
|
||||
((mount-file-system) '(mount-file-system))
|
||||
(else
|
||||
(error "unknown FreeBSD storage backend action" entry))))
|
||||
|
||||
(define (storage-plan-assembly-operations plan)
|
||||
(delete-duplicates
|
||||
(append-map storage-action->assembly-operations
|
||||
(action-ref plan 'actions '()))))
|
||||
|
||||
(define (storage-plan-script plan)
|
||||
(string-append "#!/bin/sh\n"
|
||||
"set -eu\n"
|
||||
(render-freebsd-storage-layout-plan plan)
|
||||
"\n"))
|
||||
|
||||
(define* (apply-freebsd-storage-layout layout #:key (root-mount-point "/mnt")
|
||||
(privileged-policy (default-assembly-privileged-policy)))
|
||||
(privileged-policy (default-assembly-privileged-policy))
|
||||
metadata-file)
|
||||
(let ((plan (freebsd-storage-layout-plan layout #:root-mount-point root-mount-point)))
|
||||
(for-each (lambda (entry)
|
||||
(run-action entry privileged-policy))
|
||||
(action-ref plan 'actions '()))
|
||||
(run-assembly-privileged-script privileged-policy
|
||||
"fruix-storage-layout-apply"
|
||||
(storage-plan-script plan)
|
||||
#:operations (storage-plan-assembly-operations plan)
|
||||
#:metadata-file metadata-file)
|
||||
`((plan . ,plan)
|
||||
(disk-device . ,(action-ref plan 'disk-device #f))
|
||||
(root-mount-point . ,(action-ref plan 'root-mount-point #f))
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
run-assembly-privileged-command
|
||||
run-assembly-privileged-shell-command
|
||||
assembly-privileged-command-output
|
||||
run-assembly-privileged-script
|
||||
store-reference-closure
|
||||
copy-store-items-into-rootfs
|
||||
copy-rootfs-for-image
|
||||
@@ -404,6 +405,45 @@
|
||||
" "
|
||||
(command->shell-fragment program args))))
|
||||
|
||||
(define assembly-privileged-script-metadata-version "1")
|
||||
|
||||
(define* (assembly-privileged-script-metadata policy name operations script)
|
||||
`((assembly-privileged-script-metadata-version . ,assembly-privileged-script-metadata-version)
|
||||
(name . ,name)
|
||||
(policy . ,policy)
|
||||
(operations . ,operations)
|
||||
(script . ,script)
|
||||
(command . ,(string-append (assembly-privileged-policy-command-prefix policy)
|
||||
" sh <script>"))))
|
||||
|
||||
(define* (run-assembly-privileged-script policy name script
|
||||
#:key
|
||||
(operations '())
|
||||
metadata-file)
|
||||
(for-each (lambda (operation)
|
||||
(ensure-assembly-privileged-policy-allows-operation policy operation))
|
||||
operations)
|
||||
(let ((script-path (command-output "mktemp"
|
||||
(string-append (getenv* "TMPDIR" "/tmp")
|
||||
"/fruix-assembly-privileged.XXXXXX"))))
|
||||
(dynamic-wind
|
||||
(lambda ()
|
||||
(write-file script-path script)
|
||||
(chmod script-path #o555)
|
||||
(when metadata-file
|
||||
(mkdir-p (dirname metadata-file))
|
||||
(write-file metadata-file
|
||||
(object->string
|
||||
(assembly-privileged-script-metadata policy name operations script)))
|
||||
(chmod metadata-file #o644)))
|
||||
(lambda ()
|
||||
(run-command "sh" "-c"
|
||||
(string-append (assembly-privileged-policy-command-prefix policy)
|
||||
" sh "
|
||||
(shell-quote script-path))))
|
||||
(lambda ()
|
||||
(delete-file-if-exists script-path)))))
|
||||
|
||||
(define (store-reference-closure roots)
|
||||
(let ((seen (make-hash-table))
|
||||
(result '()))
|
||||
|
||||
@@ -453,6 +453,7 @@ Common options:\n\
|
||||
(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))
|
||||
(storage_apply_metadata_path . ,(assoc-ref result 'storage-apply-metadata-path))
|
||||
(rootfs_copy_metadata_path . ,(assoc-ref result 'rootfs-copy-metadata-path))
|
||||
(store_copy_metadata_path . ,(assoc-ref result 'store-copy-metadata-path))
|
||||
(freebsd_base_name . ,(freebsd-base-name base))
|
||||
|
||||
Reference in New Issue
Block a user