linux-initrd: Delete files from the initrd ramfs when switching roots.

* guix/build/linux-initrd.scm (switch-root): Delete file from the old
  root.  Chdir to / after 'chroot' call.  Re-open file descriptors 0, 1,
  and 2.
  (boot-system): Move 'loading' message after the 'switch-root' call.
* gnu/system.scm (operating-system-boot-script): Add loop that closes
  file descriptor before calling 'execl'.
This commit is contained in:
Ludovic Courtès 2014-05-06 18:09:25 +02:00
parent 94e3029a83
commit 26a728eb09
2 changed files with 54 additions and 3 deletions

View File

@ -334,6 +334,15 @@ we're running in the final root."
;; Activate setuid programs.
(activate-setuid-programs (list #$@setuid-progs))
;; Close any remaining open file descriptors to be on the
;; safe side. This must be the very last thing we do,
;; because Guile has internal FDs such as 'sleep_pipe'
;; that need to be alive.
(let loop ((fd 3))
(when (< fd 1024)
(false-if-exception (close-fdes fd))
(loop (+ 1 fd))))
;; Start dmd.
(execl (string-append #$dmd "/bin/dmd")
"dmd" "--config" #$dmd-conf)))))

View File

@ -286,9 +286,51 @@ run a file system check."
util-linux' switch_root(8) does."
(move-essential-file-systems root)
(chdir root)
;; TODO: Delete files from the old root.
;; Since we're about to 'rm -rf /', try to make sure we're on an initrd.
;; TODO: Use 'statfs' to check the fs type, like klibc does.
(when (or (not (file-exists? "/init")) (directory-exists? "/home"))
(format (current-error-port)
"The root file system is probably not an initrd; \
bailing out.~%root contents: ~s~%" (scandir "/"))
(force-output (current-error-port))
(exit 1))
;; Delete files from the old root, without crossing mount points (assuming
;; there are no mount points in sub-directories.) That means we're leaving
;; the empty ROOT directory behind us, but that's OK.
(let ((root-device (stat:dev (stat "/"))))
(for-each (lambda (file)
(unless (member file '("." ".."))
(let* ((file (string-append "/" file))
(device (stat:dev (lstat file))))
(when (= device root-device)
(delete-file-recursively file)))))
(scandir "/")))
;; Make ROOT the new root.
(mount root "/" "" MS_MOVE)
(chroot "."))
(chroot ".")
(chdir "/")
(when (file-exists? "/dev/console")
;; Close the standard file descriptors since they refer to the old
;; /dev/console.
(for-each close-fdes '(0 1 2))
;; Reopen them.
(let ((in (open-file "/dev/console" "rbl"))
(out (open-file "/dev/console" "wbl")))
(dup2 (fileno in) 0)
(dup2 (fileno out) 1)
(dup2 (fileno out) 2)
;; Safely close IN and OUT.
(for-each (lambda (port)
(if (memv (fileno port) '(0 1 2))
(set-port-revealed! port 1)
(close-port port)))
(list in out)))))
(define* (boot-system #:key
(linux-modules '())
@ -393,8 +435,8 @@ to it are lost."
(if to-load
(begin
(format #t "loading '~a'...\n" to-load)
(switch-root "/root")
(format #t "loading '~a'...\n" to-load)
;; Obviously this has to be done each time we boot. Do it from here
;; so that statfs(2) returns DEVPTS_SUPER_MAGIC like libc's getpt(3)