[Pkg-xen-devel] Xen package security updates for jessie 4.4, XSA-213, XSA-214

Moritz Muehlenhoff jmm at inutil.org
Thu May 4 20:59:24 UTC 2017


Hi Ian,

On Thu, May 04, 2017 at 08:18:07PM +0100, Ian Jackson wrote:
> Moritz Muehlenhoff writes ("Re: Xen package security updates for jessie 4.4, XSA-213, XSA-214"):
> > Yes, the distribution line should be jessie-security, but please send
> > a debdiff to team at security.debian.org for a quick review before
> > uploading (I have no idea whether dgit supports security-master).
> 
> Here is the proposed debdiff (actually, a git diff) for xen in jessie.
> 
> My ARM test build is still running but I think it's going to work.  I
> have actually tested the i386 package.
> 
> Can I do a source-only upload ?

Unfortunately that's not supported by the dak installation on security-master
for jessie-security, stretch-security will allow that soon.

> diff --git a/debian/changelog b/debian/changelog
> index 25361a61e4..a42f68d3a9 100644
> --- a/debian/changelog
> +++ b/debian/changelog
> @@ -1,3 +1,12 @@
> +xen (4.4.1-9+deb8u9) unstable; urgency=medium

The distribution needs to be jessie-security.

> +  Security updates:
> +  * XSA-213: Closes:#861659: 64bit PV guest breakout
> +  * XSA-214: Closes:#861660: grant transfer PV privilege escalation
> +  * XSA-215: Closes:#861662: memory corruption via failsafe callback

Let's also include fixes for https://xenbits.xen.org/xsa/advisory-212.html
and https://xenbits.xen.org/xsa/advisory-200.html, for these even official
4.4 backports are available.

Wrt CVE IDs, let's use the Debian CNA next time, it's really silly that MITRE
still hasn't assigned something for XSA 213-215. We can assign those usually
within 24 hours from the Debian pool.

The patches all look fine, but the content of multicall-deal-with-early-exit-condition
is also included in the tree again (outside of debian/patches):

Cheers,
        Moritz

> diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
> index 4c910c810f..9491e662a1 100644
> --- a/xen/arch/arm/traps.c
> +++ b/xen/arch/arm/traps.c
> @@ -1243,30 +1243,31 @@ static bool_t check_multicall_32bit_clean(struct multicall_entry *multi)
>      return true;
>  }
>  
> -void do_multicall_call(struct multicall_entry *multi)
> +enum mc_disposition do_multicall_call(struct multicall_entry *multi)
>  {
>      arm_hypercall_fn_t call = NULL;
>  
>      if ( multi->op >= ARRAY_SIZE(arm_hypercall_table) )
>      {
>          multi->result = -ENOSYS;
> -        return;
> +        return mc_continue;
>      }
>  
>      call = arm_hypercall_table[multi->op].fn;
>      if ( call == NULL )
>      {
>          multi->result = -ENOSYS;
> -        return;
> +        return mc_continue;
>      }
>  
>      if ( is_pv32_domain(current->domain) &&
>           !check_multicall_32bit_clean(multi) )
> -        return;
> +        return mc_continue;
>  
>      multi->result = call(multi->args[0], multi->args[1],
>                           multi->args[2], multi->args[3],
>                           multi->args[4]);
> +    return mc_continue; /* XXX XSA-213 remains! */
>  }
>  
>  /*
> diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
> index ba13c4277e..209e9875db 100644
> --- a/xen/arch/x86/mm.c
> +++ b/xen/arch/x86/mm.c
> @@ -4227,6 +4227,17 @@ int steal_page(
>          y = cmpxchg(&page->count_info, x, x & ~PGC_count_mask);
>      } while ( y != x );
>  
> +    /*
> +     * With the sole reference dropped temporarily, no-one can update type
> +     * information. Type count also needs to be zero in this case, but e.g.
> +     * PGT_seg_desc_page may still have PGT_validated set, which we need to
> +     * clear before transferring ownership (as validation criteria vary
> +     * depending on domain type).
> +     */
> +    BUG_ON(page->u.inuse.type_info & (PGT_count_mask | PGT_locked |
> +                                      PGT_pinned));
> +    page->u.inuse.type_info = 0;
> +
>      /* Swizzle the owner then reinstate the PGC_allocated reference. */
>      page_set_owner(page, NULL);
>      y = page->count_info;
> diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
> index c634217402..be973b3985 100644
> --- a/xen/arch/x86/x86_64/entry.S
> +++ b/xen/arch/x86/x86_64/entry.S
> @@ -346,7 +346,7 @@ int80_slow_path:
>          jmp   handle_exception_saved
>  
>  /* CREATE A BASIC EXCEPTION FRAME ON GUEST OS STACK:                     */
> -/*   { RCX, R11, [DS-GS,] [CR2,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS }   */
> +/*   { RCX, R11, [DS-GS,] [ERRCODE,] RIP, CS, RFLAGS, RSP, SS }          */
>  /* %rdx: trap_bounce, %rbx: struct vcpu                                  */
>  /* On return only %rbx and %rdx are guaranteed non-clobbered.            */
>  create_bounce_frame:
> @@ -366,7 +366,7 @@ create_bounce_frame:
>  2:      andq  $~0xf,%rsi                # Stack frames are 16-byte aligned.
>          movq  $HYPERVISOR_VIRT_START,%rax
>          cmpq  %rax,%rsi
> -        movq  $HYPERVISOR_VIRT_END+60,%rax
> +        movq  $HYPERVISOR_VIRT_END+12*8,%rax
>          sbb   %ecx,%ecx                 # In +ve address space? Then okay.
>          cmpq  %rax,%rsi
>          adc   %ecx,%ecx                 # Above Xen private area? Then okay.
> diff --git a/xen/common/multicall.c b/xen/common/multicall.c
> index fa9d910594..da13573600 100644
> --- a/xen/common/multicall.c
> +++ b/xen/common/multicall.c
> @@ -40,6 +40,7 @@ do_multicall(
>      struct mc_state *mcs = &current->mc_state;
>      uint32_t         i;
>      int              rc = 0;
> +    enum mc_disposition disp = mc_continue;
>  
>      if ( unlikely(__test_and_set_bit(_MCSF_in_multicall, &mcs->flags)) )
>      {
> @@ -50,7 +51,7 @@ do_multicall(
>      if ( unlikely(!guest_handle_okay(call_list, nr_calls)) )
>          rc = -EFAULT;
>  
> -    for ( i = 0; !rc && i < nr_calls; i++ )
> +    for ( i = 0; !rc && disp == mc_continue && i < nr_calls; i++ )
>      {
>          if ( i && hypercall_preempt_check() )
>              goto preempted;
> @@ -63,7 +64,7 @@ do_multicall(
>  
>          trace_multicall_call(&mcs->call);
>  
> -        do_multicall_call(&mcs->call);
> +        disp = do_multicall_call(&mcs->call);
>  
>  #ifndef NDEBUG
>          {
> @@ -77,7 +78,14 @@ do_multicall(
>          }
>  #endif
>  
> -        if ( unlikely(__copy_field_to_guest(call_list, &mcs->call, result)) )
> +        if ( unlikely(disp == mc_exit) )
> +        {
> +            if ( __copy_field_to_guest(call_list, &mcs->call, result) )
> +                /* nothing, best effort only */;
> +            rc = mcs->call.result;
> +        }
> +        else if ( unlikely(__copy_field_to_guest(call_list, &mcs->call,
> +                                                 result)) )
>              rc = -EFAULT;
>          else if ( test_bit(_MCSF_call_preempted, &mcs->flags) )
>          {
> @@ -93,6 +101,9 @@ do_multicall(
>              guest_handle_add_offset(call_list, 1);
>      }
>  
> +    if ( unlikely(disp == mc_preempt) && i < nr_calls )
> +        goto preempted;
> +
>      perfc_incr(calls_to_multicall);
>      perfc_add(calls_from_multicall, i);
>      mcs->flags = 0;
> diff --git a/xen/include/asm-arm/multicall.h b/xen/include/asm-arm/multicall.h
> index b95926274f..ee3b345903 100644
> --- a/xen/include/asm-arm/multicall.h
> +++ b/xen/include/asm-arm/multicall.h
> @@ -1,7 +1,11 @@
>  #ifndef __ASM_ARM_MULTICALL_H__
>  #define __ASM_ARM_MULTICALL_H__
>  
> -extern void do_multicall_call(struct multicall_entry *call);
> +extern enum mc_disposition {
> +    mc_continue,
> +    mc_exit,
> +    mc_preempt,
> +} do_multicall_call(struct multicall_entry *call);
>  
>  #endif /* __ASM_ARM_MULTICALL_H__ */
>  /*
> diff --git a/xen/include/asm-x86/multicall.h b/xen/include/asm-x86/multicall.h
> index a09ac5a1ae..32060aef38 100644
> --- a/xen/include/asm-x86/multicall.h
> +++ b/xen/include/asm-x86/multicall.h
> @@ -7,8 +7,21 @@
>  
>  #include <xen/errno.h>
>  
> +enum mc_disposition {
> +    mc_continue,
> +    mc_exit,
> +    mc_preempt,
> +};
> +
> +#define multicall_ret(call)                                  \
> +    (unlikely((call)->op == __HYPERVISOR_iret)               \
> +     ? mc_exit                                               \
> +       : likely(guest_kernel_mode(current,                   \
> +                                  guest_cpu_user_regs()))    \
> +         ? mc_continue : mc_preempt)
> +
>  #define do_multicall_call(_call)                             \
> -    do {                                                     \
> +    ({                                                       \
>          __asm__ __volatile__ (                               \
>              "    movq  %c1(%0),%%rax; "                      \
>              "    leaq  hypercall_table(%%rip),%%rdi; "       \
> @@ -36,9 +49,11 @@
>                /* all the caller-saves registers */           \
>              : "rax", "rcx", "rdx", "rsi", "rdi",             \
>                "r8",  "r9",  "r10", "r11" );                  \
> -    } while ( 0 )
> +        multicall_ret(_call);                                \
> +    })
>  
>  #define compat_multicall_call(_call)                         \
> +    ({                                                       \
>          __asm__ __volatile__ (                               \
>              "    movl  %c1(%0),%%eax; "                      \
>              "    leaq  compat_hypercall_table(%%rip),%%rdi; "\
> @@ -65,6 +80,8 @@
>                "i" (offsetof(__typeof__(*_call), result))     \
>                /* all the caller-saves registers */           \
>              : "rax", "rcx", "rdx", "rsi", "rdi",             \
> -              "r8",  "r9",  "r10", "r11" )                   \
> +              "r8",  "r9",  "r10", "r11" );                  \
> +        multicall_ret(_call);                                \
> +    })
>  
>  #endif /* __ASM_X86_MULTICALL_H__ */
> 



More information about the Pkg-xen-devel mailing list