From ec7736adf6611370d7afaf3be0c1e03eda11d13a Mon Sep 17 00:00:00 2001 From: Zac Medico Date: Thu, 9 Mar 2006 21:51:40 +0000 Subject: Move the install phase qa checks from ebuild.sh to misc-functions.sh and add the necessary support to spawnebuild. svn path=/main/trunk/; revision=2837 --- bin/ebuild.sh | 256 +------------------------------------------------ bin/misc-functions.sh | 259 ++++++++++++++++++++++++++++++++++++++++++++++++++ pym/portage.py | 10 +- 3 files changed, 269 insertions(+), 256 deletions(-) diff --git a/bin/ebuild.sh b/bin/ebuild.sh index b6b7fa533..070b118c9 100755 --- a/bin/ebuild.sh +++ b/bin/ebuild.sh @@ -1022,6 +1022,7 @@ PORTAGE_INST_UID="0" PORTAGE_INST_GID="0" dyn_install() { + [ -z "$PORTAGE_BUILDDIR" ] && die "${FUNCNAME}: PORTAGE_BUILDDIR is unset" trap "abort_install" SIGINT SIGQUIT [ "$(type -t pre_src_install)" == "function" ] && pre_src_install rm -rf "${PORTAGE_BUILDDIR}/image" @@ -1038,261 +1039,6 @@ dyn_install() { #our libtool to create problematic .la files export PWORKDIR="$WORKDIR" src_install - #|| abort_install "fail" - prepall - cd "${D}" - - declare -i UNSAFE=0 - for i in $(find "${D}/" -type f -perm -2002); do - ((UNSAFE++)) - echo "UNSAFE SetGID: $i" - chmod -s,o-w "$i" - done - for i in $(find "${D}/" -type f -perm -4002); do - ((UNSAFE++)) - echo "UNSAFE SetUID: $i" - chmod -s,o-w "$i" - done - - # Now we look for all world writable files. - for i in $(find "${D}/" -type f -perm -2); do - echo -ne '\a' - echo "QA Security Notice:" - echo "- ${i:${#D}:${#i}} will be a world writable file." - echo "- This may or may not be a security problem, most of the time it is one." - echo "- Please double check that $PF really needs a world writeable bit and file bugs accordingly." - sleep 1 - done - - if type -p scanelf > /dev/null ; then - local qa_var insecure_rpath=0 - - # 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=$(scanelf -qyRF '%r %p' "${D}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )") - if [[ -n ${f} ]] ; then - echo -ne '\a\n' - echo "QA Notice: the following files contain insecure RUNPATH's" - echo " Please file a bug about this at http://bugs.gentoo.org/" - echo " with the maintaining herd of the package." - echo " Summary: $CATEGORY/$PN: insecure RPATH ${f}" - echo "${f}" - echo -ne '\a\n' - if has stricter ${FEATURES}; then - insecure_rpath=1 - else - echo "Auto fixing rpaths for ${f}" - TMPDIR=${PORTAGE_BUILDDIR} scanelf -BXr ${f} -o /dev/null - fi - fi - - # Check for setid binaries but are not built with BIND_NOW - f=$(scanelf -qyRF '%b %p' "${D}") - if [[ -n ${f} ]] ; then - echo -ne '\a\n' - echo "QA Notice: the following files are setXid, dyn linked, and using lazy bindings" - echo " This combination is generally discouraged. Try re-emerging the package:" - echo " LDFLAGS='-Wl,-z,now' emerge ${PN}" - echo "${f}" - echo -ne '\a\n' - die_msg="${die_msg} setXid lazy bindings," - sleep 1 - fi - - # TEXTREL's are baaaaaaaad - # Allow devs to mark things as ignorable ... e.g. things that are - # binary-only and upstream isn't cooperating (nvidia-glx) ... we - # allow ebuild authors to set QA_TEXTRELS_arch and QA_TEXTRELS ... - # the former overrides the latter ... regexes allowed ! :) - qa_var="QA_TEXTRELS_${ARCH}" - [[ -n ${!qa_var} ]] && QA_TEXTRELS=${!qa_var} - [[ -n ${QA_STRICT_TEXTRELS} ]] && QA_TEXTRELS="" - f=$(scanelf -qyRF '%t %p' "${D}" | grep -v ' usr/lib/debug/' | \ - gawk ' - BEGIN { split("'"${QA_TEXTRELS}"'", ignore); } - { for (idx in ignore) - if ($NF ~ "^"ignore[idx]"$") - next; - print; - }') - if [[ -n ${f} ]] ; then - scanelf -qyRF '%T %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-textrel.log - echo -ne '\a\n' - echo "QA Notice: the following files contain runtime text relocations" - echo " Text relocations force the dynamic linker to perform extra" - echo " work at startup, waste system resources, and may pose a security" - echo " risk. On some architectures, the code may not even function" - echo " properly, if at all." - echo " For more information, see http://hardened.gentoo.org/pic-fix-guide.xml" - echo " Please include this file in your report:" - echo " ${T}/scanelf-textrel.log" - echo "${f}" - echo -ne '\a\n' - die_msg="${die_msg} textrels," - sleep 1 - fi - - # Also, executable stacks only matter on linux (and just glibc atm ...) - case ${CTARGET:-${CHOST}} in - *-linux-gnu*) - # Check for files with executable stacks, but only on arches which - # are supported at the moment. Keep this list in sync with - # http://hardened.gentoo.org/gnu-stack.xml (Arch Status) - case ${CTARGET:-${CHOST}} in - i?86*|ia64*|m68k*|powerpc64*|s390*|x86_64*) - # Allow devs to mark things as ignorable ... e.g. things - # that are binary-only and upstream isn't cooperating ... - # we allow ebuild authors to set QA_EXECSTACK_arch and - # QA_EXECSTACK ... the former overrides the latter ... - # regexes allowed ! :) - - qa_var="QA_EXECSTACK_${ARCH}" - [[ -n ${!qa_var} ]] && QA_EXECSTACK=${!qa_var} - [[ -n ${QA_STRICT_EXECSTACK} ]] && QA_EXECSTACK="" - f=$(scanelf -qyRF '%e %p' "${D}" | grep -v ' usr/lib/debug/' | \ - gawk ' - BEGIN { split("'"${QA_EXECSTACK}"'", ignore); } - { for (idx in ignore) - if ($NF ~ "^"ignore[idx]"$") - next; - print; - }') - ;; - *) f="" ;; - esac - ;; - esac - if [[ -n ${f} ]] ; then - # One more pass to help devs track down the source - scanelf -qyRF '%e %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-execstack.log - echo -ne '\a\n' - echo "QA Notice: the following files contain executable stacks" - echo " Files with executable stacks will not work properly (or at all!)" - echo " on some architectures/operating systems. A bug should be filed" - echo " at http://bugs.gentoo.org/ to make sure the file is fixed." - echo " For more information, see http://hardened.gentoo.org/gnu-stack.xml" - echo " Please include this file in your report:" - echo " ${T}/scanelf-execstack.log" - echo "${f}" - echo -ne '\a\n' - die_msg="${die_msg} execstacks" - sleep 1 - fi - - # Save NEEDED information - scanelf -qyRF '%p %n' "${D}" | sed -e 's:^:/:' > "${PORTAGE_BUILDDIR}"/build-info/NEEDED - - if [[ ${insecure_rpath} -eq 1 ]] ; then - die "Aborting due to serious QA concerns with RUNPATH/RPATH" - elif [[ ${die_msg} != "" ]] && has stricter ${FEATURES} && ! has stricter ${RESTRICT} ; then - die "Aborting due to QA concerns: ${die_msg}" - fi - fi - - if [[ ${UNSAFE} > 0 ]] ; then - die "There are ${UNSAFE} unsafe files. Portage will not install them." - fi - - if [[ -d ${D}/${D} ]] ; then - declare -i INSTALLTOD=0 - for i in $(find "${D}/${D}/"); do - echo "QA Notice: /${i##${D}/${D}} installed in \${D}/\${D}" - ((INSTALLTOD++)) - done - die "Aborting due to QA concerns: ${INSTALLTOD} files installed in ${D}/${D}" - unset INSTALLTOD - fi - - # dumps perms to stdout. if error, no perms dumped. - function stat_perms() { - local f - # only define do_stat if it hasn't been already - if ! type -p do_stat &> /dev/null; then - if ! type -p stat &>/dev/null; then - do_stat() { - # Generic version -- Octal result - python -c "import os,stat; print '%o' % os.stat('$1')[stat.ST_MODE]" - } - else - if [ "${USERLAND}" == "BSD" ] || [ "${USERLAND}" == "Darwin" ]; then - do_stat() { - # BSD version -- Octal result - $(type -p stat) -f '%p' "$1" - } - else - do_stat() { - # Linux version -- Hex result converted to Octal - f=$($(type -p stat) -c '%f' "$1") || return $? - printf '%o' "0x$f" - } - fi - fi - fi - - f=$(do_stat "$@") || return - f="${f:2:4}" - echo $f - } - - local file s - local count=0 - find "${D}/" -user portage | while read file; do - count=$(( $count + 1 )) - if [ -L "${file}" ]; then - lchown ${PORTAGE_INST_UID} "${file}" - else - s=$(stat_perms "$file") - if [ -z "${s}" ]; then - ewarn "failed stat_perm'ing $file. User intervention during install isn't wise..." - continue - fi - chown ${PORTAGE_INST_UID} "$file" - chmod "$s" "$file" - fi - done - if (( $count > 0 )); then - ewarn "$count files were installed with user portage!" - fi - - count=0 - find "${D}/" -group portage | while read file; do - count=$(( $count + 1 )) - if [ -L "${file}" ]; then - lchgrp ${PORTAGE_INST_GID} "${file}" - else - s=$(stat_perms "$file") - if [ -z "${s}" ]; then - echo "failed stat_perm'ing '$file' . User intervention during install isn't wise..." - continue - fi - chgrp ${PORTAGE_INST_GID} "$file" - chmod "$s" "$file" - fi - done - if (( $count > 0 )); then - ewarn "$count files were installed with group portage!" - fi - - unset -f stat_perms - - # Portage regenerates this on the installed system. - if [ -f "${D}/usr/share/info/dir.gz" ]; then - rm -f "${D}/usr/share/info/dir.gz" - fi - - if hasq multilib-strict ${FEATURES} && [ -x /usr/bin/file -a -x /usr/bin/find -a \ - -n "${MULTILIB_STRICT_DIRS}" -a -n "${MULTILIB_STRICT_DENY}" ]; then - MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT:-"(perl5|gcc|gcc-lib|debug|portage)"} | sed -e 's:\([(|)]\):\\\1:g') - for dir in ${MULTILIB_STRICT_DIRS}; do - [ -d "${D}/${dir}" ] || continue - for file in $(find ${D}/${dir} -type f | grep -v "^${D}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do - file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" && die "File ${file} matches a file type that is not allowed in ${dir}" - done - done - fi - touch "${PORTAGE_BUILDDIR}/.installed" echo ">>> Completed installing ${PF} into ${D}" echo diff --git a/bin/misc-functions.sh b/bin/misc-functions.sh index 605c4a8dd..88ae29f87 100644 --- a/bin/misc-functions.sh +++ b/bin/misc-functions.sh @@ -16,6 +16,265 @@ MISC_FUNCTIONS_ARGS="$@" shift $# source /usr/lib/portage/bin/ebuild.sh +install_qa_check() { + + prepall + cd "${D}" + + declare -i UNSAFE=0 + for i in $(find "${D}/" -type f -perm -2002); do + ((UNSAFE++)) + echo "UNSAFE SetGID: $i" + chmod -s,o-w "$i" + done + for i in $(find "${D}/" -type f -perm -4002); do + ((UNSAFE++)) + echo "UNSAFE SetUID: $i" + chmod -s,o-w "$i" + done + + # Now we look for all world writable files. + for i in $(find "${D}/" -type f -perm -2); do + echo -ne '\a' + echo "QA Security Notice:" + echo "- ${i:${#D}:${#i}} will be a world writable file." + echo "- This may or may not be a security problem, most of the time it is one." + echo "- Please double check that $PF really needs a world writeable bit and file bugs accordingly." + sleep 1 + done + + if type -p scanelf > /dev/null ; then + local qa_var insecure_rpath=0 + + # 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=$(scanelf -qyRF '%r %p' "${D}" | grep -E "(${PORTAGE_BUILDDIR}|: |::|^:|^ )") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files contain insecure RUNPATH's" + echo " Please file a bug about this at http://bugs.gentoo.org/" + echo " with the maintaining herd of the package." + echo " Summary: $CATEGORY/$PN: insecure RPATH ${f}" + echo "${f}" + echo -ne '\a\n' + if has stricter ${FEATURES}; then + insecure_rpath=1 + else + echo "Auto fixing rpaths for ${f}" + TMPDIR=${PORTAGE_BUILDDIR} scanelf -BXr ${f} -o /dev/null + fi + fi + + # Check for setid binaries but are not built with BIND_NOW + f=$(scanelf -qyRF '%b %p' "${D}") + if [[ -n ${f} ]] ; then + echo -ne '\a\n' + echo "QA Notice: the following files are setXid, dyn linked, and using lazy bindings" + echo " This combination is generally discouraged. Try re-emerging the package:" + echo " LDFLAGS='-Wl,-z,now' emerge ${PN}" + echo "${f}" + echo -ne '\a\n' + die_msg="${die_msg} setXid lazy bindings," + sleep 1 + fi + + # TEXTREL's are baaaaaaaad + # Allow devs to mark things as ignorable ... e.g. things that are + # binary-only and upstream isn't cooperating (nvidia-glx) ... we + # allow ebuild authors to set QA_TEXTRELS_arch and QA_TEXTRELS ... + # the former overrides the latter ... regexes allowed ! :) + qa_var="QA_TEXTRELS_${ARCH}" + [[ -n ${!qa_var} ]] && QA_TEXTRELS=${!qa_var} + [[ -n ${QA_STRICT_TEXTRELS} ]] && QA_TEXTRELS="" + f=$(scanelf -qyRF '%t %p' "${D}" | grep -v ' usr/lib/debug/' | \ + gawk ' + BEGIN { split("'"${QA_TEXTRELS}"'", ignore); } + { for (idx in ignore) + if ($NF ~ "^"ignore[idx]"$") + next; + print; + }') + if [[ -n ${f} ]] ; then + scanelf -qyRF '%T %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-textrel.log + echo -ne '\a\n' + echo "QA Notice: the following files contain runtime text relocations" + echo " Text relocations force the dynamic linker to perform extra" + echo " work at startup, waste system resources, and may pose a security" + echo " risk. On some architectures, the code may not even function" + echo " properly, if at all." + echo " For more information, see http://hardened.gentoo.org/pic-fix-guide.xml" + echo " Please include this file in your report:" + echo " ${T}/scanelf-textrel.log" + echo "${f}" + echo -ne '\a\n' + die_msg="${die_msg} textrels," + sleep 1 + fi + + # Also, executable stacks only matter on linux (and just glibc atm ...) + case ${CTARGET:-${CHOST}} in + *-linux-gnu*) + # Check for files with executable stacks, but only on arches which + # are supported at the moment. Keep this list in sync with + # http://hardened.gentoo.org/gnu-stack.xml (Arch Status) + case ${CTARGET:-${CHOST}} in + i?86*|ia64*|m68k*|powerpc64*|s390*|x86_64*) + # Allow devs to mark things as ignorable ... e.g. things + # that are binary-only and upstream isn't cooperating ... + # we allow ebuild authors to set QA_EXECSTACK_arch and + # QA_EXECSTACK ... the former overrides the latter ... + # regexes allowed ! :) + + qa_var="QA_EXECSTACK_${ARCH}" + [[ -n ${!qa_var} ]] && QA_EXECSTACK=${!qa_var} + [[ -n ${QA_STRICT_EXECSTACK} ]] && QA_EXECSTACK="" + f=$(scanelf -qyRF '%e %p' "${D}" | grep -v ' usr/lib/debug/' | \ + gawk ' + BEGIN { split("'"${QA_EXECSTACK}"'", ignore); } + { for (idx in ignore) + if ($NF ~ "^"ignore[idx]"$") + next; + print; + }') + ;; + *) f="" ;; + esac + ;; + esac + if [[ -n ${f} ]] ; then + # One more pass to help devs track down the source + scanelf -qyRF '%e %p' "${PORTAGE_BUILDDIR}"/ &> "${T}"/scanelf-execstack.log + echo -ne '\a\n' + echo "QA Notice: the following files contain executable stacks" + echo " Files with executable stacks will not work properly (or at all!)" + echo " on some architectures/operating systems. A bug should be filed" + echo " at http://bugs.gentoo.org/ to make sure the file is fixed." + echo " For more information, see http://hardened.gentoo.org/gnu-stack.xml" + echo " Please include this file in your report:" + echo " ${T}/scanelf-execstack.log" + echo "${f}" + echo -ne '\a\n' + die_msg="${die_msg} execstacks" + sleep 1 + fi + + # Save NEEDED information + scanelf -qyRF '%p %n' "${D}" | sed -e 's:^:/:' > "${PORTAGE_BUILDDIR}"/build-info/NEEDED + + if [[ ${insecure_rpath} -eq 1 ]] ; then + die "Aborting due to serious QA concerns with RUNPATH/RPATH" + elif [[ ${die_msg} != "" ]] && has stricter ${FEATURES} && ! has stricter ${RESTRICT} ; then + die "Aborting due to QA concerns: ${die_msg}" + fi + fi + + if [[ ${UNSAFE} > 0 ]] ; then + die "There are ${UNSAFE} unsafe files. Portage will not install them." + fi + + if [[ -d ${D}/${D} ]] ; then + declare -i INSTALLTOD=0 + for i in $(find "${D}/${D}/"); do + echo "QA Notice: /${i##${D}/${D}} installed in \${D}/\${D}" + ((INSTALLTOD++)) + done + die "Aborting due to QA concerns: ${INSTALLTOD} files installed in ${D}/${D}" + unset INSTALLTOD + fi + + # dumps perms to stdout. if error, no perms dumped. + function stat_perms() { + local f + # only define do_stat if it hasn't been already + if ! type -p do_stat &> /dev/null; then + if ! type -p stat &>/dev/null; then + do_stat() { + # Generic version -- Octal result + python -c "import os,stat; print '%o' % os.stat('$1')[stat.ST_MODE]" + } + else + if [ "${USERLAND}" == "BSD" ] || [ "${USERLAND}" == "Darwin" ]; then + do_stat() { + # BSD version -- Octal result + $(type -p stat) -f '%p' "$1" + } + else + do_stat() { + # Linux version -- Hex result converted to Octal + f=$($(type -p stat) -c '%f' "$1") || return $? + printf '%o' "0x$f" + } + fi + fi + fi + + f=$(do_stat "$@") || return + f="${f:2:4}" + echo $f + } + + local file s + local count=0 + find "${D}/" -user portage | while read file; do + count=$(( $count + 1 )) + if [ -L "${file}" ]; then + lchown ${PORTAGE_INST_UID} "${file}" + else + s=$(stat_perms "$file") + if [ -z "${s}" ]; then + ewarn "failed stat_perm'ing $file. User intervention during install isn't wise..." + continue + fi + chown ${PORTAGE_INST_UID} "$file" + chmod "$s" "$file" + fi + done + if (( $count > 0 )); then + ewarn "$count files were installed with user portage!" + fi + + count=0 + find "${D}/" -group portage | while read file; do + count=$(( $count + 1 )) + if [ -L "${file}" ]; then + lchgrp ${PORTAGE_INST_GID} "${file}" + else + s=$(stat_perms "$file") + if [ -z "${s}" ]; then + echo "failed stat_perm'ing '$file' . User intervention during install isn't wise..." + continue + fi + chgrp ${PORTAGE_INST_GID} "$file" + chmod "$s" "$file" + fi + done + if (( $count > 0 )); then + ewarn "$count files were installed with group portage!" + fi + + unset -f stat_perms + + # Portage regenerates this on the installed system. + if [ -f "${D}/usr/share/info/dir.gz" ]; then + rm -f "${D}/usr/share/info/dir.gz" + fi + + if hasq multilib-strict ${FEATURES} && [ -x /usr/bin/file -a -x /usr/bin/find -a \ + -n "${MULTILIB_STRICT_DIRS}" -a -n "${MULTILIB_STRICT_DENY}" ]; then + MULTILIB_STRICT_EXEMPT=$(echo ${MULTILIB_STRICT_EXEMPT:-"(perl5|gcc|gcc-lib|debug|portage)"} | sed -e 's:\([(|)]\):\\\1:g') + for dir in ${MULTILIB_STRICT_DIRS}; do + [ -d "${D}/${dir}" ] || continue + for file in $(find ${D}/${dir} -type f | grep -v "^${D}/${dir}/${MULTILIB_STRICT_EXEMPT}"); do + file ${file} | egrep -q "${MULTILIB_STRICT_DENY}" && die "File ${file} matches a file type that is not allowed in ${dir}" + done + done + fi + +} + + install_mask() { local root="$1" shift diff --git a/pym/portage.py b/pym/portage.py index 07b583b1f..5fc70a7de 100644 --- a/pym/portage.py +++ b/pym/portage.py @@ -2373,10 +2373,18 @@ def spawnebuild(mydo,actionmap,mysettings,debug,alwaysdep=0,logfile=None): mycommand = MISC_SH_BINARY + " dyn_" + mydo else: mycommand = EBUILD_SH_BINARY + " " + mydo - return spawn(mycommand, mysettings, debug=debug, + phase_retval = spawn(mycommand, mysettings, debug=debug, droppriv=actionmap[mydo]["args"][0], free=actionmap[mydo]["args"][1], sesandbox=actionmap[mydo]["args"][2], logfile=logfile) + if phase_retval == os.EX_OK: + if mydo == "install": + mycommand = " ".join([MISC_SH_BINARY, "install_qa_check"]) + return spawn(mycommand, mysettings, debug=debug, + droppriv=actionmap[mydo]["args"][0], + free=actionmap[mydo]["args"][1], + sesandbox=actionmap[mydo]["args"][2], logfile=logfile) + return phase_retval # chunked out deps for each phase, so that ebuild binary can use it # to collapse targets down. -- cgit v1.2.3-1-g7c22