Merge branch 'gh-actions-bionic' of https://github.com/mrc0mmand/util-linux

* 'gh-actions-bionic' of https://github.com/mrc0mmand/util-linux:
  ci: run the build test for each pull request
  ci: build both w/ and w/o sanitizers on GH Actions
  ci: code cleanup
  ci: deal with uninstrumented binaries using instrumented libs
  text-utils: correctly detect ASan under clang
  ci: use the correct compiler version
  ci: 'downgrade' Ubuntu version to Bionic
This commit is contained in:
Karel Zak 2021-02-05 10:29:26 +01:00
commit ec89bec1cd
13 changed files with 140 additions and 49 deletions

View File

@ -2,59 +2,94 @@
PHASES=(${@:-CONFIGURE MAKE INSTALL CHECK DISTCHECK})
COMPILER="${COMPILER:?}"
COMPILER_VERSION="${COMPILER_VERSION:?}"
COMPILER_VERSION="${COMPILER_VERSION}"
CFLAGS=(-O1 -g)
CXXFLAGS=(-O1 -g)
if [[ "$COMPILER" == clang ]]; then
CC="clang"
CXX="clang++"
CC="clang${COMPILER_VERSION:+-$COMPILER_VERSION}"
CXX="clang++${COMPILER_VERSION:+-$COMPILER_VERSION}"
elif [[ "$COMPILER" == gcc ]]; then
CC="gcc"
CXX="g++"
CC="gcc${COMPILER_VERSION:+-$COMPILER_VERSION}"
CXX="g++${COMPILER_VERSION:+-$COMPILER_VERSION}"
fi
set -ex
export CC="$CC"
export CXX="$CXX"
for phase in "${PHASES[@]}"; do
case $phase in
CONFIGURE)
opts="--disable-use-tty-group \
--disable-makeinstall-chown \
--enable-all-programs \
--enable-asan \
--enable-ubsan \
--without-python \
--enable-werror"
CONFIGURE)
opts=(
--disable-use-tty-group
--disable-makeinstall-chown
--enable-all-programs
--without-python
--enable-werror
)
if [[ "$COMPILER" == clang ]]; then
opts="$opts --enable-fuzzing-engine"
fi
if [[ "$SANITIZE" == "yes" ]]; then
opts+=(--enable-asan --enable-ubsan)
CFLAGS+=(-fno-omit-frame-pointer)
CXXFLAGS+=(-fno-omit-frame-pointer)
fi
sudo -E git clean -xdf
if [[ "$COMPILER" == clang* && "$SANITIZE" == "yes" ]]; then
opts+=(--enable-fuzzing-engine)
CFLAGS+=(-shared-libasan)
CXXFLAGS+=(-shared-libasan)
fi
./autogen.sh
CC=$CC CXX=$CXX ./configure $opts
;;
MAKE)
make -j
make -j check-programs
;;
INSTALL)
make install DESTDIR=/tmp/dest
;;
CHECK)
./tests/run.sh --show-diff
;;
DISTCHECK)
make distcheck
;;
*)
echo >&2 "Unknown phase '$phase'"
exit 1
sudo -E git clean -xdf
./autogen.sh
CC="$CC" CXX="$CXX" CFLAGS="${CFLAGS[@]}" CXXFLAGS="${CXXFLAGS[@]}" ./configure "${opts[@]}"
;;
MAKE)
make -j
make -j check-programs
;;
INSTALL)
make install DESTDIR=/tmp/dest
;;
CHECK)
if [[ "$SANITIZE" == "yes" ]]; then
# All the following black magic is to make test/eject/umount work, since
# eject execl()s the uninstrumented /bin/umount binary, which confuses
# ASan. The workaround for this is to set $LD_PRELOAD to the ASan's
# runtime DSO, which works well with gcc without any additional hassle.
# However, since clang, by default, links ASan statically, we need to
# explicitly state we want dynamic linking (see -shared-libasan above).
# That, however, introduces another issue - clang's ASan runtime is in
# a non-standard path, so all binaries compiled in such way refuse
# to start. That's what the following blob of code is for - it detects
# the ASan's runtime path and adds the respective directory to
# the dynamic linker cache.
#
# The actual $LD_PRELOAD sheanigans are done directly in
# tests/ts/eject/umount.
asan_rt_name="$(ldd ./kill | awk '/lib.+asan.*.so/ {print $1; exit}')"
asan_rt_path="$($CC --print-file-name "$asan_rt_name")"
echo "Detected ASan runtime: $asan_rt_name ($asan_rt_path)"
if [[ -z "$asan_rt_name" || -z "$asan_rt_path" ]]; then
echo >&2 "Couldn't detect ASan runtime, can't continue"
exit 1
fi
if [[ "$COMPILER" == clang* ]]; then
mkdir -p /etc/ld.so.conf.d/
echo "${asan_rt_path%/*}" > /etc/ld.so.conf.d/99-clang-libasan.conf
ldconfig
fi
fi
./tests/run.sh --show-diff
;;
DISTCHECK)
make distcheck
;;
*)
echo >&2 "Unknown phase '$phase'"
exit 1
esac
done

View File

@ -1,5 +1,9 @@
name: Build test
on:
pull_request:
paths-ignore:
- 'Documentation/**'
- 'lib*/docs/**'
push:
branches:
- 'cibuild'
@ -12,13 +16,15 @@ on:
jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
env:
- { COMPILER: "gcc", COMPILER_VERSION: "10" }
- { COMPILER: "clang", COMPILER_VERSION: "10" }
- { COMPILER: "gcc", COMPILER_VERSION: "10", SANITIZE: "yes" }
- { COMPILER: "gcc", COMPILER_VERSION: "10", SANITIZE: "no" }
- { COMPILER: "clang", COMPILER_VERSION: "10", SANITIZE: "yes" }
- { COMPILER: "clang", COMPILER_VERSION: "10", SANITIZE: "no" }
env: ${{ matrix.env }}
steps:
- name: Repository checkout

View File

@ -411,6 +411,23 @@ static inline int xusleep(useconds_t usec)
#define stringify_value(s) stringify(s)
#define stringify(s) #s
/* Detect if we're compiled with Address Sanitizer
* - gcc (__SANITIZE_ADDRESS__)
* - clang (__has_feature(address_sanitizer))
*/
#if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
# ifdef __SANITIZE_ADDRESS__
# define HAS_FEATURE_ADDRESS_SANITIZER 1
# elif defined(__has_feature)
# if __has_feature(address_sanitizer)
# define HAS_FEATURE_ADDRESS_SANITIZER 1
# endif
# endif
# if !defined(HAS_FEATURE_ADDRESS_SANITIZER)
# define HAS_FEATURE_ADDRESS_SANITIZER 0
# endif
#endif
/*
* UL_ASAN_BLACKLIST is a macro to tell AddressSanitizer (a compile-time
* instrumentation shipped with Clang and GCC) to not instrument the

View File

@ -83,7 +83,7 @@ close_stdout_atexit(void)
/*
* Note that close stdout at exit disables ASAN to report memory leaks
*/
#if !defined(__SANITIZE_ADDRESS__)
#if !HAS_FEATURE_ADDRESS_SANITIZER
atexit(close_stdout);
#endif
}

View File

@ -103,7 +103,7 @@ nodist_EXTRA_test_fdisk_script_fuzz_SOURCES = dummy.cxx
test_fdisk_script_fuzz_SOURCES = libfdisk/src/script.c
test_fdisk_script_fuzz_CFLAGS = -DFUZZ_TARGET $(libfdisk_la_CFLAGS) $(NO_UNUSED_WARN_CFLAGS)
test_fdisk_script_fuzz_LDFLAGS = $(libfdisk_tests_ldflags)
test_fdisk_script_fuzz_LDFLAGS = $(libfdisk_tests_ldflags) -lpthread
test_fdisk_script_fuzz_LDADD = $(libfdisk_tests_ldadd) $(LIB_FUZZING_ENGINE)
endif

View File

@ -163,7 +163,7 @@ test_mount_fuzz_SOURCES = libmount/src/fuzz.c
nodist_EXTRA_test_mount_fuzz_SOURCES = dummy.cxx
test_mount_fuzz_CFLAGS = $(libmount_tests_cflags)
test_mount_fuzz_LDFLAGS = $(libmount_tests_ldflags)
test_mount_fuzz_LDFLAGS = $(libmount_tests_ldflags) -lpthread
test_mount_fuzz_LDADD = $(libmount_tests_ldadd) $(LIB_FUZZING_ENGINE)
endif

View File

@ -20,6 +20,7 @@ nodist_EXTRA_test_last_fuzz_SOURCES = dummy.cxx
test_last_fuzz_SOURCES = login-utils/last.c
test_last_fuzz_CFLAGS = $(AM_CFLAGS) -DFUZZ_TARGET
test_last_fuzz_LDFLAGS = -lpthread
test_last_fuzz_LDADD = $(LDADD) libcommon.la $(LIB_FUZZING_ENGINE)
endif

View File

@ -1078,3 +1078,17 @@ function ts_has_ncurses_support {
echo "no"
fi
}
# Get path to the ASan runtime DSO the given binary was compiled with
function ts_get_asan_rt_path {
local binary="${1?}"
local rt_path
ts_check_prog "ldd"
ts_check_prog "awk"
rt_path="$(ldd "$binary" | awk '/lib.+asan.*.so/ {print $3; exit}')"
if [ -n "$rt_path" -a -f "$rt_path" ]; then
echo "$rt_path"
fi
}

View File

@ -8,6 +8,7 @@ ts_init "$*"
ts_check_test_command "$TS_CMD_FDISK"
ts_check_test_command "$TS_CMD_EJECT"
ts_check_test_command "$TS_CMD_KILL"
ts_check_test_command "$TS_CMD_MOUNT"
ts_skip_nonroot
@ -59,6 +60,13 @@ function deinit_device {
ts_scsi_debug_rmmod
}
# As the eject binary execl()s an uninstrumented /bin/umount binary, we need
# to explicitly $LD_PRELOAD the ASan's runtime DSO, otherwise ASan will complain.
# Since all three utilities used by this test (eject, fdisk, mount) are just
# libtool wrappers, let's check the kill binary instead, which should have
# the needed DSO information.
ASAN_RT_PATH="$(ts_get_asan_rt_path "$TS_CMD_KILL")"
[ -n "$ASAN_RT_PATH" ] && export LD_PRELOAD="$ASAN_RT_PATH:$LD_PRELOAD"
ts_init_subtest "by-disk"
init_device

View File

@ -20,6 +20,9 @@ ts_init "$*"
ts_check_test_command "$TS_HELPER_LIBFDISK_SCRIPT_FUZZ"
ASAN_RT_PATH="$(ts_get_asan_rt_path "$TS_HELPER_LIBFDISK_SCRIPT_FUZZ")"
[ -n "$ASAN_RT_PATH" ] && export LD_PRELOAD="$ASAN_RT_PATH:$LD_PRELOAD"
mkdir -p ${TS_OUTPUT}_workdir
ts_run $TS_HELPER_LIBFDISK_SCRIPT_FUZZ ${TS_OUTPUT}_workdir ${TS_SCRIPT}_files -max_total_time=10 >$TS_OUTPUT 2>$TS_ERRLOG

View File

@ -20,6 +20,9 @@ ts_init "$*"
ts_check_test_command "$TS_HELPER_LAST_FUZZ"
ASAN_RT_PATH="$(ts_get_asan_rt_path "$TS_HELPER_LAST_FUZZ")"
[ -n "$ASAN_RT_PATH" ] && export LD_PRELOAD="$ASAN_RT_PATH:$LD_PRELOAD"
mkdir -p ${TS_OUTPUT}_workdir
ts_run $TS_HELPER_LAST_FUZZ ${TS_OUTPUT}_workdir ${TS_SCRIPT}_files -max_total_time=10 >$TS_OUTPUT 2>$TS_ERRLOG

View File

@ -20,6 +20,9 @@ ts_init "$*"
ts_check_test_command "$TS_HELPER_LIBMOUNT_FUZZ"
ASAN_RT_PATH="$(ts_get_asan_rt_path "$TS_HELPER_LIBMOUNT_FUZZ")"
[ -n "$ASAN_RT_PATH" ] && export LD_PRELOAD="$ASAN_RT_PATH:$LD_PRELOAD"
mkdir -p ${TS_OUTPUT}_workdir
ts_run $TS_HELPER_LIBMOUNT_FUZZ ${TS_OUTPUT}_workdir ${TS_SCRIPT}_files -max_total_time=10 >$TS_OUTPUT 2>$TS_ERRLOG

View File

@ -61,6 +61,7 @@
#include <string.h>
#include <unistd.h>
#include "c.h"
#include "closestream.h"
#include "nls.h"
#include "optutils.h"
@ -89,7 +90,7 @@
/* number of lines to allocate */
#define NALLOC 64
#if defined(__SANITIZE_ADDRESS__) || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
#if HAS_FEATURE_ADDRESS_SANITIZER || defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
# define COL_DEALLOCATE_ON_EXIT
#endif