Brad Bishop | 316dfdd | 2018-06-25 12:45:53 -0400 | [diff] [blame] | 1 | From: Jan Beulich <jbeulich@suse.com> |
| 2 | Subject: x86/shadow: fix refcount overflow check |
| 3 | |
| 4 | Commit c385d27079 ("x86 shadow: for multi-page shadows, explicitly track |
| 5 | the first page") reduced the refcount width to 25, without adjusting the |
| 6 | overflow check. Eliminate the disconnect by using a manifest constant. |
| 7 | |
| 8 | Interestingly, up to commit 047782fa01 ("Out-of-sync L1 shadows: OOS |
| 9 | snapshot") the refcount was 27 bits wide, yet the check was already |
| 10 | using 26. |
| 11 | |
| 12 | This is XSA-249. |
| 13 | |
| 14 | Signed-off-by: Jan Beulich <jbeulich@suse.com> |
| 15 | Reviewed-by: George Dunlap <george.dunlap@citrix.com> |
| 16 | Reviewed-by: Tim Deegan <tim@xen.org> |
| 17 | --- |
| 18 | v2: Simplify expression back to the style it was. |
| 19 | |
| 20 | --- a/xen/arch/x86/mm/shadow/private.h |
| 21 | +++ b/xen/arch/x86/mm/shadow/private.h |
| 22 | @@ -529,7 +529,7 @@ static inline int sh_get_ref(struct doma |
| 23 | x = sp->u.sh.count; |
| 24 | nx = x + 1; |
| 25 | |
| 26 | - if ( unlikely(nx >= 1U<<26) ) |
| 27 | + if ( unlikely(nx >= (1U << PAGE_SH_REFCOUNT_WIDTH)) ) |
| 28 | { |
| 29 | SHADOW_PRINTK("shadow ref overflow, gmfn=%lx smfn=%lx\n", |
| 30 | __backpointer(sp), mfn_x(smfn)); |
| 31 | --- a/xen/include/asm-x86/mm.h |
| 32 | +++ b/xen/include/asm-x86/mm.h |
| 33 | @@ -82,7 +82,8 @@ struct page_info |
| 34 | unsigned long type:5; /* What kind of shadow is this? */ |
| 35 | unsigned long pinned:1; /* Is the shadow pinned? */ |
| 36 | unsigned long head:1; /* Is this the first page of the shadow? */ |
| 37 | - unsigned long count:25; /* Reference count */ |
| 38 | +#define PAGE_SH_REFCOUNT_WIDTH 25 |
| 39 | + unsigned long count:PAGE_SH_REFCOUNT_WIDTH; /* Reference count */ |
| 40 | } sh; |
| 41 | |
| 42 | /* Page is on a free list: ((count_info & PGC_count_mask) == 0). */ |