[Nix-dev] CVE-2015-7547 stdenv-changing fix merged on master and 15.09

roconnor at theorem.ca roconnor at theorem.ca
Tue Feb 16 23:08:47 CET 2016


On Tue, 16 Feb 2016, Kosyrev Serge wrote:

> roconnor at theorem.ca writes:
>> I am using the following expression which I believe will build a patched
>> version of glibc locally, and then build a patched NixOS derivation.
>>
>> system.replaceRuntimeDependencies = with pkgs.lib;
>>       [{original = pkgs.glibc; replacement = pkgs.stdenv.lib.overrideDerivation pkgs.glibc (oldAttr: { patches = oldAttr.patches ++
>>         [(pkgs.fetchurl { url = "https://raw.githubusercontent.com/NixOS/nixpkgs/master/pkgs/development/libraries/glibc/cve-2015-7547.patch";
>>                           sha256 = "0awpc4rp2x27rjpj83ps0rclmn73hsgfv2xxk18k82w4hdxqpp5r";})];
>>        });}
>>       ];
>>
>> I didin't time it, but I think it took around 25 minutes to update my
>> desktop machine this way.  Good luck everyone.
>
> For those of us who aren't that fluent in Nix idioms -- could you
> provide a quick summary of how you manage to achieve the seemingly
> impossible?
>
> Normally, one would expect that updating glibc would cause a full system
> rebuild, but in your case it's obviously not the case.

I'll try my best to explain.  If you are familiar with how you update a 
tree structure in functional programming, the techinque is similar to 
that.  To update a leaf in a tree you trace a path from the root of the 
tree to the leaf, call this path a spine.  You can build a new copy of the 
tree by updating all the nodes along this spine including replacing the 
leaf with your updated leaf. The result is a root of a new tree where 
unchanged branches are shared with the old tree.

In this case the root is what is built by nixos-rebuild and the tree is 
the tree of dependencies, and glibc is a leaf that needs to be replaced.

Step 1) is to build the orginial unpatch derivation for the system. 
Usually this is the currently running system, so no work needs to be done, 
but in principle if you are making other changes to your configuraiton.nix 
the unpatched system needs to be built.

Step 2) Build the patched glibc.  This is done the normal way.

Step 3) List all the packages that are run-time dependecies of the 
unpatched system and pick out all those packages that either depend, 
directly or indirectly on the unpatched glibc.

Step 4) for each of those packages make a new derivation whose source is 
the output of the deriviation, and which runs a command that finds all the 
hashes that are in that list generated by Step 3 and replaced them with 
new hashes that are being generated in by Step 4.  (Clearly this step is 
preformed recursively starting at those packaged who directly depend on 
glibc and then working up to those packages that depended on packages that 
depend on glibc, etc.)

Step 5) Return the new derivation that is has replaced the hashes in the 
unpatched root.

Things to note:

(1) There is nothing impure going on.  The existing store values are never 
mutated.

(2) This only updates packages that have a runtime depenency on glibc. 
Anything that statically links glibc (ie. only has a build-time depenency 
on glibc) are not updated.

> And lastly -- is this somehow related to the techniques proposed for
> providing NixOS with security updates?

I wasn't at the last Nix meeting, so I'm not sure if it is related or not. 
I hope it is.

-- 
Russell O'Connor                                      <http://r6.ca/>
``All talk about `theft,''' the general counsel of the American Graphophone
Company wrote, ``is the merest claptrap, for there exists no property in
ideas musical, literary or artistic, except as defined by statute.''


More information about the nix-dev mailing list