diff mbox series

livepatch-build-tools: Detect special section group sizes

Message ID cc280176-7383-0600-9298-f6c981475245@rimuhosting.com (mailing list archive)
State Superseded
Headers show
Series livepatch-build-tools: Detect special section group sizes | expand

Commit Message

Glenn Enright April 12, 2019, 4:50 a.m. UTC
A recent xsa livepatch failed to generate due to the following 
message in create-diff-object.log ...

/livepatch-build-tools/create-diff-object: ERROR: grant_table.o:
kpatch_regenerate_special_section: 1162: group size mismatch for section
.altinstructions

This is similar to the issue reported and fixed in
https://github.com/dynup/kpatch/pull/528 which says ...
"Hard-coding the special section group sizes is unreliable.
 Instead, determine them dynamically by finding the related
 struct definitions in the DWARF metadata."

Signed-off-by: Glenn Enright <glenn@rimuhosting.com>
---
CC: Ross Lagerwall <ross.lagerwall@citrix.com>
CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

This patch resulted in a loadable livepatch. The alt section size in my
case was actually 14.
---
 create-diff-object.c |   30 ++++++++++++++++++++++++++++--
 livepatch-build      |   21 +++++++++++++++++++++
 2 files changed, 49 insertions(+), 2 deletions(-)

Comments

Ross Lagerwall April 16, 2019, 10:05 a.m. UTC | #1
On 4/12/19 5:50 AM, Glenn Enright wrote:
> A recent xsa livepatch failed to generate due to the following
> message in create-diff-object.log ...
> 
> /livepatch-build-tools/create-diff-object: ERROR: grant_table.o:
> kpatch_regenerate_special_section: 1162: group size mismatch for section
> .altinstructions
> 
> This is similar to the issue reported and fixed in
> https://github.com/dynup/kpatch/pull/528 which says ...
> "Hard-coding the special section group sizes is unreliable.
>   Instead, determine them dynamically by finding the related
>   struct definitions in the DWARF metadata."
> 
> Signed-off-by: Glenn Enright <glenn@rimuhosting.com>
> ---
> CC: Ross Lagerwall <ross.lagerwall@citrix.com>
> CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> 
> This patch resulted in a loadable livepatch. The alt section size in my
> case was actually 14.
Thanks for the patch!

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Konrad Rzeszutek Wilk April 25, 2019, 4:45 a.m. UTC | #2
On Tue, Apr 16, 2019 at 11:05:49AM +0100, Ross Lagerwall wrote:
> On 4/12/19 5:50 AM, Glenn Enright wrote:
> > A recent xsa livepatch failed to generate due to the following
> > message in create-diff-object.log ...
> > 
> > /livepatch-build-tools/create-diff-object: ERROR: grant_table.o:
> > kpatch_regenerate_special_section: 1162: group size mismatch for section
> > .altinstructions
> > 
> > This is similar to the issue reported and fixed in
> > https://github.com/dynup/kpatch/pull/528 which says ...
> > "Hard-coding the special section group sizes is unreliable.
> >   Instead, determine them dynamically by finding the related
> >   struct definitions in the DWARF metadata."
> > 
> > Signed-off-by: Glenn Enright <glenn@rimuhosting.com>
> > ---
> > CC: Ross Lagerwall <ross.lagerwall@citrix.com>
> > CC: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > 
> > This patch resulted in a loadable livepatch. The alt section size in my
> > case was actually 14.
> Thanks for the patch!
> 
> Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

Could you resend it with the Reviewed-by please and include me on the To list please?
diff mbox series

Patch

diff --git a/create-diff-object.c b/create-diff-object.c
index 82f777e..f9f4abf 100644
--- a/create-diff-object.c
+++ b/create-diff-object.c
@@ -962,9 +962,35 @@  static int bug_frames_0_group_size(struct kpatch_elf *kelf, int offset) { return
 static int bug_frames_1_group_size(struct kpatch_elf *kelf, int offset) { return 8; }
 static int bug_frames_2_group_size(struct kpatch_elf *kelf, int offset) { return 8; }
 static int bug_frames_3_group_size(struct kpatch_elf *kelf, int offset) { return 16; }
-static int ex_table_group_size(struct kpatch_elf *kelf, int offset) { return 8; }
-static int altinstructions_group_size(struct kpatch_elf *kelf, int offset) { return 12; }
+int ex_table_group_size(struct kpatch_elf *kelf, int offset)
+{
+       static int size = 0;
+       char *str;
+
+       if (!size) {
+               str = getenv("EX_STRUCT_SIZE");
+               if (!str)
+                       ERROR("EX_STRUCT_SIZE not set");
+               size = atoi(str);
+       }
+
+       return size;
+}
 
+int altinstructions_group_size(struct kpatch_elf *kelf, int offset)
+{
+       static int size = 0;
+       char *str;
+
+       if (!size) {
+               str = getenv("ALT_STRUCT_SIZE");
+               if (!str)
+                       ERROR("ALT_STRUCT_SIZE not set");
+               size = atoi(str);
+       }
+
+       return size;
+}
 /*
  * The rela groups in the .fixup section vary in size.  The beginning of each
  * .fixup rela group is referenced by the .ex_table section. To find the size
diff --git a/livepatch-build b/livepatch-build
index c057fa1..6c3409c 100755
--- a/livepatch-build
+++ b/livepatch-build
@@ -304,6 +304,27 @@  if [ "${SKIP}" != "build" ]; then
         XEN_DEBUG="debug=$XEN_DEBUG"
     fi
 
+    echo "Reading special section data"
+    SPECIAL_VARS=$(readelf -wi "$XENSYMS" |
+        gawk --non-decimal-data '
+       BEGIN { a = e = 0 }
+       a == 0 && /DW_AT_name.* alt_instr$/ {a = 1; next}
+       e == 0 && /DW_AT_name.* exception_table_entry$/ {e = 1; next}
+       a == 1 {printf("export ALT_STRUCT_SIZE=%d\n", $4); a = 2}
+       e == 1 {printf("export EX_STRUCT_SIZE=%d\n", $4); e = 2}
+       a == 2 && b == 2 && p == 2 && e == 2 {exit}')
+
+    [[ -n $SPECIAL_VARS ]] && eval "$SPECIAL_VARS"
+
+    if [[ -z $ALT_STRUCT_SIZE ]] || [[ -z $EX_STRUCT_SIZE ]]; then
+       die "can't find special struct size"
+    fi
+    for i in $ALT_STRUCT_SIZE $EX_STRUCT_SIZE; do 
+       if [[ ! $i -gt 0 ]] || [[ ! $i -le 16 ]]; then
+               die "invalid special struct size $i"
+       fi
+    done
+
     echo "Perform full initial build with ${CPUS} CPU(s)..."
     build_full