This is part of a series of fixes for the linked bug (failure
to preserve libraries in some situations).

We need to check if scanelf failed when calling it in the
installed-files QA check as we later use it to populate the VDB.

Silently continuing results in either blank e.g. PROVIDES,
NEEDED{,.ELF.2} or those files may be missing entirely,
resulting in a corrupt state both on the system and in
any generated binpkgs.

Adds an escape variable (PORTAGE_NO_SCANELF_CHECK) to allow
re-emerging pax-utils if it's broken.

Bug: https://bugs.gentoo.org/811462
Signed-off-by: Sam James <s...@gentoo.org>
---
 bin/misc-functions.sh | 64 +++++++++++++++++++++++++++++++++----------
 1 file changed, 50 insertions(+), 14 deletions(-)

diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh
index bd1fb7553..e4defa550 100755
--- a/bin/misc-functions.sh
+++ b/bin/misc-functions.sh
@@ -177,25 +177,61 @@ install_qa_check() {
        if type -P scanelf > /dev/null ; then
                # Save NEEDED information after removing self-contained 
providers
                rm -f "$PORTAGE_BUILDDIR"/build-info/NEEDED{,.ELF.2}
+
                # We don't use scanelf -q, since that would omit libraries like
                # musl's /usr/lib/libc.so which do not have any DT_NEEDED or
                # DT_SONAME settings. Since we don't use scanelf -q, we have to
                # handle the special rpath value "  -  " below.
-               scanelf -yRBF '%a;%p;%S;%r;%n' "${D%/}/" | { while IFS= read -r 
l; do
-                       arch=${l%%;*}; l=${l#*;}
-                       obj="/${l%%;*}"; l=${l#*;}
-                       soname=${l%%;*}; l=${l#*;}
-                       rpath=${l%%;*}; l=${l#*;}; [ "${rpath}" = "  -  " ] && 
rpath=""
-                       needed=${l%%;*}; l=${l#*;}
-
-                       # Infer implicit soname from basename (bug 715162).
-                       if [[ -z ${soname} && $(file "${D%/}${obj}") == *"SB 
shared object"* ]]; then
-                               soname=${obj##*/}
-                       fi
+               scanelf_output=$(scanelf -yRBF '%a;%p;%S;%r;%n' "${D%/}/")
+
+               case $? in
+                       0)
+                               # Proceed
+                               ;;
+                       159)
+                               # Unknown syscall
+                               eerror "Failed to run scanelf (unknown syscall)"
+
+                               if [[ -z ${PORTAGE_NO_SCANELF_CHECK} ]]; then
+                                       # Abort only if the special recovery 
variable isn't set
+                                       eerror "Please upgrade pax-utils with:"
+                                       eerror " PORTAGE_NO_SCANELF_CHECK=1 
emerge -v1 app-misc/pax-utils"
+                                       eerror "Aborting to avoid corrupting 
metadata"
+                                       die "${0##*/}: Failed to run scanelf! 
Update pax-utils?"
+                               fi
+                               ;;
+                       *)
+                               # Failed in another way
+                               eerror "Failed to run scanelf (returned: $?)!"
+
+                               if [[ -z ${PORTAGE_NO_SCANELF_CHECK} ]]; then
+                                       # Abort only if the special recovery 
variable isn't set
+                                       eerror "Please report this bug at 
https://bugs.gentoo.org/!";
+                                       eerror "It may be possible to re-emerge 
pax-utils with:"
+                                       eerror " PORTAGE_NO_SCANELF_CHECK=1 
emerge -v1 app-misc/pax-utils"
+                                       eerror "Aborting to avoid corrupting 
metadata"
+                                       die "${0##*/}: Failed to run scanelf!"
+                               fi
+                               ;;
+               esac
+
+               if [[ -n ${scanelf_output} ]]; then
+                       while IFS= read -r l; do
+                               arch=${l%%;*}; l=${l#*;}
+                               obj="/${l%%;*}"; l=${l#*;}
+                               soname=${l%%;*}; l=${l#*;}
+                               rpath=${l%%;*}; l=${l#*;}; [ "${rpath}" = "  -  
" ] && rpath=""
+                               needed=${l%%;*}; l=${l#*;}
+
+                               # Infer implicit soname from basename (bug 
715162).
+                               if [[ -z ${soname} && $(file "${D%/}${obj}") == 
*"SB shared object"* ]]; then
+                                       soname=${obj##*/}
+                               fi
 
-                       echo "${obj} ${needed}" >> 
"${PORTAGE_BUILDDIR}"/build-info/NEEDED
-                       echo "${arch#EM_};${obj};${soname};${rpath};${needed}" 
>> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
-               done }
+                               echo "${obj} ${needed}" >> 
"${PORTAGE_BUILDDIR}"/build-info/NEEDED
+                               echo 
"${arch#EM_};${obj};${soname};${rpath};${needed}" >> 
"${PORTAGE_BUILDDIR}"/build-info/NEEDED.ELF.2
+                       done <<< ${scanelf_output}
+               fi
 
                [ -n "${QA_SONAME_NO_SYMLINK}" ] && \
                        echo "${QA_SONAME_NO_SYMLINK}" > \
-- 
2.33.0


Reply via email to