From: Andrew Cooper Date: Tue, 20 Jun 2017 09:40:56 +0000 (+0100) Subject: common/gnttab: Correct error handling for gnttab_setup_table() X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~1690 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=5e436e7a45082ea2cadc176c19e1df46c178448f;p=xen.git common/gnttab: Correct error handling for gnttab_setup_table() Simplify the error labels to just "unlock" and "out". This fixes an erroneous path where a failure of rcu_lock_domain_by_any_id() still results in rcu_unlock_domain() being called. This is only not an XSA by luck. rcu_unlock_domain() is a nop other than decrementing the preempt count, and nothing reads the preempt count outside of a debug build. Signed-off-by: Andrew Cooper Reviewed-by: Jan Beulich --- diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 0f9dd1e706..a72aa06fb3 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1626,7 +1626,7 @@ gnttab_setup_table( XEN_GUEST_HANDLE_PARAM(gnttab_setup_table_t) uop, unsigned int count) { struct gnttab_setup_table op; - struct domain *d; + struct domain *d = NULL; struct grant_table *gt; int i; xen_pfn_t gmfn; @@ -1646,7 +1646,7 @@ gnttab_setup_table( " per domain.\n", max_grant_frames); op.status = GNTST_general_error; - goto out1; + goto out; } if ( !guest_handle_okay(op.frame_list, op.nr_frames) ) @@ -1657,13 +1657,13 @@ gnttab_setup_table( { gdprintk(XENLOG_INFO, "Bad domid %d.\n", op.dom); op.status = GNTST_bad_domain; - goto out2; + goto out; } if ( xsm_grant_setup(XSM_TARGET, current->domain, d) ) { op.status = GNTST_permission_denied; - goto out2; + goto out; } gt = d->grant_table; @@ -1681,7 +1681,7 @@ gnttab_setup_table( "Expand grant table to %u failed. Current: %u Max: %u\n", op.nr_frames, nr_grant_frames(gt), max_grant_frames); op.status = GNTST_general_error; - goto out3; + goto unlock; } op.status = GNTST_okay; @@ -1694,11 +1694,12 @@ gnttab_setup_table( op.status = GNTST_bad_virt_addr; } - out3: + unlock: grant_write_unlock(gt); - out2: - rcu_unlock_domain(d); - out1: + out: + if ( d ) + rcu_unlock_domain(d); + if ( unlikely(__copy_field_to_guest(uop, &op, status)) ) return -EFAULT;