create-diff-object: Remove undefined function symbols#1494
create-diff-object: Remove undefined function symbols#1494sumanthkorikkar wants to merge 1 commit intodynup:masterfrom
Conversation
|
The dynamic-debug-jump-label-issue-1253 test is failing with this PR. I will investigate the failing test. Let me know, if there are better approaches or suggestions to solve this problem. Thank you |
d94e516 to
b0f93df
Compare
|
Added RFC patch v2 |
|
Other possible fix/hack: Required rela symbols are included later in kpatch_regenerate_special_section() anyways. So, my assumption is that it might be safe to unconditionally skip relocation symbols for .rela__bug_table during the initial pass in kpatch_include_section(). Later, kpatch_generate_special_section() will explicitly add the required symbols (though not recursively). And if any of the referenced rela->sym->sec entries are actually needed, they will still get included through other sections associated with changed functions. |
|
I saw this same problem with klp-build (the kpatch-build replacement has just been upstreamed for x86), see linux commit f2dba60339a6 ("objtool/klp: Fix bug table handling for __WARN_printf()"). The fix for klp-build was simple, but it might be harder here. The problem is that WARN() has been converted to a static call, which passes a reference to its bug table entry (in __bug_table) to the static call, which looks like: Notice the I haven't looked to see how hard that would be. kpatch-build for x86 is basically deprecated at this point. |
|
WRT to this PR in particular, I don't think we want to keep all those extra bug table entries. |
Thanks for the inputs. I will recheck it. |
…e __bug_table When building shadow-pid.patch on a debug kernel, it generates __bug_table, which contains an array of struct bug_entries. create-diff-object identifies that .text.kernel_clone has changed and it includes .rela.text.kernel_clone rela section. Then later, it includes all symbols (in kpatch_include_symbols()) associated with it, which ends up including __bug_table and its rela section .rela__bug_table. Then, all the function symbols associated with .rela__bug_table is included irrespective of whether it's section is included or not. The problem occurs since WARN() has been converted to a static call, which passes a reference to its bug table entry (in __bug_table) to the static call. That direct reference from a function to a special section is new, and that's causing create-diff-object to incorrectly pull in the entire __bug_table. (As mentioned by Josh) It leads to the following modpost errors with shadow-pid.patch: kernel/fork.o: changed function: kernel_clone kernel/exit.o: changed function: do_exit fs/proc/array.o: changed function: proc_pid_status make -C /root/linux M=/root/.kpatch/tmp/patch CFLAGS_MODULE='' make[1]: Entering directory '/root/linux' make[2]: Entering directory '/root/.kpatch/tmp/patch' LDS kpatch.lds CC [M] patch-hook.o LD [M] test-shadow-newpid.o MODPOST Module.symvers WARNING: modpost: missing MODULE_DESCRIPTION() in test-shadow-newpid.o ERROR: modpost: "replace_mm_exe_file" [test-shadow-newpid.ko] undefined! ERROR: modpost: "put_task_stack" [test-shadow-newpid.ko] undefined! ERROR: modpost: "release_task" [test-shadow-newpid.ko] undefined! ERROR: modpost: "set_mm_exe_file" [test-shadow-newpid.ko] undefined! Examining the /root/.kpatch/patch/ directory reveals, these symbols are never referenced in any relas. readelf -Ws output.o | grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file' 27: 0000000000000000 0 SECTION LOCAL DEFAULT 36 .rodata.release_task.str1.2 45: 0000000000000000 0 SECTION LOCAL DEFAULT 55 .rodata.set_mm_exe_file.str1.2 47: 0000000000000000 0 SECTION LOCAL DEFAULT 57 .rodata.replace_mm_exe_file.str1.2 234: 0000000000000000 0 FUNC GLOBAL DEFAULT UND replace_mm_exe_file 254: 0000000000000000 0 FUNC GLOBAL DEFAULT UND put_task_stack 263: 0000000000000000 0 FUNC GLOBAL DEFAULT UND release_task 269: 0000000000000000 0 FUNC GLOBAL DEFAULT UND set_mm_exe_file readelf -Wr output.o | grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file' <EMPTY> Solution: Skip initial symbol inclusion from .rela__bug_table to prevent unwanted __bug_table propagation caused by static call WARN() relocations. These relocations are instead handled later during special section regeneration. Also recalculate addends of relocations targeting __bug_table when bug table entries move, ensuring all references remain consistent. Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
b0f93df to
6571f2a
Compare
|
Added v3:
|
|
/packit test |
|
@sumanthkorikkar : I haven't been following this PR closely, is this only relevant for debug kernels? Just wondering if this would be needed as a bug-fix type change in light of Josh's recent maintenance-only mode announcement (#1499). I was thinking of tagging a v0.9.12 to capture the last round of fixes and enhancements since the last version, and didn't know if this might qualify as well. |
|
@Tomcat-42 : any idea why testing-farm:RHEL-8.10.0-Nightly-ppc64le:integration-rhel failed? The other tests (save for the known Fedora infra issues) all passed, so I'm assuming something intermittent? |
|
@joe-lawrence Yep, I guess it was some transient failure on infra, I've re-runned the job and it passed. The Fedora integration-upstream jobs are fixed in master (except ppc64le), so maybe @sumanthkorikkar wants to do a rebase? (I've noticed that push by maintainers is disabled in his fork) |
Thanks for the information. It would be nice to have this PR as bug fix in the kpatch. This is relevant for only debug kernel and problem occurs in x86 and s390 Relevant commit: |
@Tomcat-42 , no - i have already done the rebasing for v3 here. Let me know, if I have to do anything else with my branch. Thank you. |
When building shadow-pid.patch on a debug kernel, it generates __bug_table, which contains an array of struct bug_entries.
.rela__bug_table contains references to bug address, line number and column.
create-diff-object identifies that .text.kernel_clone has changed and it includes .rela.text.kernel_clone rela section. Then later, it includes all symbols (in kpatch_include_symbols()) associated with it, which ends up including __bug_table and its rela section .rela__bug_table. Then, all the function symbols associated with .rela__bug_table is included irrespective of whether it's section is included or not.
This leads to the following modpost errors:
kernel/fork.o: changed function: kernel_clone
kernel/exit.o: changed function: do_exit
fs/proc/array.o: changed function: proc_pid_status make -C /root/linux M=/root/.kpatch/tmp/patch CFLAGS_MODULE='' make[1]: Entering directory '/root/linux'
make[2]: Entering directory '/root/.kpatch/tmp/patch'
LDS kpatch.lds
CC [M] patch-hook.o
LD [M] test-shadow-newpid.o
MODPOST Module.symvers
WARNING: modpost: missing MODULE_DESCRIPTION() in test-shadow-newpid.o
ERROR: modpost: "replace_mm_exe_file" [test-shadow-newpid.ko] undefined!
ERROR: modpost: "put_task_stack" [test-shadow-newpid.ko] undefined!
ERROR: modpost: "release_task" [test-shadow-newpid.ko] undefined!
ERROR: modpost: "set_mm_exe_file" [test-shadow-newpid.ko] undefined!
Examining the /root/.kpatch/patch/ directory reveals, these symbols are never referenced in any relas.
readelf -Ws output.o |
grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file'
27: 0000000000000000 0 SECTION LOCAL DEFAULT 36 .rodata.release_task.str1.2
45: 0000000000000000 0 SECTION LOCAL DEFAULT 55 .rodata.set_mm_exe_file.str1.2
47: 0000000000000000 0 SECTION LOCAL DEFAULT 57 .rodata.replace_mm_exe_file.str1.2
234: 0000000000000000 0 FUNC GLOBAL DEFAULT UND replace_mm_exe_file
254: 0000000000000000 0 FUNC GLOBAL DEFAULT UND put_task_stack
263: 0000000000000000 0 FUNC GLOBAL DEFAULT UND release_task
269: 0000000000000000 0 FUNC GLOBAL DEFAULT UND set_mm_exe_file
readelf -Wr output.o |
grep -E 'put_task_stack|replace_mm_exe_file|release_task|set_mm_exe_file'
Hence, exclude these unreferenced symbols to avoid modpost errors.
Fix:
PATCH RFC v2:
Note: Skipped need_klp_reloc()/kpatch_create_intermediate_sections()
check for .rela__bug_table section.
Reason: The function symbols that were not referenced by any sections
other than .rela__bug_table were being initialized with include = 0 (via
rela->sym->include = 0). As a result, kpatch_migrate_included_elements()
did not migrate these function symbols into kelf_out. However, later in
kpatch_create_intermediate_sections(), when parsing the .rela__bug_table
relasec and evaluating each symbol in need_klp_reloc(), the
code ended up using the previous rela->sym reference (which had already
been torn down). Since that symbol had its include field set to 0, the
dereference led to a segmentation fault. To prevent this, the
.rela__bug_table section is excluded from consideration in
kpatch_migrate_included_elements(). Additionally, if a function is
modified, the assumption is that, it will be referenced by other
relasec.