fix bugs, implement suggestions from vapier
authorKevin F. Quinn <kevquinn@gentoo.org>
Sat, 2 Dec 2006 11:33:04 +0000 (11:33 +0000)
committerKevin F. Quinn <kevquinn@gentoo.org>
Sat, 2 Dec 2006 11:33:04 +0000 (11:33 +0000)
eclass/pax-utils.eclass

index d04ae8d2ced5aba2cf73c419c1183e237a85b5cc..b5ab1506c21ca035e07a15b796e1b1e2d0f2b7c8 100644 (file)
 # Copyright 1999-2006 Gentoo Foundation
 # Distributed under the terms of the GNU General Public License v2
-# $Header: /var/cvsroot/gentoo-x86/eclass/pax-utils.eclass,v 1.3 2006/11/24 15:11:55 kevquinn Exp $
+# $Header: /var/cvsroot/gentoo-x86/eclass/pax-utils.eclass,v 1.4 2006/12/02 11:33:04 kevquinn Exp $
 
 # Author:
 #      Kevin F. Quinn <kevquinn@gentoo.org>
 #
 # This eclass provides support for manipulating PaX markings on ELF
-# binaries, wrapping the use of the chpax and paxctl utilities.
+# binaries, wrapping the use of the chpaxi, paxctl and scanelf utilities.
+# Currently it decides which to use depending on what is installed on the
+# build host; this may change in the future to use a control variable
+# (which would also mean modifying DEPEND to bring in sys-apps/paxctl etc).
+#
+#
+# CONTROL
+# -------
+#
+# To control what markings are set, assign PAX_MARKINGS in
+# /etc/make.conf to contain the strings "EI" and/or "PT".
+# If EI is present in PAX_MARKINGS (and the chpax utility
+# is present), the legacy 'chpax' style markings will be
+# set.  If PT is present in PAX_MARKINGS (and the paxctl
+# utility is present), the 'paxctl' markings will be set.
+# Default is to try to do both.  Set it to "NONE" to prevent
+# any markings being made.
+#
+#
+# PROVIDED FUNCTIONS
+# ------------------
+#
+#### pax-mark <flags> {<ELF files>}
+# Marks files <files> with provided PaX flags <flags>
+#
+# Please confirm any relaxation of restrictions with the
+# Gentoo Hardened team; either ask on the gentoo-hardened
+# mailing list, or CC/assign hardened@g.o on a bug.
+#
+# Flags are passed directly to the utilities unchanged.  Possible
+# flags at the time of writing, taken from /sbin/paxctl, are:
+#
+#      p: disable PAGEEXEC             P: enable PAGEEXEC
+#      e: disable EMUTRMAP             E: enable EMUTRMAP
+#      m: disable MPROTECT             M: enable MPROTECT
+#      r: disable RANDMMAP             R: enable RANDMMAP
+#      s: disable SEGMEXEC             S: enable SEGMEXEC
+#
+# Default flags are 'PeMRS', which are the most restrictive
+# settings.  Refer to http://pax.grsecurity.net/ for details
+# on what these flags are all about.  There is an obsolete
+# flag 'x'/'X' which has been removed from PaX.
+#
+# If chpax is not installed, the legacy EI flags (which are
+# not strip-safe, and strictly speaking violate the ELF spec)
+# will not be set.  If paxctl is not installed, it falls back
+# to scanelf.  scanelf is always present, but currently doesn't
+# quite do all that paxctl can do.
+# Returns fail if one or more files could not be marked.
+#
+#
+#### list-paxables {<files>}
+# Prints to stdout all of <files> that are suitable to having PaX
+# flags (i.e. filter to just ELF files).  Useful for passing wild-card
+# lists of files to pax-mark, although in general it is preferable
+# for ebuilds to list precisely which executables are to be marked.
+# Use like:
+#     pax-mark -m $(list-paxables ${S}/{,usr/}bin/*)
+#
+#
+#### host-is-pax
+# Returns true if the host has a PaX-enabled kernel, false otherwise.
+# Intended for use where the build process must be modified conditionally
+# in order to satisfy PaX.  Note; it is _not_ intended to indicate
+# whether the final executables should satisfy PaX - executables should
+# always be marked appropriately even if they're only going to be
+# installed on a non-PaX system.
 
 inherit eutils
 
-##### pax-mark ####
-# Mark a file for PaX, with the provided flags, and log it into
-# a PaX database.  Returns non-zero if flag marking failed.
-#
-# If paxctl is installed, but not chpax, then the legacy
-# EI flags (which are not strip-safe) will not be set.
-# If neither are installed, falls back to scanelf (which
-# is always present, but currently doesn't quite do all
-# that paxctl can do).
-_pax_list_files() {
-       local m cmd
-       m=$1 ; shift
-       for f in $*; do
-               ${cmd} "  ${f}"
-       done
-}
+# Default to both EI and PT markings.
+PAX_MARKINGS=${PAX_MARKINGS:="EI PT"}
 
+# pax-mark <flags> {<ELF files>}
 pax-mark() {
        local f flags fail=0 failures=""
+       # Ignore '-' characters - in particular so that it doesn't matter if
+       # the caller prefixes with -
        flags=${1//-}
        shift
-       if [[ -x /sbin/chpax ]]; then
+       # Try chpax, for (deprecated) EI legacy marking.
+       if type -p chpax > /dev/null && hasq EI ${PAX_MARKINGS}; then
                einfo "Legacy EI PaX marking -${flags}"
-               _pax_list_files echo $*
-               for f in $*; do
-                       /sbin/chpax -${flags} ${f} && continue
+               _pax_list_files echo "$@"
+               for f in "$@"; do
+                       /sbin/chpax -${flags} "${f}" && continue
                        fail=1
                        failures="${failures} ${f}"
                done
        fi
-       if [[ -x /sbin/paxctl ]]; then
+       # Try paxctl, then scanelf - paxctl takes precedence
+       # over scanelf.
+       if type -p paxctl > /dev/null && hasq PT ${PAX_MARKINGS}; then
+               # Try paxctl, the upstream supported tool.
                einfo "PT PaX marking -${flags}"
-               _pax_list_files echo $*
-               for f in $*; do
-                       /sbin/paxctl -q${flags} ${f} && continue
-                       /sbin/paxctl -qc${flags} ${f} && continue
-                       /sbin/paxctl -qC${flags} ${f} && continue
+               _pax_list_files echo "$@"
+               for f in "$@"; do
+                       /sbin/paxctl -q${flags} "${f}" && continue
+                       /sbin/paxctl -qc${flags} "${f}" && continue
+                       /sbin/paxctl -qC${flags} "${f}" && continue
                        fail=1
                        failures="${failures} ${f}"
                done
-       elif [[ -x /usr/bin/scanelf ]]; then
+       elif type -p scanelf > /dev/null && [[ -n ${PAX_MARKINGS} ]]; then
+               # Try scanelf, Gentoo's swiss-army knife ELF utility
+               # Currently this sets EI and PT if it can, no option to
+               # control what it does.
                einfo "Fallback PaX marking -${flags}"
-               _pax_list_files echo $*
-               /usr/bin/scanelf -Xxz ${flags} $*
+               _pax_list_files echo "$@"
+               /usr/bin/scanelf -Xxz ${flags} "$@"
        else
+               # Out of options!
                failures="$*"
                fail=1
        fi
@@ -66,13 +129,33 @@ pax-mark() {
        return ${fail}
 }
 
-##### host-is-pax
-# Indicates whether the build machine has PaX or not; intended for use
-# where the build process must be modified conditionally in order to satisfy PaX.
+# list-paxables {<files>}
+list-paxables() {
+       file "$@" 2> /dev/null | grep ELF | sed -e 's/: .*$//'
+}
+
+# host-is-pax
+# Note: if procfs is not on /proc, this returns False (e.g. Gentoo/FBSD).
 host-is-pax() {
-       # We need procfs to work this out.  PaX is only available on Linux,
-       # so result is always false on non-linux machines (e.g. Gentoo/*BSD)
-       [[ -e /proc/self/status ]] || return 1
-       grep ^PaX: /proc/self/status > /dev/null
-       return $?
+       grep -qs ^PaX: /proc/self/status
+}
+
+
+# INTERNAL FUNCTIONS
+# ------------------
+#
+# These functions are for use internally by the eclass - do not use
+# them elsewhere as they are not supported (i.e. they may be removed
+# or their function may change arbitratily).
+
+# Display a list of things, one per line, indented a bit, using the
+# display command in $1.
+_pax_list_files() {
+       local f cmd
+       cmd=$1
+       shift
+       for f in "$@"; do
+               ${cmd} "     ${f}"
+       done
 }
+