-
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 fedpkgTweak 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-loaderBuild a Fedora package as usually:
$ fedpkg clone -a logrotate
$ cd logrotate
$ git checkout f33
$ fedpkg compileRun the upstream test-suite natively:
$ cd logrotate-3.17.0/build
$ make check -j16Run 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 checkRun 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 checkWe 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.rpmThe 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.rpmLikewise, there is csmock-plugin-strace that runs the %check section of a source RPM package through strace.