Skip to content
Snippets Groups Projects
  1. May 01, 2020
  2. Apr 30, 2020
  3. Apr 29, 2020
  4. Apr 28, 2020
  5. Apr 27, 2020
    • Alyssa Ross's avatar
      Fix long paths permanently breaking GC · c05e20da
      Alyssa Ross authored
      
      Suppose I have a path /nix/store/[hash]-[name]/a/a/a/a/a/[...]/a,
      long enough that everything after "/nix/store/" is longer than 4096
      (MAX_PATH) bytes.
      
      Nix will happily allow such a path to be inserted into the store,
      because it doesn't look at all the nested structure.  It just cares
      about the /nix/store/[hash]-[name] part.  But, when the path is deleted,
      we encounter a problem.  Nix will move the path to /nix/store/trash, but
      then when it's trying to recursively delete the trash directory, it will
      at some point try to unlink
      /nix/store/trash/[hash]-[name]/a/a/a/a/a/[...]/a.  This will fail,
      because the path is too long.  After this has failed, any store deletion
      operation will never work again, because Nix needs to delete the trash
      directory before recreating it to move new things to it.  (I assume this
      is because otherwise a path being deleted could already exist in the
      trash, and then moving it would fail.)
      
      This means that if I can trick somebody into just fetching a tarball
      containing a path of the right length, they won't be able to delete
      store paths or garbage collect ever again, until the offending path is
      manually removed from /nix/store/trash.  (And even fixing this manually
      is quite difficult if you don't understand the issue, because the
      absolute path that Nix says it failed to remove is also too long for
      rm(1).)
      
      This patch fixes the issue by making Nix's recursive delete operation
      use unlinkat(2).  This function takes a relative path and a directory
      file descriptor.  We ensure that the relative path is always just the
      name of the directory entry, and therefore its length will never exceed
      255 bytes.  This means that it will never even come close to AX_PATH,
      and Nix will therefore be able to handle removing arbitrarily deep
      directory hierachies.
      
      Since the directory file descriptor is used for recursion after being
      used in readDirectory, I made a variant of readDirectory that takes an
      already open directory stream, to avoid the directory being opened
      multiple times.  As we have seen from this issue, the less we have to
      interact with paths, the better, and so it's good to reuse file
      descriptors where possible.
      
      I left _deletePath as succeeding even if the parent directory doesn't
      exist, even though that feels wrong to me, because without that early
      return, the linux-sandbox test failed.
      
      Reported-by: default avatarAlyssa Ross <hi@alyssa.is>
      Thanks-to: Puck Meerburg <puck@puckipedia.com>
      Tested-by: default avatarPuck Meerburg <puck@puckipedia.com>
      Reviewed-by: default avatarPuck Meerburg <puck@puckipedia.com>
      c05e20da
    • Matthew Kenigsberg's avatar
      comment · 9e95b95a
      Matthew Kenigsberg authored
      9e95b95a
    • Matthew Kenigsberg's avatar
  6. Apr 25, 2020
    • Linus Heckemann's avatar
      nix-env: refactor uninstallDerivations · f59404e1
      Linus Heckemann authored
      Reduces the number of store queries it performs. Also prints a warning
      if any of the selectors did not match any installed derivations.
      
      UX Caveats:
      - Will print a warning that nothing matched if a previous selector
        already removed the path
      - Will not do anything if no selectors were provided (no change from
        before).
      
      Fixes #3531
      f59404e1
  7. Apr 22, 2020
  8. Apr 21, 2020
  9. Apr 18, 2020
  10. Apr 16, 2020
Loading