LD_ASSUME_KERNELの使い方について学ぶ

LD_ASSUME_KERNELの使い方について学ぶ

LD_ASSUME_KERNEL私のシステム(Debian / bullseye + bpo)の環境変数を理解しようとしています。

によると:

$ man pthreads

私はこのようなことを実行できるはずですが、私のシステムでは次のような結果が得られます。

% LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls
/bin/bash: error while loading shared libraries: libdl.so.2: cannot open shared object file: No such file or directory

何が起こっているのか理解するには低すぎます。LD_ASSUME_KERNEL私のシステムの実装が多少壊れているのか、それとも文書が正しく読めないのかはわかりません。

その他の失敗した試み:

% LD_TRACE_LOADED_OBJECTS=1 LD_ASSUME_KERNEL=2.2.5 ldd
        linux-vdso.so.1 (0x00007ffe3f7e0000)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f5399001000)
        libdl.so.2 => not found
        libc.so.6 => not found
        libc.so.6 => not found

そして

% LD_TRACE_LOADED_OBJECTS=1 LD_ASSUME_KERNEL=2.4.19 ldd
        linux-vdso.so.1 (0x00007ffeaacb9000)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007f861cb18000)
        libdl.so.2 => not found
        libc.so.6 => not found
        libc.so.6 => not found

しかし:

% LD_TRACE_LOADED_OBJECTS=1 ldd
        linux-vdso.so.1 (0x00007ffc929a9000)
        libtinfo.so.6 => /lib/x86_64-linux-gnu/libtinfo.so.6 (0x00007fa319a29000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa319a23000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa31985e000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fa319aaa000)

引用:

$ man pthreads
[...]
   Selecting the threading implementation: LD_ASSUME_KERNEL
       On systems with a glibc that supports both LinuxThreads and NPTL (i.e., glibc 2.3.x), the LD_ASSUME_KERNEL environment variable can be used to override  the  dynamic  linker's  default  choice  of threading implementation.  This variable tells the dynamic linker to assume that it is running on top of a particular kernel version.  By specifying a kernel version that does not provide the support required by NPTL, we can force the use of LinuxThreads.  (The most likely reason for doing this is to run a (broken) application that depends on some nonconformant behavior in  LinuxThreads.)
       For example:

           bash$ $( LD_ASSUME_KERNEL=2.2.5 ldd /bin/ls | grep libc.so | \
                           awk '{print $3}' ) | egrep -i 'threads|nptl'
                   linuxthreads-0.10 by Xavier Leroy

以下にも適用されます。

$ man ld.so
[...]
       LD_ASSUME_KERNEL (since glibc 2.2.3)
              Each  shared object can inform the dynamic linker of the minimum kernel ABI version that it requires.  (This requirement is encoded in an ELF note section that is viewable via readelf -n as
              a section labeled NT_GNU_ABI_TAG.)  At run time, the dynamic linker determines the ABI version of the running kernel and will reject loading shared objects that specify minimum ABI versions
              that exceed that ABI version.

              LD_ASSUME_KERNEL  can  be  used to cause the dynamic linker to assume that it is running on a system with a different kernel ABI version.  For example, the following command line causes the
              dynamic linker to assume it is running on Linux 2.2.5 when loading the shared objects required by myprog:

                  $ LD_ASSUME_KERNEL=2.2.5 ./myprog

              On systems that provide multiple versions of a shared object (in different directories in the search path) that have different minimum kernel ABI version requirements, LD_ASSUME_KERNEL  can
              be used to select the version of the object that is used (dependent on the directory search order).

              Historically,  the  most common use of the LD_ASSUME_KERNEL feature was to manually select the older LinuxThreads POSIX threads implementation on systems that provided both LinuxThreads and
              NPTL (which latter was typically the default on such systems); see pthreads(7).
% apt-cache policy manpages
manpages:
  Installed: 5.10-1
  Candidate: 5.10-1
  Version table:
 *** 5.10-1 500
        500 http://deb.debian.org/debian bullseye/main amd64 Packages
        500 http://deb.debian.org/debian bullseye/main i386 Packages
        100 /var/lib/dpkg/status

ちなみに、次の出力は常に同じです。

/lib/x86_64-linux-gnu/libc.so.6
LD_ASSUME_KERNEL=2.2.5 /lib/x86_64-linux-gnu/libc.so.6
LD_ASSUME_KERNEL=2.4.19 /lib/x86_64-linux-gnu/libc.so.6

私は得る:

GNU C Library (Debian GLIBC 2.31-13+deb11u3) stable release version 2.31.
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.
Compiled by GNU CC version 10.2.1 20210110.
libc ABIs: UNIQUE IFUNC ABSOLUTE
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

答え1

ここで最も重要な部分は、マニュアルの次の引用です。

実行時に、動的リンカーは実行中のカーネルのABIバージョンを確認し、そのABIバージョンを超える最小ABIバージョンを指定する共有オブジェクトのロードを拒否します。

file与えられたライブラリの最小ABIバージョンが何であるかを教えてくれます。これを実行しているため、x86_64ほとんどの場合、最小ABIバージョンは3.2.0です。

$ file -L /lib/x86_64-linux-gnu/libc.so.6
/lib/x86_64-linux-gnu/libc-2.31.so: ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2e5abcee94f3bcbed7bba094f341070a2585a2ba, for GNU/Linux 3.2.0, stripped

システムでは、例外はlibtinfo.so.6最小ABIを宣言しないことです。

$ file -L /lib/x86_64-linux-gnu/libtinfo.so.6
/lib/x86_64-linux-gnu/libtinfo.so.6: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=d6920dbdd057f44edaf4c1fbce191b5854dfd9e6, stripped

3.2.0より小さい値を設定すると、バージョン3.2.0以降が必要なライブラリを拒否するように動的リンカーに指示します。LD_ASSUME_KERNELシステムは、要求が厳しくない影響を受けるライブラリの異なるバージョンを提供していないため、ld.so失敗します。

関連情報