gnu: WebKitGTK: Update to 2.28.0 [fixes CVE-2020-10018].
[jackhill/guix/guix.git] / gnu / build / vm.scm
index 5579886..9a9e5bd 100644 (file)
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015, 2016, 2017, 2018, 2019 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2016 Christopher Allan Webber <cwebber@dustycloud.org>
 ;;; Copyright © 2016, 2017 Leo Famulari <leo@famulari.name>
 ;;; Copyright © 2017 Mathieu Othacehe <m.othacehe@gmail.com>
@@ -25,7 +25,7 @@
   #:use-module (guix build utils)
   #:use-module (guix build store-copy)
   #:use-module (guix build syscalls)
-  #:use-module ((guix store database) #:select (reset-timestamps))
+  #:use-module (guix store database)
   #:use-module (gnu build linux-boot)
   #:use-module (gnu build install)
   #:use-module (gnu system uuid)
@@ -37,6 +37,7 @@
   #:use-module (ice-9 popen)
   #:use-module (srfi srfi-1)
   #:use-module (srfi srfi-9)
+  #:use-module (srfi srfi-19)
   #:use-module (srfi srfi-26)
   #:export (qemu-command
             load-in-linux-vm
   (let ((cpu (substring system 0
                         (string-index system #\-))))
     (string-append "qemu-system-"
-                   (if (string-match "^i[3456]86$" cpu)
-                       "i386"
-                       cpu))))
+                   (cond
+                    ((string-match "^i[3456]86$" cpu) "i386")
+                    ((string-match "armhf" cpu) "arm")
+                    (else cpu)))))
 
 (define* (load-in-linux-vm builder
                            #:key
@@ -81,6 +83,7 @@
                            make-disk-image?
                            single-file-output?
                            target-arm32?
+                           target-aarch64?
                            (disk-image-size (* 100 (expt 2 20)))
                            (disk-image-format "qcow2")
                            (references-graphs '()))
@@ -96,22 +99,28 @@ access it via /dev/hda.
 REFERENCES-GRAPHS can specify a list of reference-graph files as produced by
 the #:references-graphs parameter of 'derivation'."
 
+  (define target-arm? (or target-arm32? target-aarch64?))
+
   (define arch-specific-flags
     `(;; On ARM, a machine has to be specified. Use "virt" machine to avoid
       ;; hardware limits imposed by other machines.
-      ,@(if target-arm32? '("-M" "virt") '())
+      ,@(if target-arm?
+            '("-M" "virt")
+            '())
+
+      ;; On ARM32, if the kernel is built without LPAE support, ECAM conflicts
+      ;; with VIRT_PCIE_MMIO causing PCI devices not to show up.  Disable
+      ;; explicitely highmem to fix it.
+      ;; See: https://bugs.launchpad.net/qemu/+bug/1790975.
+      ,@(if target-arm32?
+            '("-machine" "highmem=off")
+            '())
 
       ;; Only enable kvm if we see /dev/kvm exists.  This allows users without
       ;; hardware virtualization to still use these commands.  KVM support is
-      ;; still buggy on some ARM32 boards. Do not use it even if available.
+      ;; still buggy on some ARM boards. Do not use it even if available.
       ,@(if (and (file-exists? "/dev/kvm")
-                 (not target-arm32?)
-
-                 ;; XXX: 32-bit 'qemu-system-i386 -enable-kvm' segfaults on
-                 ;; x86_64 hosts running Linux-libre 4.17:
-                 ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=31380#18> and
-                 ;; <https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg01166.html>.
-                 (not (string-suffix? "-i386" qemu)))
+                 (not target-arm?))
             '("-enable-kvm")
             '())
 
@@ -122,14 +131,7 @@ the #:references-graphs parameter of 'derivation'."
                       ;; The serial port name differs between emulated
                       ;; architectures/machines.
                       " console="
-                      (if target-arm32? "ttyAMA0" "ttyS0"))
-
-      ;; NIC is not supported on ARM "virt" machine, so use a user mode
-      ;; network stack instead.
-      ,@(if target-arm32?
-            '("-device" "virtio-net-pci,netdev=mynet"
-              "-netdev" "user,id=mynet")
-            '("-net" "nic,model=virtio"))))
+                      (if target-arm? "ttyAMA0" "ttyS0"))))
 
   (when make-disk-image?
     (format #t "creating ~a image of ~,2f MiB...~%"
@@ -150,7 +152,11 @@ the #:references-graphs parameter of 'derivation'."
     (_ #f))
 
   (apply invoke qemu "-nographic" "-no-reboot"
+         ;; CPU "max" behaves as "host" when KVM is enabled, and like a system
+         ;; CPU with the maximum possible feature set otherwise.
+         "-cpu" "max"
          "-m" (number->string memory-size)
+         "-nic" "user,model=virtio-net-pci"
          "-object" "rng-random,filename=/dev/urandom,id=guixsd-vm-rng"
          "-device" "virtio-rng-pci,rng=guixsd-vm-rng"
          "-virtfs"
@@ -191,6 +197,23 @@ the #:references-graphs parameter of 'derivation'."
           (mkdir output)
           (copy-recursively "xchg" output)))))
 
+(define* (register-closure prefix closure
+                           #:key
+                           (deduplicate? #t) (reset-timestamps? #t)
+                           (schema (sql-schema)))
+  "Register CLOSURE in PREFIX, where PREFIX is the directory name of the
+target store and CLOSURE is the name of a file containing a reference graph as
+produced by #:references-graphs..  As a side effect, if RESET-TIMESTAMPS? is
+true, reset timestamps on store files and, if DEDUPLICATE? is true,
+deduplicates files common to CLOSURE and the rest of PREFIX."
+  (let ((items (call-with-input-file closure read-reference-graph)))
+    (register-items items
+                    #:prefix prefix
+                    #:deduplicate? deduplicate?
+                    #:reset-timestamps? reset-timestamps?
+                    #:registration-time %epoch
+                    #:schema schema)))
+
 \f
 ;;;
 ;;; Partitions.
@@ -410,14 +433,18 @@ SYSTEM-DIRECTORY is the name of the directory of the 'system' derivation."
             ;; Graft the configuration file onto the image.
             (string-append "boot/grub/grub.cfg=" config-file))))
 
-(define* (make-iso9660-image grub config-file os-drv target
-                             #:key (volume-id "GuixSD_image") (volume-uuid #f)
+(define* (make-iso9660-image xorriso grub-mkrescue-environment
+                             grub config-file os-drv target
+                             #:key (volume-id "Guix_image") (volume-uuid #f)
                              register-closures? (closures '()))
   "Given a GRUB package, creates an iso image as TARGET, using CONFIG-FILE as
 GRUB configuration and OS-DRV as the stuff in it."
   (define grub-mkrescue
     (string-append grub "/bin/grub-mkrescue"))
 
+  (define grub-mkrescue-sed.sh
+    (string-append xorriso "/bin/grub-mkrescue-sed.sh"))
+
   (define target-store
     (string-append "/tmp/root" (%store-directory)))
 
@@ -447,9 +474,42 @@ GRUB configuration and OS-DRV as the stuff in it."
               closures)
     (register-bootcfg-root "/tmp/root" config-file))
 
+  ;; 'grub-mkrescue' calls out to mtools programs to create 'efi.img', a FAT
+  ;; file system image, and mtools honors SOURCE_DATE_EPOCH for the mtime of
+  ;; those files.  The epoch for FAT is Jan. 1st 1980, not 1970, so choose
+  ;; that.
+  (setenv "SOURCE_DATE_EPOCH"
+          (number->string
+           (time-second
+            (date->time-utc (make-date 0 0 0 0 1 1 1980 0)))))
+
+  ;; Our patched 'grub-mkrescue' honors this environment variable and passes
+  ;; it to 'mformat', which makes it the serial number of 'efi.img'.  This
+  ;; allows for deterministic builds.
+  (setenv "GRUB_FAT_SERIAL_NUMBER"
+          (number->string (if volume-uuid
+
+                              ;; On 32-bit systems the 2nd argument must be
+                              ;; lower than 2^32.
+                              (string-hash (iso9660-uuid->string volume-uuid)
+                                           (- (expt 2 32) 1))
+
+                              #x77777777)
+                          16))
+
+  (setenv "MKRESCUE_SED_MODE" "original")
+  (setenv "MKRESCUE_SED_XORRISO" (string-append xorriso
+                                                "/bin/xorriso"))
+  (setenv "MKRESCUE_SED_IN_EFI_NO_PT" "yes")
+  (for-each (match-lambda
+             ((name . value) (setenv name value)))
+            grub-mkrescue-environment)
+
   (let ((pipe
          (apply open-pipe* OPEN_WRITE
-                grub-mkrescue "-o" target
+                grub-mkrescue
+                (string-append "--xorriso=" grub-mkrescue-sed.sh)
+                "-o" target
                 (string-append "boot/grub/grub.cfg=" config-file)
                 "etc=/tmp/root/etc"
                 "var=/tmp/root/var"
@@ -460,6 +520,10 @@ GRUB configuration and OS-DRV as the stuff in it."
                 "mnt=/tmp/root/mnt"
                 "-path-list" "-"
                 "--"
+
+                ;; Set all timestamps to 1.
+                "-volume_date" "all_file_dates" "=1"
+
                 "-volid" (string-upcase volume-id)
                 (if volume-uuid
                     `("-volume_date" "uuid"
@@ -534,7 +598,7 @@ passing it a directory name where it is mounted."
           (lambda (port)
             (format port
                     "insmod part_msdos~@
-                    search --set=root --label GuixSD_image~@
+                    search --set=root --label Guix_image~@
                     configfile /boot/grub/grub.cfg~%")))
 
         (display "creating EFI firmware image...")