# 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
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
}
+