#!/bin/bash # # This file is part of the LibreOffice project. # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. # # verify that ELF NEEDED entries are known-good so hopefully builds run on # lots of different GNU/Linux distributions set -euo pipefail PARA=1 check_path="${INSTDIR:-.}" help() { cat << "EOF" -d directory to check -p run unbound parallel checks -h help EOF [ -z "${1:-}" ] && exit 0 } die() { echo "$1" echo help 1 exit 1 } while [ "${1:-}" != "" ]; do parm=${1%%=*} arg=${1#*=} has_arg= if [ "${1}" != "${parm?}" ] ; then has_arg=1 else arg="" fi case "${parm}" in --dir|-d) if [ "$has_arg" ] ; then check_path="$arg" else shift check_path="$1" fi if [ ! -d "$check_path" ]; then die "Invalid directory '$check_path'" fi ;; -h) help ;; -p) # this sounds counter intuitive but the idea # is to possibly support -p # in the meantime: 0 = nolimit and -p 1 would mean # the current default: serialize PARA=0 ;; -*) die "Invalid option $1" ;; *) if [ "$DO_NEW" = 1 ] ; then REPO="$1" else die "Invalid argument $1" fi ;; esac shift done files=$(find "${check_path}/program" "${check_path}/sdk/bin" -type f) # all RPATHs should point to ${INSTDIR}/program so that's the files they find programfiles=$(echo ${files} | grep -o '/program/[^/]* ' | xargs -n 1 basename) # whitelists should contain only system libraries that have a good reputation # of maintaining ABI stability # allow extending the whitelist using the environment variable to be able to work # on the installer stuff without the need for a baseline setup globalwhitelist="ld-linux-x86-64.so.2 ld-linux.so.2 libc.so.6 libm.so.6 libdl.so.2 libpthread.so.0 librt.so.1 libutil.so.1 libnsl.so.1 libcrypt.so.1 libgcc_s.so.1 libstdc++.so.6 libz.so.1 libfontconfig.so.1 libfreetype.so.6 libxml2.so.2 libxslt.so.1 libexslt.so.0 ${LO_ELFCHECK_WHITELIST-}" x11whitelist="libX11.so.6 libXext.so.6 libSM.so.6 libICE.so.6 libXinerama.so.1 libXrender.so.1 libXrandr.so.2 libcairo.so.2" openglwhitelist="libGL.so.1" giowhitelist="libgio-2.0.so.0 libgobject-2.0.so.0 libgmodule-2.0.so.0 libgthread-2.0.so.0 libglib-2.0.so.0 libdbus-glib-1.so.2 libdbus-1.so.3" gstreamer010whitelist="libgstpbutils-0.10.so.0 libgstinterfaces-0.10.so.0 libgstreamer-0.10.so.0" gstreamerwhitelist="libgstaudio-1.0.so.0 libgstpbutils-1.0.so.0 libgstvideo-1.0.so.0 libgstbase-1.0.so.0 libgstreamer-1.0.so.0" gtk2whitelist="libgtk-x11-2.0.so.0 libgdk-x11-2.0.so.0 libpangocairo-1.0.so.0 libfribidi.so.0 libatk-1.0.so.0 libcairo.so.2 libgio-2.0.so.0 libpangoft2-1.0.so.0 libpango-1.0.so.0 libfontconfig.so.1 libfreetype.so.6 libgdk_pixbuf-2.0.so.0 libgobject-2.0.so.0 libglib-2.0.so.0 libgmodule-2.0.so.0 libgthread-2.0.so.0 libdbus-glib-1.so.2 libdbus-1.so.3" gtk3whitelist="libgtk-3.so.0 libgdk-3.so.0 libcairo-gobject.so.2 libpangocairo-1.0.so.0 libfribidi.so.0 libatk-1.0.so.0 libcairo.so.2 libgio-2.0.so.0 libpangoft2-1.0.so.0 libpango-1.0.so.0 libfontconfig.so.1 libfreetype.so.6 libgdk_pixbuf-2.0.so.0 libgobject-2.0.so.0 libglib-2.0.so.0 libgmodule-2.0.so.0 libgthread-2.0.so.0 libdbus-glib-1.so.2 libdbus-1.so.3" qt5whitelist="libQt5Core.so.5 libQt5Gui.so.5 libQt5Network.so.5 libQt5Widgets.so.5 libQt5X11Extras.so.5 libcairo.so.2 libglib-2.0.so.0 libgobject-2.0.so.0 libxcb.so.1" kf5whitelist="libKF5ConfigCore.so.5 libKF5CoreAddons.so.5 libKF5I18n.so.5 libKF5KIOCore.so.5 libKF5KIOFileWidgets.so.5 libKF5KIOWidgets.so.5 libKF5WindowSystem.so.5" avahiwhitelist="libdbus-glib-1.so.2 libdbus-1.so.3 libgobject-2.0.so.0 libgmodule-2.0.so.0 libgthread-2.0.so.0 libglib-2.0.so.0 libavahi-common.so.3 libavahi-client.so.3" kerberoswhitelist="libgssapi_krb5.so.2 libcom_err.so.2 libkrb5.so.3" dconfwhitelist="libdconf.so.1 libgio-2.0.so.0 libglib-2.0.so.0 libgobject-2.0.so.0" check_one_file() { local file="$1" skip=0 whitelist="${globalwhitelist}" case "${file}" in */sdk/docs/*) # skip the majority of files, no ELF binaries here skip=1 ;; */libcairocanvaslo.so) whitelist="${whitelist} libcairo.so.2" ;; */libucpgio1lo.so|*/liblosessioninstalllo.so|*/libevoablo.so) whitelist="${whitelist} ${giowhitelist}" ;; */libavmediagst.so) whitelist="${whitelist} ${gtk3whitelist} ${gstreamerwhitelist}" ;; */libavmediagst_0_10.so) whitelist="${whitelist} ${gtk2whitelist} ${gstreamer010whitelist}" ;; */libvclplug_kde5lo.so|*/libkde5be1lo.so) if [ "$ENABLE_KDE5" = TRUE ]; then whitelist="${whitelist} ${qt5whitelist} ${kf5whitelist}" fi ;; */libvclplug_gtklo.so|*/libqstart_gtklo.so|*/updater) whitelist="${whitelist} ${x11whitelist} ${gtk2whitelist}" ;; */libvclplug_gtk3lo.so) whitelist="${whitelist} ${x11whitelist} ${gtk3whitelist}" ;; */libvclplug_qt5lo.so) if [ "$ENABLE_QT5" = TRUE ]; then whitelist="${whitelist} ${qt5whitelist}" fi ;; */libvclplug_gtk3_kde5lo.so) if [ "$ENABLE_GTK3_KDE5" = TRUE ]; then whitelist="${whitelist} ${x11whitelist} ${gtk3whitelist} ${qt5whitelist} ${kf5whitelist}" fi ;; */lo_kde5filepicker) if [ "$ENABLE_GTK3_KDE5" = TRUE ]; then whitelist="${whitelist} ${x11whitelist} ${gtk3whitelist} ${qt5whitelist} \ ${kf5whitelist}" fi ;; */libdesktop_detectorlo.so|*/ui-previewer|*/oosplash|*/gengal.bin) whitelist="${whitelist} ${x11whitelist}" ;; */libvclplug_genlo.so|*/libchartcorelo.so|*/libavmediaogl.so|*/libOGLTranslo.so|*/liboglcanvaslo.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist}" ;; */libvcllo.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist} ${giowhitelist} libcups.so.2" ;; */libsofficeapp.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist} ${giowhitelist} libcups.so.2" ;; */liblibreofficekitgtk.so) whitelist="${whitelist} ${gtk3whitelist}" ;; */libsdlo.so) whitelist="${whitelist} ${avahiwhitelist}" ;; */libofficebean.so) whitelist="${whitelist} libjawt.so" ;; */libpostgresql-sdbc-impllo.so) whitelist="${whitelist} ${kerberoswhitelist}" ;; */libconfigmgrlo.so) if [ "$ENABLE_DCONF" = TRUE ]; then whitelist="${whitelist} ${dconfwhitelist}" fi ;; */libmergedlo.so) whitelist="${whitelist} ${x11whitelist} ${openglwhitelist} ${giowhitelist} libcups.so.2 libcairo.so.2" ;; esac if test "${skip}" = 0 && readelf -d "${file}" &> /dev/null ; then rpath=$(readelf -d "${file}" | grep '(\(RPATH\|RUNPATH\))' || true) neededs=$(readelf -d "${file}" | grep '(NEEDED)' | sed -e 's/.*\[\(.*\)\]$/\1/') neededsinternal= for needed in ${neededs} do if ! echo ${whitelist} | grep -q -w "${needed}" ; then neededsinternal="${neededsinternal} ${needed}" if ! echo ${programfiles} | grep -q -w "${needed}" ; then echo "${file}" has suspicious NEEDED: "${needed}" status=1 fi fi done if test -z "${rpath}" ; then case "${file}" in */python-core-*/lib/lib-dynload/*) # python modules don't have RPATH ;; */share/extensions/*) # extension libraries don't have RPATH ;; *) # no NEEDED from instdir, no RPATH needed if test -n "${neededsinternal}" ; then echo "${file}" has no RPATH status=1 fi ;; esac else case "$file" in */sdk/bin/*) if echo "${rpath}" | grep -q -v '\[\$ORIGIN/../../program\]$' ; then echo "${file}" has unexpected RPATH "${rpath}" status=1 fi ;; *) if echo "${rpath}" | grep -q -v '\[\$ORIGIN\]$' ; then echo "${file}" has unexpected RPATH "${rpath}" status=1 fi ;; esac fi fi } status=0 if [ "$PARA" = "1" ] ; then for file in ${files} do check_one_file $file done else rm -f check_elf.out for file in ${files} do ( check_one_file $file )>> check_elf.out & done wait if [ -s check_elf.out ] ; then cat check_elf.out status=1 fi rm check_elf.out fi exit ${status}