Package: debhelper
Version: 13.4
Severity: normal
File: /usr/bin/dh_fixperms

In debhelper 13.4, usr/libexec was added to the array @executable_files_dirs
of directories in which all files are to be made executable.

I'm not sure that this is necessarily appropriate: several packages install
files into subdirectories of /usr/libexec that are not directly executable.
In particular:

* There is a convention in GLib and GLib-adjacent packages to install
  "as-installed" integration test suites (for use by e.g. autopkgtest),
  including both executables and non-executable data, into
  /usr/libexec/installed-tests
* Valgrind uses /usr/libexec/valgrind for private data that is
  a mixture of executables, non-executable XML files, and shared libraries
* sudo uses /usr/libexec/sudo for plugins

I recognise that this is not 100% FHS-compliant. However, there isn't
really a great FHS location for the installed-tests use-case:

* A subdirectory of ${datadir} can't have architecture-dependent files
  like compiled binaries
* A subdirectory of ${libdir} varies between architectures (and between
  operating systems, e.g. Debian vs. Red Hat), which makes automated and
  manual testing instructions harder to write, and can cause multiarch
  collisions in scripts/metadata that refer to the tests
* A subdirectory of ${prefix}/lib (like systemd uses for units, tmpfiles,
  etc.) requires repeatedly explaining to well-intentioned contributors
  and packagers that, yes, it's intentionally the same between
  architectures, and, no, they shouldn't move it to ${libdir} even though
  their favourite OS uses /usr/lib64
* Dividing test executables and test data between ${libexecdir}, ${libdir}
  and ${datadir} requires teaching the test-cases to look in the
  correct one of those paths for each resource or helper executable,
  making the tests more complicated and error-prone, particularly if
  upstream developers will usually run them as build-time tests in a
  single directory; it also means separating the tests out of a complete
  OS image (for example into an optional Flatpak extension) involves
  removing multiple directories, not just /usr/libexec/installed-tests

Presumably other use-cases like valgrind and sudo have similar concerns.
I think installing this sort of mixed content into a subdirectory of
/usr/libexec is in the spirit of the FHS, even if not obeying the letter
of the FHS.

At the moment, I'm working around this in affected packages by using
`dh_fixperms -Xusr/libexec/installed-tests`, but that means I don't get
the other behaviours of dh_fixperms such as normalizing executable
permissions to 0755 and non-executable permissions to 0644, which can
cause non-reproducibility when varying the umask.

As a result, I think it would be better if dh_fixperms didn't force all
files in subdirectories of /usr/libexec to be executable. I think there
are three reasonable routes to do that:

1. usr/libexec could be removed from the @executable_files_dirs, returning
   to bullseye behaviour
2. dh_fixperms could continue to chmod regular files in each of the
   @executable_files_dirs to be executable, but stop recursing into their
   subdirectories when doing so
3. dh_fixperms could special-case usr/libexec so that the other
   @executable_files_dirs are processed recursively, but usr/libexec is
   processed non-recursively

I would personally take option 2 and process the @executable_files_dirs
non-recursively, if it was up to me, because all the use-cases that
I'm aware of for mixing executable and non-executable files in the
${libexecdir} also want to group them into a subdirectory. The other
@executable_files_dirs don't generally have subdirectories (the only
counterexamples I know of are /usr/bin/mh/, which has a special exception
in Policy, and some mh-like mail suites) so processing the other
directories non-recursively shouldn't have any practical effect on many
packages.

In any case, I would hope that we can assume that upstream build systems
usually chmod executables +x without dh_fixperms' help, because if they
didn't do that, they would not work as expected in a manual installation
from source code or in a non-Debian packaging system.

Thanks,
    smcv

-- System Information:
Debian Release: bookworm/sid
  APT prefers unstable-debug
  APT policy: (500, 'unstable-debug'), (500, 'stable-security'), (500, 
'oldstable-debug'), (500, 'oldoldstable'), (500, 'buildd-unstable'), (500, 
'unstable'), (500, 'testing'), (500, 'stable'), (500, 'oldstable'), (1, 
'experimental-debug'), (1, 'buildd-experimental'), (1, 'experimental')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 5.16.0-3-amd64 (SMP w/4 CPU threads; PREEMPT)
Kernel taint flags: TAINT_WARN
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8), LANGUAGE=en_GB:en
Shell: /bin/sh linked to /bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages debhelper depends on:
ii  autotools-dev            20220109.1
ii  dh-autoreconf            20
ii  dh-strip-nondeterminism  1.13.0-1
ii  dpkg                     1.21.1
ii  dpkg-dev                 1.21.1
ii  dwz                      0.14-1
ii  file                     1:5.41-2
ii  libdebhelper-perl        13.6
ii  libdpkg-perl             1.21.1
ii  man-db                   2.10.1-1
ii  perl                     5.34.0-3
ii  po-debconf               1.0.21+nmu1

debhelper recommends no packages.

Versions of packages debhelper suggests:
pn  dh-make  <none>

-- no debconf information

Reply via email to