| 1 | # Copyright 1999-2006 Gentoo Foundation |
1 | # Copyright 1999-2011 Gentoo Foundation |
| 2 | # Distributed under the terms of the GNU General Public License v2 |
2 | # Distributed under the terms of the GNU General Public License v2 |
| 3 | # $Header: /var/cvsroot/gentoo-x86/eclass/pax-utils.eclass,v 1.2 2006/11/15 22:14:25 kevquinn Exp $ |
3 | # $Header: /var/cvsroot/gentoo-x86/eclass/pax-utils.eclass,v 1.15 2011/08/22 04:46:32 vapier Exp $ |
| 4 | |
4 | |
| 5 | # Author: |
5 | # @ECLASS: pax-utils.eclass |
|
|
6 | # @MAINTAINER: |
|
|
7 | # The Gentoo Linux Hardened Team <hardened@gentoo.org> |
|
|
8 | # @AUTHOR: |
| 6 | # Kevin F. Quinn <kevquinn@gentoo.org> |
9 | # Original Author: Kevin F. Quinn <kevquinn@gentoo.org> |
|
|
10 | # Modifications for bug #365825, @ ECLASS markup: Anthony G. Basile <blueness@gentoo.org> |
|
|
11 | # @BLURB: functions to provide pax markings |
|
|
12 | # @DESCRIPTION: |
|
|
13 | # This eclass provides support for manipulating PaX markings on ELF binaries, |
|
|
14 | # wrapping the use of the paxctl and scanelf utilities. It decides which to |
|
|
15 | # use depending on what is installed on the build host, preferring paxctl to |
|
|
16 | # scanelf. If paxctl is not installed, we fall back to scanelf since it is |
|
|
17 | # always present. However, currently scanelf doesn't do all that paxctl can. |
| 7 | # |
18 | # |
| 8 | # This eclass provides support for manipulating PaX markings on ELF |
19 | # To control what markings are made, set PAX_MARKINGS in /etc/make.conf to |
| 9 | # binaries, wrapping the use of the chpax and paxctl utilities. |
20 | # contain either "PT" or "none". If PAX_MARKINGS is set to "PT", and the |
|
|
21 | # necessary utility is installed, the PT_PAX_FLAGS markings will be made. If |
|
|
22 | # PAX_MARKINGS is set to "none", no markings will be made. |
| 10 | |
23 | |
| 11 | inherit eutils |
24 | inherit eutils |
| 12 | |
25 | |
| 13 | ##### pax-mark #### |
26 | # Default to PT markings. |
| 14 | # Mark a file for PaX, with the provided flags, and log it into |
27 | PAX_MARKINGS=${PAX_MARKINGS:="PT"} |
| 15 | # a PaX database. Returns non-zero if flag marking failed. |
28 | |
|
|
29 | # @FUNCTION: pax-mark |
|
|
30 | # @USAGE: <flags> {<ELF files>} |
|
|
31 | # @RETURN: Shell true if we succeed, shell false otherwise |
|
|
32 | # @DESCRIPTION: |
|
|
33 | # Marks <ELF files> with provided PaX <flags> |
| 16 | # |
34 | # |
| 17 | # If paxctl is installed, but not chpax, then the legacy |
35 | # Flags are passed directly to the utilities unchanged. Possible flags at the |
| 18 | # EI flags (which are not strip-safe) will not be set. |
36 | # time of writing, taken from /sbin/paxctl, are: |
| 19 | # If neither are installed, falls back to scanelf (which |
37 | # |
| 20 | # is always present, but currently doesn't quite do all |
38 | # p: disable PAGEEXEC P: enable PAGEEXEC |
| 21 | # that paxctl can do). |
39 | # e: disable EMUTRMAP E: enable EMUTRMAP |
| 22 | |
40 | # m: disable MPROTECT M: enable MPROTECT |
|
|
41 | # r: disable RANDMMAP R: enable RANDMMAP |
|
|
42 | # s: disable SEGMEXEC S: enable SEGMEXEC |
|
|
43 | # |
|
|
44 | # Default flags are 'PeMRS', which are the most restrictive settings. Refer |
|
|
45 | # to http://pax.grsecurity.net/ for details on what these flags are all about. |
|
|
46 | # Do not use the obsolete flag 'x'/'X' which has been deprecated. |
|
|
47 | # |
|
|
48 | # Please confirm any relaxation of restrictions with the Gentoo Hardened team. |
|
|
49 | # Either ask on the gentoo-hardened mailing list, or CC/assign hardened@g.o on |
|
|
50 | # the bug report. |
| 23 | pax-mark() { |
51 | pax-mark() { |
| 24 | local flags fail=0 |
52 | local f flags fail=0 failures="" zero_load_alignment |
|
|
53 | # Ignore '-' characters - in particular so that it doesn't matter if |
|
|
54 | # the caller prefixes with - |
| 25 | flags=$1 |
55 | flags=${1//-} |
| 26 | shift |
56 | shift |
| 27 | if [[ -x /sbin/chpax ]]; then |
57 | # Try paxctl, then scanelf. paxctl is preferred. |
| 28 | einfo "Legacy EI PaX marking $* with ${flags}" |
58 | if type -p paxctl > /dev/null && has PT ${PAX_MARKINGS}; then |
| 29 | /sbin/chpax -${flags} $* || fail=1 |
59 | # Try paxctl, the upstream supported tool. |
|
|
60 | elog "PT PaX marking -${flags}" |
|
|
61 | _pax_list_files elog "$@" |
|
|
62 | for f in "$@"; do |
|
|
63 | # First, try modifying the existing PAX_FLAGS header |
|
|
64 | paxctl -q${flags} "${f}" && continue |
|
|
65 | # Second, try stealing the (unused under PaX) PT_GNU_STACK header |
|
|
66 | paxctl -qc${flags} "${f}" && continue |
|
|
67 | # Third, try pulling the base down a page, to create space and |
|
|
68 | # insert a PT_GNU_STACK header (works on ET_EXEC) |
|
|
69 | paxctl -qC${flags} "${f}" && continue |
|
|
70 | # |
|
|
71 | # prelink is masked on hardened so we wont use this method. |
|
|
72 | # We're working on a new utiity to try to do the same safely. See |
|
|
73 | # http://git.overlays.gentoo.org/gitweb/?p=proj/elfix.git;a=summary |
|
|
74 | # |
|
|
75 | # Fourth - check if it loads to 0 (probably an ET_DYN) and if so, |
|
|
76 | # try rebasing with prelink first to give paxctl some space to |
|
|
77 | # grow downwards into. |
|
|
78 | #if type -p objdump > /dev/null && type -p prelink > /dev/null; then |
|
|
79 | # zero_load_alignment=$(objdump -p "${f}" | \ |
|
|
80 | # grep -E '^[[:space:]]*LOAD[[:space:]]*off[[:space:]]*0x0+[[:space:]]' | \ |
|
|
81 | # sed -e 's/.*align\(.*\)/\1/') |
|
|
82 | # if [[ ${zero_load_alignment} != "" ]]; then |
|
|
83 | # prelink -r $(( 2*(${zero_load_alignment}) )) && |
|
|
84 | # paxctl -qC${flags} "${f}" && continue |
|
|
85 | # fi |
|
|
86 | #fi |
|
|
87 | fail=1 |
|
|
88 | failures="${failures} ${f}" |
|
|
89 | done |
|
|
90 | elif type -p scanelf > /dev/null && [[ ${PAX_MARKINGS} != "none" ]]; then |
|
|
91 | # Try scanelf, the Gentoo swiss-army knife ELF utility |
|
|
92 | # Currently this sets PT if it can, no option to control what it does. |
|
|
93 | elog "Fallback PaX marking -${flags}" |
|
|
94 | _pax_list_files elog "$@" |
|
|
95 | scanelf -Xxz ${flags} "$@" |
|
|
96 | elif [[ ${PAX_MARKINGS} != "none" ]]; then |
|
|
97 | # Out of options! |
|
|
98 | failures="$*" |
|
|
99 | fail=1 |
| 30 | fi |
100 | fi |
| 31 | if [[ -x /sbin/paxctl ]]; then |
101 | if [[ ${fail} == 1 ]]; then |
| 32 | einfo "PT PaX marking $* with ${flags}" |
102 | ewarn "Failed to set PaX markings -${flags} for:" |
| 33 | /sbin/paxctl -${flags} $* || |
103 | _pax_list_files ewarn ${failures} |
| 34 | /sbin/paxctl -c${flags} $* || |
104 | ewarn "Executables may be killed by PaX kernels." |
| 35 | /sbin/paxctl -C${flags} $* || fail=1 |
|
|
| 36 | elif [[ -x /usr/bin/scanelf ]]; then |
|
|
| 37 | einfo "Fallback PaX marking $* with ${flags}" |
|
|
| 38 | /usr/bin/scanelf -Xxz ${flags} $* |
|
|
| 39 | else |
|
|
| 40 | ewarn "Failed to set PaX markings ${flags} for files $*. Executables may be killed by PaX kernels." |
|
|
| 41 | fail=1 |
|
|
| 42 | fi |
105 | fi |
| 43 | return ${fail} |
106 | return ${fail} |
| 44 | } |
107 | } |
| 45 | |
108 | |
| 46 | ##### host-is-pax |
109 | # @FUNCTION: list-paxables |
| 47 | # Indicates whether the build machine has PaX or not; intended for use |
110 | # @USAGE: {<files>} |
| 48 | # where the build process must be modified conditionally in order to satisfy PaX. |
111 | # @RETURN: Subset of {<files>} which are ELF executables or shared objects |
|
|
112 | # @DESCRIPTION: |
|
|
113 | # Print to stdout all of the <files> that are suitable to have PaX flag |
|
|
114 | # markings, i.e., filter out the ELF executables or shared objects from a list |
|
|
115 | # of files. This is useful for passing wild-card lists to pax-mark, although |
|
|
116 | # in general it is preferable for ebuilds to list precisely which ELFS are to |
|
|
117 | # be marked. Often not all the ELF installed by a package need remarking. |
|
|
118 | # @EXAMPLE: |
|
|
119 | # pax-mark -m $(list-paxables ${S}/{,usr/}bin/*) |
|
|
120 | list-paxables() { |
|
|
121 | file "$@" 2> /dev/null | grep -E 'ELF.*(executable|shared object)' | sed -e 's/: .*$//' |
|
|
122 | } |
|
|
123 | |
|
|
124 | # @FUNCTION: host-is-pax |
|
|
125 | # @RETURN: Shell true if the build process is PaX enabled, shell false otherwise |
|
|
126 | # @DESCRIPTION: |
|
|
127 | # This is intended for use where the build process must be modified conditionally |
|
|
128 | # depending on whether the host is PaX enabled or not. It is not intedened to |
|
|
129 | # determine whether the final binaries need PaX markings. Note: if procfs is |
|
|
130 | # not mounted on /proc, this returns shell false (e.g. Gentoo/FBSD). |
| 49 | host-is-pax() { |
131 | host-is-pax() { |
| 50 | # We need procfs to work this out. PaX is only available on Linux, |
|
|
| 51 | # so result is always false on non-linux machines (e.g. Gentoo/*BSD) |
|
|
| 52 | [[ -e /proc/self/status ]] || return 1 |
|
|
| 53 | grep ^PaX: /proc/self/status > /dev/null |
132 | grep -qs ^PaX: /proc/self/status |
| 54 | return $? |
|
|
| 55 | } |
133 | } |
|
|
134 | |
|
|
135 | |
|
|
136 | # INTERNAL FUNCTIONS |
|
|
137 | # ------------------ |
|
|
138 | # |
|
|
139 | # These functions are for use internally by the eclass - do not use |
|
|
140 | # them elsewhere as they are not supported (i.e. they may be removed |
|
|
141 | # or their function may change arbitratily). |
|
|
142 | |
|
|
143 | # Display a list of things, one per line, indented a bit, using the |
|
|
144 | # display command in $1. |
|
|
145 | _pax_list_files() { |
|
|
146 | local f cmd |
|
|
147 | cmd=$1 |
|
|
148 | shift |
|
|
149 | for f in "$@"; do |
|
|
150 | ${cmd} " ${f}" |
|
|
151 | done |
|
|
152 | } |
|
|
153 | |