kdump-lib: Harden _crashkernel_add

Resolves: https://issues.redhat.com/browse/RHEL-8727
Resolves: https://issues.redhat.com/browse/RHEL-8710
Upstream: Fedora
Conflict: spec/kdump-lib_spec.sh doesn't exist in RHEL, so I remove
          the hunk directly.

commit 64f2827a4bfa3f26974972f2f5a4477eec58f221
Author: Philipp Rudo <prudo@redhat.com>
Date:   Wed Sep 6 10:49:47 2023 +0200

    kdump-lib: Harden _crashkernel_add

    _crashkernel_add currently always assumes the good case, i.e. that the
    value of the crashkernel parameter has the correct syntax and that the
    delta added is a number. Both doesn't have to be true when the values
    are provided by users. Thus add some additional checks.

    Furthermore require the delta to have a explicit unit, i.e. no longer
    assume that is in megabytes, i.e. 100 -> 100M.

    Signed-off-by: Philipp Rudo <prudo@redhat.com>
    Reviewed-by: Pingfan Liu <piliu@redhat.com>
Signed-off-by: Baoquan He <bhe@redhat.com>
This commit is contained in:
Baoquan He 2023-09-06 10:49:47 +02:00
parent 0094f46c37
commit 0778b6add9
1 changed files with 109 additions and 46 deletions

View File

@ -993,62 +993,125 @@ has_aarch64_smmu()
ls /sys/devices/platform/arm-smmu-* 1> /dev/null 2>&1
}
# $1 crashkernel=""
# $2 delta in unit of MB
_crashkernel_add()
is_memsize() { [[ "$1" =~ ^[+-]?[0-9]+[KkMmGg]?$ ]]; }
# range defined for crashkernel parameter
# i.e. <start>-[<end>]
is_memrange()
{
local _ck _add _entry _ret
local _range _size _offset
is_memsize "${1%-*}" || return 1
[[ -n ${1#*-} ]] || return 0
is_memsize "${1#*-}"
}
_ck="$1"
_add="$2"
_ret=""
to_bytes()
{
local _s
if [[ "$_ck" == *@* ]]; then
_offset="@${_ck##*@}"
_ck=${_ck%@*}
elif [[ "$_ck" == *,high ]] || [[ "$_ck" == *,low ]]; then
_offset=",${_ck##*,}"
_ck=${_ck%,*}
_s="$1"
is_memsize "$_s" || return 1
case "${_s: -1}" in
K|k)
_s=${_s::-1}
_s="$((_s * 1024))"
;;
M|m)
_s=${_s::-1}
_s="$((_s * 1024 * 1024))"
;;
G|g)
_s=${_s::-1}
_s="$((_s * 1024 * 1024 * 1024))"
;;
*)
;;
esac
echo "$_s"
}
memsize_add()
{
local -a units=("" "K" "M" "G")
local i a b
a=$(to_bytes "$1") || return 1
b=$(to_bytes "$2") || return 1
i=0
(( a += b ))
while :; do
[[ $(( a / 1024 )) -eq 0 ]] && break
[[ $(( a % 1024 )) -ne 0 ]] && break
[[ $(( ${#units[@]} - 1 )) -eq $i ]] && break
(( a /= 1024 ))
(( i += 1 ))
done
echo "${a}${units[$i]}"
}
_crashkernel_parse()
{
local ck entry
local range size offset
ck="$1"
if [[ "$ck" == *@* ]]; then
offset="@${ck##*@}"
ck=${ck%@*}
elif [[ "$ck" == *,high ]] || [[ "$ck" == *,low ]]; then
offset=",${ck##*,}"
ck=${ck%,*}
else
_offset=''
offset=''
fi
while read -d , -r _entry; do
[[ -n "$_entry" ]] || continue
if [[ "$_entry" == *:* ]]; then
_range=${_entry%:*}
_size=${_entry#*:}
while read -d , -r entry; do
[[ -n "$entry" ]] || continue
if [[ "$entry" == *:* ]]; then
range=${entry%:*}
size=${entry#*:}
else
_range=""
_size=${_entry}
range=""
size=${entry}
fi
case "${_size: -1}" in
K)
_size=${_size::-1}
_size="$((_size + (_add * 1024)))K"
;;
M)
_size=${_size::-1}
_size="$((_size + _add))M"
;;
G)
_size=${_size::-1}
_size="$((_size * 1024 + _add))M"
;;
*)
_size="$((_size + (_add * 1024 * 1024)))"
;;
esac
echo "$size;$range;"
done <<< "$ck,"
echo ";;$offset"
}
[[ -n "$_range" ]] && _ret+="$_range:"
_ret+="$_size,"
done <<< "$_ck,"
# $1 crashkernel command line parameter
# $2 size to be added
_crashkernel_add()
{
local ck delta ret
local range size offset
_ret=${_ret%,}
[[ -n "$_offset" ]] && _ret+=$_offset
echo "$_ret"
ck="$1"
delta="$2"
ret=""
while IFS=';' read -r size range offset; do
if [[ -n "$offset" ]]; then
ret="${ret%,}$offset"
break
fi
[[ -n "$size" ]] || continue
if [[ -n "$range" ]]; then
is_memrange "$range" || return 1
ret+="$range:"
fi
size=$(memsize_add "$size" "$delta") || return 1
ret+="$size,"
done < <( _crashkernel_parse "$ck")
echo "${ret%,}"
}
# get default crashkernel
@ -1098,7 +1161,7 @@ kdump_get_arch_recommend_crashkernel()
#4k kernel, mlx5 consumes extra 124M memory, and choose 150M
has_mlx5 && ((_delta += 150))
fi
_ck_cmdline=$(_crashkernel_add "$_ck_cmdline" "$_delta")
_ck_cmdline=$(_crashkernel_add "$_ck_cmdline" "${_delta}M")
elif [[ $_arch == "ppc64le" ]]; then
if [[ $_dump_mode == "fadump" ]]; 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"