With #650, we found that using -ffunction-sections and -fdata-sections
sometimes causes GCC to output the local symbols in a different order in
the symbol table. So don't assume they're in the same order, and
instead search all the locals.
This requires two passes: once going through the lookup table symbols
and once going through the .o symbols. This is needed to make sure
there aren't any extra symbols in one of the files.
I also reorganized the code a bit to simplify it.
When compiling with -O2, it fails with:
gcc -MMD -MP -O2 -I../kmod/patch -Iinsn -Wall -g -Werror -c -o lookup.o lookup.c
lookup.c: In function ‘lookup_open’:
lookup.c:132:21: error: ‘file_sym’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
table->local_syms = file_sym;
~~~~~~~~~~~~~~~~~~^~~~~~~~~~
lookup.c:83:30: note: ‘file_sym’ was declared here
struct object_symbol *sym, *file_sym;
^~~~~~~~
lookup.c:129:27: error: ‘child_sym’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
if (in_file && !child_sym->name) {
~~~~~~~~~^~~~~~
lookup.c:85:27: note: ‘child_sym’ was declared here
struct sym_compare_type *child_sym;
^~~~~~~~~
cc1: all warnings being treated as errors
Makefile:17: recipe for target 'lookup.o' failed
make[1]: *** [lookup.o] Error 1
make[1]: Leaving directory '/home/jpoimboe/git/kpatch/kpatch-build'
Makefile:14: recipe for target 'build-kpatch-build' failed
make: *** [build-kpatch-build] Error 2
As far as I can tell, these are false positive warnings. When in_file
is 1, file_sym and child_sym are properly initialized. But silence the
warnings anyway so Gentoo users can build with -O2.
Fixes: #675
On Debian/Ubuntu, the `vmlinux` from `-dbg` package has a version number
appended to it. For example:
`/usr/lib/debug/boot/vmlinux-3.13.0-117-generic`. Make it work
nonetheless.
On Ubuntu Trusty, HWE kernels don't come with a linux-source
package. Use dget to retrieve the source package instead. This is not
the case anymore with Xenial as the linux-source package is also
provided for the HWE kernels. For Debian, backports always come with the
linux-source package.
SUSE-based kernels have a DWARF unwinder, so they build with the gcc
'-fasynchronous-unwind-tables' flag, which adds .eh_frame and
.eh_frame_hdr sections. Treat those sections like the other debug
sections.
Fixes: #703
Joe saw the following errors when loading Linux commit 128394eff343
("sg_write()/bsg_write() is not fit to be called under KERNEL_DS"):
Skipped dynrela for copy_user_generic_unrolled (0xffffffffa0475942 <- 0xffffffff813211e0): the instruction has been changed already.
Skipped dynrela for copy_user_generic_unrolled (0xffffffffa0475a57 <- 0xffffffff813211e0): the instruction has been changed already.
That is known issue #580, but it can be avoided by leaving
'copy_user_generic_unrolled' as a normal relocation instead of
converting it to a dynrela, because it's an exported symbol.
Also remove the manual check for '__fentry__' because it's covered by
the exported symbol check.
Also remove a duplicate comment about unexported global object symbols
being in another .o in the patch object.
Fixes#695.
This release has many fixes and improvements since 0.3.4. The '0.3' was
bumped to '0.4' because of commit 0bb5c106ef ("kmod: restructure
kpatch sysfs tree"), which broke the ABI between the kpatch core module
and the kpatch script, as it changed the sysfs layout.
Other notable changes since 0.3.4:
- The tools underlying kpatch-build have been made more modular, in
preparation for making create-diff-object more generally useful to
other use cases (kernel livepatch, Xen live patching, user space
patching).
- Support for all new upstream kernels up to 4.10.
- KASLR support.
- Many other bug fixes and improvements.
* remove the Fedora release number
* add part of the $(uname -r) to kernel package specifications
* add patchutils as an optional package to satisfy kpatch-test
* update to the latest ccache rpm URL @ dl.fedoraproject.org
Upstream kernel commit 7f2084fa55e6 ("[kbuild] handle exports in lib-y
objects reliably") (v4.9+) added temporary dummy .lib_exports.o objects
to the kernel build. As these ephemeral files don't contain any code,
update the kpatch-gcc glob pattern to ignore them.
(glob pattern suggested by flaming-toast)
Fixes#686.
Strip kpatch_ignore_func_* and __UNIQUE_ID_kpatch_ignore_section_*
symbols to prevent the inclusion of .kpatch.ignore.functions and
.kpatch.ignore.sections. Mark the symbols as SAME, otherwise they are
considered NEW and are recursively included. This includes the
corresponding ignore sections and rela sections and may also create new,
unnecessary dynrelas.
Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
A couple of minor cleanups:
- move the `if (locals)` check to find_local_syms()
- remove the explicit initialization of `local_syms`, the entire struct
was already previously cleared to zero.
When the core module loops through an object's list of dynrelas, it
determines whether or not the target location of the dynrela is in a
read-only region of the patch module. If it is, the readonly flag is set to
1 and it calls set_memory_{rw,ro} before and after the probe_kernel_write()
operation. This flag gets set once, and never gets reset for subsequent
iterations. Therefore, if a target happens to be in a RW section of the
patch module, and readonly = 1 had been set before, we may unintentionally
set a normally RW page to RO. Fix this by setting the readonly flag with
each iteration of the loop.
Fixes#681.
When wiping out the ~/.kpatch cache before replacing it with a new
kernel source, there's no need to keep anything around. Just wipe it
all out and start over.
Also, when building with the -s option, it doesn't need to touch
~/.kpatch/version or ~/.kpatch/src, so it can just skip the cleaning.
That keeps the previous cache around for the next incantation of
kpatch-build without '-s'.
Once upon a time, kpatch-build did the kernel build in three passes.
The extra pass was done without '-ffunction-sections -fdata-sections',
so it could produce the original vmlinux file.
At that time, there was no ~/.kpatch/obj directory. The kernel was
built directly in ~/.kpatch/src. Because the same directory was used
for both the original kernel build and the '-ffunction-sections
-fdata-sections' build, the entire tree had to be rebuilt twice for
every kpatch-build incantation, making it very slow.
That situation was improved with the following commit:
5352d8b01a ("build objects in separate directory to fix caching")
That built the regular and special binaries in ~/.kpatch/obj and
~/.kpatch/obj2, respectively.
Since then we've simplified things so that it only does two build
passes: original and patched, both with '-ffunction-sections
-fdata-sections', and ~/.kpatch/obj2 was removed. However,
~/.kpatch/obj still remained. That's because we never had a reason to
change it, until now.
Recent commit aa2907df29 ("support dup file+symbol")
triggers a new warning:
create-diff-object: ERROR: dynamic_debug.o: find_local_syms: 124: find_local_syms for dynamic_debug.c: found_none
This was actually a preexisting issue which that commit helped uncover.
The root issue is that dynamic_debug.c has some creative uses of the
`__FILE__` macro. When building the kernel objects outside the source
tree, the macro results in a absolute path like:
/home/jpoimboe/.kpatch/src/lib/dynamic_debug.c
But when building inside the source tree it's a relative path:
lib/dynamic_debug.c
The Fedora kernel is built in-tree, and I would imagine most other
distros are also built that way. So the way kpatch builds can result in
a slightly different 'original' object than the distro version, thanks
to the __FILE__ macro.
In this case, the order of the symbol table changed slightly between
vmlinux and the 'orig' object. Presumably, the difference in string
lengths was enough to convince the compiler to shuffle things around a
bit.
So considering that bug, and the possibility of other mismatches, go
back to building the kernel in the source tree.
For some reason, the backticks on this line confuse my editor's syntax
highlighter! Make vim happy by using the other form of command
substition.
Also convert the function definition syntax to comply with the
kpatch-build coding guidelines ;-)
A few symbols are discarded in the kernel linking phase, which means
they won't be in the lookup table. Skip their comparison.
This fixes a bunch of warnings seen when building a patch which triggers
a tree-wide rebuild:
create-diff-object: ERROR: aes_glue.o: find_local_syms: 112: find_local_syms for aes_glue.c: found_none
create-diff-object: ERROR: aesni-intel_glue.o: find_local_syms: 112: find_local_syms for aesni-intel_glue.c: found_none
create-diff-object: ERROR: init.o: find_local_syms: 112: find_local_syms for init.c: found_none
create-diff-object: ERROR: iosf_mbi.o: find_local_syms: 112: find_local_syms for iosf_mbi.c: found_none
create-diff-object: ERROR: setup.o: find_local_syms: 112: find_local_syms for setup.c: found_none
...
After this patch, there's still one warning remaining:
create-diff-object: ERROR: dynamic_debug.o: find_local_syms: 133: find_local_syms for dynamic_debug.c: found_none
That one has a completely different cause, which I'll fix in another
pull request (coming soon).
Fixes: #676