Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicolai Stange <nstange@suse.de>2018-07-08 13:02:18 +0200
committerMiroslav Benes <mbenes@suse.cz>2018-07-10 13:52:12 +0200
commit56f07295b288469a12dd4fd062faf2510b444f52 (patch)
tree793f0f61b0e98ed3b403034505754c284eae8239
parent98526616971665ee0eb13274384cfaa3d28b4378 (diff)
scripts/register-patches.sh: implement conditional inclusion
Currently, subpatches provide a patched_funcs.csv file describing what needs to be patched. register-patches.sh inspects those to assemble one global klp_patch structure. The current format for these patched_funcs.csv's is obj old_func(,sympos) newfun However, sometimes subpatches depend on some kernel configuration values like CONFIG_X86_64 and functions shall get patched only if the target kernel configuration matches. Extends the patched_funcs.csv format to obj old_func(,sympos) newfun (cpp condition) where everything coming after 'newfun' is taken to be a CPP condition to be used for conditional inclusion. In case there's no condition specified, assign that entry the same semantics as if a '1' had been given. Make register-patches.sh guard the corresponding klp_func entries with #if pragmas. Furthermore, let it guard the enclosing klp_object instances by or'ing together all its klp_funcs' conditions. For the sake of better readability, omit redundant #if pragmas as well as condition clauses. In particular, - if a function entry hasn't got any condition explicitly specified, there won't be any #if pragma, neither at the klp_func nor at the klp_object level, - if multiple function entries for an object are protected by the same condition, it'll be or'ed in at the klp_object level only once, - if all of an object's functions share the same condition, no #if pragmas will be emitted at the klp_func level because they would only duplicate what's already there for the enclosing object and - multiple subsequent function entries sharing the same condition get collated. Signed-off-by: Nicolai Stange <nstange@suse.de> Signed-off-by: Miroslav Benes <mbenes@suse.cz>
-rwxr-xr-xscripts/register-patches.sh128
1 files changed, 106 insertions, 22 deletions
diff --git a/scripts/register-patches.sh b/scripts/register-patches.sh
index 6bb6be4..82417fc 100755
--- a/scripts/register-patches.sh
+++ b/scripts/register-patches.sh
@@ -30,7 +30,7 @@
#
# Furthermore, each subpatch must provide a SUBPATCH/patched_funcs.csv
# file with one line of the form
-# obj old_func(,sympos) newfun
+# obj old_func(,sympos) newfun (cpp #if condition)
# for every to be patched symbol.
#
#
@@ -93,6 +93,59 @@ objs="vmlinux $objs"
KLP_PATCHES_OBJS=$(
echo -n "\t/* Auto expanded KLP_PATCHES_OBJS: */\n"
for o in $objs; do
+ # First gather the #if conditions for that object.
+ # vmlinux gets always patched because of uname().
+ declare -a o_conds
+ o_conds=()
+ if [ x"$o" != xvmlinux ]; then
+ for pf in "${patched_funcs[@]}"; do
+ while read _o oldfun newfun cond; do
+ if [ -z "$_o" ]; then
+ continue
+ elif [ -z "$newfun" ]; then
+ echo "error: invalid patched_funcs line: " \
+ "$_o $oldfun" 1>&2
+ elif [ x"$_o" != x"$o" ]; then
+ continue
+ fi
+
+ if [ -z "$cond" ]; then
+ # unconditional
+ o_conds=()
+ break
+ else
+ # Avoid adding duplicates
+ for o_c in "${o_conds[@]}"; do
+ if [ x"$o_c" = x"$cond" ]; then
+ cond=
+ break
+ fi
+ done
+ if [ -n "$cond" ]; then
+ o_conds[${#o_conds[@]}]="$cond"
+ fi
+ fi
+ done < "$pf"
+ done
+ fi
+
+ # Emit the #if condition for the object, if any
+ if [ ${#o_conds[@]} -eq 1 ]; then
+ echo -n "#if ${o_conds[0]}\n"
+ elif [ ${#o_conds[@]} -ne 0 ]; then
+ echo -n "#if "
+ i=0
+ while [ $i -lt ${#o_conds[@]} ]; do
+ if [ $i -ne 0 ]; then
+ echo -n ' || '
+ fi
+ echo -n "(${o_conds[$i]})"
+ i=$((i + 1))
+ done
+ unset i
+ echo -n '\n'
+ fi
+
echo -n '\t{\n'
if [ x"$o" = xvmlinux ]; then
echo -n '\t\t.name = NULL,\n'
@@ -106,35 +159,67 @@ KLP_PATCHES_OBJS=$(
echo -n '.new_func = klp_sys_newuname, '
echo -n '},\n'
fi
- if [ ${#patched_funcs[@]} -gt 0 ]; then
- sed '/^[[:blank:]]*$/ d;' "${patched_funcs[@]}" | \
- while read _o oldfun newfun; do
- if [ -z "$newfun" ]; then
- echo "error: invalid patched_funcs line: " \
- "$_o $oldfun" 1>&2
- elif [ x"$_o" != x"$o" ]; then
- continue
- fi
- sympos=
- if echo $oldfun | grep -q ','; then
- sympos=$(echo $oldfun | sed 's/[^,]\+,\(.\+\)/\1/')
- oldfun=$(echo $oldfun | sed 's/,.*//')
- fi
- echo -n "\t\t\t{ .old_name = \"$oldfun\", "
- echo -n ".new_func = $newfun, "
- if [ -n "$sympos" ]; then
- echo -n ".old_sympos = $sympos, "
+ last_cond=
+ for pf in "${patched_funcs[@]}"; do
+ while read _o oldfun newfun cond; do
+ if [ -z "$_o" ]; then
+ continue
+ elif [ -z "$newfun" ]; then
+ echo "error: invalid patched_funcs line: " \
+ "$_o $oldfun" 1>&2
+ elif [ x"$_o" != x"$o" ]; then
+ continue
+ fi
+
+ # Collate multiple subsequent klp_func entries
+ # guarded by the same #if condition. Also, do not
+ # emit #if pragmas at the klp_func level if it
+ # would be equivalent to what's already there at
+ # the enclosing object level.
+ if [ ${#o_conds[@]} -eq 1 -a x"${o_conds[0]}" = x"$cond" ]
+ then
+ cond=
+ fi
+ if [ x"$last_cond" = x"$cond" ]; then
+ cond=
+ else
+ if [ -n "$last_cond" ]; then
+ echo -n "#endif\n"
fi
- echo -n '},\n'
- done
+ last_cond="$cond"
+ fi
+ if [ -n "$cond" ]; then
+ echo -n "#if $cond\n"
+ fi
+
+ sympos=
+ if echo $oldfun | grep -q ','; then
+ sympos=$(echo $oldfun | sed 's/[^,]\+,\(.\+\)/\1/')
+ oldfun=$(echo $oldfun | sed 's/,.*//')
+ fi
+ echo -n "\t\t\t{ .old_name = \"$oldfun\", "
+ echo -n ".new_func = $newfun, "
+ if [ -n "$sympos" ]; then
+ echo -n ".old_sympos = $sympos, "
+ fi
+ echo -n '},\n'
+ done < "$pf"
+ done
+ if [ -n "$last_cond" ]; then
+ echo -n "#endif\n"
fi
echo -n '\t\t\t{ }\n'
echo -n '\t\t}\n'
echo -n '\t},\n'
+ if [ ${#o_conds[@]} -ne 0 ]; then
+ echo -n '#endif\n'
+ fi
done
printf '\t{ }\n'
)
+### Escape the '&' character in the sed replacement
+KLP_PATCHES_OBJS="$(echo -n "$KLP_PATCHES_OBJS" | sed 's/&/\\&/g')"
## Initialize the individual patches in livepatch_init().
KLP_PATCHES_INIT_CALLS=$(
@@ -177,7 +262,6 @@ s%\s*@@KLP_PATCHES_CLEANUP_CALLS@@;\?%$KLP_PATCHES_CLEANUP_CALLS%;
s%\s*@@KLP_PATCHES_CLEANUP_CALLS@@;\?%$KLP_PATCHES_CLEANUP_CALLS%;
EOF
-
# Finish kernel-livepatch.spec:
## Enumerate the per subpatch source *.tar.bz2.
## Note: Start with Source5