Linux kernel patch static verification helper tool
This script came about as a result of various beatings I recieved and saw others
recieve in upstream kernel discussions over the last several years. Did you run
checkpatch.pl --strict
, did you run sparse
, is your patch series bisectable,
or the newer ones - coccinelle
and smatch
. I mean, why debug or even catch
these in mailing lists, if you can programmatically try to catch them up at
developer's end?
Many of these were due to:
- Too many tools constantly evolving in linux kernel - too many goodies, and too less time for every developer to learn
- Having to run too many utilities using varied command lines - most normal folks dont remember everything everytime.
- In general, few developers are lazy, even knowing tools are not good enough and almost everyone would like to have something quick and handy.. and if possible, automated..
As a result, while working on "evil vendor" Android kernel as a domain maintainer, I had originally written a dumb application called Kmake (unrelated to the current meta build systems). This was my first attempt at automating this entire process... and was pretty crap code and was meant for me to test 1 single patch. It was born out of pure desperation from getting a hell lot of crap patches from too many internal developers.
As I shared around this original code over the years, I got feedback from various folks on varied angles:
- Dan Murphy: why cant it report required applications for it to run?
- Tero Kristo: rewrote the entire script and got me thinking along the lines of a 'patch set that needs to be applied'
- And, others who suggested tiny little things...
It was obvious, this original script needed a respin and update to newer kernel world. So, here is another attempt with enough error handling that I could reasonably think of in the few hours I spend rewriting... And I do not think it is good enough yet... there are few things I dropped - storing dtbs+zImage per patch to to allow for seperate verification by boot per patch and similar tiny little thingies... Maybe later... I guess...
Just lets keep this on github and send pull requests to merge things up? As a script developer, we all know that various developers have widely varying tastes. if you feel an bug fixed or other improvements to share, send me a pull request and we can collaborate together.
For folks wanting to write python or perl alternatives, please, go ahead and create your own tool, just dont ask me to even touch python ;) - this remains in bash.
Almost nothing - I hope you are already using bash and building kernel - The script should crib and provide recommendations for missing packages (or is supposed to ;) )
For -C
or "complete tests", the following are needed:
-
smatch: (sudo apt-get install sqlite3 libsqlite3-dev llvm)
https://blog.linuxplumbersconf.org/2011/ocw/system/presentations/165/original/transcript.txt
https://smatch.sourceforge.net/
NOTE for older Ubuntu installs, use: https://launchpad.net/ubuntu/+source/coccinelle
-
spatch: is provided by the coccinelle package in ubuntu
.config
, since dtbscheck will take significant time!
sed -n 's/^config \(ARCH.*\)/CONFIG_\1=n/p' arch/arm64/Kconfig.platforms | grep -v K3 >> .config
./kernel_patch_verify [-d] [-j CPUs] [-B build_target] [-T tmp_dir_base] [-l logfile] [-C] [-c defconfig_name] [-1]|[-p patch_dir]|[-b base_branch [-t head_branch]]
-d: if not already defined, use CROSS_COMPILE=arm-linux-gnueabi-, ARCH=arm, and builds for ' zImage dtbs' build targets
-j CPUs: override default CPUs count with build (default is 4)
-B build_target: override default build target and use provided build_target
-T temp_dir_base: temporary directory base (default is /tmp)
-l logfile: report file (defaults to ./report-kernel-patch-verify.txt)
-C: run Complete tests(WARNING: could take significant time!)
-c defconfig:_name (default uses current .config + oldconfig)
-1: test the tip of current branch (just a single patch)
-p patch_dir: which directory to take patches from (expects sorted in order)
-b base_branch: test patches from base_branch
-t test_branch: optionally used with -b, till head branch, if not provided, along with -b, default will be tip of current branch
NOTE:
- Only one of -1, -p or (-b,-t) should be used - but at least one of these should be used
- Cannot have a diff pending OR be on a dangling branch
base_branch
should exist as well - The default tests are selected with view of as minimal time as possible, while the
-C
tests are the comprehensive tests which are strongly recommended before showing your patches to any other human being.
-
Verify last commmitted patch:
./kernel_patch_verify -1
-
Verify on top of current branch patches from location
~/tmp/test-patches
:./kernel_patch_verify -p ~/tmp/test-patches
-
Verify from branch
base_branch
till current branch:./kernel_patch_verify -b base_branch
-
Verify all patches from current branch until
test_branch
:./kernel_patch_verify -t test_branch
-
Verify all patches from
base_branch
untiltest_branch
:./kernel_patch_verify -b base_branch -t test_branch
-
Verify, with complete tests, all patches from
base_branch
untiltest_branch
:./kernel_patch_verify -b base_branch -t test_branch -C
-
Verify last committed patch on a native x86 build using
make
,gcc
, and thebzImage
target:./kernel_patch_verify -B bzImage -1
-
Verify last committed patch on a cross-compiled ARM build using defaults:
./kernel_patch_verify -d -1
Alright, the shell script should be readable in it's own I hope... anyways, tests are organized as:
ptest_xyz
-> these tests take the patch as the argumentftest_xyz
-> these tests take c file (impacted by the patch) as the argumentbtest_xyz
-> there are of two types: the ones that take .o files as arguments and those that build the entire kernel
Tests are organized per patch OR overall (basically run before the patch series and after the patch series). Reports are generated after all the tests are run, I have not tried to standardize the reports in any way, except that if there is a 'change' in log, for example:
- A build warning was created with a patch.
- A build warning was removed with a patch in the series.
This will appear as a a diff (both build warning was removed or added is considered similar) and that diff is provided in the report log. the final report log is a consolidation of every single patch, over all results and also provides information about the tools and versions used.
Without the -C
switch, only tests that take a short amount of time will be
ran. Tests that take significant time should be listed under -C
. I recommend
reading the code to see the list of tests executed. This will also be printed as
you execute the tests. Just remember that false positives are irritable to
developers, so be careful of the results.
The generic strategy for the test is that everything in stderr is logged, a test should never throw anything on stdout as it just craps up the developer's screen. If a test provides result on stdout, redirect it to stderr. Pass/fail criteria is as follows:
- For
ftest_
,btest_
, the before and after logs should show 0 diff. If there are, it assumes new fail introduction - For
ptest
, no output is a pass, any output tends to be a fail.
- Nishanth Menon Dec 2013, Dallas, TX, while lying in bed with a slight migraine staring at a cloudy sky and spewing nonsense into vim... and guessing that no one might even care about this...