Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

livepatch/klp-build: Introduce klp-build script for generating livepatch modules

Add a klp-build script which automates the generation of a livepatch
module from a source .patch file by performing the following steps:

- Builds an original kernel with -function-sections and
-fdata-sections, plus objtool function checksumming.

- Applies the .patch file and rebuilds the kernel using the same
options.

- Runs 'objtool klp diff' to detect changed functions and generate
intermediate binary diff objects.

- Builds a kernel module which links the diff objects with some
livepatch module init code (scripts/livepatch/init.c).

- Finalizes the livepatch module (aka work around linker wreckage)
using 'objtool klp post-link'.

Acked-by: Petr Mladek <pmladek@suse.com>
Tested-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@kernel.org>

+749 -3
+1
scripts/Makefile.lib
··· 173 173 174 174 objtool := $(objtree)/tools/objtool/objtool 175 175 176 + objtool-args-$(CONFIG_KLP_BUILD) += --checksum 176 177 objtool-args-$(CONFIG_HAVE_JUMP_LABEL_HACK) += --hacks=jump_label 177 178 objtool-args-$(CONFIG_HAVE_NOINSTR_HACK) += --hacks=noinstr 178 179 objtool-args-$(CONFIG_MITIGATION_CALL_DEPTH_TRACKING) += --hacks=skylake
+1 -1
scripts/livepatch/fix-patch-lines
··· 23 23 24 24 in_hunk = 1 25 25 26 - # for @@ -1,3 +1,4 @@: 26 + # @@ -1,3 +1,4 @@: 27 27 # 1: line number in old file 28 28 # 3: how many lines the hunk covers in old file 29 29 # 1: line number in new file
+743
scripts/livepatch/klp-build
··· 1 + #!/bin/bash 2 + # SPDX-License-Identifier: GPL-2.0 3 + # 4 + # Build a livepatch module 5 + 6 + # shellcheck disable=SC1090,SC2155 7 + 8 + if (( BASH_VERSINFO[0] < 4 || \ 9 + (BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] < 4) )); then 10 + echo "error: this script requires bash 4.4+" >&2 11 + exit 1 12 + fi 13 + 14 + set -o errexit 15 + set -o errtrace 16 + set -o pipefail 17 + set -o nounset 18 + 19 + # Allow doing 'cmd | mapfile -t array' instead of 'mapfile -t array < <(cmd)'. 20 + # This helps keep execution in pipes so pipefail+errexit can catch errors. 21 + shopt -s lastpipe 22 + 23 + unset SKIP_CLEANUP XTRACE 24 + 25 + REPLACE=1 26 + SHORT_CIRCUIT=0 27 + JOBS="$(getconf _NPROCESSORS_ONLN)" 28 + VERBOSE="-s" 29 + shopt -o xtrace | grep -q 'on' && XTRACE=1 30 + 31 + # Avoid removing the previous $TMP_DIR until args have been fully processed. 32 + KEEP_TMP=1 33 + 34 + SCRIPT="$(basename "$0")" 35 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 36 + FIX_PATCH_LINES="$SCRIPT_DIR/fix-patch-lines" 37 + 38 + SRC="$(pwd)" 39 + OBJ="$(pwd)" 40 + 41 + CONFIG="$OBJ/.config" 42 + TMP_DIR="$OBJ/klp-tmp" 43 + 44 + ORIG_DIR="$TMP_DIR/orig" 45 + PATCHED_DIR="$TMP_DIR/patched" 46 + DIFF_DIR="$TMP_DIR/diff" 47 + KMOD_DIR="$TMP_DIR/kmod" 48 + 49 + STASH_DIR="$TMP_DIR/stash" 50 + TIMESTAMP="$TMP_DIR/timestamp" 51 + PATCH_TMP_DIR="$TMP_DIR/tmp" 52 + 53 + KLP_DIFF_LOG="$DIFF_DIR/diff.log" 54 + 55 + grep0() { 56 + command grep "$@" || true 57 + } 58 + 59 + status() { 60 + echo "$*" 61 + } 62 + 63 + warn() { 64 + echo "error: $SCRIPT: $*" >&2 65 + } 66 + 67 + die() { 68 + warn "$@" 69 + exit 1 70 + } 71 + 72 + declare -a STASHED_FILES 73 + 74 + stash_file() { 75 + local file="$1" 76 + local rel_file="${file#"$SRC"/}" 77 + 78 + [[ ! -e "$file" ]] && die "no file to stash: $file" 79 + 80 + mkdir -p "$STASH_DIR/$(dirname "$rel_file")" 81 + cp -f "$file" "$STASH_DIR/$rel_file" 82 + 83 + STASHED_FILES+=("$rel_file") 84 + } 85 + 86 + restore_files() { 87 + local file 88 + 89 + for file in "${STASHED_FILES[@]}"; do 90 + mv -f "$STASH_DIR/$file" "$SRC/$file" || warn "can't restore file: $file" 91 + done 92 + 93 + STASHED_FILES=() 94 + } 95 + 96 + cleanup() { 97 + set +o nounset 98 + revert_patches "--recount" 99 + restore_files 100 + [[ "$KEEP_TMP" -eq 0 ]] && rm -rf "$TMP_DIR" 101 + return 0 102 + } 103 + 104 + trap_err() { 105 + warn "line ${BASH_LINENO[0]}: '$BASH_COMMAND'" 106 + } 107 + 108 + trap cleanup EXIT INT TERM HUP 109 + trap trap_err ERR 110 + 111 + __usage() { 112 + cat <<EOF 113 + Usage: $SCRIPT [OPTIONS] PATCH_FILE(s) 114 + Generate a livepatch module. 115 + 116 + Options: 117 + -j, --jobs=<jobs> Build jobs to run simultaneously [default: $JOBS] 118 + -o, --output=<file.ko> Output file [default: livepatch-<patch-name>.ko] 119 + --no-replace Disable livepatch atomic replace 120 + -v, --verbose Pass V=1 to kernel/module builds 121 + 122 + Advanced Options: 123 + -S, --short-circuit=STEP Start at build step (requires prior --keep-tmp) 124 + 1|orig Build original kernel (default) 125 + 2|patched Build patched kernel 126 + 3|diff Diff objects 127 + 4|kmod Build patch module 128 + -T, --keep-tmp Preserve tmp dir on exit 129 + 130 + EOF 131 + } 132 + 133 + usage() { 134 + __usage >&2 135 + } 136 + 137 + process_args() { 138 + local keep_tmp=0 139 + local short 140 + local long 141 + local args 142 + 143 + short="hj:o:vS:T" 144 + long="help,jobs:,output:,no-replace,verbose,short-circuit:,keep-tmp" 145 + 146 + args=$(getopt --options "$short" --longoptions "$long" -- "$@") || { 147 + echo; usage; exit 148 + } 149 + eval set -- "$args" 150 + 151 + while true; do 152 + case "$1" in 153 + -h | --help) 154 + usage 155 + exit 0 156 + ;; 157 + -j | --jobs) 158 + JOBS="$2" 159 + shift 2 160 + ;; 161 + -o | --output) 162 + [[ "$2" != *.ko ]] && die "output filename should end with .ko" 163 + OUTFILE="$2" 164 + NAME="$(basename "$OUTFILE")" 165 + NAME="${NAME%.ko}" 166 + NAME="$(module_name_string "$NAME")" 167 + shift 2 168 + ;; 169 + --no-replace) 170 + REPLACE=0 171 + shift 172 + ;; 173 + -v | --verbose) 174 + VERBOSE="V=1" 175 + shift 176 + ;; 177 + -S | --short-circuit) 178 + [[ ! -d "$TMP_DIR" ]] && die "--short-circuit requires preserved klp-tmp dir" 179 + keep_tmp=1 180 + case "$2" in 181 + 1 | orig) SHORT_CIRCUIT=1; ;; 182 + 2 | patched) SHORT_CIRCUIT=2; ;; 183 + 3 | diff) SHORT_CIRCUIT=3; ;; 184 + 4 | mod) SHORT_CIRCUIT=4; ;; 185 + *) die "invalid short-circuit step '$2'" ;; 186 + esac 187 + shift 2 188 + ;; 189 + -T | --keep-tmp) 190 + keep_tmp=1 191 + shift 192 + ;; 193 + --) 194 + shift 195 + break 196 + ;; 197 + *) 198 + usage 199 + exit 1 200 + ;; 201 + esac 202 + done 203 + 204 + if [[ $# -eq 0 ]]; then 205 + usage 206 + exit 1 207 + fi 208 + 209 + KEEP_TMP="$keep_tmp" 210 + PATCHES=("$@") 211 + } 212 + 213 + # temporarily disable xtrace for especially verbose code 214 + xtrace_save() { 215 + [[ -v XTRACE ]] && set +x 216 + return 0 217 + } 218 + 219 + xtrace_restore() { 220 + [[ -v XTRACE ]] && set -x 221 + return 0 222 + } 223 + 224 + validate_config() { 225 + xtrace_save "reading .config" 226 + source "$CONFIG" || die "no .config file in $(dirname "$CONFIG")" 227 + xtrace_restore 228 + 229 + [[ -v CONFIG_LIVEPATCH ]] || \ 230 + die "CONFIG_LIVEPATCH not enabled" 231 + 232 + [[ -v CONFIG_KLP_BUILD ]] || \ 233 + die "CONFIG_KLP_BUILD not enabled" 234 + 235 + [[ -v CONFIG_GCC_PLUGIN_LATENT_ENTROPY ]] && \ 236 + die "kernel option 'CONFIG_GCC_PLUGIN_LATENT_ENTROPY' not supported" 237 + 238 + [[ -v CONFIG_GCC_PLUGIN_RANDSTRUCT ]] && \ 239 + die "kernel option 'CONFIG_GCC_PLUGIN_RANDSTRUCT' not supported" 240 + 241 + return 0 242 + } 243 + 244 + # Only allow alphanumerics and '_' and '-' in the module name. Everything else 245 + # is replaced with '-'. Also truncate to 55 chars so the full name + NUL 246 + # terminator fits in the kernel's 56-byte module name array. 247 + module_name_string() { 248 + echo "${1//[^a-zA-Z0-9_-]/-}" | cut -c 1-55 249 + } 250 + 251 + # If the module name wasn't specified on the cmdline with --output, give it a 252 + # name based on the patch name. 253 + set_module_name() { 254 + [[ -v NAME ]] && return 0 255 + 256 + if [[ "${#PATCHES[@]}" -eq 1 ]]; then 257 + NAME="$(basename "${PATCHES[0]}")" 258 + NAME="${NAME%.*}" 259 + else 260 + NAME="patch" 261 + fi 262 + 263 + NAME="livepatch-$NAME" 264 + NAME="$(module_name_string "$NAME")" 265 + 266 + OUTFILE="$NAME.ko" 267 + } 268 + 269 + # Hardcode the value printed by the localversion script to prevent patch 270 + # application from appending it with '+' due to a dirty git working tree. 271 + set_kernelversion() { 272 + local file="$SRC/scripts/setlocalversion" 273 + local localversion 274 + 275 + stash_file "$file" 276 + 277 + localversion="$(cd "$SRC" && make --no-print-directory kernelversion)" 278 + localversion="$(cd "$SRC" && KERNELVERSION="$localversion" ./scripts/setlocalversion)" 279 + [[ -z "$localversion" ]] && die "setlocalversion failed" 280 + 281 + sed -i "2i echo $localversion; exit 0" scripts/setlocalversion 282 + } 283 + 284 + get_patch_files() { 285 + local patch="$1" 286 + 287 + grep0 -E '^(--- |\+\+\+ )' "$patch" \ 288 + | gawk '{print $2}' \ 289 + | sed 's|^[^/]*/||' \ 290 + | sort -u 291 + } 292 + 293 + # Make sure git re-stats the changed files 294 + git_refresh() { 295 + local patch="$1" 296 + local files=() 297 + 298 + [[ ! -e "$SRC/.git" ]] && return 299 + 300 + get_patch_files "$patch" | mapfile -t files 301 + 302 + ( 303 + cd "$SRC" 304 + git update-index -q --refresh -- "${files[@]}" 305 + ) 306 + } 307 + 308 + check_unsupported_patches() { 309 + local patch 310 + 311 + for patch in "${PATCHES[@]}"; do 312 + local files=() 313 + 314 + get_patch_files "$patch" | mapfile -t files 315 + 316 + for file in "${files[@]}"; do 317 + case "$file" in 318 + lib/*|*.S) 319 + die "unsupported patch to $file" 320 + ;; 321 + esac 322 + done 323 + done 324 + } 325 + 326 + apply_patch() { 327 + local patch="$1" 328 + shift 329 + local extra_args=("$@") 330 + 331 + [[ ! -f "$patch" ]] && die "$patch doesn't exist" 332 + 333 + ( 334 + cd "$SRC" 335 + 336 + # The sed strips the version signature from 'git format-patch', 337 + # otherwise 'git apply --recount' warns. 338 + sed -n '/^-- /q;p' "$patch" | 339 + git apply "${extra_args[@]}" 340 + ) 341 + 342 + APPLIED_PATCHES+=("$patch") 343 + } 344 + 345 + revert_patch() { 346 + local patch="$1" 347 + shift 348 + local extra_args=("$@") 349 + local tmp=() 350 + 351 + ( 352 + cd "$SRC" 353 + 354 + sed -n '/^-- /q;p' "$patch" | 355 + git apply --reverse "${extra_args[@]}" 356 + ) 357 + git_refresh "$patch" 358 + 359 + for p in "${APPLIED_PATCHES[@]}"; do 360 + [[ "$p" == "$patch" ]] && continue 361 + tmp+=("$p") 362 + done 363 + 364 + APPLIED_PATCHES=("${tmp[@]}") 365 + } 366 + 367 + apply_patches() { 368 + local patch 369 + 370 + for patch in "${PATCHES[@]}"; do 371 + apply_patch "$patch" 372 + done 373 + } 374 + 375 + revert_patches() { 376 + local extra_args=("$@") 377 + local patches=("${APPLIED_PATCHES[@]}") 378 + 379 + for (( i=${#patches[@]}-1 ; i>=0 ; i-- )) ; do 380 + revert_patch "${patches[$i]}" "${extra_args[@]}" 381 + done 382 + 383 + APPLIED_PATCHES=() 384 + } 385 + 386 + validate_patches() { 387 + check_unsupported_patches 388 + apply_patches 389 + revert_patches 390 + } 391 + 392 + do_init() { 393 + # We're not yet smart enough to handle anything other than in-tree 394 + # builds in pwd. 395 + [[ ! "$SRC" -ef "$SCRIPT_DIR/../.." ]] && die "please run from the kernel root directory" 396 + [[ ! "$OBJ" -ef "$SCRIPT_DIR/../.." ]] && die "please run from the kernel root directory" 397 + 398 + (( SHORT_CIRCUIT <= 1 )) && rm -rf "$TMP_DIR" 399 + mkdir -p "$TMP_DIR" 400 + 401 + APPLIED_PATCHES=() 402 + 403 + [[ -x "$FIX_PATCH_LINES" ]] || die "can't find fix-patch-lines" 404 + 405 + validate_config 406 + set_module_name 407 + set_kernelversion 408 + } 409 + 410 + # Refresh the patch hunk headers, specifically the line numbers and counts. 411 + refresh_patch() { 412 + local patch="$1" 413 + local tmpdir="$PATCH_TMP_DIR" 414 + local files=() 415 + 416 + rm -rf "$tmpdir" 417 + mkdir -p "$tmpdir/a" 418 + mkdir -p "$tmpdir/b" 419 + 420 + # Get all source files affected by the patch 421 + get_patch_files "$patch" | mapfile -t files 422 + 423 + # Copy orig source files to 'a' 424 + ( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/a" ) 425 + 426 + # Copy patched source files to 'b' 427 + apply_patch "$patch" --recount 428 + ( cd "$SRC" && echo "${files[@]}" | xargs cp --parents --target-directory="$tmpdir/b" ) 429 + revert_patch "$patch" --recount 430 + 431 + # Diff 'a' and 'b' to make a clean patch 432 + ( cd "$tmpdir" && git diff --no-index --no-prefix a b > "$patch" ) || true 433 + } 434 + 435 + # Copy the patches to a temporary directory, fix their lines so as not to 436 + # affect the __LINE__ macro for otherwise unchanged functions further down the 437 + # file, and update $PATCHES to point to the fixed patches. 438 + fix_patches() { 439 + local idx 440 + local i 441 + 442 + rm -f "$TMP_DIR"/*.patch 443 + 444 + idx=0001 445 + for i in "${!PATCHES[@]}"; do 446 + local old_patch="${PATCHES[$i]}" 447 + local tmp_patch="$TMP_DIR/tmp.patch" 448 + local patch="${PATCHES[$i]}" 449 + local new_patch 450 + 451 + new_patch="$TMP_DIR/$idx-fixed-$(basename "$patch")" 452 + 453 + cp -f "$old_patch" "$tmp_patch" 454 + refresh_patch "$tmp_patch" 455 + "$FIX_PATCH_LINES" "$tmp_patch" > "$new_patch" 456 + refresh_patch "$new_patch" 457 + 458 + PATCHES[i]="$new_patch" 459 + 460 + rm -f "$tmp_patch" 461 + idx=$(printf "%04d" $(( 10#$idx + 1 ))) 462 + done 463 + } 464 + 465 + clean_kernel() { 466 + local cmd=() 467 + 468 + cmd=("make") 469 + cmd+=("--silent") 470 + cmd+=("-j$JOBS") 471 + cmd+=("clean") 472 + 473 + ( 474 + cd "$SRC" 475 + "${cmd[@]}" 476 + ) 477 + } 478 + 479 + build_kernel() { 480 + local log="$TMP_DIR/build.log" 481 + local cmd=() 482 + 483 + cmd=("make") 484 + 485 + # When a patch to a kernel module references a newly created unexported 486 + # symbol which lives in vmlinux or another kernel module, the patched 487 + # kernel build fails with the following error: 488 + # 489 + # ERROR: modpost: "klp_string" [fs/xfs/xfs.ko] undefined! 490 + # 491 + # The undefined symbols are working as designed in that case. They get 492 + # resolved later when the livepatch module build link pulls all the 493 + # disparate objects together into the same kernel module. 494 + # 495 + # It would be good to have a way to tell modpost to skip checking for 496 + # undefined symbols altogether. For now, just convert the error to a 497 + # warning with KBUILD_MODPOST_WARN, and grep out the warning to avoid 498 + # confusing the user. 499 + # 500 + cmd+=("KBUILD_MODPOST_WARN=1") 501 + 502 + cmd+=("$VERBOSE") 503 + cmd+=("-j$JOBS") 504 + cmd+=("KCFLAGS=-ffunction-sections -fdata-sections") 505 + cmd+=("vmlinux") 506 + cmd+=("modules") 507 + 508 + ( 509 + cd "$SRC" 510 + "${cmd[@]}" \ 511 + 1> >(tee -a "$log") \ 512 + 2> >(tee -a "$log" | grep0 -v "modpost.*undefined!" >&2) 513 + ) 514 + } 515 + 516 + find_objects() { 517 + local opts=("$@") 518 + 519 + # Find root-level vmlinux.o and non-root-level .ko files, 520 + # excluding klp-tmp/ and .git/ 521 + find "$OBJ" \( -path "$TMP_DIR" -o -path "$OBJ/.git" -o -regex "$OBJ/[^/][^/]*\.ko" \) -prune -o \ 522 + -type f "${opts[@]}" \ 523 + \( -name "*.ko" -o -path "$OBJ/vmlinux.o" \) \ 524 + -printf '%P\n' 525 + } 526 + 527 + # Copy all .o archives to $ORIG_DIR 528 + copy_orig_objects() { 529 + local files=() 530 + 531 + rm -rf "$ORIG_DIR" 532 + mkdir -p "$ORIG_DIR" 533 + 534 + find_objects | mapfile -t files 535 + 536 + xtrace_save "copying orig objects" 537 + for _file in "${files[@]}"; do 538 + local rel_file="${_file/.ko/.o}" 539 + local file="$OBJ/$rel_file" 540 + local file_dir="$(dirname "$file")" 541 + local orig_file="$ORIG_DIR/$rel_file" 542 + local orig_dir="$(dirname "$orig_file")" 543 + local cmd_file="$file_dir/.$(basename "$file").cmd" 544 + 545 + [[ ! -f "$file" ]] && die "missing $(basename "$file") for $_file" 546 + 547 + mkdir -p "$orig_dir" 548 + cp -f "$file" "$orig_dir" 549 + [[ -e "$cmd_file" ]] && cp -f "$cmd_file" "$orig_dir" 550 + done 551 + xtrace_restore 552 + 553 + mv -f "$TMP_DIR/build.log" "$ORIG_DIR" 554 + touch "$TIMESTAMP" 555 + } 556 + 557 + # Copy all changed objects to $PATCHED_DIR 558 + copy_patched_objects() { 559 + local files=() 560 + local opts=() 561 + local found=0 562 + 563 + rm -rf "$PATCHED_DIR" 564 + mkdir -p "$PATCHED_DIR" 565 + 566 + # Note this doesn't work with some configs, thus the 'cmp' below. 567 + opts=("-newer") 568 + opts+=("$TIMESTAMP") 569 + 570 + find_objects "${opts[@]}" | mapfile -t files 571 + 572 + xtrace_save "copying changed objects" 573 + for _file in "${files[@]}"; do 574 + local rel_file="${_file/.ko/.o}" 575 + local file="$OBJ/$rel_file" 576 + local orig_file="$ORIG_DIR/$rel_file" 577 + local patched_file="$PATCHED_DIR/$rel_file" 578 + local patched_dir="$(dirname "$patched_file")" 579 + 580 + [[ ! -f "$file" ]] && die "missing $(basename "$file") for $_file" 581 + 582 + cmp -s "$orig_file" "$file" && continue 583 + 584 + mkdir -p "$patched_dir" 585 + cp -f "$file" "$patched_dir" 586 + found=1 587 + done 588 + xtrace_restore 589 + 590 + (( found == 0 )) && die "no changes detected" 591 + 592 + mv -f "$TMP_DIR/build.log" "$PATCHED_DIR" 593 + } 594 + 595 + # Diff changed objects, writing output object to $DIFF_DIR 596 + diff_objects() { 597 + local log="$KLP_DIFF_LOG" 598 + local files=() 599 + 600 + rm -rf "$DIFF_DIR" 601 + mkdir -p "$DIFF_DIR" 602 + 603 + find "$PATCHED_DIR" -type f -name "*.o" | mapfile -t files 604 + [[ ${#files[@]} -eq 0 ]] && die "no changes detected" 605 + 606 + # Diff all changed objects 607 + for file in "${files[@]}"; do 608 + local rel_file="${file#"$PATCHED_DIR"/}" 609 + local orig_file="$rel_file" 610 + local patched_file="$PATCHED_DIR/$rel_file" 611 + local out_file="$DIFF_DIR/$rel_file" 612 + local cmd=() 613 + 614 + mkdir -p "$(dirname "$out_file")" 615 + 616 + cmd=("$SRC/tools/objtool/objtool") 617 + cmd+=("klp") 618 + cmd+=("diff") 619 + cmd+=("$orig_file") 620 + cmd+=("$patched_file") 621 + cmd+=("$out_file") 622 + 623 + ( 624 + cd "$ORIG_DIR" 625 + "${cmd[@]}" \ 626 + 1> >(tee -a "$log") \ 627 + 2> >(tee -a "$log" >&2) || \ 628 + die "objtool klp diff failed" 629 + ) 630 + done 631 + } 632 + 633 + # Build and post-process livepatch module in $KMOD_DIR 634 + build_patch_module() { 635 + local makefile="$KMOD_DIR/Kbuild" 636 + local log="$KMOD_DIR/build.log" 637 + local kmod_file 638 + local cflags=() 639 + local files=() 640 + local cmd=() 641 + 642 + rm -rf "$KMOD_DIR" 643 + mkdir -p "$KMOD_DIR" 644 + 645 + cp -f "$SRC/scripts/livepatch/init.c" "$KMOD_DIR" 646 + 647 + echo "obj-m := $NAME.o" > "$makefile" 648 + echo -n "$NAME-y := init.o" >> "$makefile" 649 + 650 + find "$DIFF_DIR" -type f -name "*.o" | mapfile -t files 651 + [[ ${#files[@]} -eq 0 ]] && die "no changes detected" 652 + 653 + for file in "${files[@]}"; do 654 + local rel_file="${file#"$DIFF_DIR"/}" 655 + local orig_file="$ORIG_DIR/$rel_file" 656 + local orig_dir="$(dirname "$orig_file")" 657 + local kmod_file="$KMOD_DIR/$rel_file" 658 + local kmod_dir="$(dirname "$kmod_file")" 659 + local cmd_file="$orig_dir/.$(basename "$file").cmd" 660 + 661 + mkdir -p "$kmod_dir" 662 + cp -f "$file" "$kmod_dir" 663 + [[ -e "$cmd_file" ]] && cp -f "$cmd_file" "$kmod_dir" 664 + 665 + # Tell kbuild this is a prebuilt object 666 + cp -f "$file" "${kmod_file}_shipped" 667 + 668 + echo -n " $rel_file" >> "$makefile" 669 + done 670 + 671 + echo >> "$makefile" 672 + 673 + cflags=("-ffunction-sections") 674 + cflags+=("-fdata-sections") 675 + [[ $REPLACE -eq 0 ]] && cflags+=("-DKLP_NO_REPLACE") 676 + 677 + cmd=("make") 678 + cmd+=("$VERBOSE") 679 + cmd+=("-j$JOBS") 680 + cmd+=("--directory=.") 681 + cmd+=("M=$KMOD_DIR") 682 + cmd+=("KCFLAGS=${cflags[*]}") 683 + 684 + # Build a "normal" kernel module with init.c and the diffed objects 685 + ( 686 + cd "$SRC" 687 + "${cmd[@]}" \ 688 + 1> >(tee -a "$log") \ 689 + 2> >(tee -a "$log" >&2) 690 + ) 691 + 692 + kmod_file="$KMOD_DIR/$NAME.ko" 693 + 694 + # Save off the intermediate binary for debugging 695 + cp -f "$kmod_file" "$kmod_file.orig" 696 + 697 + # Work around issue where slight .config change makes corrupt BTF 698 + objcopy --remove-section=.BTF "$kmod_file" 699 + 700 + # Fix (and work around) linker wreckage for klp syms / relocs 701 + "$SRC/tools/objtool/objtool" klp post-link "$kmod_file" || die "objtool klp post-link failed" 702 + 703 + cp -f "$kmod_file" "$OUTFILE" 704 + } 705 + 706 + 707 + ################################################################################ 708 + 709 + process_args "$@" 710 + do_init 711 + 712 + if (( SHORT_CIRCUIT <= 1 )); then 713 + status "Validating patch(es)" 714 + validate_patches 715 + status "Building original kernel" 716 + clean_kernel 717 + build_kernel 718 + status "Copying original object files" 719 + copy_orig_objects 720 + fi 721 + 722 + if (( SHORT_CIRCUIT <= 2 )); then 723 + status "Fixing patch(es)" 724 + fix_patches 725 + apply_patches 726 + status "Building patched kernel" 727 + build_kernel 728 + revert_patches 729 + status "Copying patched object files" 730 + copy_patched_objects 731 + fi 732 + 733 + if (( SHORT_CIRCUIT <= 3 )); then 734 + status "Diffing objects" 735 + diff_objects 736 + fi 737 + 738 + if (( SHORT_CIRCUIT <= 4 )); then 739 + status "Building patch module: $OUTFILE" 740 + build_patch_module 741 + fi 742 + 743 + status "SUCCESS"
+4 -2
tools/objtool/klp-diff.c
··· 241 241 static bool is_uncorrelated_static_local(struct symbol *sym) 242 242 { 243 243 static const char * const vars[] = { 244 - "__key.", 245 - "__warned.", 246 244 "__already_done.", 247 245 "__func__.", 246 + "__key.", 247 + "__warned.", 248 + "_entry.", 249 + "_entry_ptr.", 248 250 "_rs.", 249 251 "descriptor.", 250 252 "CSWTCH.",