dynup / kpatch

kpatch - live kernel patching
GNU General Public License v2.0
1.49k stars 305 forks source link

6.3 failure with setlocalversion #1335

Closed jpoimboe closed 1 year ago

jpoimboe commented 1 year ago

6.3-based kernel is failing with

$ kpatch-build/kpatch-build -s ~/git/linux test/integration/linux-5.18.0/shadow-newpid.patch
Using source directory at /home/jpoimboe/git/linux
Testing patch file(s)
Reading special section data
Building original source
Usage: ./scripts/setlocalversion [srctree]
ERROR: kpatch build failed. Check /home/jpoimboe/.kpatch/build.log for more details.

The setlocalversion script no longer supports the --save-scmversion hack so we'll have to come up with another hack. Replace setlocalversion with a version which does what we want?

joe-lawrence commented 1 year ago

I've never had to look at this before, our use in kpatch-build was added by Seth in 2015.. what was its purpose? Patching or replacing a kernel build script is always iffy it turns into a moving target. Could we pull similar hack completely into kpatch-build?

jpoimboe commented 1 year ago

If the kernel is based on a git tag (like v6.2), the kernel has a VERMAGIC_STRING which includes a version string "6.2.0". The module loader ensures that all loaded modules' version strings match the kernel's.

If there are changes in the git index, the version string will have a '+' appended to it like "6.2.0+".

The problem is, when kpatch-build builds the patched kernel, it has the patch applied, so it will always have the "+". This version can be seen by doing modinfo <patch>.ko.

What setlocalversion --save-scmversion did was save the version (before applying the patch) to a file, which was then read by subsequent builds' invocations of setlocalversion to force the version to stay the same despite changes to the tree. Without that --save-scmversion functionality, which disappeared in the 6.3 merge window, livepatch modules will fail to load.

jpoimboe commented 1 year ago

The proper way to fix this is probably

jpoimboe commented 1 year ago

Or we could just punt and do something similar to what's already being done for Ubuntu

if [[ -z "$USERSRCDIR" ]] && [[ "$DISTRO" = ubuntu ]]; then
        # UBUNTU: add UTS_UBUNTU_RELEASE_ABI to utsrelease.h after regenerating it                                     
        UBUNTU_ABI="${ARCHVERSION#*-}"                                                                                 
        UBUNTU_ABI="${UBUNTU_ABI%-*}"                                                                                  
        echo "#define UTS_UBUNTU_RELEASE_ABI $UBUNTU_ABI" >> "$KERNEL_SRCDIR"/include/generated/utsrelease.h           
fi

We could save off that file at the beginning and then copy it back right before the module link.

jpoimboe commented 1 year ago

Actually neither of those would work very well, because when the vermagic changes during the build of the patched objects, it changes the actual compilation of kernel/module/main.o, which confuses create-diff-object. The best option I can come up with is the original idea of replacing setlocalversion.