Occasionally, important security vulnerabilities are discovered in software
packages and must be patched. Guix developers try hard to keep track of
known vulnerabilities and to apply fixes as soon as possible in the
master branch of Guix (we do not yet provide a “stable” branch
containing only security updates). The
guix lint tool helps
developers find out about vulnerable versions of software packages in the
$ guix lint -c cve gnu/packages/base.scm:652:2: email@example.com: probably vulnerable to CVE-2015-1781, CVE-2015-7547 gnu/packages/gcc.scm:334:2: firstname.lastname@example.org: probably vulnerable to CVE-2015-5276 gnu/packages/image.scm:312:2: email@example.com: probably vulnerable to CVE-2016-1923, CVE-2016-1924 …
See 调用guix lint, for more information.
Guix follows a functional package management discipline (see 介绍), which implies that, when a package is changed, every package that depends on it must be rebuilt. This can significantly slow down the deployment of fixes in core packages such as libc or Bash, since basically the whole distribution would need to be rebuilt. Using pre-built binaries helps (see substitutes), but deployment may still take more time than desired.
To address this, Guix implements grafts, a mechanism that allows for fast deployment of critical updates without the costs associated with a whole-distribution rebuild. The idea is to rebuild only the package that needs to be patched, and then to “graft” it onto packages explicitly installed by the user and that were previously referring to the original package. The cost of grafting is typically very low, and order of magnitudes lower than a full rebuild of the dependency chain.
For instance, suppose a security update needs to be applied to Bash. Guix
developers will provide a package definition for the “fixed” Bash, say
bash-fixed, in the usual way (see 定义软件包). Then, the
original package definition is augmented with a
pointing to the package containing the bug fix:
(define bash (package (name "bash") ;; … (replacement bash-fixed)))
From there on, any package depending directly or indirectly on Bash—as
guix gc --requisites (see 调用guix gc)—that
is installed is automatically “rewritten” to refer to
bash. This grafting process takes time proportional to
the size of the package, usually less than a minute for an “average”
package on a recent machine. Grafting is recursive: when an indirect
dependency requires grafting, then grafting “propagates” up to the package
that the user is installing.
Currently, the length of the name and version of the graft and that of the
package it replaces (
bash in the example above)
must be equal. This restriction mostly comes from the fact that grafting
works by patching files, including binary files, directly. Other
restrictions may apply: for instance, when adding a graft to a package
providing a shared library, the original shared library and its replacement
must have the same
SONAME and be binary-compatible.
The --no-grafts command-line option allows you to forcefully avoid grafting (see --no-grafts). Thus, the command:
guix build bash --no-grafts
returns the store file name of the original Bash, whereas:
guix build bash
returns the store file name of the “fixed”, replacement Bash. This allows you to distinguish between the two variants of Bash.
To verify which Bash your whole profile refers to, you can run (see 调用guix gc):
guix gc -R $(readlink -f ~/.guix-profile) | grep bash
… and compare the store file names that you get with those above. Likewise for a complete Guix system generation:
guix gc -R $(guix system build my-config.scm) | grep bash
Lastly, to check which Bash running processes are using, you can use the
lsof | grep /gnu/store/.*bash