-
Notifications
You must be signed in to change notification settings - Fork 2
csexec
The ultimate goal is to run dynamic analyzers and formal verifiers on RPM packages fully automatically. We already know how to tweak the build process, how to hook static analyzers on compiler invocation, and how to capture their results. This is, however, not so easy with dynamic analyzers. The %check
section of RPM packages can use arbitrary testing frameworks and scripting languages to verify the binaries produced in the %build
section. Our goal is to dynamically analyze (or formally verify) the produced binaries. At the same time, we want to interfere with all the testing frameworks as little as possible.
csexec-loader
is a binary that can be set as ELF interpreter while linking binaries in %build
section of RPM packages. When the resulting binary is executed, the loader executes csexec
passing it real path of the executable as argv[0]
, followed by the original command-line arguments. Then csexec
runs the dynamic linker explicitly to execute the original binary. Optionally, csexec
inserts an execution wrapper (e.g. valgrind) if the CSEXEC_WRAP_CMD
environment variable is set at run time. The string may optionally contain BEL
-separated list of arguments that will be passed to the wrapper in front of the path to the dynamic linker executable.
There are some constrains on the implementation of ELF interpreters. Namely, it does not work well if a custom ELF interpreter internally uses the system ELF interpreter or C run-time libraries, which are tightly coupled with the system ELF interpreter. Therefore, csexec-loader
is implemented such that it does not use any C run-time libraries.
Install csexec
, cswrap
, and fedpkg
packages:
$ sudo yum install csexec cswrap fedpkg
Tweak environment such that any build will use /usr/bin/csexec-loader
as ELF interpreter:
$ export PATH=$(cswrap --print-path-to-wrap):$PATH
$ export CSWRAP_ADD_CFLAGS=-Wl,--dynamic-linker,/usr/bin/csexec-loader
Build a Fedora package as usually:
$ fedpkg clone -a logrotate
$ cd logrotate
$ git checkout f33
$ fedpkg compile
Run the upstream test-suite natively:
$ cd logrotate-3.17.0/build
$ make check -j16
Run the upstream test-suite through valgrind
(without touching the already built binaries):
$ sudo yum install valgrind
$ CSEXEC_WRAP_CMD=$'valgrind\a--quiet\a--log-file=/dev/tty\a--leak-check=full' make check
Run the upstream test-suite through strace
(without touching the already built binaries):
$ sudo yum install strace
$ CSEXEC_WRAP_CMD=$'strace\a-e\aopenat\a-o\a/dev/tty' make check
We can also use csexec
to dynamically analyze unmodified source RPM packages:
$ sudo yum install cswrap koji rpm-build valgrind
$ koji download-build -a src logrotate-3.17.0-3.fc33
$ sudo yum builddep ./logrotate-3.17.0-3.fc33.src.rpm
$ export PATH=$(cswrap --print-path-to-wrap):$PATH
$ export CSWRAP_ADD_CFLAGS=-Wl,--dynamic-linker,/usr/bin/csexec-loader
$ export CSEXEC_WRAP_CMD=$'valgrind\a--quiet\a--xml=yes\a--xml-file=/tmp/logrotate-valgrind-%p-%n.xml'
$ rpmbuild --rebuild ./logrotate-3.17.0-3.fc33.src.rpm
The above can be achieved in a more user-friendly way using the csmock-plugin-valgrind
plug-in of csmock:
$ sudo yum install csmock-plugin-valgrind koji
$ koji download-build -a src logrotate-3.17.0-3.fc33
$ csmock -t valgrind -r fedora-rawhide-x86_64 ./logrotate-3.17.0-3.fc33.src.rpm
Likewise, there is csmock-plugin-strace
that runs the %check
section of a source RPM package through strace
.