lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20241206000012.440827-1-elsk@google.com>
Date: Fri,  6 Dec 2024 00:00:04 +0000
From: HONG Yifan <elsk@...gle.com>
To: Masahiro Yamada <masahiroy@...nel.org>, Miguel Ojeda <ojeda@...nel.org>, 
	Matthias Maennich <maennich@...gle.com>
Cc: HONG Yifan <elsk@...gle.com>, kernel-team@...roid.com, linux-kernel@...r.kernel.org
Subject: [PATCH v2] kheaders: prevent `find` from seeing perl temp files

Symptom:

The command

    find ... | xargs ... perl -i

occasionally triggers error messages like the following, with the build
still succeeding:

    Can't open <redacted>/kernel/.tmp_cpio_dir/include/dt-bindings/clock/XXNX4nW9: No such file or directory.

Analysis:

With strace, the root cause has been identified to be `perl -i` creating
temporary files inside $cpio_dir, which causes `find` to see the
temporary files and emit the names. `find` is likely implemented with
readdir. POSIX `readdir` says:

    If a file is removed from or added to the directory after the most
    recent call to opendir() or rewinddir(), whether a subsequent call
    to readdir() returns an entry for that file is unspecified.

So if the libc that `find` links against choose to return that entry
in readdir(), a possible sequence of events is the following:

1. find emits foo.h
2. xargs executes `perl -i foo.h`
3. perl (pid=100) creates temporary file `XXXXXXXX`
4. find sees file `XXXXXXXX` and emit it
5. PID 100 exits, cleaning up the temporary file `XXXXXXXX`
6. xargs executes `perl -i XXXXXXXX`
7. perl (pid=200) tries to read the file, but it doesn't exist any more.

... triggering the error message.

One can reproduce the bug with the following command (assuming PWD
contains the list of headers in kheaders.tar.xz)

    for i in $(seq 100); do
        find -type f -print0 |
            xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;';
    done

With a `find` linking against musl libc, the error message is emitted
6/100 times.

The fix:

This change store the results of `find` before feeding them into xargs.
find and xargs will no longer be able to see temporary files that perl
creates after this change.

Signed-off-by: HONG Yifan <elsk@...gle.com>
---
v2 <- v1: change from `find *.h | xargs perl` to
    `find > file; cat file | xargs perl` because Masahiro discovered that the
    approach in v1 still causes find to see temporary files. The new approach
    is more robust.
v1: https://lore.kernel.org/all/20241107005831.15434-1-elsk@google.com/

 kernel/gen_kheaders.sh | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh
index 7e1340da5aca..4d70e6377da5 100755
--- a/kernel/gen_kheaders.sh
+++ b/kernel/gen_kheaders.sh
@@ -84,8 +84,12 @@ for f in $dir_list;
 done | cpio --quiet -pdu $cpio_dir >/dev/null 2>&1

 # Remove comments except SDPX lines
-find $cpio_dir -type f -print0 |
+# Use a temporary file to store directory contents to prevent find/xargs from
+# seeing temporary files created by perl.
+find $cpio_dir -type f -print0 > "${cpio_dir}.contents.txt"
+cat "${cpio_dir}.contents.txt" | \
 	xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;'
+rm -f "${cpio_dir}.contents.txt"

 # Create archive and try to normalize metadata for reproducibility.
 tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \
--
2.47.0.338.g60cca15819-goog


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ