NixOS / NixOS/nixpkgs

nixos/image/repart: btrfs filesystems have wrong file permissions

Open
#455,331 0 comments 2 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

0.kind: bug 2.status: stale 6.topic: nixos
Dominant language
Nix
Stars
26.2k
Forks
20.1k
PR merge metrics
PR metrics pending

Description

Nixpkgs version
  • Unstable (25.11)
Describe the bug

This is #361903 again: images with btrfs filesystems have wrong file permissions. The previous fix (#378579) was incomplete/didn't really work.

Steps to reproduce
  1. Build image through image.repart with btrfs as filesystem
nix build --expr '((builtins.getFlake "github:nixos/nixpkgs?rev=01f116e4df6a15f4ccdffb1bcd41096869fb385c").lib.nixosSystem {
 system = "x86_64-linux";
 modules = [
   ({ pkgs
    , modulesPath
    , ...
    }:

     {
       imports = [ "${modulesPath}/image/repart.nix" ];

       image.repart = {
         name = "bug-repro";

         partitions."rootfs" = {
           storePaths = [ pkgs.hello ];
           repartConfig = {
             Format = "btrfs";
             Minimize = "guess";
             Type = "root";
           };
         };
       };
     })
 ];
}).config.system.build.image'
  1. Inspect image (e.g. with systemd-dissect or guestfish): files/directories in /nix/store are writable
Expected behaviour

Files should have correct permissions (e.g. non-writable in /nix/store)

Screenshots

No response

Relevant log output

Additional context

mkfs.btrfs uses nftw to traverse the rootdir and fakeroot doesn't fake the stats passed to nftw callbacks.

Two potential fixes:

  • Use pseudo (not packaged) instead of fakeroot, which has support for nftw
  • Use a patched mkfs.btrfs: call lstat in the nftw callback. fakeroot will intercept the lstat call:
    diff --git a/mkfs/rootdir.c b/mkfs/rootdir.c
    index 7bdd6245..e940ef73 100644
    --- a/mkfs/rootdir.c
    +++ b/mkfs/rootdir.c
    @@ -1631,7 +1631,7 @@ out:
     	return ret;
     }
     
    -static int ftw_add_inode(const char *full_path, const struct stat *st,
    +static int ftw_add_inode(const char *full_path, const struct stat *ftw_st,
     			 int typeflag, struct FTW *ftwbuf)
     {
     	struct btrfs_fs_info *fs_info = g_trans->fs_info;
    @@ -1639,9 +1639,16 @@ static int ftw_add_inode(const char *full_path, const struct stat *st,
     	struct btrfs_inode_item inode_item = { 0 };
     	struct inode_entry *parent;
     	struct rootdir_subvol *rds;
    -	const bool have_hard_links = (!S_ISDIR(st->st_mode) && st->st_nlink > 1);
    +	const bool have_hard_links = (!S_ISDIR(ftw_st->st_mode) && ftw_st->st_nlink > 1);
     	u64 ino;
     	int ret;
    +	struct stat statbuf;
    +	const struct stat *st = &statbuf;
    +
    +	if (lstat(full_path, &statbuf) < 0) {
    +		error("lstat() returned error for path %s", full_path);
    +		statbuf = *ftw_st;
    +	}
     
     	/* The rootdir itself. */
     	if (unlikely(ftwbuf->level == 0)) {
    
    
System metadata
$ nix-shell -p nix-info --run "nix-info -m"
 - system: `"x86_64-linux"`
 - host os: `Linux 6.16.9, NixOS, 25.11 (Xantusia), 25.11.20251002.7df7ff7`
 - multi-user?: `yes`
 - sandbox: `yes`
 - version: `nix-env (Nix) 2.28.5`
 - nixpkgs: `/nix/store/9v6qa656sq3xc58vkxslqy646p0ajj61-source`
Notify maintainers

@nikstur
@WilliButz


Note for maintainers: Please tag this issue in your pull request description. (i.e. Resolves #ISSUE.)

I assert that this issue is relevant for Nixpkgs
Is this issue important to you?

Add a 👍 reaction to issues you find important.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

The issue points to image/repart.nix, fakeroot, and the mkfs.btrfs source file mkfs/rootdir.c. Reproduce the supplied image build first, then inspect the resulting image with systemd-dissect or guestfish and trace how nftw statistics enter the filesystem creation step. Done means /nix/store files and directories have the expected non-writable permissions, with the chosen fix covered by a reproducible check.

Written by the indexing model from the issue text.

Assessment

Tech stack
c, linux, nixos
Domain
build-system, operating-systems
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.