aboutsummaryrefslogtreecommitdiff
path: root/src/connection/chroot.lisp
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2021-05-23 13:19:46 -0700
committerSean Whitton <spwhitton@spwhitton.name>2021-05-23 16:55:07 -0700
commitb914693a33ffcf0764ea9bc87bcc573e5ddf9943 (patch)
treea5f1451810cf940d03aa33d0761aa82b050e819e /src/connection/chroot.lisp
parente4bda1ac845991cb79e6f3ad21db1d54ee36ddd2 (diff)
downloadconsfigurator-b914693a33ffcf0764ea9bc87bcc573e5ddf9943.tar.gz
convert CONNECTION slots to connattrs & fix finding homedirs
HOME does not take into account /etc/passwd inside the chroot, even when starting a login shell with, e.g., "chroot /chroot sh -lc 'echo $HOME'" -- we would need something which emulates login(1), like su(1), but the -c argument to su(1) is not portable. getent(1) is not POSIX. So use tilde expansion. Additionally, avoid having UPLOAD-ALL-PREREQUISITE-DATA store values for the remote UID, remote homedir etc. from *before* the chroot/setuid operation. Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Diffstat (limited to 'src/connection/chroot.lisp')
-rw-r--r--src/connection/chroot.lisp45
1 files changed, 30 insertions, 15 deletions
diff --git a/src/connection/chroot.lisp b/src/connection/chroot.lisp
index bfbaab5..2d8b242 100644
--- a/src/connection/chroot.lisp
+++ b/src/connection/chroot.lisp
@@ -94,6 +94,14 @@ should be the mount point, without the chroot's root prefixed.")
copy)
else collect volume)))
+(defmethod propagate-connattr
+ ((type (eql :remote-uid)) connattr (connection chroot-connection))
+ connattr)
+
+(defmethod propagate-connattr
+ ((type (eql :remote-gid)) connattr (connection chroot-connection))
+ connattr)
+
;;;; :CHROOT.FORK
@@ -109,27 +117,34 @@ should be the mount point, without the chroot's root prefixed.")
(error "~&Forking into a chroot requires a Lisp image running as root"))
(informat 1 "~&Forking into chroot at ~A" into)
(let* ((into* (ensure-directory-pathname into))
- (datadir-inside
- (stripln
- (mrun
- (format
- nil
- "chroot ~A echo ${XDG_CACHE_HOME:-$HOME/.cache}/consfigurator/data/"
- (escape-sh-token (unix-namestring into))))))
- (datadir (ensure-pathname
- (subseq datadir-inside 1)
- :defaults into* :ensure-absolute t :ensure-directory t)))
- (let ((connection (make-instance 'chroot.fork-connection
- :into into :datadir datadir)))
+ (connection (make-instance 'shell-chroot-connection :into into*)))
+ ;; This has the side effect of populating the CONSFIGURATOR::ID and
+ ;; :REMOTE-HOME connattrs correctly, so that they don't get bogus values
+ ;; when this connection object is used in UPLOAD-ALL-PREREQUISITE-DATA.
+ (multiple-value-bind (datadir-inside exit)
+ (connection-run
+ connection
+ (format nil "echo ${XDG_CACHE_HOME:-~A/.cache}/consfigurator/data/"
+ (connection-connattr connection :remote-home))
+ nil)
+ (unless (zerop exit)
+ (error "Failed to determine datadir inside chroot."))
+ (setq connection (change-class connection 'chroot.fork-connection))
+ (setf (slot-value connection 'datadir)
+ (ensure-pathname
+ (subseq datadir-inside 1)
+ :defaults into* :ensure-absolute t :ensure-directory t))
(unwind-protect-in-parent (continue-connection connection remaining)
(connection-teardown connection)))))
(defmethod post-fork ((connection chroot.fork-connection))
(unless (zerop (chroot (slot-value connection 'into)))
(error "chroot(2) failed!"))
- ;; chdir, else our current working directory is a pointer to something
- ;; outside the chroot
- (uiop:chdir "/"))
+ (let ((home (connection-connattr connection :remote-home)))
+ (setf (uiop:getenv "HOME") (unix-namestring home))
+ ;; chdir, else our current working directory is a pointer to something
+ ;; outside the chroot
+ (uiop:chdir home)))
;;;; :CHROOT.SHELL