破折号不扩展 chroot 中的 glob 通配符

Pur*_*ari 8 debian dash wildcards raspbian

我正在使用与pi-gen一起安装的 Raspbian 副本。Pi-gen 在一个 Docker 容器中运行,其中包含一个用于文件系统的卷,在该卷中运行debootstrap和自定义脚本chroot

我在 Raspbian 文件系统中使用chrootand运行 shell qemu-arm-static,但没有 Docker。

我注意到mkinitramfs脚本不起作用。我将问题追溯到dash脚本正在运行的 。

出于某种原因dash,没有在命令中扩展文件名通配符:

# echo /*
/*
# ls /
bin boot dev etc home lib media mnt opt proc root run sbin sys tmp usr var
Run Code Online (Sandbox Code Playgroud)

这发生在 chroot 内的所有文件夹以及脚本中。这打破了很多东西。

然而,通配符扩展通常工作在文件系统结合安装-内的chroot,如/proc/run。此外,使用相同dash二进制文件的路径扩展在不同的chroot.

我已经尝试过set +f,并set +o noglob没有运气。该noglob选项绝对不在:

# set -o
Current option settings
errexit         off
noglob          off
ignoreeof       off
interactive     on
monitor         on
noexec          off
stdin           on
xtrace          off
verbose         off
vi              off
emacs           off
noclobber       off
allexport       off
notify          off
nounset         off
nolog           off
debug           off
Run Code Online (Sandbox Code Playgroud)

我跑版0.5.8-2.4的的dash包从http://raspbian.raspberrypi.org/raspbian stretch/main armhf。主机正在运行带有内核的 Kali Linux 2019.1 4.19.0-kali4-amd64

有没有人见过类似的问题?我可以使用什么作为解决方法?

更新:以下是strace工作中转储的相关部分chroot

read(0, "echo /*\n", 8192)              = 8
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents(3, /* 11 entries */, 32768)    = 264
getdents(3, /* 0 entries */, 32768)     = 0
close(3)                                = 0
write(1, "/bin /dev /etc /lib /pls /proc /"..., 46) = 46
Run Code Online (Sandbox Code Playgroud)

在非工作中相同chroot

read(0, "echo /*\n", 8192)              = 8
openat(AT_FDCWD, "/", O_RDONLY|O_NONBLOCK|O_CLOEXEC|O_DIRECTORY) = 3
fstat(3, {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
getdents64(3, /* 20 entries */, 32768)  = 488
close(3)                                = 0
write(1, "/*\n", 3)                     = 3
Run Code Online (Sandbox Code Playgroud)

Pur*_*ari 3

原因

\n\n

正如\xc3\x89tienne 发现的那样(请为他们的研究工作投票),根本原因似乎是 glibc 2.28 中的更改。

\n\n
    \n
  • getdents64在 64 位 Linux 上可以返回d_off不适合 32 位int. 在 32 位系统上,它仅返回 32 位值。
  • \n
  • qemu-user在 64 位 Linux 上模拟 32 位系统只是传递系统调用,因此 32 位用户态进程可以获得溢出的值。
  • \n
  • glibc 2.28 有一个更改,使readdir始终使用并在不适合getdents64时出错。d_off在真正的 32 位系统上,这一定不会引起问题,因为 glibc 会处理它。(以前它叫getdents在 32 位系统上调用,这会返回 32 位值并且内核会进行任何截断。)
  • \n
\n\n

修复(或缺少修复)

\n\n

此 glibc 错误当前正在跟踪此问题的进展。修复并最终部署到您的发行版需要时间。

\n\n

解决方法

\n\n
    \n
  • 我能看到的最简单的解决方法是在具有 32 位 Linux 内核的系统上运行这些构建。
  • \n
  • 如果您可以将 glibc 版本(在 chroot 中!)降级到 2.27,这将解决该问题,但这可能会导致依赖性问题并会改变您正在构建的映像。
  • \n
  • 人们还可以在链接线程中应用众多补丁之一,但这需要编译(并且可能从包管理器中分离)您的内核、glibc 或(可能是最简单的)QEMU。
  • \n
\n