Skip to content

Symbol relocation errors when used with more than 1 layer on squashfs or dwarfs filesystems #432

Description

@ruanformigoni

Greetings,

I've found an issue where if overlayfs is used with more than one layer it breaks system libraries when used with squashfs or dwarfs. This is shown by symbol not found errors:

Error relocating /usr/lib/libQt5Gui.so.5: glLoadIdentity: symbol not found
Error relocating /usr/lib/libQt5Gui.so.5: glMatrixMode: symbol not found
Error relocating /usr/lib/libQt5Gui.so.5: glLoadMatrixf: symbol not found
Error relocating /usr/lib/libQt5Gui.so.5: glOrtho: symbol not found
Error relocating /usr/lib/libxcb.so.1: XauGetBestAuthByAddr: symbol not found
Error relocating /usr/lib/libxcb.so.1: XauDisposeAuth: symbol not found

If I copy the libraries to the upper directory, it works again. Here is a script to replicate the issue, it quickly sets up two layers, one with an xorg base and another with krita and its dependencies, the issue arises when krita (layer-1) requires libraries from layer-0. If everything is on the same layer this issue does not happen.

#!/usr/bin/env bash

# Script to setup alpine base
# First layer contains an xorg setup
# Second layer contains krita and its dependencies

set -x

DIR_SCRIPT="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

DIR_BUILD="$DIR_SCRIPT"/build

# Cleanup previous execution
fusermount -u "$DIR_BUILD/mount"
rm -rf "$DIR_BUILD/mount"
fusermount -u "$DIR_BUILD/root-0"
rm -rf "$DIR_BUILD/root-0"
fusermount -u "$DIR_BUILD/root-1"
rm -rf "$DIR_BUILD/root-1"

rm -rf "$DIR_BUILD"
mkdir -p "$DIR_BUILD"
cd "$DIR_BUILD"

# Bootstrap alpine
wget -O apk-tools.apk http://dl-cdn.alpinelinux.org/alpine/v3.12/main/x86_64/apk-tools-static-2.10.8-r1.apk
tar zxf apk-tools.apk
./sbin/apk.static --arch x86_64 -X http://dl-cdn.alpinelinux.org/alpine/latest-stable/main/ -U --allow-untrusted --root ./root-0 --initdb add alpine-base
{ sed -E 's/^\s+://' | tee ./root-0/etc/apk/repositories; } <<-END
  :http://dl-cdn.alpinelinux.org/alpine/v3.16/main
  :http://dl-cdn.alpinelinux.org/alpine/v3.16/community
  :#http://dl-cdn.alpinelinux.org/alpine/edge/main
  :#http://dl-cdn.alpinelinux.org/alpine/edge/community
  :#http://dl-cdn.alpinelinux.org/alpine/edge/testing
END

# Configure base
proot -R ./root-0 /bin/sh -c 'apk update'
proot -R ./root-0 /bin/sh -c 'apk upgrade'
proot -R ./root-0 /bin/sh -c 'setup-xorg-base'

# Compress first layer
mksquashfs root-0 root-0.layer
# Remove original root & replace with mounted squashfs
rm -rf root-0 && mkdir root-0
# Mount root
squashfuse root-0.layer root-0
# Mount overlayfs and install krita
mkdir -p upper work mount
overlayfs \
  -o lowerdir="$DIR_BUILD"/root-0 \
  -o upperdir="$DIR_BUILD"/upper \
  -o workdir="$DIR_BUILD"/work \
  mount
proot -R ./mount /bin/sh -c 'apk add krita'
fusermount -u mount
# Compress second layer
mksquashfs upper root-1.layer
# Remove original root & replace with mounted squashfs
rm -rf upper && mkdir -p upper root-1
# Mount root
squashfuse root-1.layer root-1
overlayfs \
  -o lowerdir="$DIR_BUILD"/root-1:"$DIR_BUILD"/root-0 \
  -o upperdir="$DIR_BUILD"/upper \
  -o workdir="$DIR_BUILD"/work \
  mount
proot -R ./mount /bin/sh -c 'krita'

Note that this is not a proot issue, since this also breaks in bwrap. I tested with bwrap new --overlay options, and they do not present the issue found here.

Activity

  1. ruanformigoni commented on Nov 13, 2024

    @ruanformigoni
    Author

    The commit 6a0de4a is the culprit behind this issue, reverting to the one previous to it with git reset --hard 918e19c fixes the symbol issues and krita opens.

  2. tjwoodall commented on Dec 21, 2025

    @tjwoodall

    I'm seeing something very similar. However, reverting the commit suggested above didn't help. I haven't tried going back to the commit suggested.

    $ cat test-chroot.sh 
    #!/bin/bash
    
    unshare --mount -r /bin/bash <<LXEOF
      ./test.sh
    LXEOF
    
    exit 0
    
    $ cat test.sh
    #!/bin/bash
    
    set -Eeuo pipefail
    
    TRACEX="set -x"
    #TRACEX=
    export PS4='+${BASH_SOURCE:-}:${LINENO:-}:${FUNCNAME:-} $ '
    ${TRACEX}
    
    HOMEDIR=$( readlink -f "$( dirname "${BASH_SOURCE[0]}" )" )
    
    # shellcheck disable=SC2317  # called from a trap
    cleanup()
    {
      set +x
      cd "${HOMEDIR}/"
      umount "${BUILDCHROOT}"
      umount "${SCRATCHDIR}/lower0"
      umount "${SCRATCHDIR}/lower1"
    
      [[ -z ${SCRATCHDIR:-} ]] || rm -fr --one-file-system "${SCRATCHDIR}"
    }
    
    trap cleanup EXIT
    
    build_deb()
    {
      local dist=${1}
      local arch=${2}
    
      SCRATCHDIR=$( mktemp -d -p "/tmp" scratch.XXXXXXXXXX )
      BUILDCHROOT=${SCRATCHDIR}/build.chroot
      mkdir -p "${BUILDCHROOT}"
      mkdir "${SCRATCHDIR}/overlay"
      mkdir "${SCRATCHDIR}/work"
      mkdir "${SCRATCHDIR}/lower0"
      mkdir "${SCRATCHDIR}/lower1"
      squashfuse "/mnt/mirror/ftp/mirror/bootstrap/tarfiles/${dist}.${arch}.minimal.sqfs" "${SCRATCHDIR}/lower0"
      squashfuse "/mnt/mirror/ftp/mirror/bootstrap/tarfiles/${dist}.${arch}.build-deb.sqfs" "${SCRATCHDIR}/lower1"
      fuse-overlayfs -o lowerdir="${SCRATCHDIR}/lower1:${SCRATCHDIR}/lower0,upperdir=${SCRATCHDIR}/overlay,workdir=${SCRATCHDIR}/work" "${BUILDCHROOT}"
    
    #  find ${BUILDCHROOT}/etc/apt -xdev -type d >& /dev/null
    
      touch "${BUILDCHROOT}/etc/apt/x"
    
      /sbin/chroot "${BUILDCHROOT}" /bin/bash <<CHEOF
        if [[ ${arch} = arm64 ]]; then
          export QEMU_CPU=max,pauth=off
        fi
        set -Eeuo pipefail
        ${TRACEX}
        export PS4='+chroot:${BASH_SOURCE:-}:${LINENO:-}:${FUNCNAME:-}:\${BASH_SOURCE:-}:\$(( ${LINENO} + \${LINENO:-} )):\${FUNCHAME:-} $ '
        cd /build
    
        cat >x.c <<EOF
    int main (void)
    {
      return 0;
    }
    EOF
        cc -o x x.c
    CHEOF
    }
    
    build_deb "bookworm" "amd64" # fails
    #build_deb "bookworm" "arm64" # fails
    #build_deb "trixie" "amd64" # fails
    #build_deb "trixie" "arm64" # works
    echo finished at "$( date )"
    
    exit 0
    
    $ ./test-chroot.sh
    ...
    +chroot:./test.sh:46:build_deb::61: $ cc -o x x.c
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_audit_symbind_alt@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__nptl_change_stack_perm@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_deallocate_tls@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__rseq_size@GLIBC_2.35'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_argv@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_allocate_tls@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_find_dso_for_object@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__libc_enable_secure@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_fatal_printf@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_exception_create@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__tunable_get_val@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_allocate_tls_init@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_rtld_di_serinfo@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_rtld_global@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__tls_get_addr@GLIBC_2.3'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `__libc_stack_end@GLIBC_2.2.5'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_dl_audit_preinit@GLIBC_PRIVATE'
    /usr/bin/ld: /lib/x86_64-linux-gnu/libc.so.6: undefined reference to `_rtld_global_ro@GLIBC_PRIVATE'
    collect2: error: ld returned 1 exit status
    

    If I comment out the touch or I uncomment the find then it compiles successfully.

    $ fuse-overlayfs -V
    fuse-overlayfs: version 1.16
    FUSE library version 3.14.0
    using FUSE kernel interface version 7.31
    fusermount3 version: 3.14.0
    
    
  3. tjwoodall commented on Jan 4, 2026

    @tjwoodall

    Found it!

    e.attr.st_ino and e.ino are not consistent. st_ino typically gets set from tmp_ino which comes from the lower level while e.ino is set via node_to_inode;

    The primary problem then occurs when the file is mmapped because this violates the VFS invariant and pages can be returned from the wrong file because it has two identities.

    diff --git a/main.c b/main.c
    index 4df64ec..0175349 100644
    --- a/main.c
    +++ b/main.c
    @@ -957,8 +957,7 @@ rpl_stat (fuse_req_t req, struct ovl_node *node, int fd, const char *path, struc
       st->st_uid = find_mapping (st->st_uid, data, true, true);
       st->st_gid = find_mapping (st->st_gid, data, true, false);
     
    -  st->st_ino = node->tmp_ino;
    -  st->st_dev = node->tmp_dev;
    +  st->st_ino = node_to_inode(node);
     
       if (node->loaded && node->n_links > 0)
         st->st_nlink = node->n_links;
    @@ -2554,8 +2553,7 @@ ovl_do_readdir (fuse_req_t req, fuse_ino_t ino, size_t size,
               /* From the 'stbuf' argument the st_ino field and bits 12-15 of the
                * st_mode field are used.  The other fields are ignored.
                */
    -          st->st_ino = node->tmp_ino;
    -          st->st_dev = node->tmp_dev;
    +          st->st_ino = node_to_inode(node);
               st->st_mode = node->ino->mode;
     
               entsize = fuse_add_direntry (req, p, remaining, name, st, offset + 1);
    

    There is no need to set st_dev - it gets replaced by the kernel with the correct st_dev for the fuse filesystem.

    I've only done some very basic checks using this patch so far but all seems good.

  4. tjwoodall commented on Jan 4, 2026

    @tjwoodall

    In particular, the problem goes like this:
    We have two files on the two different layers that have the same st_ino but different st_dev.
    fuse-overlayfs returns st_dev and st_ino, which is unique, but the kernel overwrites st_dev with the st_dev for the mount point.
    So now we have two completely unrelated files that have the same st_dev/st_ino identity which breaks mmap.

  5. tjwoodall commented on Jan 6, 2026

    @tjwoodall

    Still needs work but much improved from the quick hack above here:
    https://github.com/tjwoodall/fuse-overlayfs/tree/unique-inodes

    I've tried to roughly follow what the kernel overlayfs does.

    #!/bin/bash
    
    #set -x
    
    mkdir -p lower
    mkdir -p upper
    mkdir -p mnt
    
    touch lower/lower
    touch upper/upper
    
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o lowerdir=lower:upper mnt
    
    echo
    echo "All on same fs - ino passthrough - stable ino"
    echo -n "lower/lower "
    stat -c %i lower/lower
    echo -n "upper/upper "
    stat -c %i upper/upper
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    
    umount mnt
    
    rm -f img
    truncate -s 10M img
    /sbin/mke2fs -t ext2 img >& /dev/null
    
    mkdir -p ext2
    
    fuse2fs -o fakeroot,uid=$(id -u),gid=$(id -u) img ext2
    mkdir -p ext2/work
    mkdir -p ext2/upper
    mkdir -p ext2/mnt
    
    # mount -t overlay overlay -o lowerdir=fuseoverlayfs-lower,upperdir=fuseoverlayfs-upper,workdir=fuseoverlayfs-work fuseoverlayfs-mount
    echo
    echo "Upper on different fs - non-stable ino across mounts"
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o lowerdir=lower:upper,upperdir=ext2/upper,workdir=ext2/work mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    umount mnt
    echo "=="
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o lowerdir=lower:upper,upperdir=ext2/upper,workdir=ext2/work mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    umount mnt
    
    echo
    echo "Upper on different fs xino - stable ino across mounts"
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o xino,lowerdir=lower:upper,upperdir=ext2/upper,workdir=ext2/work mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    umount mnt
    echo "=="
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o xino,lowerdir=lower:upper,upperdir=ext2/upper,workdir=ext2/work mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    umount mnt
    
    echo
    echo "kernel fuse - disables xino - non-stable ino across mounts"
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o xino,lowerdir=lower:upper:fuseoverlayfs-mount mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    umount mnt
    echo "=="
    /mnt/nobackup/build/fuse-overlayfs/overlay/build/fuse-overlayfs/fuse-overlayfs -o xino,lowerdir=lower:upper:fuseoverlayfs-mount mnt
    echo -n "  mnt/lower "
    stat -c %i mnt/lower
    echo -n "  mnt/upper "
    stat -c %i mnt/upper
    
    umount mnt
    
    umount ext2
    
    rm -fr lower upper mnt img ext2
    
    $ ./test-passthrough.sh 
    
    All on same fs - ino passthrough - stable ino
    lower/lower 3416920
    upper/upper 3416921
      mnt/lower 3416920
      mnt/upper 3416921
    
    Upper on different fs - non-stable ino across mounts
      mnt/lower 94353636742544
      mnt/upper 94353636742800
    ==
      mnt/lower 94220651775376
      mnt/upper 94220651775632
    
    Upper on different fs xino - stable ino across mounts
      mnt/lower 1428392772843533875
      mnt/upper 742672234944029848
    ==
      mnt/lower 1428392772843533875
      mnt/upper 742672234944029848
    
    kernel fuse - disables xino - non-stable ino across mounts
      mnt/lower 93855548077344
      mnt/upper 93855548077600
    ==
      mnt/lower 94202806027552
      mnt/upper 94202806027808
    
  6. tjwoodall commented on Jan 8, 2026

    @tjwoodall

    I've now got a small testcase that I'll add to that branch:

    cat test-mmap.sh 
    #!/bin/bash
    
    set -e
    
    BIN=../fuse-overlayfs
    BIN=fuse-overlayfs
    
    cleanup()
    {
      umount mnt || true
      umount ext1 ext2 || true
      rm -fr mnt img1 img2 ext1 ext2 mupper mlower
    
      echo
      echo "FAILED"
      echo
    }
    
    trap cleanup EXIT
    
    rm -fr mnt img1 img2 ext1 ext2
    
    # override any other settings.
    export LC_ALL=C
    
    echo
    echo "Testing mmap where files have the same inodes across layers."
    
    rm -f img1
    truncate -s 10M img1
    /sbin/mke2fs -t ext2 img1 >& /dev/null
    rm -f img2
    truncate -s 10M img2
    /sbin/mke2fs -t ext2 img2 >& /dev/null
    mkdir -p ext1
    mkdir -p ext2
    fuse2fs -o fakeroot,uid=0,gid=0 img1 ext1
    fuse2fs -o fakeroot,uid=0,gid=0 img2 ext2
    
    # We assume that the files will get the same inode number on both layers, this is checked in test-passthrough.sh for a single file.
    dst=ext1
    for i in $( ldd $( gcc -print-prog-name=cc1 ) | awk '{print $3}' ); do
      cp $i $dst
      if [[ $dst == ext1 ]]; then
        dst=ext2
      else
        dst=ext1
      fi
    done
    
    mkdir mnt
    $BIN -o lowerdir=ext2:ext1 mnt
    
    echo "int main(void) { return 0; }" >test.c
    
    LD_LIBRARY_PATH=mnt/ gcc test.c
    
    echo "PASSED"
    
    umount mnt
    
    umount ext1
    umount ext2
    
    rm -fr mnt img1 img2 ext1 ext2
    
    trap - EXIT
    echo
    echo "FINISHED"
    echo
    

    Which fails like this:

    ./test-mmap.sh 
    
    Testing mmap where files have the same inodes across layers.
    unknown argument ignored: lazytime
    gcc: mnt/libm.so.6: version `GLIBC_2.33' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.11' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.4' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.6' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.34' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.3' not found (required by gcc)
    gcc: mnt/libm.so.6: version `GLIBC_2.33' not found (required by /lib/x86_64-linux-gnu/libfmt.so.10)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.4' not found (required by /lib/x86_64-linux-gnu/libfmt.so.10)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by /lib/x86_64-linux-gnu/libfmt.so.10)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by /lib/x86_64-linux-gnu/libxxhash.so.0)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.4' not found (required by mnt/libzstd.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.34' not found (required by mnt/libzstd.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.8' not found (required by mnt/libzstd.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by mnt/libzstd.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.2' not found (required by mnt/libzstd.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by /lib/x86_64-linux-gnu/libhiredis.so.1.1.0)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.4' not found (required by /lib/x86_64-linux-gnu/libhiredis.so.1.1.0)
    gcc: mnt/libm.so.6: version `GLIBC_2.3' not found (required by /lib/x86_64-linux-gnu/libhiredis.so.1.1.0)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.6' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.33' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.17' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.3' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.36' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.2' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.34' not found (required by /lib/x86_64-linux-gnu/libstdc++.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.36' not found (required by mnt/libm.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_ABI_DT_RELR' not found (required by mnt/libm.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_PRIVATE' not found (required by mnt/libm.so.6)
    gcc: mnt/libm.so.6: version `GLIBC_2.14' not found (required by /lib/x86_64-linux-gnu/libgcc_s.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.34' not found (required by /lib/x86_64-linux-gnu/libgcc_s.so.1)
    gcc: mnt/libm.so.6: version `GLIBC_2.3.2' not found (required by /lib/x86_64-linux-gnu/libgcc_s.so.1)
    
    FAILED
    
    

    and with the changes in that branch:

    ./test-mmap.sh 
    
    Testing mmap where files have the same inodes across layers.
    PASSED
    
    FINISHED
    
    
  7. tjwoodall commented on Jan 8, 2026

    @tjwoodall

    Created a merge request: #452

  8. tjwoodall commented on Jan 11, 2026

    @tjwoodall

    The issues I was seeing with the above MR appear to be a consequence of older userspace that did not always correctly handle 64 bit inodes. The branch now includes an option -o ino32_t which masks out the high order bits and my basic tests suggest that all is ok.

    I have a variety of setups I can test this on all the way back to debian jessie on amd64, i386, arm64 and armel, once all my tests are completed I'll reopen the MR.

    I didn't investigate the issue in detail but when running gcc as /usr/lib/ccache/gcc on an i386 buster system, it appears to get into what is most likely an infinite recursion doing stat on / eventually leading to SIGSEGV.

    /sbin/chroot mount /bin/bash
    
    root@dirac:/# dpkg --print-architecture
    i386
    root@dirac:/# cat /etc/debian_version 
    10.13
    root@dirac:/# gcc
    Segmentation fault
    root@dirac:/# which gcc
    /usr/lib/ccache/gcc
    root@dirac:/# strace -f gcc |& cat -n
        53  openat(AT_FDCWD, "/etc/ccache.conf", O_RDONLY) = 3
        54  fstat64(3, {st_mode=S_IFREG|0664, st_size=20, ...}) = 0
        55  read(3, "cache_dir = /ccache\n", 8192)  = 20
        56  read(3, "", 8192)                       = 0
        57  close(3)                                = 0
        58  openat(AT_FDCWD, "/ccache/ccache.conf", O_RDONLY) = -1 ENOENT (No such file or directory)
        59  stat64("/ccache", {st_mode=S_IFDIR|0775, st_size=0, ...}) = 0
        60  stat64("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
    ...
     65502  stat64("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
     65503  stat64("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
     65504  stat64("/", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
     65505  --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0xff0fefa0} ---
     65506  +++ killed by SIGSEGV +++
    

    using -o ino32_t fixes.

  9. tjwoodall commented on Jan 13, 2026

    @tjwoodall

    #455

    Won't let me reopen the previous branch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions