pkgsrc-Changes archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

CVS commit: pkgsrc/sysutils/xenkernel415



Module Name:    pkgsrc
Committed By:   bouyer
Date:           Thu Sep 21 10:39:45 UTC 2023

Modified Files:
        pkgsrc/sysutils/xenkernel415: Makefile distinfo
Added Files:
        pkgsrc/sysutils/xenkernel415/patches: patch-XSA438

Log Message:
Apply upstream patch for security issue XSA438
Bump PKGREVISION


To generate a diff of this commit:
cvs rdiff -u -r1.10 -r1.11 pkgsrc/sysutils/xenkernel415/Makefile
cvs rdiff -u -r1.9 -r1.10 pkgsrc/sysutils/xenkernel415/distinfo
cvs rdiff -u -r0 -r1.1 pkgsrc/sysutils/xenkernel415/patches/patch-XSA438

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: pkgsrc/sysutils/xenkernel415/Makefile
diff -u pkgsrc/sysutils/xenkernel415/Makefile:1.10 pkgsrc/sysutils/xenkernel415/Makefile:1.11
--- pkgsrc/sysutils/xenkernel415/Makefile:1.10  Thu Aug 24 10:27:09 2023
+++ pkgsrc/sysutils/xenkernel415/Makefile       Thu Sep 21 10:39:45 2023
@@ -1,8 +1,9 @@
-# $NetBSD: Makefile,v 1.10 2023/08/24 10:27:09 bouyer Exp $
+# $NetBSD: Makefile,v 1.11 2023/09/21 10:39:45 bouyer Exp $
 
 VERSION=       4.15.5
 DISTNAME=      xen-${VERSION}
 PKGNAME=       xenkernel415-${VERSION}
+PKGREVISION=   1
 CATEGORIES=    sysutils
 MASTER_SITES=  https://downloads.xenproject.org/release/xen/${VERSION}/
 DIST_SUBDIR=   xen415

Index: pkgsrc/sysutils/xenkernel415/distinfo
diff -u pkgsrc/sysutils/xenkernel415/distinfo:1.9 pkgsrc/sysutils/xenkernel415/distinfo:1.10
--- pkgsrc/sysutils/xenkernel415/distinfo:1.9   Thu Aug 24 10:27:09 2023
+++ pkgsrc/sysutils/xenkernel415/distinfo       Thu Sep 21 10:39:45 2023
@@ -1,9 +1,10 @@
-$NetBSD: distinfo,v 1.9 2023/08/24 10:27:09 bouyer Exp $
+$NetBSD: distinfo,v 1.10 2023/09/21 10:39:45 bouyer Exp $
 
 BLAKE2s (xen415/xen-4.15.5.tar.gz) = 85bef27c99fd9fd3037ec6df5e514289b650f2f073bcc543d13d5997c03332d4
 SHA512 (xen415/xen-4.15.5.tar.gz) = 790f3d75df78f63f5b2ce3b99c1f2287f75ef5571d1b7a9bb9bac470bd28ccbd4816d07a1af8320eee4107626c75be029bd6dad1d99d58f3816906ed98d206d9
 Size (xen415/xen-4.15.5.tar.gz) = 40835793 bytes
 SHA1 (patch-Config.mk) = 9372a09efd05c9fbdbc06f8121e411fcb7c7ba65
+SHA1 (patch-XSA438) = a8288bbbe8ffe799cebbf6bb184b1a2b59b59089
 SHA1 (patch-xen_Makefile) = 465388d80de414ca3bb84faefa0f52d817e423a6
 SHA1 (patch-xen_Rules.mk) = c743dc63f51fc280d529a7d9e08650292c171dac
 SHA1 (patch-xen_arch_x86_Kconfig) = df14bfa09b9a0008ca59d53c938d43a644822dd9

Added files:

Index: pkgsrc/sysutils/xenkernel415/patches/patch-XSA438
diff -u /dev/null pkgsrc/sysutils/xenkernel415/patches/patch-XSA438:1.1
--- /dev/null   Thu Sep 21 10:39:45 2023
+++ pkgsrc/sysutils/xenkernel415/patches/patch-XSA438   Thu Sep 21 10:39:45 2023
@@ -0,0 +1,420 @@
+$NetBSD: patch-XSA438,v 1.1 2023/09/21 10:39:45 bouyer Exp $
+
+From: Jan Beulich <jbeulich%suse.com@localhost>
+Subject: x86/shadow: defer releasing of PV's top-level shadow reference
+
+sh_set_toplevel_shadow() re-pinning the top-level shadow we may be
+running on is not enough (and at the same time unnecessary when the
+shadow isn't what we're running on): That shadow becomes eligible for
+blowing away (from e.g. shadow_prealloc()) immediately after the
+paging lock was dropped. Yet it needs to remain valid until the actual
+page table switch occurred.
+
+Propagate up the call chain the shadow entry that needs releasing
+eventually, and carry out the release immediately after switching page
+tables. Handle update_cr3() failures by switching to idle pagetables.
+Note that various further uses of update_cr3() are HVM-only or only act
+on paused vCPU-s, in which case sh_set_toplevel_shadow() will not defer
+releasing of the reference.
+
+While changing the update_cr3() hook, also convert the "do_locking"
+parameter to boolean.
+
+This is CVE-2023-34322 / XSA-438.
+
+Reported-by: Tim Deegan <tim%xen.org@localhost>
+Signed-off-by: Jan Beulich <jbeulich%suse.com@localhost>
+Reviewed-by: George Dunlap <george.dunlap%cloud.com@localhost>
+
+--- xen/arch/x86/mm/hap/hap.c.orig
++++ xen/arch/x86/mm/hap/hap.c
+@@ -728,10 +728,12 @@ static bool_t hap_invlpg(struct vcpu *v,
+     return 1;
+ }
+ 
+-static void hap_update_cr3(struct vcpu *v, int do_locking, bool noflush)
++static pagetable_t hap_update_cr3(struct vcpu *v, bool do_locking, bool noflush)
+ {
+     v->arch.hvm.hw_cr[3] = v->arch.hvm.guest_cr[3];
+     hvm_update_guest_cr3(v, noflush);
++
++    return pagetable_null();
+ }
+ 
+ /*
+--- xen/arch/x86/mm/shadow/common.c.orig
++++ xen/arch/x86/mm/shadow/common.c
+@@ -2641,13 +2641,13 @@ void shadow_update_paging_modes(struct v
+ }
+ 
+ /* Set up the top-level shadow and install it in slot 'slot' of shadow_table */
+-void sh_set_toplevel_shadow(struct vcpu *v,
+-                            unsigned int slot,
+-                            mfn_t gmfn,
+-                            unsigned int root_type,
+-                            mfn_t (*make_shadow)(struct vcpu *v,
+-                                                 mfn_t gmfn,
+-                                                 uint32_t shadow_type))
++pagetable_t sh_set_toplevel_shadow(struct vcpu *v,
++                                   unsigned int slot,
++                                   mfn_t gmfn,
++                                   unsigned int root_type,
++                                   mfn_t (*make_shadow)(struct vcpu *v,
++                                                        mfn_t gmfn,
++                                                        uint32_t shadow_type))
+ {
+     mfn_t smfn;
+     pagetable_t old_entry, new_entry;
+@@ -2704,20 +2704,37 @@ void sh_set_toplevel_shadow(struct vcpu
+                   mfn_x(gmfn), mfn_x(pagetable_get_mfn(new_entry)));
+     v->arch.paging.shadow.shadow_table[slot] = new_entry;
+ 
+-    /* Decrement the refcount of the old contents of this slot */
+-    if ( !pagetable_is_null(old_entry) )
++    /*
++     * Decrement the refcount of the old contents of this slot, unless
++     * we're still running on that shadow - in that case it'll need holding
++     * on to until the actual page table switch did occur.
++     */
++    if ( !pagetable_is_null(old_entry) && (v != current || !is_pv_domain(d)) )
+     {
+-        mfn_t old_smfn = pagetable_get_mfn(old_entry);
+-        /* Need to repin the old toplevel shadow if it's been unpinned
+-         * by shadow_prealloc(): in PV mode we're still running on this
+-         * shadow and it's not safe to free it yet. */
+-        if ( !mfn_to_page(old_smfn)->u.sh.pinned && !sh_pin(d, old_smfn) )
+-        {
+-            printk(XENLOG_G_ERR "can't re-pin %"PRI_mfn"\n", mfn_x(old_smfn));
+-            domain_crash(d);
+-        }
+-        sh_put_ref(d, old_smfn, 0);
++        sh_put_ref(d, pagetable_get_mfn(old_entry), 0);
++        old_entry = pagetable_null();
+     }
++
++    /*
++     * 2- and 3-level shadow mode is used for HVM only. Therefore we never run
++     * on such a shadow, so only call sites requesting an L4 shadow need to pay
++     * attention to the returned value.
++     */
++    ASSERT(pagetable_is_null(old_entry) || root_type == SH_type_l4_64_shadow);
++
++    return old_entry;
++}
++
++/*
++ * Helper invoked when releasing of a top-level shadow's reference was
++ * deferred in sh_set_toplevel_shadow() above.
++ */
++void shadow_put_top_level(struct domain *d, pagetable_t old_entry)
++{
++    ASSERT(!pagetable_is_null(old_entry));
++    paging_lock(d);
++    sh_put_ref(d, pagetable_get_mfn(old_entry), 0);
++    paging_unlock(d);
+ }
+ 
+ /**************************************************************************/
+--- xen/arch/x86/mm/shadow/multi.c.orig
++++ xen/arch/x86/mm/shadow/multi.c
+@@ -3604,8 +3604,8 @@ sh_detach_old_tables(struct vcpu *v)
+     }
+ }
+ 
+-static void
+-sh_update_cr3(struct vcpu *v, int do_locking, bool noflush)
++static pagetable_t
++sh_update_cr3(struct vcpu *v, bool do_locking, bool noflush)
+ /* Updates vcpu->arch.cr3 after the guest has changed CR3.
+  * Paravirtual guests should set v->arch.guest_table (and guest_table_user,
+  * if appropriate).
+@@ -3619,6 +3619,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
+ {
+     struct domain *d = v->domain;
+     mfn_t gmfn;
++    pagetable_t old_entry = pagetable_null();
+ #if GUEST_PAGING_LEVELS == 3 && defined(CONFIG_HVM)
+     const guest_l3e_t *gl3e;
+     unsigned int i, guest_idx;
+@@ -3628,7 +3629,7 @@ sh_update_cr3(struct vcpu *v, int do_loc
+     if ( is_pv_domain(d) && !v->is_initialised )
+     {
+         ASSERT(v->arch.cr3 == 0);
+-        return;
++        return old_entry;
+     }
+ 
+     if ( do_locking ) paging_lock(v->domain);
+@@ -3701,11 +3702,12 @@ sh_update_cr3(struct vcpu *v, int do_loc
+ #if GUEST_PAGING_LEVELS == 4
+     if ( sh_remove_write_access(d, gmfn, 4, 0) != 0 )
+         guest_flush_tlb_mask(d, d->dirty_cpumask);
+-    sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l4_shadow, sh_make_shadow);
++    old_entry = sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l4_shadow,
++                                       sh_make_shadow);
+     if ( unlikely(pagetable_is_null(v->arch.paging.shadow.shadow_table[0])) )
+     {
+         ASSERT(d->is_dying || d->is_shutting_down);
+-        return;
++        return old_entry;
+     }
+     if ( !shadow_mode_external(d) && !is_pv_32bit_domain(d) )
+     {
+@@ -3751,26 +3753,32 @@ sh_update_cr3(struct vcpu *v, int do_loc
+                 gl2gfn = guest_l3e_get_gfn(gl3e[i]);
+                 gl2mfn = get_gfn_query_unlocked(d, gfn_x(gl2gfn), &p2mt);
+                 if ( p2m_is_ram(p2mt) )
+-                    sh_set_toplevel_shadow(v, i, gl2mfn, (i == 3)
+-                                           ? SH_type_l2h_shadow
+-                                           : SH_type_l2_shadow,
+-                                           sh_make_shadow);
++                    old_entry = sh_set_toplevel_shadow(v, i, gl2mfn,
++                                                       (i == 3
++                                                        ? SH_type_l2h_shadow
++                                                        : SH_type_l2_shadow),
++                                                       sh_make_shadow);
+                 else
+-                    sh_set_toplevel_shadow(v, i, INVALID_MFN, 0,
+-                                           sh_make_shadow);
++                    old_entry = sh_set_toplevel_shadow(v, i, INVALID_MFN, 0,
++                                                       sh_make_shadow);
+             }
+             else
+-                sh_set_toplevel_shadow(v, i, INVALID_MFN, 0, sh_make_shadow);
++                old_entry = sh_set_toplevel_shadow(v, i, INVALID_MFN, 0,
++                                                   sh_make_shadow);
++
++            ASSERT(pagetable_is_null(old_entry));
+         }
+     }
+ #elif GUEST_PAGING_LEVELS == 2
+     if ( sh_remove_write_access(d, gmfn, 2, 0) != 0 )
+         guest_flush_tlb_mask(d, d->dirty_cpumask);
+-    sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l2_shadow, sh_make_shadow);
++    old_entry = sh_set_toplevel_shadow(v, 0, gmfn, SH_type_l2_shadow,
++                                       sh_make_shadow);
++    ASSERT(pagetable_is_null(old_entry));
+     if ( unlikely(pagetable_is_null(v->arch.paging.shadow.shadow_table[0])) )
+     {
+         ASSERT(d->is_dying || d->is_shutting_down);
+-        return;
++        return old_entry;
+     }
+ #else
+ #error This should never happen
+@@ -3864,6 +3872,8 @@ sh_update_cr3(struct vcpu *v, int do_loc
+ 
+     /* Release the lock, if we took it (otherwise it's the caller's problem) */
+     if ( do_locking ) paging_unlock(v->domain);
++
++    return old_entry;
+ }
+ 
+ 
+--- xen/arch/x86/mm/shadow/none.c.orig
++++ xen/arch/x86/mm/shadow/none.c
+@@ -50,9 +50,10 @@ static unsigned long _gva_to_gfn(struct
+     return gfn_x(INVALID_GFN);
+ }
+ 
+-static void _update_cr3(struct vcpu *v, int do_locking, bool noflush)
++static pagetable_t _update_cr3(struct vcpu *v, bool do_locking, bool noflush)
+ {
+     ASSERT_UNREACHABLE();
++    return pagetable_null();
+ }
+ 
+ static void _update_paging_modes(struct vcpu *v)
+--- xen/arch/x86/mm/shadow/private.h.orig
++++ xen/arch/x86/mm/shadow/private.h
+@@ -360,13 +360,13 @@ mfn_t shadow_alloc(struct domain *d,
+ void  shadow_free(struct domain *d, mfn_t smfn);
+ 
+ /* Set up the top-level shadow and install it in slot 'slot' of shadow_table */
+-void sh_set_toplevel_shadow(struct vcpu *v,
+-                            unsigned int slot,
+-                            mfn_t gmfn,
+-                            unsigned int root_type,
+-                            mfn_t (*make_shadow)(struct vcpu *v,
+-                                                 mfn_t gmfn,
+-                                                 uint32_t shadow_type));
++pagetable_t sh_set_toplevel_shadow(struct vcpu *v,
++                                   unsigned int slot,
++                                   mfn_t gmfn,
++                                   unsigned int root_type,
++                                   mfn_t (*make_shadow)(struct vcpu *v,
++                                                        mfn_t gmfn,
++                                                        uint32_t shadow_type));
+ 
+ /* Update the shadows in response to a pagetable write from Xen */
+ int sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void *entry, u32 size);
+--- xen/arch/x86/mm.c.orig
++++ xen/arch/x86/mm.c
+@@ -564,15 +564,12 @@ void write_ptbase(struct vcpu *v)
+  *
+  * Update ref counts to shadow tables appropriately.
+  */
+-void update_cr3(struct vcpu *v)
++pagetable_t update_cr3(struct vcpu *v)
+ {
+     mfn_t cr3_mfn;
+ 
+     if ( paging_mode_enabled(v->domain) )
+-    {
+-        paging_update_cr3(v, false);
+-        return;
+-    }
++        return paging_update_cr3(v, false);
+ 
+     if ( !(v->arch.flags & TF_kernel_mode) )
+         cr3_mfn = pagetable_get_mfn(v->arch.guest_table_user);
+@@ -580,6 +577,8 @@ void update_cr3(struct vcpu *v)
+         cr3_mfn = pagetable_get_mfn(v->arch.guest_table);
+ 
+     make_cr3(v, cr3_mfn);
++
++    return pagetable_null();
+ }
+ 
+ static inline void set_tlbflush_timestamp(struct page_info *page)
+@@ -3241,6 +3240,7 @@ int new_guest_cr3(mfn_t mfn)
+     struct domain *d = curr->domain;
+     int rc;
+     mfn_t old_base_mfn;
++    pagetable_t old_shadow;
+ 
+     if ( is_pv_32bit_domain(d) )
+     {
+@@ -3308,9 +3308,22 @@ int new_guest_cr3(mfn_t mfn)
+     if ( !VM_ASSIST(d, m2p_strict) )
+         fill_ro_mpt(mfn);
+     curr->arch.guest_table = pagetable_from_mfn(mfn);
+-    update_cr3(curr);
++    old_shadow = update_cr3(curr);
++
++    /*
++     * In shadow mode update_cr3() can fail, in which case here we're still
++     * running on the prior top-level shadow (which we're about to release).
++     * Switch to the idle page tables in such an event; the guest will have
++     * been crashed already.
++     */
++    if ( likely(!mfn_eq(pagetable_get_mfn(old_shadow),
++                        maddr_to_mfn(curr->arch.cr3 & ~X86_CR3_NOFLUSH))) )
++        write_ptbase(curr);
++    else
++        write_ptbase(idle_vcpu[curr->processor]);
+ 
+-    write_ptbase(curr);
++    if ( !pagetable_is_null(old_shadow) )
++        shadow_put_top_level(d, old_shadow);
+ 
+     if ( likely(mfn_x(old_base_mfn) != 0) )
+     {
+--- xen/arch/x86/pv/domain.c.orig
++++ xen/arch/x86/pv/domain.c
+@@ -408,10 +408,13 @@ bool __init xpti_pcid_enabled(void)
+ 
+ static void _toggle_guest_pt(struct vcpu *v)
+ {
++    bool guest_update;
++    pagetable_t old_shadow;
+     unsigned long cr3;
+ 
+     v->arch.flags ^= TF_kernel_mode;
+-    update_cr3(v);
++    guest_update = v->arch.flags & TF_kernel_mode;
++    old_shadow = update_cr3(v);
+ 
+     /*
+      * Don't flush user global mappings from the TLB. Don't tick TLB clock.
+@@ -420,13 +423,31 @@ static void _toggle_guest_pt(struct vcpu
+      * TLB flush (for just the incoming PCID), as the top level page table may
+      * have changed behind our backs. To be on the safe side, suppress the
+      * no-flush unconditionally in this case.
++     *
++     * Furthermore in shadow mode update_cr3() can fail, in which case here
++     * we're still running on the prior top-level shadow (which we're about
++     * to release). Switch to the idle page tables in such an event; the
++     * guest will have been crashed already.
+      */
+     cr3 = v->arch.cr3;
+     if ( shadow_mode_enabled(v->domain) )
++    {
+         cr3 &= ~X86_CR3_NOFLUSH;
++
++        if ( unlikely(mfn_eq(pagetable_get_mfn(old_shadow),
++                             maddr_to_mfn(cr3))) )
++        {
++            cr3 = idle_vcpu[v->processor]->arch.cr3;
++            /* Also suppress runstate/time area updates below. */
++            guest_update = false;
++        }
++    }
+     write_cr3(cr3);
+ 
+-    if ( !(v->arch.flags & TF_kernel_mode) )
++    if ( !pagetable_is_null(old_shadow) )
++        shadow_put_top_level(v->domain, old_shadow);
++
++    if ( !guest_update )
+         return;
+ 
+     if ( v->arch.pv.need_update_runstate_area && update_runstate_area(v) )
+--- xen/include/asm-x86/mm.h.orig
++++ xen/include/asm-x86/mm.h
+@@ -569,7 +569,7 @@ void audit_domains(void);
+ #endif
+ 
+ void make_cr3(struct vcpu *v, mfn_t mfn);
+-void update_cr3(struct vcpu *v);
++pagetable_t update_cr3(struct vcpu *v);
+ int vcpu_destroy_pagetables(struct vcpu *);
+ void *do_page_walk(struct vcpu *v, unsigned long addr);
+ 
+--- xen/include/asm-x86/paging.h.orig
++++ xen/include/asm-x86/paging.h
+@@ -136,7 +136,7 @@ struct paging_mode {
+                                             unsigned long cr3,
+                                             paddr_t ga, uint32_t *pfec,
+                                             unsigned int *page_order);
+-    void          (*update_cr3            )(struct vcpu *v, int do_locking,
++    pagetable_t   (*update_cr3            )(struct vcpu *v, bool do_locking,
+                                             bool noflush);
+     void          (*update_paging_modes   )(struct vcpu *v);
+     bool          (*flush_tlb             )(bool (*flush_vcpu)(void *ctxt,
+@@ -309,9 +309,9 @@ static inline unsigned long paging_ga_to
+ /* Update all the things that are derived from the guest's CR3.
+  * Called when the guest changes CR3; the caller can then use v->arch.cr3
+  * as the value to load into the host CR3 to schedule this vcpu */
+-static inline void paging_update_cr3(struct vcpu *v, bool noflush)
++static inline pagetable_t paging_update_cr3(struct vcpu *v, bool noflush)
+ {
+-    paging_get_hostmode(v)->update_cr3(v, 1, noflush);
++    return paging_get_hostmode(v)->update_cr3(v, 1, noflush);
+ }
+ 
+ /* Update all the things that are derived from the guest's CR0/CR3/CR4.
+--- xen/include/asm-x86/shadow.h.orig
++++ xen/include/asm-x86/shadow.h
+@@ -97,6 +97,9 @@ void shadow_blow_tables_per_domain(struc
+ int shadow_set_allocation(struct domain *d, unsigned int pages,
+                           bool *preempted);
+ 
++/* Helper to invoke for deferred releasing of a top-level shadow's reference. */
++void shadow_put_top_level(struct domain *d, pagetable_t old);
++
+ #else /* !CONFIG_SHADOW_PAGING */
+ 
+ #define shadow_vcpu_teardown(v) ASSERT(is_pv_vcpu(v))
+@@ -118,6 +121,11 @@ static inline void shadow_prepare_page_t
+ 
+ static inline void shadow_blow_tables_per_domain(struct domain *d) {}
+ 
++static inline void shadow_put_top_level(struct domain *d, pagetable_t old)
++{
++    ASSERT_UNREACHABLE();
++}
++
+ static inline int shadow_domctl(struct domain *d,
+                                 struct xen_domctl_shadow_op *sc,
+                                 XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)



Home | Main Index | Thread Index | Old Index