summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--config-daemon.ac2
-rw-r--r--doc/guix.texi17
-rw-r--r--gnu-system.am13
-rw-r--r--gnu/build/file-systems.scm9
-rw-r--r--gnu/build/linux-boot.scm5
-rw-r--r--gnu/packages.scm17
-rw-r--r--gnu/packages/autotools.scm32
-rw-r--r--gnu/packages/cpio.scm15
-rw-r--r--gnu/packages/games.scm11
-rw-r--r--gnu/packages/gcc.scm24
-rw-r--r--gnu/packages/gl.scm13
-rw-r--r--gnu/packages/gnome.scm12
-rw-r--r--gnu/packages/mail.scm3
-rw-r--r--gnu/packages/patches/cpio-CVE-2014-9112-pt1.patch231
-rw-r--r--gnu/packages/patches/cpio-CVE-2014-9112-pt2.patch51
-rw-r--r--gnu/packages/patches/cpio-CVE-2014-9112-pt3.patch23
-rw-r--r--gnu/packages/patches/cpio-CVE-2014-9112-pt4.patch105
-rw-r--r--gnu/packages/patches/cpio-CVE-2014-9112-pt5.patch88
-rw-r--r--gnu/packages/patches/libtool-2.4-skip-tests.patch24
-rw-r--r--gnu/packages/patches/minetest-subgame-env-var.patch92
-rw-r--r--gnu/packages/patches/mutt-CVE-2014-9116.patch46
-rw-r--r--gnu/packages/patches/unzip-CVE-2014-8139.patch49
-rw-r--r--gnu/packages/patches/unzip-CVE-2014-8140.patch27
-rw-r--r--gnu/packages/patches/unzip-CVE-2014-8141.patch137
-rw-r--r--gnu/packages/version-control.scm53
-rw-r--r--gnu/packages/xdisorg.scm22
-rw-r--r--gnu/packages/xml.scm2
-rw-r--r--gnu/packages/zip.scm6
-rw-r--r--guix/build/syscalls.scm4
-rw-r--r--guix/pk-crypto.scm14
-rw-r--r--nix/libstore/build.cc1
-rw-r--r--nix/libstore/derivations.cc16
-rw-r--r--nix/libstore/derivations.hh4
-rw-r--r--nix/libstore/local-store.cc33
-rw-r--r--nix/libstore/local-store.hh19
-rw-r--r--nix/libstore/misc.cc2
-rw-r--r--nix/libstore/optimise-store.cc76
-rw-r--r--nix/libutil/archive.cc2
-rw-r--r--nix/libutil/util.cc2
-rw-r--r--nix/libutil/util.hh2
-rw-r--r--tests/guix-package.sh23
41 files changed, 1132 insertions, 195 deletions
diff --git a/config-daemon.ac b/config-daemon.ac
index 072fb84b46..28cae23b9d 100644
--- a/config-daemon.ac
+++ b/config-daemon.ac
@@ -73,7 +73,7 @@ if test "x$guix_build_daemon" = "xyes"; then
 
   dnl Chroot support.
   AC_CHECK_FUNCS([chroot unshare])
-  AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h])
+  AC_CHECK_HEADERS([sched.h sys/param.h sys/mount.h tr1/unordered_set])
 
   dnl lutimes and lchown: used when canonicalizing store items.
   dnl posix_fallocate: used when extracting archives.
diff --git a/doc/guix.texi b/doc/guix.texi
index 00737850fd..12a1808137 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -10,7 +10,7 @@
 @include version.texi
 
 @copying
-Copyright @copyright{} 2012, 2013, 2014 Ludovic Courtès@*
+Copyright @copyright{} 2012, 2013, 2014, 2015 Ludovic Courtès@*
 Copyright @copyright{} 2013, 2014 Andreas Enge@*
 Copyright @copyright{} 2013 Nikita Karetnikov
 
@@ -830,16 +830,15 @@ current generation of the user's default profile.  Thus, users can add
 @file{$HOME/.guix-profile/bin} to their @code{PATH} environment
 variable, and so on.
 
-In a multi-user setup, user profiles must be stored in a place
-registered as a @dfn{garbage-collector root}, which
-@file{$HOME/.guix-profile} points to (@pxref{Invoking guix gc}).  That
-directory is normally
+In a multi-user setup, user profiles are stored in a place registered as
+a @dfn{garbage-collector root}, which @file{$HOME/.guix-profile} points
+to (@pxref{Invoking guix gc}).  That directory is normally
 @code{@var{localstatedir}/profiles/per-user/@var{user}}, where
 @var{localstatedir} is the value passed to @code{configure} as
-@code{--localstatedir}, and @var{user} is the user name.  It must be
-created by @code{root}, with @var{user} as the owner.  When it does not
-exist, or is not owned by @var{user}, @command{guix package} emits an
-error about it.
+@code{--localstatedir}, and @var{user} is the user name.  The
+@file{per-user} directory is created when @command{guix-daemon} is
+started, and the @var{user} sub-directory is created by @command{guix
+package}.
 
 The @var{options} can be among the following:
 
diff --git a/gnu-system.am b/gnu-system.am
index 405c01fb07..fc7f326c4f 100644
--- a/gnu-system.am
+++ b/gnu-system.am
@@ -1,5 +1,5 @@
 # GNU Guix --- Functional package management for GNU
-# Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 # Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
 # Copyright © 2013, 2014 Mark H Weaver <mhw@netris.org>
 #
@@ -339,6 +339,11 @@ dist_patch_DATA =						\
   gnu/packages/patches/clucene-pkgconfig.patch			\
   gnu/packages/patches/cmake-fix-tests.patch			\
   gnu/packages/patches/coreutils-dummy-man.patch		\
+  gnu/packages/patches/cpio-CVE-2014-9112-pt1.patch		\
+  gnu/packages/patches/cpio-CVE-2014-9112-pt2.patch		\
+  gnu/packages/patches/cpio-CVE-2014-9112-pt3.patch		\
+  gnu/packages/patches/cpio-CVE-2014-9112-pt4.patch		\
+  gnu/packages/patches/cpio-CVE-2014-9112-pt5.patch		\
   gnu/packages/patches/cpio-gets-undeclared.patch		\
   gnu/packages/patches/cssc-gets-undeclared.patch               \
   gnu/packages/patches/cssc-missing-include.patch               \
@@ -402,6 +407,7 @@ dist_patch_DATA =						\
   gnu/packages/patches/libtheora-config-guess.patch		\
   gnu/packages/patches/libtool-skip-tests.patch			\
   gnu/packages/patches/libtool-skip-tests-for-mips.patch	\
+  gnu/packages/patches/libtool-2.4-skip-tests.patch		\
   gnu/packages/patches/libssh-CVE-2014-0017.patch		\
   gnu/packages/patches/lm-sensors-hwmon-attrs.patch		\
   gnu/packages/patches/luit-posix.patch				\
@@ -410,11 +416,11 @@ dist_patch_DATA =						\
   gnu/packages/patches/mc-fix-ncurses-build.patch		\
   gnu/packages/patches/mcron-install.patch			\
   gnu/packages/patches/mhash-keygen-test-segfault.patch		\
-  gnu/packages/patches/minetest-subgame-env-var.patch		\
   gnu/packages/patches/mit-krb5-init-fix.patch			\
   gnu/packages/patches/mpc123-initialize-ao.patch		\
   gnu/packages/patches/module-init-tools-moduledir.patch	\
   gnu/packages/patches/mupdf-buildsystem-fix.patch		\
+  gnu/packages/patches/mutt-CVE-2014-9116.patch			\
   gnu/packages/patches/net-tools-bitrot.patch			\
   gnu/packages/patches/nvi-assume-preserve-path.patch           \
   gnu/packages/patches/orpheus-cast-errors-and-includes.patch	\
@@ -456,6 +462,9 @@ dist_patch_DATA =						\
   gnu/packages/patches/texi2html-document-encoding.patch	\
   gnu/packages/patches/texi2html-i18n.patch			\
   gnu/packages/patches/udev-gir-libtool.patch			\
+  gnu/packages/patches/unzip-CVE-2014-8139.patch		\
+  gnu/packages/patches/unzip-CVE-2014-8140.patch		\
+  gnu/packages/patches/unzip-CVE-2014-8141.patch		\
   gnu/packages/patches/util-linux-perl.patch			\
   gnu/packages/patches/vpnc-script.patch			\
   gnu/packages/patches/vtk-mesa-10.patch			\
diff --git a/gnu/build/file-systems.scm b/gnu/build/file-systems.scm
index 84f58538fd..38e4851515 100644
--- a/gnu/build/file-systems.scm
+++ b/gnu/build/file-systems.scm
@@ -287,13 +287,6 @@ run a file system check."
        (mount source mount-point type (mount-flags->bit-mask flags)
               (if options
                   (string->pointer options)
-                  %null-pointer))
-
-       ;; Update /etc/mtab.
-       (mkdir-p (string-append root "/etc"))
-       (let ((port (open-file (string-append root "/etc/mtab") "a")))
-         (format port "~a ~a ~a ~a 0 0~%"
-                 source mount-point type (or options "rw"))
-         (close-port port))))))
+                  %null-pointer))))))
 
 ;;; file-systems.scm ends here
diff --git a/gnu/build/linux-boot.scm b/gnu/build/linux-boot.scm
index b2ed1a8b54..3096989468 100644
--- a/gnu/build/linux-boot.scm
+++ b/gnu/build/linux-boot.scm
@@ -275,7 +275,10 @@ UNIONFS."
         (check-file-system root type)
         (mount root "/root" type)))
 
-  (copy-file "/proc/mounts" "/root/etc/mtab"))
+  ;; Make sure /root/etc/mtab is a symlink to /proc/self/mounts.
+  (when (file-exists? "/root/etc/mtab")
+    (delete-file "/root/etc/mtab"))
+  (symlink "/proc/self/mounts" "/root/etc/mtab"))
 
 (define (switch-root root)
   "Switch to ROOT as the root file system, in a way similar to what
diff --git a/gnu/packages.scm b/gnu/packages.scm
index 6109d1f896..7f0b58b971 100644
--- a/gnu/packages.scm
+++ b/gnu/packages.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
 ;;;
@@ -64,11 +64,6 @@
 ;; and an extra environment variable.  One advantage of this setup is
 ;; that everything just works in an auto-compilation setting.
 
-(define %patch-path
-  (make-parameter
-   (map (cut string-append <> "/gnu/packages/patches")
-        %load-path)))
-
 (define %bootstrap-binaries-path
   (make-parameter
    (map (cut string-append <> "/gnu/packages/bootstrap")
@@ -104,6 +99,16 @@
     (make-parameter
      (append environment `((,%distro-root-directory . "gnu/packages"))))))
 
+(define %patch-path
+  ;; Define it after '%package-module-path' so that '%load-path' contains user
+  ;; directories, allowing patches in $GUIX_PACKAGE_PATH to be found.
+  (make-parameter
+   (map (lambda (directory)
+          (if (string=? directory %distro-root-directory)
+              (string-append directory "/gnu/packages/patches")
+              directory))
+        %load-path)))
+
 (define* (scheme-files directory)
   "Return the list of Scheme files found under DIRECTORY, recursively.  The
 returned list is sorted in alphabetical order."
diff --git a/gnu/packages/autotools.scm b/gnu/packages/autotools.scm
index a3afcdcfff..427c6e3113 100644
--- a/gnu/packages/autotools.scm
+++ b/gnu/packages/autotools.scm
@@ -1,6 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
-;;; Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2014 Manolis Fragkiskos Ragkousis <manolis837@gmail.com>
 ;;;
 ;;; This file is part of GNU Guix.
@@ -161,14 +161,14 @@ exec ~a --no-auto-compile \"$0\" \"$@\"
 (define-public automake
   (package
     (name "automake")
-    (version "1.14.1")
+    (version "1.15")
     (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/automake/automake-"
                                  version ".tar.xz"))
              (sha256
               (base32
-               "0s86rzdayj1licgj35q0mnynv5xa8f4p32m36blc5jk9id5z1d59"))
+               "0dl6vfi2lzz8alnklwxzfz624b95hb1ipjvd3mk177flmddcf24r"))
              (patches
               (list (search-patch "automake-skip-amhello-tests.patch")))))
     (build-system gnu-build-system)
@@ -291,3 +291,29 @@ presenting a single consistent, portable interface that hides the usual
 complexity of working with shared libraries across platforms.")
     (license gpl3+)
     (home-page "http://www.gnu.org/software/libtool/")))
+
+(define-public libtool-2.4.4
+  (package (inherit libtool)
+    (version "2.4.4")
+    (source (origin
+              (method url-fetch)
+              (uri (string-append "mirror://gnu/libtool/libtool-"
+                                  version ".tar.xz"))
+              (sha256
+               (base32
+                "0v3zq08qxv7k5067mpqrkjkjl3wphhg06i696mka90mzadc5nad8"))
+              (patches
+               (list (search-patch "libtool-2.4-skip-tests.patch")))))
+
+    (native-inputs `(("automake" ,automake)      ;some tests rely on 'aclocal'
+                     ("autoconf" ,(autoconf-wrapper)) ;others on 'autom4te'
+                     ,@(package-native-inputs libtool)))
+
+    (arguments
+     ;; XXX: There are test failures on mips64el-linux starting from 2.4.4:
+     ;; <http://hydra.gnu.org/build/181662>.
+     (if (string-prefix? "mips64el"
+                         (or (%current-target-system) (%current-system)))
+         `(#:tests? #f
+           ,@(package-arguments libtool))
+         (package-arguments libtool)))))
diff --git a/gnu/packages/cpio.scm b/gnu/packages/cpio.scm
index eff146ded5..87f85d00e8 100644
--- a/gnu/packages/cpio.scm
+++ b/gnu/packages/cpio.scm
@@ -1,5 +1,6 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2012 Nikita Karetnikov <nikita@karetnikov.org>
+;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -19,6 +20,7 @@
 (define-module (gnu packages cpio)
   #:use-module (guix licenses)
   #:use-module (gnu packages)
+  #:use-module (gnu packages autotools)
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix build-system gnu))
@@ -34,8 +36,19 @@
              (sha256
               (base32
                "1gavgpzqwgkpagjxw72xgxz52y1ifgz0ckqh8g7cckz7jvyhp0mv"))
-             (patches (list (search-patch "cpio-gets-undeclared.patch")))))
+             (patches (list (search-patch "cpio-CVE-2014-9112-pt1.patch")
+                            (search-patch "cpio-CVE-2014-9112-pt2.patch")
+                            (search-patch "cpio-CVE-2014-9112-pt3.patch")
+                            (search-patch "cpio-CVE-2014-9112-pt4.patch")
+                            (search-patch "cpio-CVE-2014-9112-pt5.patch")
+                            (search-patch "cpio-gets-undeclared.patch")))))
     (build-system gnu-build-system)
+
+    ;; FIXME: autoconf is needed to run autom4te, to update to test suite
+    ;;        after the CVE-2014-9112 patches.  Remove this when cpio is
+    ;;        updated to post-2.11.
+    (native-inputs `(("autoconf" ,autoconf)))
+
     (home-page "https://www.gnu.org/software/cpio/")
     (synopsis "Manage cpio and tar file archives")
     (description
diff --git a/gnu/packages/games.scm b/gnu/packages/games.scm
index 5261c192eb..b1a68a72c7 100644
--- a/gnu/packages/games.scm
+++ b/gnu/packages/games.scm
@@ -638,7 +638,7 @@ for common mesh file formats, and collision detection.")
 (define minetest-data
   (package
     (name "minetest-data")
-    (version "0.4.10")
+    (version "0.4.11")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -646,7 +646,7 @@ for common mesh file formats, and collision detection.")
                     version ".tar.gz"))
               (sha256
                (base32
-                "09mr71kl7mf4ihszqz1vnwk814p7fvqknad150iic2340a7qzf0i"))))
+                "0hzb27srv6f2j84dpxx2p0p0aaq9vdp5jvbrfpklb5q5ssdjxvc6"))))
     (build-system trivial-build-system)
     (native-inputs
      `(("source" ,source)
@@ -678,7 +678,7 @@ for common mesh file formats, and collision detection.")
 (define-public minetest
   (package
     (name "minetest")
-    (version "0.4.10")
+    (version "0.4.11")
     (source (origin
               (method url-fetch)
               (uri (string-append
@@ -686,10 +686,7 @@ for common mesh file formats, and collision detection.")
                     version ".tar.gz"))
               (sha256
                (base32
-                "1xxv0g83iqszjgwnbdcbsprqg76cb6jnbsh5qhm7lcwx4wy2y2k2"))
-              ;; This patch will be included in future upstream releases.
-              ;; See: https://github.com/minetest/minetest/commit/fd5eaae2babb322f8a3e2acab55a12e218814c8e
-              (patches (list (search-patch "minetest-subgame-env-var.patch")))))
+                "0h223svzkvp63b77nqfxy7k8whw4543gahs3kxd3x4myi5ax5z5f"))))
     (build-system cmake-build-system)
     (arguments
      '(#:modules ((guix build utils)
diff --git a/gnu/packages/gcc.scm b/gnu/packages/gcc.scm
index e795f9749f..4733fc1af6 100644
--- a/gnu/packages/gcc.scm
+++ b/gnu/packages/gcc.scm
@@ -279,7 +279,29 @@ Go.  It also includes runtime support libraries for these languages.")
                                  version "/gcc-" version ".tar.bz2"))
              (sha256
               (base32
-               "1pbjp4blk2ycaa6r3jmw4ky5f1s9ji3klbqgv8zs2sl5jn1cj810"))))))
+               "1pbjp4blk2ycaa6r3jmw4ky5f1s9ji3klbqgv8zs2sl5jn1cj810"))))
+
+    ;; TODO: In core-updates, improve the 'pre-configure phase of the main
+    ;; 'gcc' package so that the 'join-two-line-dynamic-linker-defns phase is
+    ;; no longer needed here.  Then the entire 'arguments' override below can
+    ;; be removed.
+    (arguments
+     (substitute-keyword-arguments (package-arguments gcc-4.7)
+       ((#:phases phases)
+        `(alist-cons-before
+          'pre-configure 'join-two-line-dynamic-linker-defns
+          (lambda* (#:key inputs outputs #:allow-other-keys)
+            (let ((libc (assoc-ref inputs "libc")))
+              (when libc
+                ;; Join two-line definitions of GLIBC_DYNAMIC_LINKER* into a
+                ;; single line, to allow the 'pre-configure phase to work
+                ;; properly.
+                (substitute* (find-files "gcc/config"
+                                         "^linux(64|-elf)?\\.h$")
+                  (("(#define GLIBC_DYNAMIC_LINKER[^ ]*.*)\\\\\n$" _ line)
+                   line)))
+              #t))
+          ,phases))))))
 
 (define* (custom-gcc gcc name languages #:key (separate-lib-output? #t))
   "Return a custom version of GCC that supports LANGUAGES."
diff --git a/gnu/packages/gl.scm b/gnu/packages/gl.scm
index 791b413da6..aa90c7e214 100644
--- a/gnu/packages/gl.scm
+++ b/gnu/packages/gl.scm
@@ -20,6 +20,7 @@
 ;;; along with GNU Guix.  If not, see <http://www.gnu.org/licenses/>.
 
 (define-module (gnu packages gl)
+  #:use-module (ice-9 match)
   #:use-module ((guix licenses) #:prefix l:)
   #:use-module (guix packages)
   #:use-module (guix download)
@@ -161,9 +162,17 @@ Polygon meshes, and Extruded polygon meshes")
         ("python" ,python-2))) ; incompatible with Python 3 (print syntax)
     (arguments
      `(#:configure-flags
-       `(;; drop r300 from default gallium drivers, as it requires llvm
+       '(;; drop r300 from default gallium drivers, as it requires llvm
          "--with-gallium-drivers=r600,svga,swrast"
-         "--enable-xa")
+         "--enable-xa"
+
+         ;; on non-intel systems, drop i915 and i965
+         ;; from the default dri drivers
+         ,@(match (%current-system)
+             ((or "x86_64-linux" "i686-linux")
+              '())
+             (_
+              '("--with-dri-drivers=nouveau,r200,radeon,swrast"))))
        #:phases (alist-cons-after
                  'unpack 'add-missing-m4-files
                  (lambda _
diff --git a/gnu/packages/gnome.scm b/gnu/packages/gnome.scm
index ab988cd70d..61260557e3 100644
--- a/gnu/packages/gnome.scm
+++ b/gnu/packages/gnome.scm
@@ -301,6 +301,18 @@ for settings shared by various components of the GNOME desktop.")
     (inputs
      `(("perl" ,perl)
        ("perl-xml-simple" ,perl-xml-simple)))
+    (arguments
+     '(#:phases
+       (alist-cons-after
+        'install 'set-load-paths
+        ;; Tell 'icon-name-mapping' where XML::Simple is.
+        (lambda* (#:key outputs #:allow-other-keys)
+          (let* ((out  (assoc-ref outputs "out"))
+                 (prog (string-append out "/libexec/icon-name-mapping")))
+            (wrap-program
+             prog
+             `("PERL5LIB" = ,(list (getenv "PERL5LIB"))))))
+        %standard-phases)))
     (home-page "http://tango.freedesktop.org/Standard_Icon_Naming_Specification")
     (synopsis
      "Utility to implement the Freedesktop Icon Naming Specification")
diff --git a/gnu/packages/mail.scm b/gnu/packages/mail.scm
index 534476f7d1..8424d8ccbe 100644
--- a/gnu/packages/mail.scm
+++ b/gnu/packages/mail.scm
@@ -174,7 +174,8 @@ aliasing facilities to work just as they would on normal mail.")
                                        version ".tar.gz")))
              (sha256
               (base32
-               "0dzx4qk50pjfsb6cs5jahng96a52k12f7pm0sc78iqdrawg71w1s"))))
+               "0dzx4qk50pjfsb6cs5jahng96a52k12f7pm0sc78iqdrawg71w1s"))
+             (patches (list (search-patch "mutt-CVE-2014-9116.patch")))))
     (build-system gnu-build-system)
     (inputs
      `(("cyrus-sasl" ,cyrus-sasl)
diff --git a/gnu/packages/patches/cpio-CVE-2014-9112-pt1.patch b/gnu/packages/patches/cpio-CVE-2014-9112-pt1.patch
new file mode 100644
index 0000000000..1224c6c22d
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2014-9112-pt1.patch
@@ -0,0 +1,231 @@
+Partially fix CVE-2014-9112, part 1/5.  Backported to 2.11.
+
+From 746f3ff670dcfcdd28fcc990e79cd6fccc7ae48d Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Mon, 01 Dec 2014 13:15:28 +0000
+Subject: Fix memory overrun on reading improperly created link records.
+
+See http://lists.gnu.org/archive/html/bug-cpio/2014-11/msg00007.html
+
+* src/copyin.c (get_link_name): New function.
+(list_file, copyin_link): use get_link_name
+
+* tests/symlink-bad-length.at: New file.
+* tests/symlink-long.at: New file.
+* tests/Makefile.am: Add new files.
+* tests/testsuite.at: Likewise.
+---
+diff --git a/src/copyin.c b/src/copyin.c
+index 38d809f..c502c7d 100644
+--- a/src/copyin.c
++++ b/src/copyin.c
+@@ -124,10 +124,30 @@ tape_skip_padding (int in_file_des, off_t offset)
+   if (pad != 0)
+     tape_toss_input (in_file_des, pad);
+ }
+-
++
++static char *
++get_link_name (struct cpio_file_stat *file_hdr, int in_file_des)
++{
++  off_t n = file_hdr->c_filesize + 1;
++  char *link_name;
++  
++  if (n == 0 || n > SIZE_MAX)
++    {
++      error (0, 0, _("%s: stored filename length too big"), file_hdr->c_name);
++      link_name = NULL;
++    }
++  else
++    {
++      link_name = xmalloc (n);
++      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
++      link_name[file_hdr->c_filesize] = '\0';
++      tape_skip_padding (in_file_des, file_hdr->c_filesize);
++    }
++  return link_name;
++}
+ 
+ static void
+-list_file(struct cpio_file_stat* file_hdr, int in_file_des)
++list_file (struct cpio_file_stat* file_hdr, int in_file_des)
+ {
+   if (verbose_flag)
+     {
+@@ -136,21 +156,16 @@ list_file(struct cpio_file_stat* file_hdr, int in_file_des)
+ 	{
+ 	  if (archive_format != arf_tar && archive_format != arf_ustar)
+ 	    {
+-	      char *link_name = NULL;	/* Name of hard and symbolic links.  */
+-
+-	      link_name = (char *) xmalloc ((unsigned int) file_hdr->c_filesize + 1);
+-	      link_name[file_hdr->c_filesize] = '\0';
+-	      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+-	      long_format (file_hdr, link_name);
+-	      free (link_name);
+-	      tape_skip_padding (in_file_des, file_hdr->c_filesize);
+-	      return;
++	      char *link_name = get_link_name (file_hdr, in_file_des);
++	      if (link_name)
++		{
++		  long_format (file_hdr, link_name);
++		  free (link_name);
++		}
+ 	    }
+ 	  else
+-	    {
+-	      long_format (file_hdr, file_hdr->c_tar_linkname);
+-	      return;
+-	    }
++	    long_format (file_hdr, file_hdr->c_tar_linkname);
++	  return;
+ 	}
+       else
+ #endif
+@@ -650,10 +665,7 @@ copyin_link(struct cpio_file_stat *file_
+ 
+   if (archive_format != arf_tar && archive_format != arf_ustar)
+     {
+-      link_name = (char *) xmalloc ((unsigned int) file_hdr->c_filesize + 1);
+-      link_name[file_hdr->c_filesize] = '\0';
+-      tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+-      tape_skip_padding (in_file_des, file_hdr->c_filesize);
++      link_name = get_link_name (file_hdr, in_file_des);
+     }
+   else
+     {
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 3f714d1..b4ca92d 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -52,6 +52,8 @@ TESTSUITE_AT = \
+  setstat04.at\
+  setstat05.at\
+  symlink.at\
++ symlink-bad-length.at\
++ symlink-long.at\
+  version.at
+ 
+ TESTSUITE = $(srcdir)/testsuite
+diff --git a/tests/symlink-bad-length.at b/tests/symlink-bad-length.at
+new file mode 100644
+index 0000000..6f804b1
+--- a/dev/null
++++ b/tests/symlink-bad-length.at
+@@ -0,0 +1,49 @@
++# Process this file with autom4te to create testsuite.  -*- Autotest -*-
++# Copyright (C) 2014 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3, or (at your option)
++# any later version.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++# 02110-1301 USA.
++
++# Cpio v2.11 did segfault with badly set symlink length.
++# References:
++# http://lists.gnu.org/archive/html/bug-cpio/2014-11/msg00007.html
++
++AT_SETUP([symlink-bad-length])
++AT_KEYWORDS([symlink-long copyout])
++
++AT_DATA([ARCHIVE.base64],
++[x3EjAIBAtIEtJy8nAQAAAHRUYW0FAAAADQBGSUxFAABzb21lIGNvbnRlbnQKAMdxIwBgQ/+hLScv
++JwEAAAB0VEhuBQD/////TElOSwAARklMRcdxAAAAAAAAAAAAAAEAAAAAAAAACwAAAAAAVFJBSUxF
++UiEhIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
++])
++
++AT_CHECK([
++base64 -d ARCHIVE.base64 > ARCHIVE || AT_SKIP_TEST
++cpio -ntv < ARCHIVE
++test $? -eq 2
++],
++[0],
++[-rw-rw-r--   1 10029    10031          13 Nov 25 13:52 FILE
++],[cpio: LINK: stored filename length too big
++cpio: premature end of file
++])
++
++AT_CLEANUP
+diff --git a/tests/symlink-long.at b/tests/symlink-long.at
+new file mode 100644
+index 0000000..d3def2d
+--- a/dev/null
++++ b/tests/symlink-long.at
+@@ -0,0 +1,46 @@
++# Process this file with autom4te to create testsuite.  -*- Autotest -*-
++# Copyright (C) 2014 Free Software Foundation, Inc.
++
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 3, or (at your option)
++# any later version.
++
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++# GNU General Public License for more details.
++
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
++# 02110-1301 USA.
++
++# Cpio v2.11.90 changed the way symlink name is read from archive.
++# References:
++# http://lists.gnu.org/archive/html/bug-cpio/2014-11/msg00007.html
++
++AT_SETUP([symlink-long])
++AT_KEYWORDS([symlink-long copyout])
++
++AT_CHECK([
++
++# len(dirname) > READBUFSIZE
++dirname=
++for i in {1..52}; do
++    dirname="xxxxxxxxx/$dirname"
++    mkdir "$dirname"
++done
++ln -s "$dirname" x || AT_SKIP_TEST
++
++echo x | cpio -o > ar
++list=`cpio -tv < ar | sed 's|.*-> ||'`
++test "$list" = "$dirname" && echo success || echo fail
++],
++[0],
++[success
++],[2 blocks
++2 blocks
++])
++
++AT_CLEANUP
+diff --git a/tests/testsuite.at b/tests/testsuite.at
+index e67689f..3b5377e 100644
+--- a/tests/testsuite.at
++++ b/tests/testsuite.at
+@@ -31,6 +31,8 @@ m4_include([version.at])
+ 
+ m4_include([inout.at])
+ m4_include([symlink.at])
++m4_include([symlink-bad-length.at])
++m4_include([symlink-long.at])
+ m4_include([interdir.at])
+ 
+ m4_include([setstat01.at])
+--
+cgit v0.9.0.2
diff --git a/gnu/packages/patches/cpio-CVE-2014-9112-pt2.patch b/gnu/packages/patches/cpio-CVE-2014-9112-pt2.patch
new file mode 100644
index 0000000000..77c531cb54
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2014-9112-pt2.patch
@@ -0,0 +1,51 @@
+Partially fix CVE-2014-9112, part 2/5.
+
+From 54d1c42ac2cb91389fca04a5018ad573e4ae265a Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Mon, 01 Dec 2014 19:10:39 +0000
+Subject: Bugfix
+
+* src/copyin.c (get_link_name): Fix range checking.
+* tests/symlink-bad-length.at: Change expected error message.
+---
+diff --git a/src/copyin.c b/src/copyin.c
+index c502c7d..042cc41 100644
+--- a/src/copyin.c
++++ b/src/copyin.c
+@@ -128,17 +128,17 @@ tape_skip_padding (int in_file_des, off_t offset)
+ static char *
+ get_link_name (struct cpio_file_stat *file_hdr, int in_file_des)
+ {
+-  off_t n = file_hdr->c_filesize + 1;
+   char *link_name;
+   
+-  if (n == 0 || n > SIZE_MAX)
++  if (file_hdr->c_filesize < 0 || file_hdr->c_filesize > SIZE_MAX-1)
+     {
+-      error (0, 0, _("%s: stored filename length too big"), file_hdr->c_name);
++      error (0, 0, _("%s: stored filename length is out of range"),
++	     file_hdr->c_name);
+       link_name = NULL;
+     }
+   else
+     {
+-      link_name = xmalloc (n);
++      link_name = xmalloc (file_hdr->c_filesize);
+       tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+       link_name[file_hdr->c_filesize] = '\0';
+       tape_skip_padding (in_file_des, file_hdr->c_filesize);
+diff --git a/tests/symlink-bad-length.at b/tests/symlink-bad-length.at
+index 6f804b1..cbf4aa7 100644
+--- a/tests/symlink-bad-length.at
++++ b/tests/symlink-bad-length.at
+@@ -42,7 +42,7 @@ test $? -eq 2
+ ],
+ [0],
+ [-rw-rw-r--   1 10029    10031          13 Nov 25 13:52 FILE
+-],[cpio: LINK: stored filename length too big
++],[cpio: LINK: stored filename length is out of range
+ cpio: premature end of file
+ ])
+ 
+--
+cgit v0.9.0.2
diff --git a/gnu/packages/patches/cpio-CVE-2014-9112-pt3.patch b/gnu/packages/patches/cpio-CVE-2014-9112-pt3.patch
new file mode 100644
index 0000000000..644dc6f9ef
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2014-9112-pt3.patch
@@ -0,0 +1,23 @@
+Partially fix CVE-2014-9112, part 3/5.
+
+From 58df4f1b44a1142bba500f980fd26806413b1728 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Tue, 02 Dec 2014 09:33:29 +0000
+Subject: Fix typo
+
+---
+diff --git a/src/copyin.c b/src/copyin.c
+index 042cc41..264bfcb 100644
+--- a/src/copyin.c
++++ b/src/copyin.c
+@@ -138,7 +138,7 @@ get_link_name (struct cpio_file_stat *file_hdr, int in_file_des)
+     }
+   else
+     {
+-      link_name = xmalloc (file_hdr->c_filesize);
++      link_name = xmalloc (file_hdr->c_filesize + 1);
+       tape_buffered_read (link_name, in_file_des, file_hdr->c_filesize);
+       link_name[file_hdr->c_filesize] = '\0';
+       tape_skip_padding (in_file_des, file_hdr->c_filesize);
+--
+cgit v0.9.0.2
diff --git a/gnu/packages/patches/cpio-CVE-2014-9112-pt4.patch b/gnu/packages/patches/cpio-CVE-2014-9112-pt4.patch
new file mode 100644
index 0000000000..fa2e8530b2
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2014-9112-pt4.patch
@@ -0,0 +1,105 @@
+Partially fix CVE-2014-9112, part 4/5.  Backported to 2.11.
+
+From fd262d116c4564c1796be9be2799619cf7785d07 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Thu, 11 Dec 2014 10:51:21 +0000
+Subject: Fix error recovery in copy-in mode
+
+* src/copyin.c (copyin_link): Fix null dereference.
+(read_in_header): Fix error recovery (bug introduced by
+27e0ae55).
+* tests/symlink-bad-length.at: Test error recovery.
+Catch various architecture-dependent error messages (suggested
+by Pavel Raiskup).
+---
+diff --git a/src/copyin.c b/src/copyin.c
+index 264bfcb..ca12356 100644
+--- a/src/copyin.c
++++ b/src/copyin.c
+@@ -655,7 +655,7 @@ copyin_device (struct cpio_file_stat* file_hdr)
+ }
+ 
+ static void
+-copyin_link(struct cpio_file_stat *file_hdr, int in_file_des)
++copyin_link (struct cpio_file_stat *file_hdr, int in_file_des)
+ {
+   char *link_name = NULL;	/* Name of hard and symbolic links.  */
+   int res;			/* Result of various function calls.  */
+@@ -666,6 +666,8 @@ copyin_link(struct cpio_file_stat *file_
+   if (archive_format != arf_tar && archive_format != arf_ustar)
+     {
+       link_name = get_link_name (file_hdr, in_file_des);
++      if (!link_name)
++	return;
+     }
+   else
+     {
+@@ -1017,7 +1019,7 @@ read_in_header (struct cpio_file_stat *file_hdr, int in_des)
+ 
+   file_hdr->c_tar_linkname = NULL;
+ 
+-  tape_buffered_read (magic.str, in_des, 6L);
++  tape_buffered_read (magic.str, in_des, sizeof (magic.str));
+   while (1)
+     {
+       if (append_flag)
+@@ -1062,8 +1064,8 @@ read_in_header (struct cpio_file_stat *file_hdr, int in_des)
+ 	  break;
+ 	}
+       bytes_skipped++;
+-      memmove (magic.str, magic.str + 1, 5);
+-      tape_buffered_read (magic.str, in_des, 1L);
++      memmove (magic.str, magic.str + 1, sizeof (magic.str) - 1);
++      tape_buffered_read (magic.str + sizeof (magic.str) - 1, in_des, 1L);
+     }
+ }
+ 
+diff --git a/tests/symlink-bad-length.at b/tests/symlink-bad-length.at
+index cbf4aa7..4dbeaa3 100644
+--- a/tests/symlink-bad-length.at
++++ b/tests/symlink-bad-length.at
+@@ -24,9 +24,9 @@ AT_SETUP([symlink-bad-length])
+ AT_KEYWORDS([symlink-long copyout])
+ 
+ AT_DATA([ARCHIVE.base64],
+-[x3EjAIBAtIEtJy8nAQAAAHRUYW0FAAAADQBGSUxFAABzb21lIGNvbnRlbnQKAMdxIwBgQ/+hLScv
+-JwEAAAB0VEhuBQD/////TElOSwAARklMRcdxAAAAAAAAAAAAAAEAAAAAAAAACwAAAAAAVFJBSUxF
+-UiEhIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
++[x3ECCJ1jtIHoA2QAAQAAAIlUwl0FAAAADQBGSUxFAABzb21lIGNvbnRlbnQKAMdxAgidHv+h6ANk
++AAEAAACJVHFtBQD/////TElOSwAARklMRcdxAgieHqSB6ANkAAEAAACJVDJuBgAAABIARklMRTIA
++c29tZSBtb3JlIGNvbnRlbnQKx3EAAAAAAAAAAAAAAQAAAAAAAAALAAAAAABUUkFJTEVSISEhAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+@@ -37,13 +37,23 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+ 
+ AT_CHECK([
+ base64 -d ARCHIVE.base64 > ARCHIVE || AT_SKIP_TEST
+-cpio -ntv < ARCHIVE
+-test $? -eq 2
++TZ=UTC cpio -ntv < ARCHIVE 2>stderr
++rc=$?
++cat stderr | grep -v \
++    -e 'stored filename length is out of range' \
++    -e 'premature end of file' \
++    -e 'archive header has reverse byte-order' \
++    -e 'memory exhausted' \
++    >&2
++echo >&2 STDERR
++test "$rc" -ne 0
+ ],
+-[0],
+-[-rw-rw-r--   1 10029    10031          13 Nov 25 13:52 FILE
+-],[cpio: LINK: stored filename length is out of range
+-cpio: premature end of file
++[1],
++[-rw-rw-r--   1 1000     100            13 Dec 11 09:02 FILE
++-rw-r--r--   1 1000     100            18 Dec 11 10:13 FILE2
++],[cpio: warning: skipped 4 bytes of junk
++1 block
++STDERR
+ ])
+ 
+ AT_CLEANUP
+--
+cgit v0.9.0.2
diff --git a/gnu/packages/patches/cpio-CVE-2014-9112-pt5.patch b/gnu/packages/patches/cpio-CVE-2014-9112-pt5.patch
new file mode 100644
index 0000000000..75313cbefa
--- /dev/null
+++ b/gnu/packages/patches/cpio-CVE-2014-9112-pt5.patch
@@ -0,0 +1,88 @@
+Partially fix CVE-2014-9112, part 5/5.  Backported to 2.11.
+
+From f6a8a2cbd2d5ca40ea94900b55b845dd5ca87328 Mon Sep 17 00:00:00 2001
+From: Sergey Poznyakoff <gray@gnu.org.ua>
+Date: Thu, 11 Dec 2014 13:21:40 +0000
+Subject: Fix symlink-bad-length test for 64-bit architectures.
+
+* src/util.c: Return non-zero exit code if EOF is hit prematurely.
+* tests/symlink-bad-length.at: Revert to original archive: there's
+no use testing for recovery, because that depends on the host
+architecture.  Don't test for exit code as well (same reason).
+Account for eventual warning messages.
+---
+diff --git a/src/util.c b/src/util.c
+index 6c483f8..39c9813 100644
+--- a/src/util.c
++++ b/src/util.c
+@@ -206,10 +206,7 @@ tape_fill_input_buffer (int in_des, int
+   if (input_size < 0)
+     error (1, errno, _("read error"));
+   if (input_size == 0)
+-    {
+-      error (0, 0, _("premature end of file"));
+-      exit (1);
+-    }
++    error (PAXEXIT_FAILURE, 0, _("premature end of file"));
+   input_bytes += input_size;
+ }
+ 
+diff --git a/tests/symlink-bad-length.at b/tests/symlink-bad-length.at
+index 4dbeaa3..e1a7093 100644
+--- a/tests/symlink-bad-length.at
++++ b/tests/symlink-bad-length.at
+@@ -24,9 +24,9 @@ AT_SETUP([symlink-bad-length])
+ AT_KEYWORDS([symlink-long copyout])
+ 
+ AT_DATA([ARCHIVE.base64],
+-[x3ECCJ1jtIHoA2QAAQAAAIlUwl0FAAAADQBGSUxFAABzb21lIGNvbnRlbnQKAMdxAgidHv+h6ANk
+-AAEAAACJVHFtBQD/////TElOSwAARklMRcdxAgieHqSB6ANkAAEAAACJVDJuBgAAABIARklMRTIA
+-c29tZSBtb3JlIGNvbnRlbnQKx3EAAAAAAAAAAAAAAQAAAAAAAAALAAAAAABUUkFJTEVSISEhAAAA
++[x3EjAIBAtIEtJy8nAQAAAHRUYW0FAAAADQBGSUxFAABzb21lIGNvbnRlbnQKAMdxIwBgQ/+hLScv
++JwEAAAB0VEhuBQD/////TElOSwAARklMRcdxAAAAAAAAAAAAAAEAAAAAAAAACwAAAAAAVFJBSUxF
++UiEhIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+@@ -35,25 +35,30 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
+ ])
+ 
++# The exact error message and exit status depend on the host architecture,
++# therefore strderr is filtered out and error code is not checked.
++
++# So far the only case when cpio would exit with code 0 is when it skips
++# several bytes and encounters a valid record header.  Perhaps it should
++# exit with code 2 (non-critical error), if at least one byte was skipped,
++# but that could hurt backward compatibility.
++
+ AT_CHECK([
+ base64 -d ARCHIVE.base64 > ARCHIVE || AT_SKIP_TEST
+-TZ=UTC cpio -ntv < ARCHIVE 2>stderr
+-rc=$?
++TZ=UTC cpio -ntv < ARCHIVE 2>stderr 
+ cat stderr | grep -v \
+     -e 'stored filename length is out of range' \
+     -e 'premature end of file' \
+     -e 'archive header has reverse byte-order' \
+     -e 'memory exhausted' \
++    -e 'skipped [[0-9][0-9]*] bytes of junk' \
++    -e '[[0-9][0-9]*] block' \
+     >&2
+ echo >&2 STDERR
+-test "$rc" -ne 0
+ ],
+-[1],
+-[-rw-rw-r--   1 1000     100            13 Dec 11 09:02 FILE
+--rw-r--r--   1 1000     100            18 Dec 11 10:13 FILE2
+-],[cpio: warning: skipped 4 bytes of junk
+-1 block
+-STDERR
++[0],
++[-rw-rw-r--   1 10029    10031          13 Nov 25 11:52 FILE
++],[STDERR
+ ])
+ 
+ AT_CLEANUP
+--
+cgit v0.9.0.2
diff --git a/gnu/packages/patches/libtool-2.4-skip-tests.patch b/gnu/packages/patches/libtool-2.4-skip-tests.patch
new file mode 100644
index 0000000000..95747dfef0
--- /dev/null
+++ b/gnu/packages/patches/libtool-2.4-skip-tests.patch
@@ -0,0 +1,24 @@
+Because our GCC 'lib' spec automatically adds '-rpath' for each '-L'
+and a couple more '-rpath, there are two test failures:
+one in demo.test, and one in destdir.at.  Disable these.
+
+--- libtool-2.4.4/tests/testsuite	2014-11-29 17:43:11.000000000 +0100
++++ libtool-2.4.4/tests/testsuite	2015-01-03 23:00:09.367775122 +0100
+@@ -9185,7 +9185,7 @@ read at_status <"$at_status_file"
+ #AT_START_33
+ at_fn_group_banner 33 'demo.at:548' \
+   "hardcoding library path" "                        " 3
+-at_xfail=no
++at_xfail=yes
+       test no = "$ACLOCAL" && at_xfail=yes
+       test no = "$AUTOHEADER" && at_xfail=yes
+       test no = "$AUTOMAKE" && at_xfail=yes
+@@ -27052,7 +27052,7 @@ read at_status <"$at_status_file"
+ #AT_START_97
+ at_fn_group_banner 97 'destdir.at:75' \
+   "DESTDIR with in-package deplibs" "                " 7
+-at_xfail=no
++at_xfail=yes
+       eval `$LIBTOOL --config | $GREP '^fast_install='`
+            case $fast_install in no) :;; *) false;; esac && at_xfail=yes
+ (
diff --git a/gnu/packages/patches/minetest-subgame-env-var.patch b/gnu/packages/patches/minetest-subgame-env-var.patch
deleted file mode 100644
index de782284c9..0000000000
--- a/gnu/packages/patches/minetest-subgame-env-var.patch
+++ /dev/null
@@ -1,92 +0,0 @@
-From fd5eaae2babb322f8a3e2acab55a12e218814c8e Mon Sep 17 00:00:00 2001
-From: David Thompson <dthompson2@worcester.edu>
-Date: Sat, 6 Sep 2014 13:21:46 -0400
-Subject: [PATCH] Search for subgames using $MINETEST_SUBGAME_PATH.
-
----
- doc/minetest.6  |  6 ++++++
- src/subgame.cpp | 30 ++++++++++++++++++++++++++++++
- 2 files changed, 36 insertions(+)
-
-diff --git a/doc/minetest.6 b/doc/minetest.6
-index d94c12c..ff54520 100644
---- a/doc/minetest.6
-+++ b/doc/minetest.6
-@@ -83,6 +83,12 @@ Set world path
- Migrate from current map backend to another. Possible values are sqlite3
- and leveldb. Only works when using --server.
- 
-+.SH ENVIRONMENT VARIABLES
-+
-+.TP
-+MINETEST_SUBGAME_PATH
-+Colon delimited list of directories to search for subgames.
-+
- .SH BUGS
- Please report all bugs to Perttu Ahola <celeron55@gmail.com>.
- 
-diff --git a/src/subgame.cpp b/src/subgame.cpp
-index f2465c9..e86655b 100644
---- a/src/subgame.cpp
-+++ b/src/subgame.cpp
-@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
- #include "filesys.h"
- #include "settings.h"
- #include "log.h"
-+#include "strfnd.h"
- #ifndef SERVER
- #include "tile.h" // getImagePath
- #endif
-@@ -59,6 +60,17 @@ struct GameFindPath
- 	{}
- };
- 
-+Strfnd getSubgamePathEnv() {
-+  std::string sp;
-+  char *subgame_path = getenv("MINETEST_SUBGAME_PATH");
-+
-+  if(subgame_path) {
-+    sp = std::string(subgame_path);
-+  }
-+
-+  return Strfnd(sp);
-+}
-+
- SubgameSpec findSubgame(const std::string &id)
- {
- 	if(id == "")
-@@ -66,6 +78,17 @@ SubgameSpec findSubgame(const std::string &id)
- 	std::string share = porting::path_share;
- 	std::string user = porting::path_user;
- 	std::vector<GameFindPath> find_paths;
-+
-+        Strfnd search_paths = getSubgamePathEnv();
-+
-+        while(!search_paths.atend()) {
-+                std::string path = search_paths.next(":");
-+                find_paths.push_back(GameFindPath(
-+                                       path + DIR_DELIM + id, false));
-+                find_paths.push_back(GameFindPath(
-+                                       path + DIR_DELIM + id + "_game", false));
-+        }
-+
- 	find_paths.push_back(GameFindPath(
- 			user + DIR_DELIM + "games" + DIR_DELIM + id + "_game", true));
- 	find_paths.push_back(GameFindPath(
-@@ -129,6 +152,13 @@ std::set<std::string> getAvailableGameIds()
- 	std::set<std::string> gamespaths;
- 	gamespaths.insert(porting::path_share + DIR_DELIM + "games");
- 	gamespaths.insert(porting::path_user + DIR_DELIM + "games");
-+
-+        Strfnd search_paths = getSubgamePathEnv();
-+
-+        while(!search_paths.atend()) {
-+                gamespaths.insert(search_paths.next(":"));
-+        }
-+
- 	for(std::set<std::string>::const_iterator i = gamespaths.begin();
- 			i != gamespaths.end(); i++){
- 		std::vector<fs::DirListNode> dirlist = fs::GetDirListing(*i);
--- 
-2.1.1
-
diff --git a/gnu/packages/patches/mutt-CVE-2014-9116.patch b/gnu/packages/patches/mutt-CVE-2014-9116.patch
new file mode 100644
index 0000000000..91e17ecbe0
--- /dev/null
+++ b/gnu/packages/patches/mutt-CVE-2014-9116.patch
@@ -0,0 +1,46 @@
+Fix CVE-2014-9116.  Copied from Debian:
+
+This patch solves the issue raised by CVE-2014-9116 in bug 771125.
+
+We correctly redefine what are the whitespace characters as per RFC5322; by
+doing so we prevent mutt_substrdup from being used in a way that could lead to
+a segfault.
+
+The lib.c part was written by Antonio Radici <antonio@debian.org> to prevent
+crashes due to this kind of bugs from happening again.
+
+The wheezy version of this patch is slightly different, therefore this patch
+has -jessie prefixed in its name.
+
+The sendlib.c part was provided by Salvatore Bonaccorso and it is the same as
+the upstream patch reported here:
+http://dev.mutt.org/trac/attachment/ticket/3716/ticket-3716-stable.patch
+
+--- a/lib.c
++++ b/lib.c
+@@ -815,6 +815,9 @@ char *mutt_substrdup (const char *begin,
+   size_t len;
+   char *p;
+ 
++  if (end != NULL && end < begin)
++    return NULL;
++
+   if (end)
+     len = end - begin;
+   else
+--- a/sendlib.c
++++ b/sendlib.c
+@@ -1814,7 +1814,12 @@ static int write_one_header (FILE *fp, i
+     {
+       tagbuf = mutt_substrdup (start, t);
+       /* skip over the colon separating the header field name and value */
+-      t = skip_email_wsp(t + 1);
++      ++t;
++
++      /* skip over any leading whitespace (WSP, as defined in RFC5322) */
++      while (*t == ' ' || *t == '\t')
++        t++;
++
+       valbuf = mutt_substrdup (t, end);
+     }
+     dprint(4,(debugfile,"mwoh: buf[%s%s] too long, "
diff --git a/gnu/packages/patches/unzip-CVE-2014-8139.patch b/gnu/packages/patches/unzip-CVE-2014-8139.patch
new file mode 100644
index 0000000000..433efd1aaf
--- /dev/null
+++ b/gnu/packages/patches/unzip-CVE-2014-8139.patch
@@ -0,0 +1,49 @@
+From: sms
+Subject: Fix CVE-2014-8139: CRC32 verification heap-based overflow
+Bug-Debian: http://bugs.debian.org/773722
+
+--- a/extract.c
++++ b/extract.c
+@@ -1,5 +1,5 @@
+ /*
+-  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
++  Copyright (c) 1990-2014 Info-ZIP.  All rights reserved.
+ 
+   See the accompanying file LICENSE, version 2009-Jan-02 or later
+   (the contents of which are also included in unzip.h) for terms of use.
+@@ -298,6 +298,8 @@
+ #ifndef SFX
+    static ZCONST char Far InconsistEFlength[] = "bad extra-field entry:\n \
+      EF block length (%u bytes) exceeds remaining EF data (%u bytes)\n";
++   static ZCONST char Far TooSmallEFlength[] = "bad extra-field entry:\n \
++     EF block length (%u bytes) invalid (< %d)\n";
+    static ZCONST char Far InvalidComprDataEAs[] =
+      " invalid compressed data for EAs\n";
+ #  if (defined(WIN32) && defined(NTSD_EAS))
+@@ -2023,7 +2025,8 @@
+         ebID = makeword(ef);
+         ebLen = (unsigned)makeword(ef+EB_LEN);
+ 
+-        if (ebLen > (ef_len - EB_HEADSIZE)) {
++        if (ebLen > (ef_len - EB_HEADSIZE))
++        {
+            /* Discovered some extra field inconsistency! */
+             if (uO.qflag)
+                 Info(slide, 1, ((char *)slide, "%-22s ",
+@@ -2032,6 +2035,16 @@
+               ebLen, (ef_len - EB_HEADSIZE)));
+             return PK_ERR;
+         }
++        else if (ebLen < EB_HEADSIZE)
++        {
++            /* Extra block length smaller than header length. */
++            if (uO.qflag)
++                Info(slide, 1, ((char *)slide, "%-22s ",
++                  FnFilter1(G.filename)));
++            Info(slide, 1, ((char *)slide, LoadFarString(TooSmallEFlength),
++              ebLen, EB_HEADSIZE));
++            return PK_ERR;
++        }
+ 
+         switch (ebID) {
+             case EF_OS2:
diff --git a/gnu/packages/patches/unzip-CVE-2014-8140.patch b/gnu/packages/patches/unzip-CVE-2014-8140.patch
new file mode 100644
index 0000000000..595d8d5bcd
--- /dev/null
+++ b/gnu/packages/patches/unzip-CVE-2014-8140.patch
@@ -0,0 +1,27 @@
+From: sms
+Subject: Fix CVE-2014-8140: out-of-bounds write issue in test_compr_eb()
+Bug-Debian: http://bugs.debian.org/773722
+
+--- a/extract.c
++++ b/extract.c
+@@ -2234,10 +2234,17 @@
+     if (compr_offset < 4)                /* field is not compressed: */
+         return PK_OK;                    /* do nothing and signal OK */
+ 
++    /* Return no/bad-data error status if any problem is found:
++     *    1. eb_size is too small to hold the uncompressed size
++     *       (eb_ucsize).  (Else extract eb_ucsize.)
++     *    2. eb_ucsize is zero (invalid).  2014-12-04 SMS.
++     *    3. eb_ucsize is positive, but eb_size is too small to hold
++     *       the compressed data header.
++     */
+     if ((eb_size < (EB_UCSIZE_P + 4)) ||
+-        ((eb_ucsize = makelong(eb+(EB_HEADSIZE+EB_UCSIZE_P))) > 0L &&
+-         eb_size <= (compr_offset + EB_CMPRHEADLEN)))
+-        return IZ_EF_TRUNC;               /* no compressed data! */
++     ((eb_ucsize = makelong( eb+ (EB_HEADSIZE+ EB_UCSIZE_P))) == 0L) ||
++     ((eb_ucsize > 0L) && (eb_size <= (compr_offset + EB_CMPRHEADLEN))))
++        return IZ_EF_TRUNC;             /* no/bad compressed data! */
+ 
+     if (
+ #ifdef INT_16BIT
diff --git a/gnu/packages/patches/unzip-CVE-2014-8141.patch b/gnu/packages/patches/unzip-CVE-2014-8141.patch
new file mode 100644
index 0000000000..283925fc34
--- /dev/null
+++ b/gnu/packages/patches/unzip-CVE-2014-8141.patch
@@ -0,0 +1,137 @@
+From: sms
+Subject: Fix CVE-2014-8141: out-of-bounds read issues in getZip64Data()
+Bug-Debian: http://bugs.debian.org/773722
+
+--- a/fileio.c
++++ b/fileio.c
+@@ -176,6 +176,8 @@
+ #endif
+ static ZCONST char Far ExtraFieldTooLong[] =
+   "warning:  extra field too long (%d).  Ignoring...\n";
++static ZCONST char Far ExtraFieldCorrupt[] =
++  "warning:  extra field (type: 0x%04x) corrupt.  Continuing...\n";
+ 
+ #ifdef WINDLL
+    static ZCONST char Far DiskFullQuery[] =
+@@ -2295,7 +2297,12 @@
+             if (readbuf(__G__ (char *)G.extra_field, length) == 0)
+                 return PK_EOF;
+             /* Looks like here is where extra fields are read */
+-            getZip64Data(__G__ G.extra_field, length);
++            if (getZip64Data(__G__ G.extra_field, length) != PK_COOL)
++            {
++                Info(slide, 0x401, ((char *)slide,
++                 LoadFarString( ExtraFieldCorrupt), EF_PKSZ64));
++                error = PK_WARN;
++            }
+ #ifdef UNICODE_SUPPORT
+             G.unipath_filename = NULL;
+             if (G.UzO.U_flag < 2) {
+--- a/process.c
++++ b/process.c
+@@ -1,5 +1,5 @@
+ /*
+-  Copyright (c) 1990-2009 Info-ZIP.  All rights reserved.
++  Copyright (c) 1990-2014 Info-ZIP.  All rights reserved.
+ 
+   See the accompanying file LICENSE, version 2009-Jan-02 or later
+   (the contents of which are also included in unzip.h) for terms of use.
+@@ -1901,48 +1901,82 @@
+     and a 4-byte version of disk start number.
+     Sets both local header and central header fields.  Not terribly clever,
+     but it means that this procedure is only called in one place.
++
++    2014-12-05 SMS.
++    Added checks to ensure that enough data are available before calling
++    makeint64() or makelong().  Replaced various sizeof() values with
++    simple ("4" or "8") constants.  (The Zip64 structures do not depend
++    on our variable sizes.)  Error handling is crude, but we should now
++    stay within the buffer.
+   ---------------------------------------------------------------------------*/
+ 
++#define Z64FLGS 0xffff
++#define Z64FLGL 0xffffffff
++
+     if (ef_len == 0 || ef_buf == NULL)
+         return PK_COOL;
+ 
+     Trace((stderr,"\ngetZip64Data: scanning extra field of length %u\n",
+       ef_len));
+ 
+-    while (ef_len >= EB_HEADSIZE) {
++    while (ef_len >= EB_HEADSIZE)
++    {
+         eb_id = makeword(EB_ID + ef_buf);
+         eb_len = makeword(EB_LEN + ef_buf);
+ 
+-        if (eb_len > (ef_len - EB_HEADSIZE)) {
+-            /* discovered some extra field inconsistency! */
++        if (eb_len > (ef_len - EB_HEADSIZE))
++        {
++            /* Extra block length exceeds remaining extra field length. */
+             Trace((stderr,
+               "getZip64Data: block length %u > rest ef_size %u\n", eb_len,
+               ef_len - EB_HEADSIZE));
+             break;
+         }
+-        if (eb_id == EF_PKSZ64) {
+-
++        if (eb_id == EF_PKSZ64)
++        {
+           int offset = EB_HEADSIZE;
+ 
+-          if (G.crec.ucsize == 0xffffffff || G.lrec.ucsize == 0xffffffff){
+-            G.lrec.ucsize = G.crec.ucsize = makeint64(offset + ef_buf);
+-            offset += sizeof(G.crec.ucsize);
++          if ((G.crec.ucsize == Z64FLGL) || (G.lrec.ucsize == Z64FLGL))
++          {
++            if (offset+ 8 > ef_len)
++              return PK_ERR;
++
++            G.crec.ucsize = G.lrec.ucsize = makeint64(offset + ef_buf);
++            offset += 8;
+           }
+-          if (G.crec.csize == 0xffffffff || G.lrec.csize == 0xffffffff){
+-            G.csize = G.lrec.csize = G.crec.csize = makeint64(offset + ef_buf);
+-            offset += sizeof(G.crec.csize);
++
++          if ((G.crec.csize == Z64FLGL) || (G.lrec.csize == Z64FLGL))
++          {
++            if (offset+ 8 > ef_len)
++              return PK_ERR;
++
++            G.csize = G.crec.csize = G.lrec.csize = makeint64(offset + ef_buf);
++            offset += 8;
+           }
+-          if (G.crec.relative_offset_local_header == 0xffffffff){
++
++          if (G.crec.relative_offset_local_header == Z64FLGL)
++          {
++            if (offset+ 8 > ef_len)
++              return PK_ERR;
++
+             G.crec.relative_offset_local_header = makeint64(offset + ef_buf);
+-            offset += sizeof(G.crec.relative_offset_local_header);
++            offset += 8;
+           }
+-          if (G.crec.disk_number_start == 0xffff){
++
++          if (G.crec.disk_number_start == Z64FLGS)
++          {
++            if (offset+ 4 > ef_len)
++              return PK_ERR;
++
+             G.crec.disk_number_start = (zuvl_t)makelong(offset + ef_buf);
+-            offset += sizeof(G.crec.disk_number_start);
++            offset += 4;
+           }
++#if 0
++          break;                /* Expect only one EF_PKSZ64 block. */
++#endif /* 0 */
+         }
+ 
+-        /* Skip this extra field block */
++        /* Skip this extra field block. */
+         ef_buf += (eb_len + EB_HEADSIZE);
+         ef_len -= (eb_len + EB_HEADSIZE);
+     }
diff --git a/gnu/packages/version-control.scm b/gnu/packages/version-control.scm
index 4f9ed54d56..47b4692d7c 100644
--- a/gnu/packages/version-control.scm
+++ b/gnu/packages/version-control.scm
@@ -1,7 +1,7 @@
 ;;; GNU Guix --- Functional package management for GNU
 ;;; Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 ;;; Copyright © 2013 Cyril Roelandt <tipecaml@gmail.com>
-;;; Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;; Copyright © 2013, 2014 Andreas Enge <andreas@enge.fr>
 ;;; Copyright © 2014 Mark H Weaver <mhw@netris.org>
 ;;; Copyright © 2014 Eric Bavier <bavier@member.fsf.org>
@@ -95,16 +95,17 @@ as well as the classic centralized workflow.")
     (license gpl2+)))
 
 (define-public git
+  ;; Keep in sync with 'git-manpages'!
   (package
    (name "git")
-   (version "2.1.2")
+   (version "2.2.1")
    (source (origin
             (method url-fetch)
             (uri (string-append "mirror://kernel.org/software/scm/git/git-"
                                 version ".tar.xz"))
             (sha256
              (base32
-              "12x1qycc0rii6fqpiizp9v9ysdmj6lpi9imqqbrkdx6cifbwh9vv"))))
+              "0l7l9rv1ww474rm4whj7dhjjacgdw5qlqqxqsnyzdpdxl34jshh9"))))
    (build-system gnu-build-system)
    (native-inputs
     `(("native-perl" ,perl)
@@ -210,6 +211,52 @@ everything from small to very large projects with speed and efficiency.")
    (license gpl2)
    (home-page "http://git-scm.com/")))
 
+(define-public git-manpages
+  ;; Keep in sync with 'git'!
+
+  ;; Granted, we could build the man pages from the 'git' package itself,
+  ;; which contains the real source.  However, it would add a dependency on a
+  ;; full XML tool chain, and building it actually takes ages.  So we use this
+  ;; lazy approach.
+  (package
+    (name "git-manpages")
+    (version (package-version git))
+    (source (origin
+              (method url-fetch)
+              (uri (string-append
+                    "mirror://kernel.org/software/scm/git/git-manpages-"
+                    version ".tar.xz"))
+              (sha256
+               (base32
+                "0f75n5yfrzb55qbg5wq4bmv43lay806v51yhglwkp7mbv1zkby00"))))
+    (build-system trivial-build-system)
+    (arguments
+     '(#:modules ((guix build utils))
+       #:builder
+       (begin
+         (use-modules (guix build utils))
+
+         (let* ((xz  (assoc-ref %build-inputs "xz"))
+                (tar (assoc-ref %build-inputs "tar"))
+                (out (assoc-ref %outputs "out"))
+                (man (string-append out "/share/man")))
+           (setenv "PATH" (string-append tar "/bin:" xz "/bin"))
+
+           (mkdir-p man)
+           (with-directory-excursion man
+             (zero? (system* "tar" "xvf"
+                             (assoc-ref %build-inputs "source"))))))))
+
+    (native-inputs `(("tar" ,tar)
+                     ("xz" ,xz)))
+    (home-page (package-home-page git))
+    (license (package-license git))
+    (synopsis "Man pages of the Git version control system")
+    (description
+     "This package provides the man pages of the Git version control system.
+This is the documentation displayed when using the '--help' option of a 'git'
+command.")))
+
 (define-public shflags
   (package
     (name "shflags")
diff --git a/gnu/packages/xdisorg.scm b/gnu/packages/xdisorg.scm
index d44b6a6246..2052f7b9be 100644
--- a/gnu/packages/xdisorg.scm
+++ b/gnu/packages/xdisorg.scm
@@ -189,28 +189,6 @@ and Matrox.")
     (license license:x11)))
 
 
-;; old version, required by old mesa, see
-;; http://www.mail-archive.com/nouveau@lists.freedesktop.org/msg10098.html
-(define-public libdrm-2.4.33
-  (package (inherit libdrm)
-    (version "2.4.33")
-    (source
-      (origin
-        (method url-fetch)
-        (uri (string-append
-               "http://dri.freedesktop.org/libdrm/libdrm-"
-               version
-               ".tar.bz2"))
-        (sha256
-          (base32
-            "1slgi61n4dlsfli47ql354fd1ppj7n40jd94wvnsdqx0mna9syrd"))))
-    (arguments
-      `(#:configure-flags
-         ;; create libdrm_nouveau.so, needed by mesa, see
-         ;; http://comments.gmane.org/gmane.linux.lfs.beyond.support/43261
-         `("--enable-nouveau-experimental-api")))))
-
-
 (define-public mtdev
   (package
     (name "mtdev")
diff --git a/gnu/packages/xml.scm b/gnu/packages/xml.scm
index b4b91408af..f2b3baa418 100644
--- a/gnu/packages/xml.scm
+++ b/gnu/packages/xml.scm
@@ -191,7 +191,7 @@ module.")
               (base32
                "0jj3jiray1l4pi9wkjcpxjc3v431whdwx5aqnhgdm4i7h3817zsw"))))
     (build-system perl-build-system)
-    (inputs
+    (propagated-inputs
      `(("perl-xml-parser" ,perl-xml-parser)))
     (license (package-license perl))
     (synopsis "Perl module for easy reading/writing of XML files")
diff --git a/gnu/packages/zip.scm b/gnu/packages/zip.scm
index 29ab555ae4..f9eeb5c32c 100644
--- a/gnu/packages/zip.scm
+++ b/gnu/packages/zip.scm
@@ -22,6 +22,7 @@
   #:use-module (guix packages)
   #:use-module (guix download)
   #:use-module (guix build-system gnu)
+  #:use-module (gnu packages)
   #:use-module (gnu packages compression)
   #:use-module (gnu packages perl)
   #:use-module (guix build-system perl)
@@ -79,7 +80,10 @@ Compression ratios of 2:1 to 3:1 are common for text files.")
       (uri (string-append "mirror://sourceforge/infozip/UnZip%206.x%20%28latest%29/UnZip%206.0/unzip60.tar.gz"))
       (sha256
        (base32
-        "0dxx11knh3nk95p2gg2ak777dd11pr7jx5das2g49l262scrcv83"))))
+        "0dxx11knh3nk95p2gg2ak777dd11pr7jx5das2g49l262scrcv83"))
+      (patches (list (search-patch "unzip-CVE-2014-8139.patch")
+                     (search-patch "unzip-CVE-2014-8140.patch")
+                     (search-patch "unzip-CVE-2014-8141.patch")))))
     (build-system gnu-build-system)
     ;; no inputs; bzip2 is not supported, since not compiled with BZ_NO_STDIO
     (arguments
diff --git a/guix/build/syscalls.scm b/guix/build/syscalls.scm
index b210f8faa8..b62a8cce64 100644
--- a/guix/build/syscalls.scm
+++ b/guix/build/syscalls.scm
@@ -130,7 +130,7 @@
   (let* ((ptr  (dynamic-func "mount" (dynamic-link)))
          (proc (pointer->procedure int ptr `(* * * ,unsigned-long *))))
     (lambda* (source target type #:optional (flags 0) options
-                     #:key (update-mtab? #t))
+                     #:key (update-mtab? #f))
       "Mount device SOURCE on TARGET as a file system TYPE.  Optionally, FLAGS
 may be a bitwise-or of the MS_* <sys/mount.h> constants, and OPTIONS may be a
 string.  When FLAGS contains MS_REMOUNT, SOURCE and TYPE are ignored.  When
@@ -159,7 +159,7 @@ error."
   (let* ((ptr  (dynamic-func "umount2" (dynamic-link)))
          (proc (pointer->procedure int ptr `(* ,int))))
     (lambda* (target #:optional (flags 0)
-                     #:key (update-mtab? #t))
+                     #:key (update-mtab? #f))
       "Unmount TARGET.  Optionally FLAGS may be one of the MNT_* or UMOUNT_*
 constants from <sys/mount.h>."
       (let ((ret (proc (string->pointer target) flags))
diff --git a/guix/pk-crypto.scm b/guix/pk-crypto.scm
index 71104128c1..e5d4dc9ecc 100644
--- a/guix/pk-crypto.scm
+++ b/guix/pk-crypto.scm
@@ -1,5 +1,5 @@
 ;;; GNU Guix --- Functional package management for GNU
-;;; Copyright © 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -254,9 +254,9 @@ Return #f if that element does not exist, or if it's a list."
                                 #:optional
                                 (hash-algo "sha256")
                                 #:key (key-type 'ecc))
-  "Given BV, a bytevector containing a hash, return an s-expression suitable
-for use as the data for 'sign'.  KEY-TYPE must be a symbol: 'dsa, 'ecc, or
-'rsa."
+  "Given BV, a bytevector containing a hash of type HASH-ALGO, return an
+s-expression suitable for use as the 'data' argument for 'sign'.  KEY-TYPE
+must be a symbol: 'dsa, 'ecc, or 'rsa."
   (string->canonical-sexp
    (format #f "(data (flags ~a) (hash \"~a\" #~a#))"
            (case key-type
@@ -289,8 +289,10 @@ Return #f if DATA does not conform."
   (let* ((ptr  (libgcrypt-func "gcry_pk_sign"))
          (proc (pointer->procedure int ptr '(* * *))))
     (lambda (data secret-key)
-      "Sign DATA (an s-expression) with SECRET-KEY (an s-expression whose car
-is 'private-key'.)"
+      "Sign DATA, a canonical s-expression representing a suitable hash, with
+SECRET-KEY (a canonical s-expression whose car is 'private-key'.)  Note that
+DATA must be a 'data' s-expression, as returned by
+'bytevector->hash-data' (info \"(gcrypt) Cryptographic Functions\")."
       (let* ((sig (bytevector->pointer (make-bytevector (sizeof '*))))
              (err (proc sig (canonical-sexp->pointer data)
                         (canonical-sexp->pointer secret-key))))
diff --git a/nix/libstore/build.cc b/nix/libstore/build.cc
index 2e2f92fadf..f38cd29940 100644
--- a/nix/libstore/build.cc
+++ b/nix/libstore/build.cc
@@ -13,6 +13,7 @@
 #include <sstream>
 #include <algorithm>
 
+#include <limits.h>
 #include <time.h>
 #include <sys/time.h>
 #include <sys/wait.h>
diff --git a/nix/libstore/derivations.cc b/nix/libstore/derivations.cc
index d91e42784c..b452aa2caf 100644
--- a/nix/libstore/derivations.cc
+++ b/nix/libstore/derivations.cc
@@ -48,7 +48,7 @@ static Path parsePath(std::istream & str)
 {
     string s = parseString(str);
     if (s.size() == 0 || s[0] != '/')
-        throw Error(format("bad path `%1%' in derivation") % s);
+        throw FormatError(format("bad path `%1%' in derivation") % s);
     return s;
 }
 
@@ -62,7 +62,7 @@ static StringSet parseStrings(std::istream & str, bool arePaths)
 }
 
 
-Derivation parseDerivation(const string & s)
+static Derivation parseDerivation(const string & s)
 {
     Derivation drv;
     std::istringstream str(s);
@@ -112,6 +112,16 @@ Derivation parseDerivation(const string & s)
 }
 
 
+Derivation readDerivation(const Path & drvPath)
+{
+    try {
+        return parseDerivation(readFile(drvPath));
+    } catch (FormatError & e) {
+        throw Error(format("error parsing derivation `%1%': %2%") % drvPath % e.msg());
+    }
+}
+
+
 static void printString(string & res, const string & s)
 {
     res += '"';
@@ -240,7 +250,7 @@ Hash hashDerivationModulo(StoreAPI & store, Derivation drv)
         Hash h = drvHashes[i->first];
         if (h.type == htUnknown) {
             assert(store.isValidPath(i->first));
-            Derivation drv2 = parseDerivation(readFile(i->first));
+            Derivation drv2 = readDerivation(i->first);
             h = hashDerivationModulo(store, drv2);
             drvHashes[i->first] = h;
         }
diff --git a/nix/libstore/derivations.hh b/nix/libstore/derivations.hh
index 703410b925..04b64dfc88 100644
--- a/nix/libstore/derivations.hh
+++ b/nix/libstore/derivations.hh
@@ -59,8 +59,8 @@ class StoreAPI;
 Path writeDerivation(StoreAPI & store,
     const Derivation & drv, const string & name, bool repair = false);
 
-/* Parse a derivation. */
-Derivation parseDerivation(const string & s);
+/* Read a derivation from a file. */
+Derivation readDerivation(const Path & drvPath);
 
 /* Print a derivation. */
 string unparseDerivation(const Derivation & drv);
diff --git a/nix/libstore/local-store.cc b/nix/libstore/local-store.cc
index 1293a6e8f2..5d210ae017 100644
--- a/nix/libstore/local-store.cc
+++ b/nix/libstore/local-store.cc
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <stdio.h>
 #include <time.h>
+#include <grp.h>
 
 #if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H
 #include <sched.h>
@@ -237,7 +238,7 @@ LocalStore::LocalStore(bool reserveSpace)
     makeStoreWritable();
     createDirs(linksDir = settings.nixStore + "/.links");
     Path profilesDir = settings.nixStateDir + "/profiles";
-    createDirs(settings.nixStateDir + "/profiles");
+    createDirs(profilesDir);
     createDirs(settings.nixStateDir + "/temproots");
     createDirs(settings.nixDBPath);
     Path gcRootsDir = settings.nixStateDir + "/gcroots";
@@ -246,6 +247,32 @@ LocalStore::LocalStore(bool reserveSpace)
         createSymlink(profilesDir, gcRootsDir + "/profiles");
     }
 
+    /* Optionally, create directories and set permissions for a
+       multi-user install. */
+    if (getuid() == 0 && settings.buildUsersGroup != "") {
+
+        Path perUserDir = profilesDir + "/per-user";
+        createDirs(perUserDir);
+        if (chmod(perUserDir.c_str(), 01777) == -1)
+            throw SysError(format("could not set permissions on `%1%' to 1777") % perUserDir);
+
+        struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
+        if (!gr)
+            throw Error(format("the group `%1%' specified in `build-users-group' does not exist")
+                % settings.buildUsersGroup);
+
+        struct stat st;
+        if (stat(settings.nixStore.c_str(), &st))
+            throw SysError(format("getting attributes of path `%1%'") % settings.nixStore);
+
+        if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != 01775) {
+            if (chown(settings.nixStore.c_str(), 0, gr->gr_gid) == -1)
+                throw SysError(format("changing ownership of path `%1%'") % settings.nixStore);
+            if (chmod(settings.nixStore.c_str(), 01775) == -1)
+                throw SysError(format("changing permissions on path `%1%'") % settings.nixStore);
+        }
+    }
+
     checkStoreNotSymlink();
 
     /* We can't open a SQLite database if the disk is full.  Since
@@ -661,7 +688,7 @@ unsigned long long LocalStore::addValidPath(const ValidPathInfo & info, bool che
        efficiently query whether a path is an output of some
        derivation. */
     if (isDerivation(info.path)) {
-        Derivation drv = parseDerivation(readFile(info.path));
+        Derivation drv = readDerivation(info.path);
 
         /* Verify that the output paths in the derivation are correct
            (i.e., follow the scheme for computing output paths from
@@ -1290,7 +1317,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
             if (isDerivation(i->path)) {
                 // FIXME: inefficient; we already loaded the
                 // derivation in addValidPath().
-                Derivation drv = parseDerivation(readFile(i->path));
+                Derivation drv = readDerivation(i->path);
                 checkDerivationOutputs(i->path, drv);
             }
 
diff --git a/nix/libstore/local-store.hh b/nix/libstore/local-store.hh
index 09639e74cf..54331e448a 100644
--- a/nix/libstore/local-store.hh
+++ b/nix/libstore/local-store.hh
@@ -6,6 +6,11 @@
 #include "util.hh"
 #include "pathlocks.hh"
 
+#if HAVE_TR1_UNORDERED_SET
+#include <tr1/unordered_set>
+#endif
+
+
 
 class sqlite3;
 class sqlite3_stmt;
@@ -29,14 +34,12 @@ struct Derivation;
 
 struct OptimiseStats
 {
-    unsigned long totalFiles;
-    unsigned long sameContents;
     unsigned long filesLinked;
     unsigned long long bytesFreed;
     unsigned long long blocksFreed;
     OptimiseStats()
     {
-        totalFiles = sameContents = filesLinked = 0;
+        filesLinked = 0;
         bytesFreed = blocksFreed = 0;
     }
 };
@@ -303,7 +306,15 @@ private:
 
     void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);
 
-    void optimisePath_(OptimiseStats & stats, const Path & path);
+#if HAVE_TR1_UNORDERED_SET
+    typedef std::tr1::unordered_set<ino_t> InodeHash;
+#else
+    typedef std::set<ino_t> InodeHash;
+#endif
+
+    InodeHash loadInodeHash();
+    Strings readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash);
+    void optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash);
 
     // Internal versions that are not wrapped in retry_sqlite.
     bool isValidPath_(const Path & path);
diff --git a/nix/libstore/misc.cc b/nix/libstore/misc.cc
index 1bf3f93782..6ecf8787cf 100644
--- a/nix/libstore/misc.cc
+++ b/nix/libstore/misc.cc
@@ -11,7 +11,7 @@ Derivation derivationFromPath(StoreAPI & store, const Path & drvPath)
 {
     assertStorePath(drvPath);
     store.ensurePath(drvPath);
-    return parseDerivation(readFile(drvPath));
+    return readDerivation(drvPath);
 }
 
 
diff --git a/nix/libstore/optimise-store.cc b/nix/libstore/optimise-store.cc
index d833f3aa05..67ee94a4bd 100644
--- a/nix/libstore/optimise-store.cc
+++ b/nix/libstore/optimise-store.cc
@@ -40,18 +40,66 @@ struct MakeReadOnly
 };
 
 
-void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
+LocalStore::InodeHash LocalStore::loadInodeHash()
+{
+    printMsg(lvlDebug, "loading hash inodes in memory");
+    InodeHash inodeHash;
+
+    AutoCloseDir dir = opendir(linksDir.c_str());
+    if (!dir) throw SysError(format("opening directory `%1%'") % linksDir);
+
+    struct dirent * dirent;
+    while (errno = 0, dirent = readdir(dir)) { /* sic */
+        checkInterrupt();
+        // We don't care if we hit non-hash files, anything goes
+        inodeHash.insert(dirent->d_ino);
+    }
+    if (errno) throw SysError(format("reading directory `%1%'") % linksDir);
+
+    printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size());
+
+    return inodeHash;
+}
+
+
+Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHash & inodeHash)
+{
+    Strings names;
+
+    AutoCloseDir dir = opendir(path.c_str());
+    if (!dir) throw SysError(format("opening directory `%1%'") % path);
+
+    struct dirent * dirent;
+    while (errno = 0, dirent = readdir(dir)) { /* sic */
+        checkInterrupt();
+
+        if (inodeHash.count(dirent->d_ino)) {
+            printMsg(lvlDebug, format("`%1%' is already linked") % dirent->d_name);
+            continue;
+        }
+
+        string name = dirent->d_name;
+        if (name == "." || name == "..") continue;
+        names.push_back(name);
+    }
+    if (errno) throw SysError(format("reading directory `%1%'") % path);
+
+    return names;
+}
+
+
+void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHash & inodeHash)
 {
     checkInterrupt();
-    
+
     struct stat st;
     if (lstat(path.c_str(), &st))
         throw SysError(format("getting attributes of path `%1%'") % path);
 
     if (S_ISDIR(st.st_mode)) {
-        Strings names = readDirectory(path);
+        Strings names = readDirectoryIgnoringInodes(path, inodeHash);
         foreach (Strings::iterator, i, names)
-            optimisePath_(stats, path + "/" + *i);
+            optimisePath_(stats, path + "/" + *i, inodeHash);
         return;
     }
 
@@ -71,6 +119,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
         return;
     }
 
+    /* This can still happen on top-level files */
+    if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
+        printMsg(lvlDebug, format("`%1%' is already linked, with %2% other file(s).") % path % (st.st_nlink - 2));
+        return;
+    }
+
     /* Hash the file.  Note that hashPath() returns the hash over the
        NAR serialisation, which includes the execute bit on the file.
        Thus, executable and non-executable files with the same
@@ -81,7 +135,6 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
        contents of the symlink (i.e. the result of readlink()), not
        the contents of the target (which may not even exist). */
     Hash hash = hashPath(htSHA256, path).first;
-    stats.totalFiles++;
     printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash));
 
     /* Check if this is a known hash. */
@@ -89,7 +142,10 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
 
     if (!pathExists(linkPath)) {
         /* Nope, create a hard link in the links directory. */
-        if (link(path.c_str(), linkPath.c_str()) == 0) return;
+        if (link(path.c_str(), linkPath.c_str()) == 0) {
+            inodeHash.insert(st.st_ino);
+            return;
+        }
         if (errno != EEXIST)
             throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path);
         /* Fall through if another process created ‘linkPath’ before
@@ -102,7 +158,6 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
     if (lstat(linkPath.c_str(), &stLink))
         throw SysError(format("getting attributes of path `%1%'") % linkPath);
 
-    stats.sameContents++;
     if (st.st_ino == stLink.st_ino) {
         printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath);
         return;
@@ -160,12 +215,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
 void LocalStore::optimiseStore(OptimiseStats & stats)
 {
     PathSet paths = queryAllValidPaths();
+    InodeHash inodeHash = loadInodeHash();
 
     foreach (PathSet::iterator, i, paths) {
         addTempRoot(*i);
         if (!isValidPath(*i)) continue; /* path was GC'ed, probably */
         startNest(nest, lvlChatty, format("hashing files in `%1%'") % *i);
-        optimisePath_(stats, *i);
+        optimisePath_(stats, *i, inodeHash);
     }
 }
 
@@ -173,7 +229,9 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
 void LocalStore::optimisePath(const Path & path)
 {
     OptimiseStats stats;
-    if (settings.autoOptimiseStore) optimisePath_(stats, path);
+    InodeHash inodeHash;
+
+    if (settings.autoOptimiseStore) optimisePath_(stats, path, inodeHash);
 }
 
 
diff --git a/nix/libutil/archive.cc b/nix/libutil/archive.cc
index ab4cd47351..70a1c580dd 100644
--- a/nix/libutil/archive.cc
+++ b/nix/libutil/archive.cc
@@ -104,7 +104,7 @@ static void dump(const Path & path, Sink & sink, PathFilter & filter)
         writeString(readLink(path), sink);
     }
 
-    else throw Error(format("file `%1%' has an unknown type") % path);
+    else throw Error(format("file `%1%' has an unsupported type") % path);
 
     writeString(")", sink);
 }
diff --git a/nix/libutil/util.cc b/nix/libutil/util.cc
index 15c462ce4e..846674a29d 100644
--- a/nix/libutil/util.cc
+++ b/nix/libutil/util.cc
@@ -1041,7 +1041,7 @@ void expect(std::istream & str, const string & s)
     char s2[s.size()];
     str.read(s2, s.size());
     if (string(s2, s.size()) != s)
-        throw Error(format("expected string `%1%'") % s);
+        throw FormatError(format("expected string `%1%'") % s);
 }
 
 
diff --git a/nix/libutil/util.hh b/nix/libutil/util.hh
index 8bedfea9a0..ce2d77c19a 100644
--- a/nix/libutil/util.hh
+++ b/nix/libutil/util.hh
@@ -326,6 +326,8 @@ bool hasSuffix(const string & s, const string & suffix);
 /* Read string `s' from stream `str'. */
 void expect(std::istream & str, const string & s);
 
+MakeError(FormatError, Error)
+
 
 /* Read a C-style string from stream `str'. */
 string parseString(std::istream & str);
diff --git a/tests/guix-package.sh b/tests/guix-package.sh
index f4e091a5a2..3959269d44 100644
--- a/tests/guix-package.sh
+++ b/tests/guix-package.sh
@@ -1,5 +1,5 @@
 # GNU Guix --- Functional package management for GNU
-# Copyright © 2012, 2013, 2014 Ludovic Courtès <ludo@gnu.org>
+# Copyright © 2012, 2013, 2014, 2015 Ludovic Courtès <ludo@gnu.org>
 # Copyright © 2013 Nikita Karetnikov <nikita@karetnikov.org>
 #
 # This file is part of GNU Guix.
@@ -289,10 +289,29 @@ GUIX_PACKAGE_PATH="$module_dir"
 export GUIX_PACKAGE_PATH
 guix package -A emacs-foo-bar | grep 42
 guix package -i emacs-foo-bar-42 -n
+
+# Make sure patches that live under $GUIX_PACKAGE_PATH are found.
+cat > "$module_dir/emacs.patch"<<EOF
+This is a fake patch.
+EOF
+cat > "$module_dir/foo.scm"<<EOF
+(define-module (foo)
+  #:use-module (guix packages)
+  #:use-module (gnu packages)
+  #:use-module (gnu packages emacs))
+
+(define-public x
+  (package (inherit emacs)
+    (source (origin (inherit (package-source emacs))
+              (patches (list (search-patch "emacs.patch")))))
+    (name "emacs-foo-bar-patched")
+    (version "42")))
+EOF
+guix package -i emacs-foo-bar-patched -n
+
 unset GUIX_PACKAGE_PATH
 
 # Using 'GUIX_BUILD_OPTIONS'.
-
 available="`guix package -A | sort`"
 GUIX_BUILD_OPTIONS="--dry-run"
 export GUIX_BUILD_OPTIONS