core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
2017-07-04 16:03:54 +02:00
|
|
|
# This script scans $(HOST_DIR)/{bin,sbin} for all ELF files, and checks
|
2017-07-05 14:09:49 +02:00
|
|
|
# they have an RPATH to $(HOST_DIR)/lib if they need libraries from
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
# there.
|
|
|
|
|
|
|
|
# Override the user's locale so we are sure we can parse the output of
|
|
|
|
# readelf(1) and file(1)
|
|
|
|
export LC_ALL=C
|
|
|
|
|
|
|
|
main() {
|
|
|
|
local pkg="${1}"
|
|
|
|
local hostdir="${2}"
|
|
|
|
local file ret
|
|
|
|
|
|
|
|
# Remove duplicate and trailing '/' for proper match
|
2015-12-01 23:19:06 +01:00
|
|
|
hostdir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${hostdir}" )"
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
|
|
|
|
ret=0
|
|
|
|
while read file; do
|
support/check-rpath: recognise PIE
We sanity-check the host executables that they have a correct RPATH
pointing to the host libraries.
This is currently done by looking for all files in $(HOST_DIR) that
match the 'ELF executable' pattern (a bit more complex, but that's
idea).
However, when an executable is built with -fPIE of -fpie, it no longer
appears to be an 'ELF executable', but it rather looks like an 'ELF
sheard object' (like if it were an library.
So, we miss those files.
It turns out that the problem is a real one, because quite a few
mainline distros, expecially those based on Debian for example, have
already switched to generating PIE code by default, and thus we miss on
a whole class of systems..
We fix that by simply looking if we can find an ELF interpreter in each
file. If we there is one, this is an ELF executable; if not, it may be
anything else: we don't care (not even about ELF libraries).
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Arnout Vandecappelle <arnout@mind.be>
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2017-09-24 18:22:44 +02:00
|
|
|
is_elf "${file}" || continue
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
elf_needs_rpath "${file}" "${hostdir}" || continue
|
|
|
|
check_elf_has_rpath "${file}" "${hostdir}" && continue
|
|
|
|
if [ ${ret} -eq 0 ]; then
|
|
|
|
ret=1
|
|
|
|
printf "***\n"
|
|
|
|
printf "*** ERROR: package %s installs executables without proper RPATH:\n" "${pkg}"
|
|
|
|
fi
|
|
|
|
printf "*** %s\n" "${file}"
|
support/check-rpath: recognise PIE
We sanity-check the host executables that they have a correct RPATH
pointing to the host libraries.
This is currently done by looking for all files in $(HOST_DIR) that
match the 'ELF executable' pattern (a bit more complex, but that's
idea).
However, when an executable is built with -fPIE of -fpie, it no longer
appears to be an 'ELF executable', but it rather looks like an 'ELF
sheard object' (like if it were an library.
So, we miss those files.
It turns out that the problem is a real one, because quite a few
mainline distros, expecially those based on Debian for example, have
already switched to generating PIE code by default, and thus we miss on
a whole class of systems..
We fix that by simply looking if we can find an ELF interpreter in each
file. If we there is one, this is an ELF executable; if not, it may be
anything else: we don't care (not even about ELF libraries).
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Arnout Vandecappelle <arnout@mind.be>
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2017-09-24 18:22:44 +02:00
|
|
|
done < <( find "${hostdir}"/{bin,sbin} -type f 2>/dev/null )
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
|
|
|
|
return ${ret}
|
|
|
|
}
|
|
|
|
|
support/check-rpath: recognise PIE
We sanity-check the host executables that they have a correct RPATH
pointing to the host libraries.
This is currently done by looking for all files in $(HOST_DIR) that
match the 'ELF executable' pattern (a bit more complex, but that's
idea).
However, when an executable is built with -fPIE of -fpie, it no longer
appears to be an 'ELF executable', but it rather looks like an 'ELF
sheard object' (like if it were an library.
So, we miss those files.
It turns out that the problem is a real one, because quite a few
mainline distros, expecially those based on Debian for example, have
already switched to generating PIE code by default, and thus we miss on
a whole class of systems..
We fix that by simply looking if we can find an ELF interpreter in each
file. If we there is one, this is an ELF executable; if not, it may be
anything else: we don't care (not even about ELF libraries).
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Arnout Vandecappelle <arnout@mind.be>
Signed-off-by: Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be>
2017-09-24 18:22:44 +02:00
|
|
|
is_elf() {
|
|
|
|
local f="${1}"
|
|
|
|
|
|
|
|
readelf -l "${f}" 2>/dev/null \
|
|
|
|
|grep -E 'Requesting program interpreter:' >/dev/null 2>&1
|
|
|
|
}
|
|
|
|
|
2018-12-28 11:43:28 +01:00
|
|
|
# This function tells whether a given ELF executable (first argument)
|
|
|
|
# needs a RPATH pointing to the host library directory or not. It
|
|
|
|
# needs such an RPATH if at least of the libraries used by the ELF
|
|
|
|
# executable is available in the host library directory. This function
|
|
|
|
# returns 0 when a RPATH is needed, 1 otherwise.
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
elf_needs_rpath() {
|
|
|
|
local file="${1}"
|
|
|
|
local hostdir="${2}"
|
|
|
|
local lib
|
|
|
|
|
|
|
|
while read lib; do
|
2017-07-04 16:03:52 +02:00
|
|
|
[ -e "${hostdir}/lib/${lib}" ] && return 0
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
done < <( readelf -d "${file}" \
|
|
|
|
|sed -r -e '/^.* \(NEEDED\) .*Shared library: \[(.+)\]$/!d;' \
|
|
|
|
-e 's//\1/;' \
|
|
|
|
)
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2018-12-28 11:43:28 +01:00
|
|
|
# This function checks whether at least one of the RPATH of the given
|
|
|
|
# ELF executable (first argument) properly points to the host library
|
|
|
|
# directory (second argument), either through an absolute RPATH or a
|
|
|
|
# relative RPATH. Having such a RPATH will make sure the ELF
|
|
|
|
# executable will find at runtime the shared libraries it depends
|
|
|
|
# on. This function returns 0 when a proper RPATH was found, or 1
|
|
|
|
# otherwise.
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
check_elf_has_rpath() {
|
|
|
|
local file="${1}"
|
|
|
|
local hostdir="${2}"
|
|
|
|
local rpath dir
|
|
|
|
|
|
|
|
while read rpath; do
|
|
|
|
for dir in ${rpath//:/ }; do
|
|
|
|
# Remove duplicate and trailing '/' for proper match
|
|
|
|
dir="$( sed -r -e 's:/+:/:g; s:/$::;' <<<"${dir}" )"
|
2018-11-23 15:58:07 +01:00
|
|
|
[ "${dir}" = "${hostdir}/lib" ] && return 0
|
|
|
|
[ "${dir}" = "\$ORIGIN/../lib" ] && return 0
|
core: check host executables have appropriate RPATH
When we build our host programs, and they depend on a host library we
also build, we want to ensure that program actually uses that library at
runtime, and not the one from the system.
We currently ensure that in two ways:
- we add a RPATH tag that points to our host library directory,
- we export LD_LIBRARY_PATH to point to that same directory.
With these two in place, we're pretty much confident that our host
libraries will be used by our host programs.
However, it turns our that not all the host programs we build end up
with an RPATH tag:
- some packages do not use our $(HOST_LDFLAGS)
- some packages' build system are oblivious to those LDFLAGS
In this case, there are two situations:
- the program is not linked to one of our host libraries: it in fact
does not need an RPATH tag [0]
- the program actually uses one of our host libraries: in that case it
should have had an RPATH tag pointing to the host directory.
For libraries, they only need an RPATH if they depend on another library
that is not installed in the standard library path. However, any system
library will already be in the standard library path, and any library we
install ourselves is in $(HOST_DIR)/usr/lib so already in RPATH.
We add a new support script that checks that all ELF executables have
a proper DT_RPATH (or DT_RUNPATH) tag when they link to our host
libraries, and reports those file that are missing an RPATH. If a file
missing an RPATH is an executable, the script aborts; if only libraries
are are missing an RPATH, the script does not abort.
[0] Except if it were to dlopen() it, of course, but the only program
I'm aware of that does that is openssl, and it has a correct RPATH tag.
[Peter: reworded as suggested by Arnout, fix HOT_DIR typo in comment]
Signed-off-by: "Yann E. MORIN" <yann.morin.1998@free.fr>
Cc: Thomas Petazzoni <thomas.petazzoni@free-electrons.com>
Cc: Arnout Vandecappelle <arnout@mind.be>
Cc: Peter Korsgaard <jacmet@uclibc.org>
Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
2015-11-13 22:48:51 +01:00
|
|
|
done
|
|
|
|
done < <( readelf -d "${file}" \
|
|
|
|
|sed -r -e '/.* \(R(UN)?PATH\) +Library r(un)?path: \[(.+)\]$/!d' \
|
|
|
|
-e 's//\3/;' \
|
|
|
|
)
|
|
|
|
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
main "${@}"
|