LivePatch

From Xen
Jump to navigationJump to search

Design

Xen 4.7 implements v1 of the xSplice Design.


The code for hypervisor (Must enable it by by changing xen/.config to have CONFIG_XSPLICE=y or using:

cd xen make menuconfig

And selecting Common Features|xSplice live patching support.

It is marked as TECH PREVIEW.

The tool to patch/load/etc is called xen-xsplice and is also part of the Xen source tree.

The Xen source is at:

git://xenbits.xen.org/xen.git

The generation of payload is at:

git://xenbits.xen.org/people/konradwilk/xsplice-build-tools.git

IRC

We will have monthly IRC meetings to discuss code/issues/etc.

They are on the fourth Tuesday of every month. At 10:00AM EST on #xsplice channel on irc.freenode.net

OSSTest

Make OSSTest do regression tests.

Toolstack

Things that need to be done in there:

  • xen-xsplice better smarts. Right now you need to do 'upload','check' and 'apply'. Three operations which could be folded in one - since the system admin probably want to have all of those done at once. The 'all' option does that.
  • Instead of using 'xen-xsplice' we should use 'xl'. That above mentioned logic could be part of 'xl' while 'xen-xsplice' is an accessory function for expert users?
  • If hypervisor is compiled without xSplice the tool should print simply '"xsplice support not available in Xen'
  • If the build-id is wrong and one tries to apply the payload the message of 'hello failed with 1(Operation not permitted)' is lacking. We should have more details (and maybe a different error?). Or perhaps check the build-d as as being upload (however we may load them out of order). Perhaps have the toolstack check the build-id? How to do that against loaded patches (have them locally saved?)

Build

To build hot-patches aka payloads aka binary fixes against the hypervisor, you need two things:

  • Xen hypervisor which supports xSplice hypercalls. See above URL for the patches.
  • Tool to build binary fixes against hypervisor. See above URL for the tool. Note that the #xsplice.v4 patchset also includes three examples of payloads for testing/development.

Hypervisor

Currently the implementation has many TODOs implemented.

However we need to expand the hypervisor to include support for:

  • build_id support Done!
  • The check for --build-id needs to deal with localized binutils.
  • Make .xsplice.funcs be an SHF_MERGE type with .sh_entsize having the size of the struct.
  • Make the usage of tools/symbols use common list model
  • Need 'dl_sym' functionality in hypervisor to parse ELF payload. Do dynamic linking. (Ross) Done!
  • Lookup and insertion in the symbol table. Compute the proper offset and virtual address based on symbol name (<do_domctl>) (Ross) Done!
  • When figuring out the new_addr and the name is <symbol>+<offset> - compute that.
  • Need to either remove duplicate names from the symbol table or have the hypervisor implement proper ELF parsing - integrate the elf sections and parse that during runtime. Done!
  • Insertion of exceptions in the exception table. Also support resorting it. The hot-patch may have new exceptions that need to be dealt with.Done!
  • Code to verify signature of the ELF payload.
  • Checking the build-id against the hypervisor.Done!
  • Code to patch and revert the hot-patch (for simplicity we could boot Xen with 'cpus=1' so we don't have to worry about proper code to trigger patching)Done!
    • Patching requires saving the initial state. That needs to be saved for revert.Done!
    • Patching needs allocation of memory, putting in the code at memory.Done!
    • Doing the verification - checking if any code that uses the to-be-patched-function is in use. Save what the virtual address for the functions is - and verify the stack when patching (this incidentally is what .xsplice_section structures can have).
    • Deal with proper page table types for the modification (ro for .data, x for .text, etc).Done!
    • Code to revert.Done!
  • Code to activate patching mechanism. On VMEXIT routine right before checking the do_softirq. Ditto for PV paths. Call the top patching mechanism - which can IPI other CPUs (or wait until all CPUs have come to the same point).Done!
  • The code for doing the patching - call from __do_softirq - can also be used for runtime microcode loading.
  • Add functionality to execute ELF code.Done!
  • Patch with NOPs if .xsplice.funcs->new_size has 0.
  • Seperate pages for .text; .rodata; .bss and .data
  • A better mechanism to "mask" NMIs during patching. The existing mechanism looses NMI if they have been sent and we don't have a mechanism to replay them. Note that this is also fixes alternative section patching.
  • Make it work under ARM32:
    • Support ARM32 ELF relocations
    • Support ARM32 virtual addresses
    • Support a similar to CPU flushing semantics as x86
    • Support NMI? (or something similar?)
  • Make it work under ARM64:
    • Support ARM64 ELF relocations
    • Support ARM64 virtual addresses
    • Support a similar to CPU flushing semantics as x86
    • Support NMI? (or something similar?)

ELF payload file

The spec details how the structures look.

The external tool:

http://xenbits.xen.org/gitweb/?p=people/konradwilk/xsplice-build-tools.git

can generate the payloads against the hypervisor.

Regression hot-patches

There are three regression/test-cases:

  • xen_hello_world: changes xen_extra_version() to return "Hello World".
  • xen_bye_world: over-writes the xen_hello_world patch so it returns "Bye World."
  • xen_replace_world: Used to replace the two other payloads and make xen_extra_version() print "Hello Again World".

The idea is to do:

 # cd /usr/lib/debug
 # ls
 xen-syms-4.7-unstable  xen_bye_world.xsplice  xen_hello_world.xsplice  
 xen_replace_world.xsplice
 # xen-xsplice load xen_hello_world.xsplice 
 Uploading xen_hello_world.xsplice (12336 bytes)
 Performing apply:. completed
 # xl info | grep extra
 xen_extra              : Hello World
 # xen-xsplice load xen_bye_world.xsplice 
 Uploading xen_bye_world.xsplice (9244 bytes)
 Performing apply:. completed
 # xl info | grep extra
 xen_extra              : Bye World!
 # xen-xsplice upload replace_bye_and_hello xen_replace_world.xsplice 
 Uploading xen_replace_world.xsplice (9328 bytes)
 # xen-xsplice list
  ID                                     | status
 ----------------------------------------+------------
 xen_hello_world                         | APPLIED
 xen_bye_world                           | APPLIED
 replace_bye_and_hello                   | CHECKED
 # xen-xsplice replace replace_bye_and_hello
 Performing replace:. completed
 # xl info | grep extra
 xen_extra              : Hello Again World!
 # xen-xsplice list
  ID                                     | status
 ----------------------------------------+------------
 xen_hello_world                         | CHECKED
 xen_bye_world                           | CHECKED
 replace_bye_and_hello                   | APPLIED

Build hot-patches

This explanation was lifted from this link and modified a bit:

This transcript should demonstrate how to use the tool.


 $ mkdir ~/work
 $ cd ~/work
 $ git clone git://xenbits.xen.org/people/konradwilk/xen.git
 $ cd xen
 # git checkout xsplice.v4
 $ # Build a debug Xen and tools (including misc/xen-xsplice), install on a host  and reboot
 
 $ # Write a patch
 $ git diff > ~/work/test1.patch
 $ git reset --hard
 $ # Write another patch
 $ git diff > ~/work/test2.patch
 $ git reset --hard
 $ # Write another patch
 $ git diff > ~/work/test3.patch
 $ git reset --hard
 
 $ cd ~/work
 $ git clone git://xenbits.xen.org/people/konradwilk/xsplice-build-tools.git
 $ cd xsplice-build
 $ make
 $ ./xsplice-build -s ~/work/xen -p ~/work/test1.patch -o out1 --xen-debug --debug $ ./xsplice-build -s ~/work/xen -p ~/work/test2.patch -o out2 --xen-debug --debug $ ./xsplice-build -s ~/work/xen -p ~/work/test3.patch -o out3 --xen-debug --debug
 $ # copy out*/test*.xsplice onto the host
 
 
 On the host:
 # xen-xsplice upload test1 test1.xsplice
 # xen-xsplice upload test2 test2.xsplice
 # xen-xsplice upload test3 test3.xsplice
 
 # xen-xsplice apply test1
 # # Verify test1 is applied
 # xen-xsplice apply test2
 # # Verify test2 is also applied
 # xen-xsplice replace test3
 # # Verify test3 is applied and test1 and test2 are not
 # xen-xsplice revert test3
 # # Verify test3 is not applied
 
 # xen-xsplice unload test1
 # xen-xsplice unload test2
 # xen-xsplice unload test3