guix-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

01/08: gnu: glibc: Catch all cases of a glibc user not requesting 64-bit


From: guix-commits
Subject: 01/08: gnu: glibc: Catch all cases of a glibc user not requesting 64-bit offsets and then using readdir regardless.
Date: Sun, 4 Oct 2020 03:30:10 -0400 (EDT)

dannym pushed a commit to branch wip-file-offset-bits-64-sledgehammer
in repository guix.

commit 6d513b776a449fdb5c7c50b33060a5476edf61cb
Author: Danny Milosavljevic <dannym@scratchpost.org>
AuthorDate: Sun Oct 4 00:03:00 2020 +0200

    gnu: glibc: Catch all cases of a glibc user not requesting 64-bit offsets 
and
    then using readdir regardless.
    
    * gnu/packages/base.scm (glibc)[arguments]#<:phases>[patch-dirent]: Catch 
all
    cases of a glibc user not requesting 64-bit offsets and then using readdir
    regardless.
---
 gnu/packages/base.scm | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 64 insertions(+)

diff --git a/gnu/packages/base.scm b/gnu/packages/base.scm
index 41976c5..a5c41b5 100644
--- a/gnu/packages/base.scm
+++ b/gnu/packages/base.scm
@@ -782,6 +782,70 @@ the store.")
 
       #:tests? #f                                 ; XXX
       #:phases (modify-phases %standard-phases
+                 (add-after 'unpack 'patch-dirent
+                   (lambda* (#:key outputs #:allow-other-keys)
+                     ;; Linux kernel file offsets are always 64 bits.
+                     ;; But userspace can be built to use 32 bit offsets.
+                     ;;
+                     ;; "struct dirent", returned by readdir, uses d_off to 
store
+                     ;; such an "offset" that it got from the Linux kernel.
+                     ;; In the case of ext4 that "offset" is actually a 64 bit
+                     ;; hash value.
+                     ;;
+                     ;; Therefore, there are cases where such an offset that 
it got
+                     ;; from the Linux kernel does not fit in the "struct 
dirent"
+                     ;; field "d_off".
+                     ;;
+                     ;; If the guest system's glibc is 32 bit AND uses 32 bit
+                     ;; file offsets it is going to be very confused.
+                     ;; It does check whether d_off fits into the structure
+                     ;; it gives back to the user--and it doesn't fit.  Hence 
readdir
+                     ;; fails, with errno == EOVERFLOW (which is undocumented 
and thus
+                     ;; an API error).
+                     ;; This manifests itself in simple directory reads not 
working
+                     ;; anymore in parts of cmake, for example.
+                     ;;
+                     ;; This manifested in Guix when building stuff for
+                     ;; ARMHF on a x86_64 build host using QEMU transparent 
emulation.
+                     ;;
+                     ;; There is a very simple and complete way to avoid this 
problem:
+                     ;; Just always use 64 bit offsets in user space programs 
(also
+                     ;; on 32 bit machines).  The Linux kernel does that 
already
+                     ;; anyway.
+                     ;;
+                     ;; Note: We might want to avoid using 64 bit when 
bootstrapping
+                     ;; using mescc (since mescc doesn't directly support 64 
bit
+                     ;; values)--but then bootstrapping has to be done on a
+                     ;; file system other than ext4, or on ext4 with the 
feature
+                     ;; "dir_index" disabled.
+                     ;;
+                     ;; The change below does not affect 64 bit users.
+                     ;;
+                     ;; See <https://issues.guix.gnu.org/43513>.
+                     (let ((port (open-file "dirent/dirent.h" "a")))
+                       (display "
+#ifndef _LIBC
+#if __SIZEOF_LONG__ < 8
+#ifndef __USE_FILE_OFFSET64
+#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS == 32
+#warning \"Using -D_FILE_OFFSET_BITS=32 and using readdir is a bad idea, see 
<https://bugzilla.kernel.org/show_bug.cgi?id=205957>\"
+#else
+#undef readdir
+#define readdir @READDIR_WITHOUT_FILE_OFFSET64_IS_A_REALLY_BAD_IDEA@
+#endif
+#endif
+#endif
+#endif
+" port)
+                       (close-port port))
+                     ;; This file includes <dirent.h> and thus checks sanity 
already.
+                     ;; TODO: Check dirent/scandir-tail.c, 
dirent/scandir64-tail.c.
+                     (substitute* "posix/glob.c"
+                      (("(#[ ]*define[ ][ ]*readdir)") "
+#undef readdir
+#define readdir"))
+                     #t))
+
                  (add-before
                   'configure 'pre-configure
                   (lambda* (#:key inputs native-inputs outputs



reply via email to

[Prev in Thread] Current Thread [Next in Thread]