From 8beb980c5595ae1e1e6e426085167c47ea7c4dc6 Mon Sep 17 00:00:00 2001 From: Fabian Groffen Date: Wed, 28 Oct 2009 20:40:24 +0000 Subject: [PATCH] Attempt to align this more with trunk - reshuffle qa_check code using functions such that the order is the same as in trunk, but with some extra offsets (at the same time avoid running QA checks for platforms other than the current one) - split out elf, macho, pecoff, xcoff, misc and prefix qa code blocks, keep a bit of general (misc) checks in the original qa_check func for the point mentioned above - only chdir to ${D}, not ${ED}, this has the advantage that if that fails we're on the same panic level as normal Portage, and that we no longer need default src_install implementations that just create ${ED} to avoid a failing QA check, like bug #290245 svn path=/main/branches/prefix/; revision=14746 --- bin/ebuild.sh | 17 - bin/misc-functions.sh | 835 ++++++++++++++++++++++-------------------- 2 files changed, 442 insertions(+), 410 deletions(-) diff --git a/bin/ebuild.sh b/bin/ebuild.sh index b91122fab..e839c54e8 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -597,10 +597,6 @@ _eapi0_src_compile() { _eapi2_src_compile } -_eapi0_src_install() { - _eapi1_src_install -} - _eapi0_src_test() { if emake -j1 check -n &> /dev/null; then vecho ">>> Test phase [check]: ${CATEGORY}/${PF}" @@ -624,15 +620,6 @@ _eapi1_src_compile() { _eapi2_src_compile } -_eapi1_src_install() { - if use prefix ; then - # this avoids misc QA errors in Prefix because it doesn't exist - # by default - mkdir -p "${ED}" - return - fi -} - _eapi2_src_configure() { if [[ -x ${ECONF_SOURCE:-.}/configure ]] ; then econf @@ -661,10 +648,6 @@ _eapi3_src_install() { else dodoc ${DOCS} fi - - # this avoids misc QA errors in Prefix because it doesn't exist - # by default - use prefix && mkdir -p "${ED}" } ebuild_phase() { diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh index 53808a6eb..212d09a16 100644 --- a/bin/misc-functions.sh +++ b/bin/misc-functions.sh @@ -18,7 +18,9 @@ shift $# source @PORTAGE_BASE@/bin/ebuild.sh install_symlink_html_docs() { - cd "${ED}" || die "cd failed" + cd "${D}" || die "cd failed" + [[ ! -d ${ED} ]] && dodir / + cd "${ED}" || die "cd shouldn't have failed" #symlink the html documentation (if DOC_SYMLINKS_DIR is set in make.conf) if [ -n "${DOC_SYMLINKS_DIR}" ] ; then local mydocdir docdir @@ -42,7 +44,7 @@ install_symlink_html_docs() { } install_qa_check() { - cd "${ED}" || die "cd failed" + cd "${D}" || die "cd failed" export STRIP_MASK prepall @@ -59,7 +61,36 @@ install_qa_check() { sleep 1 done - if [[ ${CHOST} != *-darwin* ]] && type -P scanelf > /dev/null && ! hasq binchecks ${RESTRICT}; then + case ${CHOST} in + *-darwin*) + # Mach-O platforms (NeXT, Darwin, OSX) + install_qa_check_macho + ;; + *-interix*|*-winnt*) + # PECOFF platforms (Windows/Interix) + install_qa_check_pecoff + ;; + *-aix*) + # XCOFF platforms (AIX) + install_qa_check_xcoff + ;; + *) + # because this is the majority: ELF platforms (Linux, + # Solaris, *BSD, IRIX, etc.) + install_qa_check_elf + ;; + esac + + # this is basically here such that the diff with trunk remains just + # offsetted and not out of order + install_qa_check_misc + + # Prefix specific checks + [[ -n ${EPREFIX} ]] && install_qa_check_prefix +} + +install_qa_check_elf() { + if type -P scanelf > /dev/null && ! hasq binchecks ${RESTRICT}; then local qa_var insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET} local f x @@ -313,244 +344,227 @@ install_qa_check() { PORTAGE_QUIET=${tmp_quiet} fi +} - local _pfx_scan="readpecoff ${CHOST}" - - # this one uses readpecoff, which supports multiple prefix platforms! - # this is absolutely _not_ optimized for speed, and there may be plenty - # of possibilities by introducing one or the other cache! - if [[ ${CHOST} == *-interix* || ${CHOST} == *-winnt* ]] && ! hasq binchecks ${RESTRICT}; then - # copied and adapted from the above scanelf code. - local qa_var insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET} - local f x - - # display warnings when using stricter because we die afterwards - if has stricter ${FEATURES} ; then - unset PORTAGE_QUIET - fi +install_qa_check_misc() { + local unsafe_files=$(find "${ED}" -type f '(' -perm -2002 -o -perm -4002 ')') + if [[ -n ${unsafe_files} ]] ; then + eqawarn "QA Notice: Unsafe files detected (set*id and world writable)" + eqawarn "${unsafe_files}" + die "Unsafe files found in \${ED}. Portage will not install them." + fi - local _exec_find_opt="-executable" - [[ ${CHOST} == *-winnt* ]] && _exec_find_opt='-name *.dll -o -name *.exe' + if [[ -d ${D}/${D} ]] ; then + find "${D}/${D}" | \ + while read i ; do + eqawarn "QA Notice: /${i##${D}/${D}} installed in \${D}/\${D}" + done + die "Aborting due to QA concerns: files installed in ${D}/${D}" + fi - # Make sure we disallow insecure RUNPATH/RPATH's - # Don't want paths that point to the tree where the package was built - # (older, broken libtools would do this). Also check for null paths - # because the loader will search $PWD when it finds null paths. + # this should help to ensure that all (most?) shared libraries are executable + # and that all libtool scripts / static libraries are not executable + for i in "${ED}"opt/*/lib{,32,64} \ + "${ED}"lib{,32,64} \ + "${ED}"usr/lib{,32,64} \ + "${ED}"usr/X11R6/lib{,32,64} ; do + [[ ! -d ${i} ]] && continue - f=$( - find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | \ - while IFS=";" read arch obj soname rpath needed ; do \ - echo "${rpath}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )" > /dev/null 2>&1 \ - && echo "${obj}"; done; - ) - # Reject set*id binaries with $ORIGIN in RPATH #260331 - x=$( - find "${ED}" -type f '(' -perm -u+s -o -perm -g+s ')' -print0 | \ - xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; do \ - echo "${rpath}" | grep '$ORIGIN' > /dev/null 2>&1 && echo "${obj}"; done; - ) - if [[ -n ${f}${x} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: The following files contain insecure RUNPATH's" - eqawarn " Please file a bug about this at http://bugs.gentoo.org/" - eqawarn " with the maintaining herd of the package." - eqawarn "${f}${f:+${x:+\n}}${x}" - vecho -ne '\a\n' - if [[ -n ${x} ]] || has stricter ${FEATURES} ; then - insecure_rpath=1 - else - eqawarn "cannot automatically fix runpaths on interix platforms!" + for j in "${i}"/*.so.* "${i}"/*.so "${i}"/*.dylib "${i}"/*.dll ; do + [[ ! -e ${j} ]] && continue + if [[ -L ${j} ]] ; then + linkdest=$(readlink "${j}") + if [[ ${linkdest} == /* ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: Found an absolute symlink in a library directory:" + eqawarn " ${j#${D}} -> ${linkdest}" + eqawarn " It should be a relative symlink if in the same directory" + eqawarn " or a linker script if it crosses the /usr boundary." + fi + continue fi - fi + [[ -x ${j} ]] && continue + vecho "making executable: ${j#${D}}" + chmod +x "${j}" + done - rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED - rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 + for j in "${i}"/*.a "${i}"/*.la ; do + [[ ! -e ${j} ]] && continue + [[ -L ${j} ]] && continue + [[ ! -x ${j} ]] && continue + vecho "removing executable bit: ${j#${D}}" + chmod -x "${j}" + done + done - # Save NEEDED information after removing self-contained providers - find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | { while IFS=';' read arch obj soname rpath needed; do - # need to strip image dir from object name. - obj="/${obj#${D}}" - if [ -z "${rpath}" -o -n "${rpath//*ORIGIN*}" ]; then - # object doesn't contain $ORIGIN in its runpath attribute - echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED - echo "${arch};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 - else - dir=${obj%/*} - # replace $ORIGIN with the dirname of the current object for the lookup - opath=$(echo :${rpath}: | sed -e "s#.*:\(.*\)\$ORIGIN\(.*\):.*#\1${dir}\2#") - sneeded=$(echo ${needed} | tr , ' ') - rneeded="" - for lib in ${sneeded}; do - found=0 - for path in ${opath//:/ }; do - [ -e "${ED}/${path}/${lib}" ] && found=1 && break - done - [ "${found}" -eq 0 ] && rneeded="${rneeded},${lib}" - done - rneeded=${rneeded:1} - if [ -n "${rneeded}" ]; then - echo "${obj} ${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED - echo "${arch};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 - fi + # When installing static libraries into /usr/lib and shared libraries into + # /lib, we have to make sure we have a linker script in /usr/lib along side + # the static library, or gcc will utilize the static lib when linking :(. + # http://bugs.gentoo.org/4411 + abort="no" + for a in "${ED}"usr/lib*/*.a ; do + [[ ${CHOST} == *-darwin* ]] \ + && s=${a%.a}.dylib \ + || s=${a%.a}.so + if [[ ! -e ${s} ]] ; then + s=${s%usr/*}${s##*/usr/} + if [[ -e ${s} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: Missing gen_usr_ldscript for ${s##*/}" + abort="yes" fi - done } - - if [[ ${insecure_rpath} -eq 1 ]] ; then - die "Aborting due to serious QA concerns with RUNPATH/RPATH" - elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then - die "Aborting due to QA concerns: ${die_msg}" fi + done + [[ ${abort} == "yes" ]] && die "add those ldscripts" - local _so_ext='.so*' + # Make sure people don't store libtool files or static libs in /lib + # on AIX, "dynamic libs" have extention .a, so don't get false + # positives + [[ ${CHOST} == *-aix* ]] \ + && f=$(ls "${ED}"lib*/*.la 2>/dev/null || true) \ + || f=$(ls "${ED}"lib*/*.{a,la} 2>/dev/null) + if [[ -n ${f} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: Excessive files found in the / partition" + eqawarn "${f}" + vecho -ne '\a\n' + die "static archives (*.a) and libtool library files (*.la) do not belong in /" + fi - case "${CHOST}" in - *-winnt*) _so_ext=".dll" ;; # no "*" intentionally! - esac + # Verify that the libtool files don't contain bogus $D entries. + local abort=no gentoo_bug=no + for a in "${ED}"usr/lib*/*.la ; do + s=${a##*/} + if grep -qs "${D}" "${a}" ; then + vecho -ne '\a\n' + eqawarn "QA Notice: ${s} appears to contain PORTAGE_TMPDIR paths" + abort="yes" + fi + done + [[ ${abort} == "yes" ]] && die "soiled libtool library files found" - # Run some sanity checks on shared libraries - for d in "${ED}"lib* "${ED}"usr/lib* ; do - [[ -d "${d}" ]] || continue - f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \ - xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \ - do [[ -z "${soname}" ]] && echo "${obj}"; done) + # Evaluate misc gcc warnings + if [[ -n ${PORTAGE_LOG_FILE} && -r ${PORTAGE_LOG_FILE} ]] ; then + # In debug mode, this variable definition and corresponding grep calls + # will produce false positives if they're shown in the trace. + local reset_debug=0 + if [[ ${-/x/} != $- ]] ; then + set +x + reset_debug=1 + fi + local m msgs=( + ": warning: dereferencing type-punned pointer will break strict-aliasing rules$" + ": warning: dereferencing pointer .* does break strict-aliasing rules$" + ": warning: implicit declaration of function " + ": warning: incompatible implicit declaration of built-in function " + ": warning: is used uninitialized in this function$" # we'll ignore "may" and "might" + ": warning: comparisons like X<=Y<=Z do not have their mathematical meaning$" + ": warning: null argument where non-null required " + ) + abort="no" + i=0 + while [[ -n ${msgs[${i}]} ]] ; do + m=${msgs[$((i++))]} + # force C locale to work around slow unicode locales #160234 + f=$(LC_ALL=C grep "${m}" "${PORTAGE_LOG_FILE}") if [[ -n ${f} ]] ; then vecho -ne '\a\n' - eqawarn "QA Notice: The following shared libraries lack a SONAME" + eqawarn "QA Notice: Package has poor programming practices which may compile" + eqawarn " fine but exhibit random runtime failures." eqawarn "${f}" vecho -ne '\a\n' - sleep 1 + abort="yes" fi + done + [[ $reset_debug = 1 ]] && set -x + f=$(cat "${PORTAGE_LOG_FILE}" | \ + EPYTHON= "$PORTAGE_BIN_PATH"/check-implicit-pointer-usage.py) + if [[ -n ${f} ]] ; then - f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \ - xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \ - do [[ -z "${needed}" ]] && echo "${obj}"; done) - if [[ -n ${f} ]] ; then + # In the future this will be a forced "die". In preparation, + # increase the log level from "qa" to "eerror" so that people + # are aware this is a problem that must be fixed asap. + + # just warn on 32bit hosts but bail on 64bit hosts + case ${CHOST} in + alpha*|hppa64*|ia64*|powerpc64*|mips64*|sparc64*|sparcv9*|x86_64*) gentoo_bug=yes ;; + esac + + abort=yes + + if [[ $gentoo_bug = yes ]] ; then + eerror + eerror "QA Notice: Package has poor programming practices which may compile" + eerror " but will almost certainly crash on 64bit architectures." + eerror + eerror "${f}" + eerror + eerror " Please file a bug about this at http://bugs.gentoo.org/" + eerror " with the maintaining herd of the package." + eerror + else vecho -ne '\a\n' - eqawarn "QA Notice: The following shared libraries lack NEEDED entries" + eqawarn "QA Notice: Package has poor programming practices which may compile" + eqawarn " but will almost certainly crash on 64bit architectures." eqawarn "${f}" vecho -ne '\a\n' - sleep 1 fi - done - PORTAGE_QUIET=${tmp_quiet} + fi + if [[ ${abort} == "yes" ]] ; then + if [[ ${gentoo_bug} == "yes" ]] ; then + die "install aborted due to" \ + "poor programming practices shown above" + else + echo "Please do not file a Gentoo bug and instead" \ + "report the above QA issues directly to the upstream" \ + "developers of this software." | fmt -w 70 | \ + while read line ; do eqawarn "${line}" ; done + eqawarn "Homepage: ${HOMEPAGE}" + hasq stricter ${FEATURES} && die "install aborted due to" \ + "poor programming practices shown above" + fi + fi fi - if [[ ${CHOST} == *-aix* ]] && ! hasq binchecks ${RESTRICT}; then - local tmp_quiet=${PORTAGE_QUIET} - local queryline deplib - local insecure_rpath_list= undefined_symbols_list= - - # display warnings when using stricter because we die afterwards - if has stricter ${FEATURES} ; then - unset PORTAGE_QUIET - fi - - rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 - find "${ED}" -not -type d -exec \ - "${EPREFIX}/usr/bin/aixdll-query" '{}' FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS ';' \ - > "${T}"/needed 2>/dev/null + # Compiled python objects do not belong in /usr/share (FHS violation) + # and can be a pain when upgrading python + f=$([ -d "${ED}"/usr/share ] && \ + find "${ED}"usr/share -name '*.py[co]' | sed "s:${D}:/:") + if [[ -n ${f} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: Precompiled python object files do not belong in /usr/share" + eqawarn "${f}" + vecho -ne '\a\n' + fi - # Symlinking archive libraries is not a good idea on aix, - # as there is nothing like "soname" on pure filesystem level. - # So we create a copy instead of the symlink. - local prev_FILE= - while read queryline - do - local FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS= - eval ${queryline} + # Portage regenerates this on the installed system. + rm -f "${ED}"/usr/share/info/dir{,.gz,.bz2} - if [[ ${prev_FILE} != ${FILE} ]]; then - prev_FILE=${FILE} - if [[ -n ${MEMBER} || " ${FLAGS} " == *" SHROBJ "* ]] && [[ -h ${FILE} ]]; then - local target=$(readlink "${FILE}") - if [[ ${target} == /* ]]; then - target=${D}${target} - else - target=${FILE%/*}/${target} + if hasq multilib-strict ${FEATURES} && \ + [[ -x ${EPREFIX}/usr/bin/file && -x ${EPREFIX}/usr/bin/find ]] && \ + [[ -n ${MULTILIB_STRICT_DIRS} && -n ${MULTILIB_STRICT_DENY} ]] + then + local abort=no firstrun=yes + MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT} | sed -e 's:\([(|)]\):\\\1:g') + for dir in ${MULTILIB_STRICT_DIRS} ; do + [[ -d ${ED}/${dir} ]] || continue + for file in $(find ${ED}/${dir} -type f | grep -v "^${ED}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do + if file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" ; then + if [[ ${firstrun} == yes ]] ; then + echo "Files matching a file type that is not allowed:" + firstrun=no fi - rm -f "${FILE}" || die "cannot prune ${FILE#${ED}}" - cp -f "${target}" "${FILE}" || die "cannot copy ${target#${ED}} to ${FILE#${ED}}" - fi - fi - done <"${T}"/needed - - prev_FILE= - while read queryline - do - local FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS= - eval ${queryline} - - if [[ ${prev_FILE} != ${FILE} ]]; then - # Save NEEDED information for the archive library stub - echo "${FORMAT##* }${FORMAT%%-*};${FILE#${D%/}};${FILE##*/};;" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 - fi - - # Make sure we disallow insecure RUNPATH's - # Don't want paths that point to the tree where the package was built - # (older, broken libtools would do this). Also check for null paths - # because the loader will search $PWD when it finds null paths. - # And we really want absolute paths only. - if [[ -n $(echo ":${RUNPATH}:" | grep -E "(${PORTAGE_BUILDDIR}|::|:[^/])") ]]; then - insecure_rpath_list="${insecure_rpath_list}\n${FILE}" - fi - - # Although we do have runtime linking, we don't want undefined symbols. - # AIX does indicate this by needing either '.' or '..' - local needed=${FILE##*/} - for deplib in ${DEPLIBS}; do - eval deplib=${deplib} - if [[ ${deplib} == '.' || ${deplib} == '..' ]]; then - undefined_symbols_list="${undefined_symbols_list}\n${FILE}" - else - needed="${needed},${deplib}" + abort=yes + echo " ${file#${ED}//}" fi done - - FILE=${FILE#${D%/}} - - [[ -n ${MEMBER} ]] && MEMBER="[${MEMBER}]" - # Save NEEDED information - echo "${FORMAT##* }${FORMAT%%-*};${FILE}${MEMBER};${FILE##*/}${MEMBER};${RUNPATH};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 - done <"${T}"/needed - - if [[ -n ${undefined_symbols_list} ]]; then - vecho -ne '\a\n' - eqawarn "QA Notice: The following files contain undefined symbols." - eqawarn " Please file a bug about this at http://bugs.gentoo.org/" - eqawarn " with 'prefix' as the maintaining herd of the package." - eqawarn "${undefined_symbols_list}" - vecho -ne '\a\n' - fi - - if [[ -n ${insecure_rpath_list} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: The following files contain insecure RUNPATH's" - eqawarn " Please file a bug about this at http://bugs.gentoo.org/" - eqawarn " with 'prefix' as the maintaining herd of the package." - eqawarn "${insecure_rpath_list}" - vecho -ne '\a\n' - if [[ -n ${x} ]] || has stricter ${FEATURES} ; then - insecure_rpath=1 - fi - fi - - if [[ ${insecure_rpath} -eq 1 ]] ; then - die "Aborting due to serious QA concerns with RUNPATH/RPATH" - elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then - die "Aborting due to QA concerns: ${die_msg}" - fi - - PORTAGE_QUIET=${tmp_quiet} - fi - - local unsafe_files=$(find "${ED}" -type f '(' -perm -2002 -o -perm -4002 ')') - if [[ -n ${unsafe_files} ]] ; then - eqawarn "QA Notice: Unsafe files detected (set*id and world writable)" - eqawarn "${unsafe_files}" - die "Unsafe files found in \${ED}. Portage will not install them." + done + [[ ${abort} == yes ]] && die "multilib-strict check failed!" fi +} +install_qa_check_prefix() { if [[ -d ${ED}/${D} ]] ; then find "${ED}/${D}" | \ while read i ; do @@ -559,7 +573,7 @@ install_qa_check() { die "Aborting due to QA concerns: files installed in ${ED}/${D}" fi - if [[ -n ${EPREFIX} && -d ${ED}/${EPREFIX} ]] ; then + if [[ -d ${ED}/${EPREFIX} ]] ; then find "${ED}/${EPREFIX}/" | \ while read i ; do eqawarn "QA Notice: ${i#${D}} double prefix" @@ -627,8 +641,10 @@ install_qa_check() { rm -f "${T}"/non-prefix-shebangs-errs fi fi +} - if [[ ${CHOST} == *-darwin* ]] && ! hasq binchecks ${RESTRICT} ; then +install_qa_check_macho() { + if ! hasq binchecks ${RESTRICT} ; then # on Darwin, dynamic libraries are called .dylibs instead of # .sos. In addition the version component is before the # extension, not after it. Check for this, and *only* warn @@ -665,91 +681,10 @@ install_qa_check() { rm -f "${T}/mach-o.check" fi - # this should help to ensure that all (most?) shared libraries are executable - # and that all libtool scripts / static libraries are not executable - for i in "${ED}"opt/*/lib{,32,64} \ - "${ED}"lib{,32,64} \ - "${ED}"usr/lib{,32,64} \ - "${ED}"usr/X11R6/lib{,32,64} ; do - [[ ! -d ${i} ]] && continue - - for j in "${i}"/*.so.* "${i}"/*.so "${i}"/*.dylib "${i}"/*.dll ; do - [[ ! -e ${j} ]] && continue - if [[ -L ${j} ]] ; then - linkdest=$(readlink "${j}") - if [[ ${linkdest} == /* ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: Found an absolute symlink in a library directory:" - eqawarn " ${j#${D}} -> ${linkdest}" - eqawarn " It should be a relative symlink if in the same directory" - eqawarn " or a linker script if it crosses the /usr boundary." - fi - continue - fi - [[ -x ${j} ]] && continue - vecho "making executable: ${j#${D}}" - chmod +x "${j}" - done - - for j in "${i}"/*.a "${i}"/*.la ; do - [[ ! -e ${j} ]] && continue - [[ -L ${j} ]] && continue - [[ ! -x ${j} ]] && continue - vecho "removing executable bit: ${j#${D}}" - chmod -x "${j}" - done - done - - # When installing static libraries into /usr/lib and shared libraries into - # /lib, we have to make sure we have a linker script in /usr/lib along side - # the static library, or gcc will utilize the static lib when linking :(. - # http://bugs.gentoo.org/4411 - abort="no" - for a in "${ED}"usr/lib*/*.a ; do - [[ ${CHOST} == *-darwin* ]] \ - && s=${a%.a}.dylib \ - || s=${a%.a}.so - if [[ ! -e ${s} ]] ; then - s=${s%usr/*}${s##*/usr/} - if [[ -e ${s} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: Missing gen_usr_ldscript for ${s##*/}" - abort="yes" - fi - fi - done - [[ ${abort} == "yes" ]] && die "add those ldscripts" - - # Make sure people don't store libtool files or static libs in /lib - # on AIX, "dynamic libs" have extention .a, so don't get false - # positives - [[ ${CHOST} == *-aix* ]] \ - && f=$(ls "${ED}"lib*/*.la 2>/dev/null || true) \ - || f=$(ls "${ED}"lib*/*.{a,la} 2>/dev/null) - if [[ -n ${f} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: Excessive files found in the / partition" - eqawarn "${f}" - vecho -ne '\a\n' - die "static archives (*.a) and libtool library files (*.la) do not belong in /" - fi - - # Verify that the libtool files don't contain bogus $D entries. - local abort=no gentoo_bug=no - for a in "${ED}"usr/lib*/*.la ; do - s=${a##*/} - if grep -qs "${D}" "${a}" ; then - vecho -ne '\a\n' - eqawarn "QA Notice: ${s} appears to contain PORTAGE_TMPDIR paths" - abort="yes" - fi - done - [[ ${abort} == "yes" ]] && die "soiled libtool library files found" - # While we generate the NEEDED files, check that we don't get kernel # traps at runtime because of broken install_names on Darwin. rm -f "${T}"/.install_name_check_failed - [[ ${CHOST} == *-darwin* ]] && scanmacho -qyRF '%a;%p;%S;%n' "${D}" | { while IFS= read l ; do + scanmacho -qyRF '%a;%p;%S;%n' "${D}" | { while IFS= read l ; do arch=${l%%;*}; l=${l#*;} obj="/${l%%;*}"; l=${l#*;} install_name=${l%%;*}; l=${l#*;} @@ -808,125 +743,239 @@ install_qa_check() { hasq allow_broken_install_names ${FEATURES} || \ die "invalid install_name found, your application or library will crash at runtime" fi +} - # Evaluate misc gcc warnings - if [[ -n ${PORTAGE_LOG_FILE} && -r ${PORTAGE_LOG_FILE} ]] ; then - # In debug mode, this variable definition and corresponding grep calls - # will produce false positives if they're shown in the trace. - local reset_debug=0 - if [[ ${-/x/} != $- ]] ; then - set +x - reset_debug=1 - fi - local m msgs=( - ": warning: dereferencing type-punned pointer will break strict-aliasing rules$" - ": warning: dereferencing pointer .* does break strict-aliasing rules$" - ": warning: implicit declaration of function " - ": warning: incompatible implicit declaration of built-in function " - ": warning: is used uninitialized in this function$" # we'll ignore "may" and "might" - ": warning: comparisons like X<=Y<=Z do not have their mathematical meaning$" - ": warning: null argument where non-null required " - ) - abort="no" - i=0 - while [[ -n ${msgs[${i}]} ]] ; do - m=${msgs[$((i++))]} - # force C locale to work around slow unicode locales #160234 - f=$(LC_ALL=C grep "${m}" "${PORTAGE_LOG_FILE}") - if [[ -n ${f} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: Package has poor programming practices which may compile" - eqawarn " fine but exhibit random runtime failures." - eqawarn "${f}" - vecho -ne '\a\n' - abort="yes" - fi - done - [[ $reset_debug = 1 ]] && set -x - f=$(cat "${PORTAGE_LOG_FILE}" | \ - EPYTHON= "$PORTAGE_BIN_PATH"/check-implicit-pointer-usage.py) - if [[ -n ${f} ]] ; then +install_qa_check_pecoff() { + local _pfx_scan="readpecoff ${CHOST}" - # In the future this will be a forced "die". In preparation, - # increase the log level from "qa" to "eerror" so that people - # are aware this is a problem that must be fixed asap. + # this one uses readpecoff, which supports multiple prefix platforms! + # this is absolutely _not_ optimized for speed, and there may be plenty + # of possibilities by introducing one or the other cache! + if ! hasq binchecks ${RESTRICT}; then + # copied and adapted from the above scanelf code. + local qa_var insecure_rpath=0 tmp_quiet=${PORTAGE_QUIET} + local f x - # just warn on 32bit hosts but bail on 64bit hosts - case ${CHOST} in - alpha*|hppa64*|ia64*|powerpc64*|mips64*|sparc64*|sparcv9*|x86_64*) gentoo_bug=yes ;; - esac + # display warnings when using stricter because we die afterwards + if has stricter ${FEATURES} ; then + unset PORTAGE_QUIET + fi - abort=yes + local _exec_find_opt="-executable" + [[ ${CHOST} == *-winnt* ]] && _exec_find_opt='-name *.dll -o -name *.exe' - if [[ $gentoo_bug = yes ]] ; then - eerror - eerror "QA Notice: Package has poor programming practices which may compile" - eerror " but will almost certainly crash on 64bit architectures." - eerror - eerror "${f}" - eerror - eerror " Please file a bug about this at http://bugs.gentoo.org/" - eerror " with the maintaining herd of the package." - eerror + # Make sure we disallow insecure RUNPATH/RPATH's + # Don't want paths that point to the tree where the package was built + # (older, broken libtools would do this). Also check for null paths + # because the loader will search $PWD when it finds null paths. + + f=$( + find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | \ + while IFS=";" read arch obj soname rpath needed ; do \ + echo "${rpath}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )" > /dev/null 2>&1 \ + && echo "${obj}"; done; + ) + # Reject set*id binaries with $ORIGIN in RPATH #260331 + x=$( + find "${ED}" -type f '(' -perm -u+s -o -perm -g+s ')' -print0 | \ + xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; do \ + echo "${rpath}" | grep '$ORIGIN' > /dev/null 2>&1 && echo "${obj}"; done; + ) + if [[ -n ${f}${x} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: The following files contain insecure RUNPATH's" + eqawarn " Please file a bug about this at http://bugs.gentoo.org/" + eqawarn " with the maintaining herd of the package." + eqawarn "${f}${f:+${x:+\n}}${x}" + vecho -ne '\a\n' + if [[ -n ${x} ]] || has stricter ${FEATURES} ; then + insecure_rpath=1 + else + eqawarn "cannot automatically fix runpaths on interix platforms!" + fi + fi + + rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED + rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 + + # Save NEEDED information after removing self-contained providers + find "${ED}" -type f '(' ${_exec_find_opt} ')' -print0 | xargs -0 ${_pfx_scan} | { while IFS=';' read arch obj soname rpath needed; do + # need to strip image dir from object name. + obj="/${obj#${D}}" + if [ -z "${rpath}" -o -n "${rpath//*ORIGIN*}" ]; then + # object doesn't contain $ORIGIN in its runpath attribute + echo "${obj} ${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED + echo "${arch};${obj};${soname};${rpath};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 else + dir=${obj%/*} + # replace $ORIGIN with the dirname of the current object for the lookup + opath=$(echo :${rpath}: | sed -e "s#.*:\(.*\)\$ORIGIN\(.*\):.*#\1${dir}\2#") + sneeded=$(echo ${needed} | tr , ' ') + rneeded="" + for lib in ${sneeded}; do + found=0 + for path in ${opath//:/ }; do + [ -e "${ED}/${path}/${lib}" ] && found=1 && break + done + [ "${found}" -eq 0 ] && rneeded="${rneeded},${lib}" + done + rneeded=${rneeded:1} + if [ -n "${rneeded}" ]; then + echo "${obj} ${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED + echo "${arch};${obj};${soname};${rpath};${rneeded}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.PECOFF.1 + fi + fi + done } + + if [[ ${insecure_rpath} -eq 1 ]] ; then + die "Aborting due to serious QA concerns with RUNPATH/RPATH" + elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then + die "Aborting due to QA concerns: ${die_msg}" + fi + + local _so_ext='.so*' + + case "${CHOST}" in + *-winnt*) _so_ext=".dll" ;; # no "*" intentionally! + esac + + # Run some sanity checks on shared libraries + for d in "${ED}"lib* "${ED}"usr/lib* ; do + [[ -d "${d}" ]] || continue + f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \ + xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \ + do [[ -z "${soname}" ]] && echo "${obj}"; done) + if [[ -n ${f} ]] ; then vecho -ne '\a\n' - eqawarn "QA Notice: Package has poor programming practices which may compile" - eqawarn " but will almost certainly crash on 64bit architectures." + eqawarn "QA Notice: The following shared libraries lack a SONAME" eqawarn "${f}" vecho -ne '\a\n' + sleep 1 fi - fi - if [[ ${abort} == "yes" ]] ; then - if [[ ${gentoo_bug} == "yes" ]] ; then - die "install aborted due to" \ - "poor programming practices shown above" - else - echo "Please do not file a Gentoo bug and instead" \ - "report the above QA issues directly to the upstream" \ - "developers of this software." | fmt -w 70 | \ - while read line ; do eqawarn "${line}" ; done - eqawarn "Homepage: ${HOMEPAGE}" - hasq stricter ${FEATURES} && die "install aborted due to" \ - "poor programming practices shown above" + f=$(find "${d}" -name "lib*${_so_ext}" -print0 | \ + xargs -0 ${_pfx_scan} | while IFS=";" read arch obj soname rpath needed; \ + do [[ -z "${needed}" ]] && echo "${obj}"; done) + if [[ -n ${f} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: The following shared libraries lack NEEDED entries" + eqawarn "${f}" + vecho -ne '\a\n' + sleep 1 fi - fi - fi + done - # Compiled python objects do not belong in /usr/share (FHS violation) - # and can be a pain when upgrading python - f=$([ -d "${ED}"/usr/share ] && \ - find "${ED}"usr/share -name '*.py[co]' | sed "s:${D}:/:") - if [[ -n ${f} ]] ; then - vecho -ne '\a\n' - eqawarn "QA Notice: Precompiled python object files do not belong in /usr/share" - eqawarn "${f}" - vecho -ne '\a\n' + PORTAGE_QUIET=${tmp_quiet} fi +} - # Portage regenerates this on the installed system. - rm -f "${ED}"/usr/share/info/dir{,.gz,.bz2} +install_qa_check_xcoff() { + if ! hasq binchecks ${RESTRICT}; then + local tmp_quiet=${PORTAGE_QUIET} + local queryline deplib + local insecure_rpath_list= undefined_symbols_list= - if hasq multilib-strict ${FEATURES} && \ - [[ -x ${EPREFIX}/usr/bin/file && -x ${EPREFIX}/usr/bin/find ]] && \ - [[ -n ${MULTILIB_STRICT_DIRS} && -n ${MULTILIB_STRICT_DENY} ]] - then - local abort=no firstrun=yes - MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT} | sed -e 's:\([(|)]\):\\\1:g') - for dir in ${MULTILIB_STRICT_DIRS} ; do - [[ -d ${ED}/${dir} ]] || continue - for file in $(find ${ED}/${dir} -type f | grep -v "^${ED}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do - if file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" ; then - if [[ ${firstrun} == yes ]] ; then - echo "Files matching a file type that is not allowed:" - firstrun=no + # display warnings when using stricter because we die afterwards + if has stricter ${FEATURES} ; then + unset PORTAGE_QUIET + fi + + rm -f "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 + find "${ED}" -not -type d -exec \ + "${EPREFIX}/usr/bin/aixdll-query" '{}' FILE MEMBER FLAGS FORMAT RUNPATH DEPLIBS ';' \ + > "${T}"/needed 2>/dev/null + + # Symlinking archive libraries is not a good idea on aix, + # as there is nothing like "soname" on pure filesystem level. + # So we create a copy instead of the symlink. + local prev_FILE= + while read queryline + do + local FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS= + eval ${queryline} + + if [[ ${prev_FILE} != ${FILE} ]]; then + prev_FILE=${FILE} + if [[ -n ${MEMBER} || " ${FLAGS} " == *" SHROBJ "* ]] && [[ -h ${FILE} ]]; then + local target=$(readlink "${FILE}") + if [[ ${target} == /* ]]; then + target=${D}${target} + else + target=${FILE%/*}/${target} fi - abort=yes - echo " ${file#${ED}//}" + rm -f "${FILE}" || die "cannot prune ${FILE#${ED}}" + cp -f "${target}" "${FILE}" || die "cannot copy ${target#${ED}} to ${FILE#${ED}}" + fi + fi + done <"${T}"/needed + + prev_FILE= + while read queryline + do + local FILE= MEMBER= FLAGS= FORMAT= RUNPATH= DEPLIBS= + eval ${queryline} + + if [[ ${prev_FILE} != ${FILE} ]]; then + # Save NEEDED information for the archive library stub + echo "${FORMAT##* }${FORMAT%%-*};${FILE#${D%/}};${FILE##*/};;" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 + fi + + # Make sure we disallow insecure RUNPATH's + # Don't want paths that point to the tree where the package was built + # (older, broken libtools would do this). Also check for null paths + # because the loader will search $PWD when it finds null paths. + # And we really want absolute paths only. + if [[ -n $(echo ":${RUNPATH}:" | grep -E "(${PORTAGE_BUILDDIR}|::|:[^/])") ]]; then + insecure_rpath_list="${insecure_rpath_list}\n${FILE}" + fi + + # Although we do have runtime linking, we don't want undefined symbols. + # AIX does indicate this by needing either '.' or '..' + local needed=${FILE##*/} + for deplib in ${DEPLIBS}; do + eval deplib=${deplib} + if [[ ${deplib} == '.' || ${deplib} == '..' ]]; then + undefined_symbols_list="${undefined_symbols_list}\n${FILE}" + else + needed="${needed},${deplib}" fi done - done - [[ ${abort} == yes ]] && die "multilib-strict check failed!" + + FILE=${FILE#${D%/}} + + [[ -n ${MEMBER} ]] && MEMBER="[${MEMBER}]" + # Save NEEDED information + echo "${FORMAT##* }${FORMAT%%-*};${FILE}${MEMBER};${FILE##*/}${MEMBER};${RUNPATH};${needed}" >> "${PORTAGE_BUILDDIR}"/build-info/NEEDED.XCOFF.1 + done <"${T}"/needed + + if [[ -n ${undefined_symbols_list} ]]; then + vecho -ne '\a\n' + eqawarn "QA Notice: The following files contain undefined symbols." + eqawarn " Please file a bug about this at http://bugs.gentoo.org/" + eqawarn " with 'prefix' as the maintaining herd of the package." + eqawarn "${undefined_symbols_list}" + vecho -ne '\a\n' + fi + + if [[ -n ${insecure_rpath_list} ]] ; then + vecho -ne '\a\n' + eqawarn "QA Notice: The following files contain insecure RUNPATH's" + eqawarn " Please file a bug about this at http://bugs.gentoo.org/" + eqawarn " with 'prefix' as the maintaining herd of the package." + eqawarn "${insecure_rpath_list}" + vecho -ne '\a\n' + if [[ -n ${x} ]] || has stricter ${FEATURES} ; then + insecure_rpath=1 + fi + fi + + if [[ ${insecure_rpath} -eq 1 ]] ; then + die "Aborting due to serious QA concerns with RUNPATH/RPATH" + elif [[ -n ${die_msg} ]] && has stricter ${FEATURES} ; then + die "Aborting due to QA concerns: ${die_msg}" + fi + + PORTAGE_QUIET=${tmp_quiet} fi } -- 2.26.2