From f22d46eeecc11dc23fbf6fc7957ba5e9e3c846aa Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Wed, 6 Oct 2021 10:28:37 -0400 Subject: [PATCH] import kexec-tools-2.0.20-57.el8 --- SOURCES/60-kdump.install | 14 +- SOURCES/98-kexec.rules.ppc64 | 17 +- SOURCES/dracut-kdump.sh | 4 +- SOURCES/dracut-module-setup.sh | 175 +++++++++++++- SOURCES/fadump-howto.txt | 16 +- SOURCES/kdump-lib-initramfs.sh | 2 + SOURCES/kdump-lib.sh | 224 +++++++++++++++++- SOURCES/kdump-migrate-action.sh | 8 + SOURCES/kdump-restart.sh | 8 + SOURCES/kdump.sysconfig.s390x | 2 +- SOURCES/kdumpctl | 147 +++++++++++- SOURCES/kdumpctl.8 | 5 + ...dd-dry-run-option-to-prevent-writing.patch | 177 ++++++++++++++ ...-shorthand-show-stats-option-to-show.patch | 107 +++++++++ ...w-write-byte-size-in-report-messages.patch | 59 +++++ ...ss-proc-kcore-when-finding-max_paddr.patch | 60 +++++ ...-proc-kcore-when-making-ELF-dumpfile.patch | 43 ++++ SOURCES/mkdumprd | 34 +-- SPECS/kexec-tools.spec | 86 ++++++- 19 files changed, 1112 insertions(+), 76 deletions(-) create mode 100755 SOURCES/kdump-migrate-action.sh create mode 100644 SOURCES/kdump-restart.sh create mode 100644 SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch create mode 100644 SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch create mode 100644 SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch create mode 100644 SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch create mode 100644 SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch diff --git a/SOURCES/60-kdump.install b/SOURCES/60-kdump.install index 0a3b40e..5b0e021 100755 --- a/SOURCES/60-kdump.install +++ b/SOURCES/60-kdump.install @@ -2,17 +2,23 @@ COMMAND="$1" KERNEL_VERSION="$2" -BOOT_DIR_ABS="$3" +KDUMP_INITRD_DIR_ABS="$3" KERNEL_IMAGE="$4" if ! [[ ${KERNEL_INSTALL_MACHINE_ID-x} ]]; then exit 0 fi -if [[ -d "$BOOT_DIR_ABS" ]]; then +if [[ -d "$KDUMP_INITRD_DIR_ABS" ]]; then KDUMP_INITRD="initrdkdump" else - BOOT_DIR_ABS="/boot" + # If `KDUMP_BOOTDIR` is not writable, then the kdump + # initrd must have been placed at `/var/lib/kdump` + if [[ ! -w "/boot" ]]; then + KDUMP_INITRD_DIR_ABS="/var/lib/kdump" + else + KDUMP_INITRD_DIR_ABS="/boot" + fi KDUMP_INITRD="initramfs-${KERNEL_VERSION}kdump.img" fi @@ -23,7 +29,7 @@ case "$COMMAND" in # and managed by kdump service ;; remove) - rm -f -- "$BOOT_DIR_ABS/$KDUMP_INITRD" + rm -f -- "$KDUMP_INITRD_DIR_ABS/$KDUMP_INITRD" ret=$? ;; esac diff --git a/SOURCES/98-kexec.rules.ppc64 b/SOURCES/98-kexec.rules.ppc64 index 1a91220..a1c00a9 100644 --- a/SOURCES/98-kexec.rules.ppc64 +++ b/SOURCES/98-kexec.rules.ppc64 @@ -1,15 +1,22 @@ -SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload" -SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload" -SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload" +SUBSYSTEM=="cpu", ACTION=="online", GOTO="kdump_reload_cpu" +SUBSYSTEM=="memory", ACTION=="online", GOTO="kdump_reload_mem" +SUBSYSTEM=="memory", ACTION=="offline", GOTO="kdump_reload_mem" GOTO="kdump_reload_end" -LABEL="kdump_reload" - # If kdump is not loaded, calling kdump-udev-throttle will end up # doing nothing, but systemd-run will always generate extra logs for # each call, so trigger the kdump-udev-throttler only if kdump # service is active to avoid unnecessary logs + +LABEL="kdump_reload_mem" + RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'" +GOTO="kdump_reload_end" + +LABEL="kdump_reload_cpu" + +RUN+="/bin/sh -c '/usr/bin/systemctl is-active kdump.service || exit 0; ! test -f /sys/kernel/fadump_enabled || cat /sys/kernel/fadump_enabled | grep 0 || exit 0; /usr/bin/systemd-run --quiet --no-block /usr/lib/udev/kdump-udev-throttler'" + LABEL="kdump_reload_end" diff --git a/SOURCES/dracut-kdump.sh b/SOURCES/dracut-kdump.sh index 2497218..c7cf528 100755 --- a/SOURCES/dracut-kdump.sh +++ b/SOURCES/dracut-kdump.sh @@ -136,7 +136,7 @@ dump_ssh() fi _exitcode=$? else - $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "dd bs=512 of=$_dir/vmcore-incomplete" + $CORE_COLLECTOR /proc/vmcore | ssh $_opt $_host "umask 0077 && dd bs=512 of=$_dir/vmcore-incomplete" _exitcode=$? _vmcore="vmcore.flat" fi @@ -218,7 +218,7 @@ save_vmcore_dmesg_ssh() { local _location=$4 dinfo "saving vmcore-dmesg.txt to $_location:$_path" - $_dmesg_collector /proc/vmcore | ssh $_opts $_location "dd of=$_path/vmcore-dmesg-incomplete.txt" + $_dmesg_collector /proc/vmcore | ssh $_opts $_location "umask 0077 && dd of=$_path/vmcore-dmesg-incomplete.txt" _exitcode=$? if [ $_exitcode -eq 0 ]; then diff --git a/SOURCES/dracut-module-setup.sh b/SOURCES/dracut-module-setup.sh index 917afed..dafdad6 100755 --- a/SOURCES/dracut-module-setup.sh +++ b/SOURCES/dracut-module-setup.sh @@ -119,12 +119,122 @@ kdump_setup_dns() { done < "/etc/resolv.conf" } +# $1: repeat times +# $2: string to be repeated +# $3: separator +repeatedly_join_str() { + local _count="$1" + local _str="$2" + local _separator="$3" + local i _res + + if [[ "$_count" -le 0 ]]; then + echo -n "" + return + fi + + i=0 + _res="$_str" + ((_count--)) + + while [[ "$i" -lt "$_count" ]]; do + ((i++)) + _res="${_res}${_separator}${_str}" + done + echo -n "$_res" +} + +# $1: prefix +# $2: ipv6_flag="-6" indicates it's IPv6 +# Given a prefix, calculate the netmask (equivalent of "ipcalc -m") +# by concatenating three parts, +# 1) the groups with all bits set 1 +# 2) a group with partial bits set to 0 +# 3) the groups with all bits set to 0 +cal_netmask_by_prefix() { + local _prefix="$1" + local _ipv6_flag="$2" _ipv6 + local _bits_per_octet=8 + local _count _res _octets_per_group _octets_total _seperator _total_groups + local _max_group_value _max_group_value_repr _bits_per_group _tmp _zero_bits + + if [[ "$_ipv6_flag" == "-6" ]]; then + _ipv6=1 + else + _ipv6=0 + fi + + if [[ "$_prefix" -lt 0 || "$_prefix" -gt 128 ]] || \ + ( ((!_ipv6)) && [[ "$_prefix" -gt 32 ]] ); then + derror "Bad prefix:$_prefix for calculating netmask" + exit 1 + fi + + if ((_ipv6)); then + _octets_per_group=2 + _octets_total=16 + _seperator=":" + else + _octets_per_group=1 + _octets_total=4 + _seperator="." + fi + + _total_groups=$((_octets_total/_octets_per_group)) + _bits_per_group=$((_octets_per_group * _bits_per_octet)) + _max_group_value=$(((1 << _bits_per_group) - 1)) + + if ((_ipv6)); then + _max_group_value_repr=$(printf "%x" $_max_group_value) + else + _max_group_value_repr="$_max_group_value" + fi + + _count=$((_prefix/_octets_per_group/_bits_per_octet)) + _first_part=$(repeatedly_join_str "$_count" "$_max_group_value_repr" "$_seperator") + _res="$_first_part" + + _tmp=$((_octets_total*_bits_per_octet-_prefix)) + _zero_bits=$(expr $_tmp % $_bits_per_group) + if [[ "$_zero_bits" -ne 0 ]]; then + _second_part=$((_max_group_value >> _zero_bits << _zero_bits)) + if ((_ipv6)); then + _second_part=$(printf "%x" $_second_part) + fi + ((_count++)) + if [[ -z "$_first_part" ]]; then + _res="$_second_part" + else + _res="${_first_part}${_seperator}${_second_part}" + fi + fi + + _count=$((_total_groups-_count)) + if [[ "$_count" -eq 0 ]]; then + echo -n "$_res" + return + fi + + if ((_ipv6)) && [[ "$_count" -gt 1 ]] ; then + # use condensed notion for IPv6 + _third_part=":" + else + _third_part=$(repeatedly_join_str "$_count" "0" "$_seperator") + fi + + if [[ -z "$_res" ]] && ((!_ipv6)) ; then + echo -n "${_third_part}" + else + echo -n "${_res}${_seperator}${_third_part}" + fi +} + #$1: netdev name #$2: srcaddr #if it use static ip echo it, or echo null kdump_static_ip() { - local _netdev="$1" _srcaddr="$2" _ipv6_flag - local _netmask _gateway _ipaddr _target _nexthop + local _netdev="$1" _srcaddr="$2" kdumpnic="$3" _ipv6_flag + local _netmask _gateway _ipaddr _target _nexthop _prefix _ipaddr=$(ip addr show dev $_netdev permanent | awk "/ $_srcaddr\/.* /{print \$2}") @@ -142,7 +252,12 @@ kdump_static_ip() { _srcaddr="[$_srcaddr]" _gateway="[$_gateway]" else - _netmask=$(ipcalc -m $_ipaddr | cut -d'=' -f2) + _prefix=$(cut -d'/' -f2 <<< "$_ipaddr") + _netmask=$(cal_netmask_by_prefix "$_prefix" "$_ipv6_flag") + if [[ "$?" -ne 0 ]]; then + derror "Failed to calculate netmask for $_ipaddr" + exit 1 + fi fi echo -n "${_srcaddr}::${_gateway}:${_netmask}::" fi @@ -155,7 +270,7 @@ kdump_static_ip() { _target="[$_target]" _nexthop="[$_nexthop]" fi - echo "rd.route=$_target:$_nexthop:$_netdev" + echo "rd.route=$_target:$_nexthop:$kdumpnic" done >> ${initdir}/etc/cmdline.d/45route-static.conf } @@ -276,6 +391,37 @@ kdump_setup_vlan() { fi } +# find online znet device +# return ifname (_netdev) +# code reaped from the list_configured function of +# https://github.com/hreinecke/s390-tools/blob/master/zconf/znetconf +find_online_znet_device() { + local CCWGROUPBUS_DEVICEDIR="/sys/bus/ccwgroup/devices" + local NETWORK_DEVICES d ifname ONLINE + + [ ! -d "$CCWGROUPBUS_DEVICEDIR" ] && return + NETWORK_DEVICES=$(find $CCWGROUPBUS_DEVICEDIR) + for d in $NETWORK_DEVICES + do + [ ! -f "$d/online" ] && continue + read ONLINE < $d/online + if [ $ONLINE -ne 1 ]; then + continue + fi + # determine interface name, if there (only for qeth and if + # device is online) + if [ -f $d/if_name ] + then + read ifname < $d/if_name + elif [ -d $d/net ] + then + ifname=$(ls $d/net/) + fi + [ -n "$ifname" ] && break + done + echo -n "$ifname" +} + # setup s390 znet cmdline # $1: netdev name kdump_setup_znet() { @@ -293,14 +439,22 @@ kdump_setup_znet() { # Setup dracut to bringup a given network interface kdump_setup_netdev() { local _netdev=$1 _srcaddr=$2 - local _static _proto _ip_conf _ip_opts _ifname_opts + local _static _proto _ip_conf _ip_opts _ifname_opts kdumpnic local _netmac=$(kdump_get_mac_addr $_netdev) + local _znet_netdev - if [ "$(uname -m)" = "s390x" ]; then - kdump_setup_znet $_netdev + kdumpnic=$(kdump_setup_ifname $_netdev) + + _znet_netdev=$(find_online_znet_device) + if [[ -n "$_znet_netdev" ]]; then + $(kdump_setup_znet "$_znet_netdev") + if [[ $? != 0 ]]; then + derror "Failed to set up znet" + exit 1 + fi fi - _static=$(kdump_static_ip $_netdev $_srcaddr) + _static=$(kdump_static_ip $_netdev $_srcaddr $kdumpnic) if [ -n "$_static" ]; then _proto=none elif is_ipv6_address $_srcaddr; then @@ -310,7 +464,7 @@ kdump_setup_netdev() { fi _ip_conf="${initdir}/etc/cmdline.d/40ip.conf" - _ip_opts=" ip=${_static}$(kdump_setup_ifname $_netdev):${_proto}" + _ip_opts=" ip=${_static}$kdumpnic:${_proto}" # dracut doesn't allow duplicated configuration for same NIC, even they're exactly the same. # so we have to avoid adding duplicates @@ -330,7 +484,7 @@ kdump_setup_netdev() { elif kdump_is_vlan "$_netdev"; then kdump_setup_vlan "$_netdev" else - _ifname_opts=" ifname=$(kdump_setup_ifname $_netdev):$_netmac" + _ifname_opts=" ifname=$kdumpnic:$_netmac" echo "$_ifname_opts" >> $_ip_conf fi @@ -829,6 +983,7 @@ install() { inst "/sbin/vmcore-dmesg" "/sbin/vmcore-dmesg" inst "/usr/bin/printf" "/sbin/printf" inst "/usr/bin/logger" "/sbin/logger" + inst "/usr/bin/chmod" "/sbin/chmod" inst "/lib/kdump/kdump-lib.sh" "/lib/kdump-lib.sh" inst "/lib/kdump/kdump-lib-initramfs.sh" "/lib/kdump-lib-initramfs.sh" inst "/lib/kdump/kdump-logger.sh" "/lib/kdump-logger.sh" diff --git a/SOURCES/fadump-howto.txt b/SOURCES/fadump-howto.txt index 5360f3d..433e9a6 100644 --- a/SOURCES/fadump-howto.txt +++ b/SOURCES/fadump-howto.txt @@ -224,12 +224,16 @@ Things to remember: dracut_args --add "network" 4) If FADump is configured to capture vmcore to a remote dump target using SSH - or NFS protocol, the network interface is renamed to kdump- - if is generic, for example, *eth#, or net#. This problem - occurs because the vmcore capture scripts in the initial RAM disk (initrd) - add the kdump- prefix to the network interface name to secure persistent - naming. As the same initrd is used for production kernel boot, the interface - name is changed for the production kernel too. + or NFS protocol, the corresponding network interface '' is + renamed to 'kdump-', if it is generic (like *eth# or net#). + It happens because vmcore capture scripts in the initial RAM disk (initrd) + add the 'kdump-' prefix to the network interface name to secure persistent + naming. And as capture kernel and production kernel use the same initrd in + case of FADump, the interface name is changed for the production kernel too. + This is likely to impact network configuration setup for production kernel. + So, it is recommended to use a non-generic name for a network interface, + before setting up FADump to capture vmcore to a remote dump target based on + that network interface, to avoid running into network configuration issues. Dump Triggering methods: diff --git a/SOURCES/kdump-lib-initramfs.sh b/SOURCES/kdump-lib-initramfs.sh index a43c7dd..e030fe6 100755 --- a/SOURCES/kdump-lib-initramfs.sh +++ b/SOURCES/kdump-lib-initramfs.sh @@ -111,6 +111,7 @@ save_log() if command -v journalctl > /dev/null; then journalctl -ab >> $KDUMP_LOG_FILE fi + chmod 600 $KDUMP_LOG_FILE } # dump_fs @@ -171,6 +172,7 @@ save_vmcore_dmesg_fs() { _exitcode=$? if [ $_exitcode -eq 0 ]; then mv ${_path}/vmcore-dmesg-incomplete.txt ${_path}/vmcore-dmesg.txt + chmod 600 ${_path}/vmcore-dmesg.txt # Make sure file is on disk. There have been instances where later # saving vmcore failed and system rebooted without sync and there diff --git a/SOURCES/kdump-lib.sh b/SOURCES/kdump-lib.sh index 8ae8617..67ee10e 100755 --- a/SOURCES/kdump-lib.sh +++ b/SOURCES/kdump-lib.sh @@ -617,11 +617,16 @@ is_secure_boot_enforced() local secure_boot_file setup_mode_file local secure_boot_byte setup_mode_byte - # On powerpc, os-secureboot-enforcing DT property indicates whether secureboot - # is enforced. Return success, if it is found. + # On powerpc, secure boot is enforced if: + # host secure boot: /ibm,secure-boot/os-secureboot-enforcing DT property exists + # guest secure boot: /ibm,secure-boot >= 2 if [ -f /proc/device-tree/ibm,secureboot/os-secureboot-enforcing ]; then return 0 fi + if [ -f /proc/device-tree/ibm,secure-boot ] && \ + [ $(lsprop /proc/device-tree/ibm,secure-boot | tail -1) -ge 2 ]; then + return 0 + fi # Detect secure boot on x86 and arm64 secure_boot_file=$(find /sys/firmware/efi/efivars -name SecureBoot-* 2>/dev/null) @@ -689,7 +694,7 @@ prepare_kdump_bootinfo() local boot_imglist boot_dirlist boot_initrdlist curr_kver="$(uname -r)" local machine_id - if [ -z "$KDUMP_KERNELVER"]; then + if [ -z "$KDUMP_KERNELVER" ]; then KDUMP_KERNELVER="$(uname -r)" fi @@ -724,20 +729,30 @@ prepare_kdump_bootinfo() boot_initrdlist="initramfs-$KDUMP_KERNELVER.img initrd" for initrd in $boot_initrdlist; do if [ -f "$KDUMP_BOOTDIR/$initrd" ]; then - DEFAULT_INITRD="$KDUMP_BOOTDIR/$initrd" + defaut_initrd_base="$initrd" + DEFAULT_INITRD="$KDUMP_BOOTDIR/$defaut_initrd_base" break fi done - # Get kdump initrd from default initrd filename + # Create kdump initrd basename from default initrd basename # initramfs-5.7.9-200.fc32.x86_64.img => initramfs-5.7.9-200.fc32.x86_64kdump.img # initrd => initrdkdump - if [[ -z "$DEFAULT_INITRD" ]]; then - KDUMP_INITRD=${KDUMP_BOOTDIR}/initramfs-${KDUMP_KERNELVER}kdump.img - elif [[ $(basename $DEFAULT_INITRD) == *.* ]]; then - KDUMP_INITRD=${DEFAULT_INITRD%.*}kdump.${DEFAULT_INITRD##*.} + if [[ -z "$defaut_initrd_base" ]]; then + kdump_initrd_base=initramfs-${KDUMP_KERNELVER}kdump.img + elif [[ $defaut_initrd_base == *.* ]]; then + kdump_initrd_base=${defaut_initrd_base%.*}kdump.${DEFAULT_INITRD##*.} else - KDUMP_INITRD=${DEFAULT_INITRD}kdump + kdump_initrd_base=${defaut_initrd_base}kdump + fi + + # Place kdump initrd in `/var/lib/kdump` if `KDUMP_BOOTDIR` not writable + if [[ ! -w "$KDUMP_BOOTDIR" ]];then + var_target_initrd_dir="/var/lib/kdump" + mkdir -p "$var_target_initrd_dir" + KDUMP_INITRD="$var_target_initrd_dir/$kdump_initrd_base" + else + KDUMP_INITRD="$KDUMP_BOOTDIR/$kdump_initrd_base" fi } @@ -819,3 +834,192 @@ prepare_cmdline() echo ${cmdline} } + +#get system memory size in the unit of GB +get_system_size() +{ + result=$(cat /proc/iomem | grep "System RAM" | awk -F ":" '{ print $1 }' | tr [:lower:] [:upper:] | paste -sd+) + result="+$result" + # replace '-' with '+0x' and '+' with '-0x' + sum=$( echo $result | sed -e 's/-/K0x/g' | sed -e 's/+/-0x/g' | sed -e 's/K/+/g' ) + size=$(printf "%d\n" $(($sum))) + + # in MB unit + let size=$size/1024/1024 + # since RHEL-8.5 kernel round up total memory to 128M, so should user space + let size=($size+127)/128 + let size=$size*128 + # in GB unit + let size=$size/1024 + + echo $size +} + +get_recommend_size() +{ + local mem_size=$1 + local _ck_cmdline=$2 + local OLDIFS="$IFS" + + last_sz="" + last_unit="" + + start=${_ck_cmdline: :1} + if [ $mem_size -lt $start ]; then + echo "0M" + return + fi + IFS=',' + for i in $_ck_cmdline; do + end=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $1 }') + recommend=$(echo $i | awk -F "-" '{ print $2 }' | awk -F ":" '{ print $2 }') + size=${end: : -1} + unit=${end: -1} + if [ $unit == 'T' ]; then + let size=$size*1024 + fi + if [ $mem_size -lt $size ]; then + echo $recommend + IFS="$OLDIFS" + return + fi + done + IFS="$OLDIFS" +} + +# return recommended size based on current system RAM size +kdump_get_arch_recommend_size() +{ + if ! [[ -r "/proc/iomem" ]] ; then + echo "Error, can not access /proc/iomem." + return 1 + fi + arch=$(lscpu | grep Architecture | awk -F ":" '{ print $2 }' | tr [:lower:] [:upper:]) + + if [ $arch == "X86_64" ] || [ $arch == "S390X" ]; then + ck_cmdline="1G-4G:160M,4G-64G:192M,64G-1T:256M,1T-:512M" + elif [ $arch == "AARCH64" ]; then + ck_cmdline="2G-:448M" + elif [ $arch == "PPC64LE" ]; then + if is_fadump_capable; then + ck_cmdline="4G-16G:768M,16G-64G:1G,64G-128G:2G,128G-1T:4G,1T-2T:6G,2T-4T:12G,4T-8T:20G,8T-16T:36G,16T-32T:64G,32T-64T:128G,64T-:180G" + else + ck_cmdline="2G-4G:384M,4G-16G:512M,16G-64G:1G,64G-128G:2G,128G-:4G" + fi + fi + + ck_cmdline=$(echo $ck_cmdline | sed -e 's/-:/-102400T:/g') + sys_mem=$(get_system_size) + result=$(get_recommend_size $sys_mem "$ck_cmdline") + echo $result + return 0 +} + +# Print all underlying crypt devices of a block device +# print nothing if device is not on top of a crypt device +# $1: the block device to be checked in maj:min format +get_luks_crypt_dev() +{ + [[ -b /dev/block/$1 ]] || return 1 + + local _type=$(eval "$(blkid -u filesystem,crypto -o export -- /dev/block/$1); echo \$TYPE") + [[ $_type == "crypto_LUKS" ]] && echo $1 + + for _x in /sys/dev/block/$1/slaves/*; do + [[ -f $_x/dev ]] || continue + [[ $_x/subsystem -ef /sys/class/block ]] || continue + get_luks_crypt_dev "$(< "$_x/dev")" + done +} + +# kdump_get_maj_min +# Prints the major and minor of a device node. +# Example: +# $ get_maj_min /dev/sda2 +# 8:2 +kdump_get_maj_min() { + local _majmin + _majmin="$(stat -L -c '%t:%T' "$1" 2> /dev/null)" + printf "%s" "$((0x${_majmin%:*})):$((0x${_majmin#*:}))" +} + +get_all_kdump_crypt_dev() +{ + local _dev _crypt + + for _dev in $(get_block_dump_target); do + _crypt=$(get_luks_crypt_dev $(kdump_get_maj_min "$_dev")) + [[ -n "$_crypt" ]] && echo $_crypt + done +} + +check_vmlinux() +{ + # Use readelf to check if it's a valid ELF + readelf -h $1 &>/dev/null || return 1 +} + +get_vmlinux_size() +{ + local size=0 + + while read _type _offset _virtaddr _physaddr _fsize _msize _flg _aln; do + size=$(( $size + $_msize )) + done <<< $(readelf -l -W $1 | grep "^ LOAD" 2>/dev/stderr) + + echo $size +} + +try_decompress() +{ + # The obscure use of the "tr" filter is to work around older versions of + # "grep" that report the byte offset of the line instead of the pattern. + + # Try to find the header ($1) and decompress from here + for pos in `tr "$1\n$2" "\n$2=" < "$4" | grep -abo "^$2"` + do + if ! type -P $3 > /dev/null; then + ddebug "Signiature detected but '$3' is missing, skip this decompressor" + break + fi + + pos=${pos%%:*} + tail -c+$pos "$img" | $3 > $5 2> /dev/null + if check_vmlinux $5; then + ddebug "Kernel is extracted with '$3'" + return 0 + fi + done + + return 1 +} + +# Borrowed from linux/scripts/extract-vmlinux +get_kernel_size() +{ + # Prepare temp files: + local img=$1 tmp=$(mktemp /tmp/vmlinux-XXX) + trap "rm -f $tmp" 0 + + # Try to check if it's a vmlinux already + check_vmlinux $img && get_vmlinux_size $img && return 0 + + # That didn't work, so retry after decompression. + try_decompress '\037\213\010' xy gunzip $img $tmp || \ + try_decompress '\3757zXZ\000' abcde unxz $img $tmp || \ + try_decompress 'BZh' xy bunzip2 $img $tmp || \ + try_decompress '\135\0\0\0' xxx unlzma $img $tmp || \ + try_decompress '\211\114\132' xy 'lzop -d' $img $tmp || \ + try_decompress '\002!L\030' xxx 'lz4 -d' $img $tmp || \ + try_decompress '(\265/\375' xxx unzstd $img $tmp + + # Finally check for uncompressed images or objects: + [[ $? -eq 0 ]] && get_vmlinux_size $tmp && return 0 + + # Fallback to use iomem + local _size=0 + for _seg in $(cat /proc/iomem | grep -E "Kernel (code|rodata|data|bss)" | cut -d ":" -f 1); do + _size=$(( $_size + 0x${_seg#*-} - 0x${_seg%-*} )) + done + echo $_size +} diff --git a/SOURCES/kdump-migrate-action.sh b/SOURCES/kdump-migrate-action.sh new file mode 100755 index 0000000..c516639 --- /dev/null +++ b/SOURCES/kdump-migrate-action.sh @@ -0,0 +1,8 @@ +#!/bin/sh + +systemctl is-active kdump +if [ $? -ne 0 ]; then + exit 0 +fi + +/usr/lib/kdump/kdump-restart.sh diff --git a/SOURCES/kdump-restart.sh b/SOURCES/kdump-restart.sh new file mode 100644 index 0000000..a9ecfc1 --- /dev/null +++ b/SOURCES/kdump-restart.sh @@ -0,0 +1,8 @@ +#!/bin/bash +export PATH="$PATH:/usr/bin:/usr/sbin" + +exec >>/var/log/kdump-migration.log 2>&1 + +echo "kdump: Partition Migration detected. Rebuilding initramfs image to reload." +/usr/bin/kdumpctl rebuild +/usr/bin/kdumpctl reload diff --git a/SOURCES/kdump.sysconfig.s390x b/SOURCES/kdump.sysconfig.s390x index 3f75b76..efa0394 100644 --- a/SOURCES/kdump.sysconfig.s390x +++ b/SOURCES/kdump.sysconfig.s390x @@ -17,7 +17,7 @@ KDUMP_COMMANDLINE="" # This variable lets us remove arguments from the current kdump commandline # as taken from either KDUMP_COMMANDLINE above, or from /proc/cmdline # NOTE: some arguments such as crashkernel will always be removed -KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len swiotlb" +KDUMP_COMMANDLINE_REMOVE="hugepages hugepagesz slub_debug quiet log_buf_len swiotlb prot_virt" # This variable lets us append arguments to the current kdump commandline # after processed by KDUMP_COMMANDLINE_REMOVE diff --git a/SOURCES/kdumpctl b/SOURCES/kdumpctl index ef86571..e8a7a3a 100755 --- a/SOURCES/kdumpctl +++ b/SOURCES/kdumpctl @@ -151,8 +151,8 @@ rebuild_kdump_initrd() rebuild_initrd() { - if [[ ! -w "$KDUMP_BOOTDIR" ]];then - derror "$KDUMP_BOOTDIR does not have write permission. Can not rebuild $TARGET_INITRD" + if [[ ! -w $(dirname $TARGET_INITRD) ]];then + derror "$(dirname $TARGET_INITRD) does not have write permission. Cannot rebuild $TARGET_INITRD" return 1 fi @@ -237,12 +237,7 @@ restore_default_initrd() check_config() { local -A _opt_rec - while read config_opt config_val; do - if [ -z "$config_val" ]; then - derror "Invalid kdump config value for option $config_opt" - return 1 - fi - + while read -r config_opt config_val; do case "$config_opt" in dracut_args) if [[ $config_val == *--mount* ]]; then @@ -269,12 +264,20 @@ check_config() derror "Deprecated kdump config option: $config_opt. Refer to kdump.conf manpage for alternatives." return 1 ;; + '') + continue + ;; *) derror "Invalid kdump config option $config_opt" return 1 ;; esac + if [[ -z "$config_val" ]]; then + derror "Invalid kdump config value for option '$config_opt'" + return 1 + fi + if [ -n "${_opt_rec[$config_opt]}" ]; then if [ $config_opt == _target ]; then derror "More than one dump targets specified" @@ -643,6 +646,35 @@ check_rebuild() return $? } +# On ppc64le LPARs, the keys trusted by firmware do not end up in +# .builtin_trusted_keys. So instead, add the key to the .ima keyring +function load_kdump_kernel_key() +{ + # this is only called inside is_secure_boot_enforced, + # no need to retest + + # this is only required if DT /ibm,secure-boot is a file. + # if it is a dir, we are on OpenPower and don't need this. + if ! [ -f /proc/device-tree/ibm,secure-boot ]; then + return + fi + + KDUMP_KEY_ID=$(cat /usr/share/doc/kernel-keys/$KDUMP_KERNELVER/kernel-signing-ppc.cer | + keyctl padd asymmetric kernelkey-$RANDOM %:.ima) +} + +# remove a previously loaded key. There's no real security implication +# to leaving it around, we choose to do this because it makes it easier +# to be idempotent and so as to reduce the potential for confusion. +function remove_kdump_kernel_key() +{ + if [ -z "$KDUMP_KEY_ID" ]; then + return + fi + + keyctl unlink $KDUMP_KEY_ID %:.ima +} + # Load the kdump kernel specified in /etc/sysconfig/kdump # If none is specified, try to load a kdump kernel with the same version # as the currently running kernel. @@ -659,6 +691,7 @@ load_kdump() if is_secure_boot_enforced; then dinfo "Secure Boot is enabled. Using kexec file based syscall." KEXEC_ARGS="$KEXEC_ARGS -s" + load_kdump_kernel_key fi ddebug "$KEXEC $KEXEC_ARGS $standard_kexec_args --command-line=$KDUMP_COMMANDLINE --initrd=$TARGET_INITRD $KDUMP_KERNEL" @@ -680,6 +713,8 @@ load_kdump() set +x exec 2>&12 12>&- + remove_kdump_kernel_key + if [ $ret == 0 ]; then dinfo "kexec: loaded kdump kernel" return 0 @@ -1214,6 +1249,97 @@ rebuild() { return $? } +do_estimate() { + local kdump_mods + local -A large_mods + local baseline + local kernel_size mod_size initrd_size baseline_size runtime_size reserved_size estimated_size recommended_size + local size_mb=$(( 1024 * 1024 )) + + setup_initrd + if [ ! -f "$TARGET_INITRD" ]; then + derror "kdumpctl estimate: kdump initramfs is not built yet." + exit 1 + fi + + kdump_mods="$(lsinitrd "$TARGET_INITRD" -f /usr/lib/dracut/loaded-kernel-modules.txt | tr '\n' ' ')" + baseline=$(kdump_get_arch_recommend_size) + if [[ "${baseline: -1}" == "M" ]]; then + baseline=${baseline%M} + elif [[ "${baseline: -1}" == "G" ]]; then + baseline=$(( ${baseline%G} * 1024 )) + elif [[ "${baseline: -1}" == "T" ]]; then + baseline=$(( ${baseline%Y} * 1048576 )) + fi + + # The default value when using crashkernel=auto + baseline_size=$((baseline * size_mb)) + # Current reserved crashkernel size + reserved_size=$(cat /sys/kernel/kexec_crash_size) + # A pre-estimated value for userspace usage and kernel + # runtime allocation, 64M should good for most cases + runtime_size=$((64 * size_mb)) + # Kernel image size + kernel_size=$(get_kernel_size "$KDUMP_KERNEL") + # Kdump initramfs size + initrd_size=$(du -b "$TARGET_INITRD" | awk '{print $1}') + # Kernel modules static size after loaded + mod_size=0 + while read -r _name _size _; do + if [[ ! " $kdump_mods " == *" $_name "* ]]; then + continue + fi + mod_size=$((mod_size + _size)) + + # Mark module with static size larger than 2M as large module + if [[ $((_size / size_mb)) -ge 1 ]]; then + large_mods[$_name]=$_size + fi + done <<< "$(< /proc/modules)" + + # Extra memory usage required for LUKS2 decryption + crypt_size=0 + for _dev in $(get_all_kdump_crypt_dev); do + _crypt_info=$(cryptsetup luksDump "/dev/block/$_dev") + [[ $(echo "$_crypt_info" | sed -n "s/^Version:\s*\(.*\)/\1/p" ) == "2" ]] || continue + for _mem in $(echo "$_crypt_info" | sed -n "s/\sMemory:\s*\(.*\)/\1/p" | sort -n ); do + crypt_size=$((crypt_size + _mem * 1024)) + break + done + done + [[ $crypt_size -ne 0 ]] && echo -e "Encrypted kdump target requires extra memory, assuming using the keyslot with minimun memory requirement\n" + + estimated_size=$((kernel_size + mod_size + initrd_size + runtime_size + crypt_size)) + if [[ $baseline_size -gt $estimated_size ]]; then + recommended_size=$baseline_size + else + recommended_size=$estimated_size + fi + + echo "Reserved crashkernel: $((reserved_size / size_mb))M" + echo "Recommended crashkernel: $((recommended_size / size_mb))M" + echo + echo "Kernel image size: $((kernel_size / size_mb))M" + echo "Kernel modules size: $((mod_size / size_mb))M" + echo "Initramfs size: $((initrd_size / size_mb))M" + echo "Runtime reservation: $((runtime_size / size_mb))M" + [[ $crypt_size -ne 0 ]] && \ + echo "LUKS required size: $((crypt_size / size_mb))M" + echo -n "Large modules:" + if [[ "${#large_mods[@]}" -eq 0 ]]; then + echo " " + else + echo "" + for _mod in "${!large_mods[@]}"; do + echo " $_mod: ${large_mods[$_mod]}" + done + fi + + if [[ $reserved_size -lt $recommended_size ]]; then + echo "WARNING: Current crashkernel size is lower than recommended size $((recommended_size / size_mb))M." + fi +} + if [ ! -f "$KDUMP_CONFIG_FILE" ]; then derror "Error: No kdump config file found!" exit 1 @@ -1269,8 +1395,11 @@ main () showmem) show_reserved_mem ;; + estimate) + do_estimate + ;; *) - dinfo $"Usage: $0 {start|stop|status|restart|reload|rebuild|propagate|showmem}" + dinfo $"Usage: $0 {estimate|start|stop|status|restart|reload|rebuild|propagate|showmem}" exit 1 esac } diff --git a/SOURCES/kdumpctl.8 b/SOURCES/kdumpctl.8 index ae97af7..a32a972 100644 --- a/SOURCES/kdumpctl.8 +++ b/SOURCES/kdumpctl.8 @@ -44,6 +44,11 @@ impossible to use password authentication during kdump. .TP .I showmem Prints the size of reserved memory for crash kernel in megabytes. +.TP +.I estimate +Estimate a suitable crashkernel value for current machine. This is a +best-effort estimate. It will print a recommanded crashkernel value +based on current kdump setup, and list some details of memory usage. .SH "SEE ALSO" .BR kdump.conf (5), diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch new file mode 100644 index 0000000..631d039 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch @@ -0,0 +1,177 @@ +From 3422e1d6bc3511c5af9cb05ba74ad97dd93ffd7f Mon Sep 17 00:00:00 2001 +From: Julien Thierry +Date: Tue, 24 Nov 2020 10:45:24 +0000 +Subject: [PATCH] [PATCH 1/2] Add --dry-run option to prevent writing the + dumpfile + +Add a --dry-run option to run all operations without writing the +dump to the output file. + +Signed-off-by: Julien Thierry +Signed-off-by: Kazuhito Hagio +--- + makedumpfile.8 | 6 ++++++ + makedumpfile.c | 37 ++++++++++++++++++++++++++++++------- + makedumpfile.h | 2 ++ + print_info.c | 3 +++ + 4 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8 +index b68a7e3..5e902cd 100644 +--- a/makedumpfile-1.6.8/makedumpfile.8 ++++ b/makedumpfile-1.6.8/makedumpfile.8 +@@ -637,6 +637,12 @@ Show the version of makedumpfile. + Only check whether the command-line parameters are valid or not, and exit. + Preferable to be given as the first parameter. + ++.TP ++\fB\-\-dry-run\fR ++Do not write the output dump file while still performing operations specified ++by other options. ++This option cannot be used with the --dump-dmesg, --reassemble and -g options. ++ + .SH ENVIRONMENT VARIABLES + + .TP 8 +diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c +index ecd63fa..8c80c49 100644 +--- a/makedumpfile-1.6.8/makedumpfile.c ++++ b/makedumpfile-1.6.8/makedumpfile.c +@@ -1372,6 +1372,8 @@ open_dump_file(void) + if (info->flag_flatten) { + fd = STDOUT_FILENO; + info->name_dumpfile = filename_stdout; ++ } else if (info->flag_dry_run) { ++ fd = -1; + } else if ((fd = open(info->name_dumpfile, open_flags, + S_IRUSR|S_IWUSR)) < 0) { + ERRMSG("Can't open the dump file(%s). %s\n", +@@ -4711,6 +4713,9 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name) + { + int status, written_size = 0; + ++ if (info->flag_dry_run) ++ return TRUE; ++ + while (written_size < buf_size) { + status = write(fd, buf + written_size, + buf_size - written_size); +@@ -4748,13 +4753,12 @@ write_buffer(int fd, off_t offset, void *buf, size_t buf_size, char *file_name) + } + if (!write_and_check_space(fd, &fdh, sizeof(fdh), file_name)) + return FALSE; +- } else { +- if (lseek(fd, offset, SEEK_SET) == failed) { +- ERRMSG("Can't seek the dump file(%s). %s\n", +- file_name, strerror(errno)); +- return FALSE; +- } ++ } else if (!info->flag_dry_run && ++ lseek(fd, offset, SEEK_SET) == failed) { ++ ERRMSG("Can't seek the dump file(%s). %s\n", file_name, strerror(errno)); ++ return FALSE; + } ++ + if (!write_and_check_space(fd, buf, buf_size, file_name)) + return FALSE; + +@@ -9112,7 +9116,7 @@ close_dump_memory(void) + void + close_dump_file(void) + { +- if (info->flag_flatten) ++ if (info->flag_flatten || info->flag_dry_run) + return; + + if (close(info->fd_dumpfile) < 0) +@@ -10985,6 +10989,11 @@ check_param_for_generating_vmcoreinfo(int argc, char *argv[]) + + return FALSE; + ++ if (info->flag_dry_run) { ++ MSG("--dry-run cannot be used with -g.\n"); ++ return FALSE; ++ } ++ + return TRUE; + } + +@@ -11029,6 +11038,11 @@ check_param_for_reassembling_dumpfile(int argc, char *argv[]) + || info->flag_exclude_xen_dom || info->flag_split) + return FALSE; + ++ if (info->flag_dry_run) { ++ MSG("--dry-run cannot be used with --reassemble.\n"); ++ return FALSE; ++ } ++ + if ((info->splitting_info + = malloc(sizeof(struct splitting_info) * info->num_dumpfile)) + == NULL) { +@@ -11057,6 +11071,11 @@ check_param_for_creating_dumpfile(int argc, char *argv[]) + || (info->flag_read_vmcoreinfo && info->name_xen_syms)) + return FALSE; + ++ if (info->flag_dry_run && info->flag_dmesg) { ++ MSG("--dry-run cannot be used with --dump-dmesg.\n"); ++ return FALSE; ++ } ++ + if (info->flag_flatten && info->flag_split) + return FALSE; + +@@ -11520,6 +11539,7 @@ static struct option longopts[] = { + {"work-dir", required_argument, NULL, OPT_WORKING_DIR}, + {"num-threads", required_argument, NULL, OPT_NUM_THREADS}, + {"check-params", no_argument, NULL, OPT_CHECK_PARAMS}, ++ {"dry-run", no_argument, NULL, OPT_DRY_RUN}, + {0, 0, 0, 0} + }; + +@@ -11686,6 +11706,9 @@ main(int argc, char *argv[]) + info->flag_check_params = TRUE; + message_level = DEFAULT_MSG_LEVEL; + break; ++ case OPT_DRY_RUN: ++ info->flag_dry_run = TRUE; ++ break; + case '?': + MSG("Commandline parameter is invalid.\n"); + MSG("Try `makedumpfile --help' for more information.\n"); +diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h +index 5f50080..4c4222c 100644 +--- a/makedumpfile-1.6.8/makedumpfile.h ++++ b/makedumpfile-1.6.8/makedumpfile.h +@@ -1322,6 +1322,7 @@ struct DumpInfo { + int flag_vmemmap; /* kernel supports vmemmap address space */ + int flag_excludevm; /* -e - excluding unused vmemmap pages */ + int flag_use_count; /* _refcount is named _count in struct page */ ++ int flag_dry_run; /* do not create a vmcore file */ + unsigned long vaddr_for_vtop; /* virtual address for debugging */ + long page_size; /* size of page */ + long page_shift; +@@ -2425,6 +2426,7 @@ struct elf_prstatus { + #define OPT_NUM_THREADS OPT_START+16 + #define OPT_PARTIAL_DMESG OPT_START+17 + #define OPT_CHECK_PARAMS OPT_START+18 ++#define OPT_DRY_RUN OPT_START+19 + + /* + * Function Prototype. +diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c +index e0c38b4..d2b0cb7 100644 +--- a/makedumpfile-1.6.8/print_info.c ++++ b/makedumpfile-1.6.8/print_info.c +@@ -308,6 +308,9 @@ print_usage(void) + MSG(" the crashkernel range, then calculates the page number of different kind per\n"); + MSG(" vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n"); + MSG("\n"); ++ MSG(" [--dry-run]:\n"); ++ MSG(" This option runs makedumpfile without writting output dump file.\n"); ++ MSG("\n"); + MSG(" [-D]:\n"); + MSG(" Print debugging message.\n"); + MSG("\n"); +-- +2.29.2 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch new file mode 100644 index 0000000..5e935f0 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch @@ -0,0 +1,107 @@ +From 6f3e75a558ed50d6ff0b42e3f61c099b2005b7bb Mon Sep 17 00:00:00 2001 +From: Julien Thierry +Date: Tue, 24 Nov 2020 10:45:25 +0000 +Subject: [PATCH] [PATCH 2/2] Add shorthand --show-stats option to show report + stats + +Provide shorthand --show-stats option to enable report messages +without needing to set a particular value for message-level. + +Signed-off-by: Julien Thierry +Signed-off-by: Kazuhito Hagio +--- + makedumpfile.8 | 5 +++++ + makedumpfile.c | 9 ++++++++- + makedumpfile.h | 1 + + print_info.c | 7 ++++++- + 4 files changed, 20 insertions(+), 2 deletions(-) + +diff --git a/makedumpfile-1.6.8/makedumpfile.8 b/makedumpfile-1.6.8/makedumpfile.8 +index 5e902cd..dcca2dd 100644 +--- a/makedumpfile-1.6.8/makedumpfile.8 ++++ b/makedumpfile-1.6.8/makedumpfile.8 +@@ -643,6 +643,11 @@ Do not write the output dump file while still performing operations specified + by other options. + This option cannot be used with the --dump-dmesg, --reassemble and -g options. + ++.TP ++\fB\-\-show-stats\fR ++Display report messages. This is an alternative to enabling bit 4 in the level ++provided to --message-level. ++ + .SH ENVIRONMENT VARIABLES + + .TP 8 +diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c +index 8c80c49..ba0003a 100644 +--- a/makedumpfile-1.6.8/makedumpfile.c ++++ b/makedumpfile-1.6.8/makedumpfile.c +@@ -11540,13 +11540,14 @@ static struct option longopts[] = { + {"num-threads", required_argument, NULL, OPT_NUM_THREADS}, + {"check-params", no_argument, NULL, OPT_CHECK_PARAMS}, + {"dry-run", no_argument, NULL, OPT_DRY_RUN}, ++ {"show-stats", no_argument, NULL, OPT_SHOW_STATS}, + {0, 0, 0, 0} + }; + + int + main(int argc, char *argv[]) + { +- int i, opt, flag_debug = FALSE; ++ int i, opt, flag_debug = FALSE, flag_show_stats = FALSE; + + if ((info = calloc(1, sizeof(struct DumpInfo))) == NULL) { + ERRMSG("Can't allocate memory for the pagedesc cache. %s.\n", +@@ -11709,6 +11710,9 @@ main(int argc, char *argv[]) + case OPT_DRY_RUN: + info->flag_dry_run = TRUE; + break; ++ case OPT_SHOW_STATS: ++ flag_show_stats = TRUE; ++ break; + case '?': + MSG("Commandline parameter is invalid.\n"); + MSG("Try `makedumpfile --help' for more information.\n"); +@@ -11718,6 +11722,9 @@ main(int argc, char *argv[]) + if (flag_debug) + message_level |= ML_PRINT_DEBUG_MSG; + ++ if (flag_show_stats) ++ message_level |= ML_PRINT_REPORT_MSG; ++ + if (info->flag_check_params) + /* suppress debugging messages */ + message_level = DEFAULT_MSG_LEVEL; +diff --git a/makedumpfile-1.6.8/makedumpfile.h b/makedumpfile-1.6.8/makedumpfile.h +index 4c4222c..2fcb62e 100644 +--- a/makedumpfile-1.6.8/makedumpfile.h ++++ b/makedumpfile-1.6.8/makedumpfile.h +@@ -2427,6 +2427,7 @@ struct elf_prstatus { + #define OPT_PARTIAL_DMESG OPT_START+17 + #define OPT_CHECK_PARAMS OPT_START+18 + #define OPT_DRY_RUN OPT_START+19 ++#define OPT_SHOW_STATS OPT_START+20 + + /* + * Function Prototype. +diff --git a/makedumpfile-1.6.8/print_info.c b/makedumpfile-1.6.8/print_info.c +index d2b0cb7..ad4184e 100644 +--- a/makedumpfile-1.6.8/print_info.c ++++ b/makedumpfile-1.6.8/print_info.c +@@ -309,7 +309,12 @@ print_usage(void) + MSG(" vmcoreinfo. So currently /proc/kcore need be specified explicitly.\n"); + MSG("\n"); + MSG(" [--dry-run]:\n"); +- MSG(" This option runs makedumpfile without writting output dump file.\n"); ++ MSG(" Do not write the output dump file while still performing operations specified\n"); ++ MSG(" by other options. This option cannot be used with --dump-dmesg, --reassemble\n"); ++ MSG(" and -g options.\n"); ++ MSG("\n"); ++ MSG(" [--show-stats]:\n"); ++ MSG(" Set message-level to print report messages\n"); + MSG("\n"); + MSG(" [-D]:\n"); + MSG(" Print debugging message.\n"); +-- +2.29.2 + diff --git a/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch new file mode 100644 index 0000000..337288e --- /dev/null +++ b/SOURCES/kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch @@ -0,0 +1,59 @@ +From 0ef2ca6c9fa2f61f217a4bf5d7fd70f24e12b2eb Mon Sep 17 00:00:00 2001 +From: Kazuhito Hagio +Date: Thu, 4 Feb 2021 16:29:06 +0900 +Subject: [PATCH] [PATCH] Show write byte size in report messages + +Show write byte size in report messages. This value can be different +from the size of the actual file because of some holes on dumpfile +data structure. + + $ makedumpfile --show-stats -l -d 1 vmcore dump.ld1 + ... + Total pages : 0x0000000000080000 + Write bytes : 377686445 + ... + # ls -l dump.ld1 + -rw------- 1 root root 377691573 Feb 4 16:28 dump.ld1 + +Note that this value should not be used with /proc/kcore to determine +how much disk space is needed for crash dump, because the real memory +usage when a crash occurs can vary widely. + +Signed-off-by: Kazuhito Hagio +--- + makedumpfile.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c +index fcd766b..894c88e 100644 +--- a/makedumpfile-1.6.8/makedumpfile.c ++++ b/makedumpfile-1.6.8/makedumpfile.c +@@ -48,6 +48,8 @@ char filename_stdout[] = FILENAME_STDOUT; + static unsigned long long cache_hit; + static unsigned long long cache_miss; + ++static unsigned long long write_bytes; ++ + static void first_cycle(mdf_pfn_t start, mdf_pfn_t max, struct cycle *cycle) + { + cycle->start_pfn = round(start, info->pfn_cyclic); +@@ -4715,6 +4717,8 @@ write_and_check_space(int fd, void *buf, size_t buf_size, char *file_name) + { + int status, written_size = 0; + ++ write_bytes += buf_size; ++ + if (info->flag_dry_run) + return TRUE; + +@@ -10002,6 +10006,7 @@ print_report(void) + REPORT_MSG("Memory Hole : 0x%016llx\n", pfn_memhole); + REPORT_MSG("--------------------------------------------------\n"); + REPORT_MSG("Total pages : 0x%016llx\n", info->max_mapnr); ++ REPORT_MSG("Write bytes : %llu\n", write_bytes); + REPORT_MSG("\n"); + REPORT_MSG("Cache hit: %lld, miss: %lld", cache_hit, cache_miss); + if (cache_hit + cache_miss) +-- +2.29.2 + diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch new file mode 100644 index 0000000..c6eb40f --- /dev/null +++ b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch @@ -0,0 +1,60 @@ +From 38d921a2ef50ebd36258097553626443ffe27496 Mon Sep 17 00:00:00 2001 +From: Coiby Xu +Date: Tue, 15 Jun 2021 18:26:31 +0800 +Subject: [PATCH] check for invalid physical address of /proc/kcore + when finding max_paddr + +Kernel commit 464920104bf7adac12722035bfefb3d772eb04d8 ("/proc/kcore: +update physical address for kcore ram and text") sets an invalid paddr +(0xffffffffffffffff = -1) for PT_LOAD segments of not direct mapped +regions: + + $ readelf -l /proc/kcore + ... + Program Headers: + Type Offset VirtAddr PhysAddr + FileSiz MemSiz Flags Align + NOTE 0x0000000000000120 0x0000000000000000 0x0000000000000000 + 0x0000000000002320 0x0000000000000000 0x0 + LOAD 0x1000000000010000 0xd000000000000000 0xffffffffffffffff + ^^^^^^^^^^^^^^^^^^ + 0x0001f80000000000 0x0001f80000000000 RWE 0x10000 + +makedumpfile uses max_paddr to calculate the number of sections for +sparse memory model thus wrong number is obtained based on max_paddr +(-1). This error could lead to the failure of copying /proc/kcore +for RHEL-8.5 on ppc64le machine [1]: + + $ makedumpfile /proc/kcore vmcore1 + get_mem_section: Could not validate mem_section. + get_mm_sparsemem: Can't get the address of mem_section. + + makedumpfile Failed. + +Let's check if the phys_start of the segment is a valid physical +address to fix this problem. + +[1] https://bugzilla.redhat.com/show_bug.cgi?id=1965267 + +Reported-by: Xiaoying Yan +Signed-off-by: Coiby Xu +--- + elf_info.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.8/elf_info.c b/makedumpfile-1.6.8/elf_info.c +index e8affb7..bc24083 100644 +--- a/makedumpfile-1.6.8/elf_info.c ++++ b/makedumpfile-1.6.8/elf_info.c +@@ -628,7 +628,7 @@ get_max_paddr(void) + + for (i = 0; i < num_pt_loads; i++) { + pls = &pt_loads[i]; +- if (max_paddr < pls->phys_end) ++ if (pls->phys_start != NOT_PADDR && max_paddr < pls->phys_end) + max_paddr = pls->phys_end; + } + return max_paddr; +-- +2.29.2 + diff --git a/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch new file mode 100644 index 0000000..9180dc6 --- /dev/null +++ b/SOURCES/kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch @@ -0,0 +1,43 @@ +From 9a6f589d99dcef114c89fde992157f5467028c8f Mon Sep 17 00:00:00 2001 +From: Tao Liu +Date: Fri, 18 Jun 2021 18:28:04 +0800 +Subject: [PATCH] check for invalid physical address of /proc/kcore + when making ELF dumpfile + +Previously when executing makedumpfile with -E option against +/proc/kcore, makedumpfile will fail: + + # makedumpfile -E -d 31 /proc/kcore kcore.dump + ... + write_elf_load_segment: Can't convert physaddr(ffffffffffffffff) to an offset. + + makedumpfile Failed. + +It's because /proc/kcore contains PT_LOAD program headers which have +physaddr (0xffffffffffffffff). With -E option, makedumpfile will +try to convert the physaddr to an offset and fails. + +Skip the PT_LOAD program headers which have such physaddr. + +Signed-off-by: Tao Liu +Signed-off-by: Kazuhito Hagio +--- + makedumpfile.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/makedumpfile-1.6.8/makedumpfile.c b/makedumpfile-1.6.8/makedumpfile.c +index 894c88e..fcb571f 100644 +--- a/makedumpfile-1.6.8/makedumpfile.c ++++ b/makedumpfile-1.6.8/makedumpfile.c +@@ -7764,7 +7764,7 @@ write_elf_pages_cyclic(struct cache_data *cd_header, struct cache_data *cd_page) + if (!get_phdr_memory(i, &load)) + return FALSE; + +- if (load.p_type != PT_LOAD) ++ if (load.p_type != PT_LOAD || load.p_paddr == NOT_PADDR) + continue; + + off_memory= load.p_offset; +-- +2.29.2 + diff --git a/SOURCES/mkdumprd b/SOURCES/mkdumprd index 6e923fe..3c2fb5d 100644 --- a/SOURCES/mkdumprd +++ b/SOURCES/mkdumprd @@ -226,7 +226,7 @@ check_user_configured_target() # For user configured target, use $SAVE_PATH as the dump path within the target if [ ! -d "$_mnt/$SAVE_PATH" ]; then - perror_exit "Dump path \"$SAVE_PATH\" does not exist in dump target \"$_target\"" + perror_exit "Dump path \"$_mnt/$SAVE_PATH\" does not exist in dump target \"$_target\"" fi check_size fs "$_target" @@ -305,7 +305,6 @@ get_override_resettable() fi } - # $1: function name for_each_block_target() { @@ -320,8 +319,6 @@ for_each_block_target() return 0 } - - #judge if a specific device with $1 is unresettable #return false if unresettable. is_unresettable() @@ -358,32 +355,15 @@ check_resettable() return 1 } -# $1: maj:min -is_crypt() -{ - local majmin=$1 dev line ID_FS_TYPE="" - - line=$(udevadm info --query=property --path=/sys/dev/block/$majmin \ - | grep "^ID_FS_TYPE") - eval "$line" - [[ "$ID_FS_TYPE" = "crypto_LUKS" ]] && { - dev=$(udevadm info --query=all --path=/sys/dev/block/$majmin | awk -F= '/DEVNAME/{print $2}') - derror "Device $dev is encrypted." - return 0 - } - return 1 -} - check_crypt() { - local _ret _target + local _dev - for_each_block_target is_crypt - _ret=$? - - [ $_ret -eq 0 ] && return - - return 1 + for _dev in $(get_kdump_targets); do + if [[ -n $(get_luks_crypt_dev "$(get_maj_min "$_dev")") ]]; then + derror "Device $_dev is encrypted." && return 1 + fi + done } if ! check_resettable; then diff --git a/SPECS/kexec-tools.spec b/SPECS/kexec-tools.spec index 94aa05d..8ab65a9 100644 --- a/SPECS/kexec-tools.spec +++ b/SPECS/kexec-tools.spec @@ -1,6 +1,6 @@ Name: kexec-tools Version: 2.0.20 -Release: 45%{?dist} +Release: 57%{?dist} License: GPLv2 Group: Applications/System Summary: The kexec/kdump userspace component @@ -36,6 +36,8 @@ Source30: kdump.sysconfig.aarch64 Source31: fadump-howto.txt Source32: 60-kdump.install Source33: kdump-logger.sh +Source34: kdump-migrate-action.sh +Source35: kdump-restart.sh ####################################### # These are sources for mkdumpramfs @@ -52,6 +54,9 @@ Source107: dracut-kdump-emergency.target Source108: dracut-early-kdump.sh Source109: dracut-early-kdump-module-setup.sh +%ifarch ppc64 ppc64le +Requires(post): servicelog +%endif Requires(post): systemd-units Requires(preun): systemd-units Requires(postun): systemd-units @@ -111,7 +116,11 @@ Patch613: kexec-tools-2.0.20-eppic-Remove-duplicated-variable-declaration.patch # Patches 701 onward for makedumpfile Patch701: rhelonly-kexec-tools-2.0.20-makedumpfile-arm64-Add-support-for-ARMv8.2-LVA-52-bi.patch - +Patch702: kexec-tools-2.0.20-makedumpfile-Add-dry-run-option-to-prevent-writing.patch +Patch703: kexec-tools-2.0.20-makedumpfile-Add-shorthand-show-stats-option-to-show.patch +Patch704: kexec-tools-2.0.20-makedumpfile-Show-write-byte-size-in-report-messages.patch +Patch705: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-finding-max_paddr.patch +Patch706: kexec-tools-2.0.22-makedumpfile-check-for-invalid-physical-address-proc-kcore-when-making-ELF-dumpfile.patch %description kexec-tools provides /usr/sbin/kexec binary that facilitates a new @@ -141,6 +150,11 @@ tar -z -x -v -f %{SOURCE19} %patch612 -p1 %patch613 -p1 %patch701 -p1 +%patch702 -p1 +%patch703 -p1 +%patch704 -p1 +%patch705 -p1 +%patch706 -p1 %ifarch ppc %define archdef ARCH=ppc @@ -190,6 +204,7 @@ mkdir -p $RPM_BUILD_ROOT%{_unitdir} mkdir -p -m755 $RPM_BUILD_ROOT%{_bindir} mkdir -p -m755 $RPM_BUILD_ROOT%{_libdir} mkdir -p -m755 $RPM_BUILD_ROOT%{_prefix}/lib/kdump +mkdir -p -m755 $RPM_BUILD_ROOT%{_sharedstatedir}/kdump install -m 755 %{SOURCE1} $RPM_BUILD_ROOT%{_bindir}/kdumpctl install -m 755 build/sbin/kexec $RPM_BUILD_ROOT/usr/sbin/kexec @@ -217,6 +232,8 @@ install -m 644 %{SOURCE13} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules %endif %ifarch ppc64 ppc64le install -m 644 %{SOURCE14} $RPM_BUILD_ROOT%{_udevrulesdir}/98-kexec.rules +install -m 755 %{SOURCE34} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-migrate-action.sh +install -m 755 %{SOURCE35} $RPM_BUILD_ROOT%{_prefix}/lib/kdump/kdump-restart.sh %endif %ifnarch s390x install -m 755 %{SOURCE29} $RPM_BUILD_ROOT%{_udevrulesdir}/../kdump-udev-throttler @@ -269,6 +286,13 @@ mv $RPM_BUILD_ROOT/etc/kdump-adv-conf/kdump_dracut_modules/* $RPM_BUILD_ROOT/%{d %systemd_post kdump.service touch /etc/kdump.conf + +%ifarch ppc64 ppc64le +servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh +servicelog_notify --add --command=/usr/lib/kdump/kdump-migrate-action.sh --match='refcode="#MIGRATE" and serviceable=0' --type=EVENT --method=pairs_stdin +%endif + + # This portion of the script is temporary. Its only here # to fix up broken boxes that require special settings # in /etc/sysconfig/kdump. It will be removed when @@ -296,6 +320,9 @@ fi %systemd_postun_with_restart kdump.service %preun +%ifarch ppc64 ppc64le +servicelog_notify --remove --command=/usr/lib/kdump/kdump-migrate-action.sh +%endif # Package removal, not upgrade %systemd_preun kdump.service @@ -354,6 +381,7 @@ done %dir %{_sysconfdir}/kdump %dir %{_sysconfdir}/kdump/pre.d %dir %{_sysconfdir}/kdump/post.d +%dir %{_sharedstatedir}/kdump %{_mandir}/man8/kdumpctl.8.gz %{_mandir}/man8/kexec.8.gz %{_mandir}/man8/makedumpfile.8.gz @@ -378,6 +406,60 @@ done %endif %changelog +* Fri Aug 27 2021 Pingfan Liu - 2.0.20-57 +- kdumpctl: enable secure boot on ppc64le LPARs + +* Fri Aug 6 2021 Pingfan Liu - 2.0.20-56 +- kdumpctl: fix a typo + +* Mon Aug 2 2021 Pingfan Liu - 2.0.20-55 +- kdump/ppc64: migration action registration clean up + +* Fri Jul 23 2021 Pingfan Liu - 2.0.20-54 +- kdump/ppc64: rebuild initramfs image after migration +- Check the existence of /sys/bus/ccwgroup/devices/*/online beforehand +- kdump.sysconfig.s390: Remove "prot_virt" from kdump kernel cmdline + +* Fri Jul 2 2021 Pingfan Liu - 2.0.20-53 +- check for invalid physical address of /proc/kcore when making ELF dumpfile +- check for invalid physical address of /proc/kcore when finding max_paddr +- fix format issue in find_online_znet_device +- check the existence of /sys/bus/ccwgroup/devices before trying to find online network device +- kdump-lib.sh: fix a warning in prepare_kdump_bootinfo() + +* Thu Jun 17 2021 Pingfan Liu - 2.0.20-52 +- Write to `/var/lib/kdump` if $KDUMP_BOOTDIR not writable +- Iterate /sys/bus/ccwgroup/devices to tell if we should set up rd.znet +- mkdumprd: display the absolute path of dump location in the check_user_configured_target() + +* Wed Jun 2 2021 Pingfan Liu - 2.0.20-51 +- Stop reloading kdump service on CPU hotplug event for FADump +- fadump: improve fadump-howto.txt about remote dump target setup + +* Tue May 25 2021 Pingfan Liu - 2.0.20-50 +- rd.route should use the name from kdump_setup_ifname +- get kdump ifname once in kdump_install_netdev + +* Tue May 25 2021 Pingfan Liu - 2.0.20-49 +- kdump-lib.sh: fix the case if no enough total RAM for kdump in get_recommend_size() + +* Thu May 20 2021 Pingfan Liu - 2.0.20-48 +- kdumpctl: Add kdumpctl estimate +- mkdumprd: make use of the new get_luks_crypt_dev helper +- kdump-lib.sh: introduce a helper to get all crypt dev used by kdump +- kdump-lib.sh: introduce a helper to get underlying crypt device +- RHEL-only: keep total memory size coherent to RHEL-only kernel patch +- Show write byte size in report messages +- Add shorthand --show-stats option to show report stats +- Add --dry-run option to prevent writing the dumpfile +- kdump-lib.sh: introduce functions to return recommened mem size + +* Mon May 10 2021 Pingfan Liu - 2.0.20-47 +- Implement IP netmask calculation to replace "ipcalc -m" +- kdumpctl: fix check_config error when kdump.conf is empty +- Fix incorrect vmcore permissions when dumped through ssh +- Fix incorrect permissions on kdump dmesg file + * Mon Jan 25 2021 Pingfan Liu - 2.0.20-45 - origin/rhel-8.4.0) Revert "Revert "Append both nofail and x-systemd.before to kdump mount target"" - kdump.conf: add ipv6 example for nfs and ssh dump