[PATCH] livepatch-build: Check compiler version matches

Ross Lagerwall posted 1 patch 1 year, 2 months ago
Failed in applying to current master (apply log)
livepatch-build | 54 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 39 insertions(+), 15 deletions(-)
[PATCH] livepatch-build: Check compiler version matches
Posted by Ross Lagerwall 1 year, 2 months ago
For reliable live patch generation, the compiler version used should
match the original binary. Check that this is the case and add a
--skip-compiler-check option to override this.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
---
 livepatch-build | 54 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/livepatch-build b/livepatch-build
index 91d203b..e4b4dba 100755
--- a/livepatch-build
+++ b/livepatch-build
@@ -33,6 +33,7 @@ DEPENDS=
 XEN_DEPENDS=
 PRELINK=
 STRIP=0
+SKIP_COMPILER_CHECK=0
 XENSYMS=xen-syms
 
 warn() {
@@ -266,27 +267,44 @@ function create_patch()
     objcopy --set-section-flags .livepatch.xen_depends=alloc,readonly "${PATCHNAME}.livepatch"
 }
 
+check_compiler() {
+    orig_ver=$(readelf -p .comment "$XENSYMS" | grep -o 'GCC.*')
+
+    in_file=$(mktemp --suffix=.c)
+    out_file=$(mktemp --suffix=.o)
+    echo 'int main(void) {}' > "$in_file"
+    gcc -c -o "$out_file" "$in_file"
+    new_ver=$(readelf -p .comment "$out_file" | grep -o 'GCC.*')
+
+    rm -f "$infile" "$outfile"
+
+    if [ "$orig_ver" != "$new_ver" ]; then
+        die "Mismatched compiler version: Original \"$orig_ver\" New \"$new_ver\""
+    fi
+}
+
 usage() {
     echo "usage: $(basename $0) [options]" >&2
-    echo "        -h, --help         Show this help message" >&2
-    echo "        -s, --srcdir       Xen source directory" >&2
-    echo "        -p, --patch        Patch file" >&2
-    echo "        -c, --config       .config file" >&2
-    echo "        -o, --output       Output directory" >&2
-    echo "        -j, --cpus         Number of CPUs to use" >&2
-    echo "        -k, --skip         Skip build or diff phase" >&2
-    echo "        -d, --debug        Enable debug logging" >&2
-    echo "        --xen-debug        Build debug Xen (if your .config does not have the options)" >&2
-    echo "        --xen-syms         Build against a xen-syms" >&2
-    echo "        --depends          Required build-id" >&2
-    echo "        --xen-depends      Required Xen build-id" >&2
-    echo "        --prelink          Prelink" >&2
-    echo "        --strip            Remove all symbols that are not needed for relocation processing." >&2
+    echo "        -h, --help            Show this help message" >&2
+    echo "        -s, --srcdir          Xen source directory" >&2
+    echo "        -p, --patch           Patch file" >&2
+    echo "        -c, --config          .config file" >&2
+    echo "        -o, --output          Output directory" >&2
+    echo "        -j, --cpus            Number of CPUs to use" >&2
+    echo "        -k, --skip            Skip build or diff phase" >&2
+    echo "        -d, --debug           Enable debug logging" >&2
+    echo "        --xen-debug           Build debug Xen (if your .config does not have the options)" >&2
+    echo "        --xen-syms            Build against a xen-syms" >&2
+    echo "        --depends             Required build-id" >&2
+    echo "        --xen-depends         Required Xen build-id" >&2
+    echo "        --prelink             Prelink" >&2
+    echo "        --strip               Remove all symbols that are not needed for relocation processing." >&2
+    echo "        --skip-compiler-check Skip compiler version check." >&2
 }
 
 find_tools || die "can't find supporting tools"
 
-options=$(getopt -o hs:p:c:o:j:k:d -l "help,srcdir:,patch:,config:,output:,cpus:,skip:,debug,xen-debug,xen-syms:,depends:,xen-depends:,prelink,strip" -- "$@") || die "getopt failed"
+options=$(getopt -o hs:p:c:o:j:k:d -l "help,srcdir:,patch:,config:,output:,cpus:,skip:,debug,xen-debug,xen-syms:,depends:,xen-depends:,prelink,strip,skip-compiler-check" -- "$@") || die "getopt failed"
 
 eval set -- "$options"
 
@@ -358,6 +376,10 @@ while [[ $# -gt 0 ]]; do
             STRIP=1
             shift
             ;;
+        --skip-compiler-check)
+            SKIP_COMPILER_CHECK=1
+            shift
+            ;;
         --)
             shift
             break
@@ -383,6 +405,8 @@ OUTPUT="$(readlink -m -- "$outputarg")"
 [ -f "${PATCHFILE}" ] || die "Patchfile does not exist"
 [ -f "${CONFIGFILE}" ] || die ".config does not exist"
 
+[ -f "$XENSYMS" ] && [ "$SKIP_COMPILER_CHECK" -eq 0 ] && check_compiler
+
 PATCHNAME=$(make_patch_name "${PATCHFILE}")
 
 echo "Building LivePatch patch: ${PATCHNAME}"
-- 
2.31.1
Re: [PATCH] livepatch-build: Check compiler version matches
Posted by Andrew Cooper 1 year, 2 months ago
On 21/02/2023 2:14 pm, Ross Lagerwall wrote:
> For reliable live patch generation, the compiler version used should
> match the original binary. Check that this is the case and add a
> --skip-compiler-check option to override this.
>
> Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
> ---
>  livepatch-build | 54 +++++++++++++++++++++++++++++++++++--------------
>  1 file changed, 39 insertions(+), 15 deletions(-)
>
> diff --git a/livepatch-build b/livepatch-build
> index 91d203b..e4b4dba 100755
> --- a/livepatch-build
> +++ b/livepatch-build
> @@ -33,6 +33,7 @@ DEPENDS=
>  XEN_DEPENDS=
>  PRELINK=
>  STRIP=0
> +SKIP_COMPILER_CHECK=0
>  XENSYMS=xen-syms
>  
>  warn() {
> @@ -266,27 +267,44 @@ function create_patch()
>      objcopy --set-section-flags .livepatch.xen_depends=alloc,readonly "${PATCHNAME}.livepatch"
>  }
>  
> +check_compiler() {
> +    orig_ver=$(readelf -p .comment "$XENSYMS" | grep -o 'GCC.*')

This rather breaks Clang as a toolchain, but it doesn't seem to be the
only GCC-expectation in livepatch build tools.

$ readelf -p .comment xen-syms

String dump of section '.comment':
  [     0]  Debian clang version 11.0.1-2


Irritatingly, while clang* --version always reports itself as "clang
version ..." matching the .ident it writes out, gcc* substitutes argv[0]
into it's --version.  But the way the Xen build is invoked, I think Xen
will always substituent cc for gcc, so this may not be a problem.

A build of Xen should only use a single compiler, so I think you're
better off looking for s/[     0]  \(.*\)/\1/ rather than assuming that
GCC was used.

Also, I think you should error out if we can't identify a compiler,
because very little good will come from trying to proceed.

~Andrew