[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen stable-4.5] gnttab: don't use possibly unbounded tail calls
commit 42c8ba5dfc0be9d646f191c744c5fa71d7f372fa Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Thu Aug 17 15:15:35 2017 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu Aug 17 15:15:35 2017 +0200 gnttab: don't use possibly unbounded tail calls There is no guarantee that the compiler would actually translate them to branches instead of calls, so only ones with a known recursion limit are okay: - __release_grant_for_copy() can call itself only once, as __acquire_grant_for_copy() won't permit use of multi-level transitive grants, - __acquire_grant_for_copy() is fine to call itself with the last argument false, as that prevents further recursion, - __acquire_grant_for_copy() must not call itself to recover from an observed change to the active entry's pin count This is part of XSA-226. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> master commit: 999d2ccb7f73408aa22656e1ba2f98b077eaa1c2 master date: 2017-08-17 14:39:18 +0200 --- xen/common/grant_table.c | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c index 2cba4d7..e6b9073 100644 --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -1860,8 +1860,10 @@ __release_grant_for_copy( if ( td != rd ) { - /* Recursive calls, but they're tail calls, so it's - okay. */ + /* + * Recursive calls, but they're bounded (acquire permits only a single + * level of transitivity), so it's okay. + */ if ( released_write ) __release_grant_for_copy(td, trans_gref, 0); else if ( released_read ) @@ -1997,19 +1999,19 @@ __acquire_grant_for_copy( return rc; } - /* We dropped the lock, so we have to check that nobody - else tried to pin (or, for that matter, unpin) the - reference in *this* domain. If they did, just give up - and try again. */ + /* + * We dropped the lock, so we have to check that nobody else tried + * to pin (or, for that matter, unpin) the reference in *this* + * domain. If they did, just give up and tell the caller to retry. + */ if ( act->pin != old_pin ) { __fixup_status_for_copy_pin(act, status); rcu_unlock_domain(td); spin_unlock(&rgt->lock); put_page(*page); - return __acquire_grant_for_copy(rd, gref, ldom, readonly, - frame, page, page_off, length, - allow_transitive); + *page = NULL; + return ERESTART; } /* The actual remote remote grant may or may not be a @@ -2089,7 +2091,7 @@ __acquire_grant_for_copy( return rc; } -static void +static bool_t __gnttab_copy( struct gnttab_copy *op) { @@ -2213,9 +2215,20 @@ __gnttab_copy( rcu_unlock_domain(sd); if ( dd ) rcu_unlock_domain(dd); + if ( rc > 0 ) + return 0; op->status = rc; + return 1; } +/* + * gnttab_copy(), other than the various other helpers of + * do_grant_table_op(), returns (besides possible error indicators) + * "count - i" rather than "i" to ensure that even if no progress + * was made at all (perhaps due to gnttab_copy_one() returning a + * positive value) a non-zero value is being handed back (zero needs + * to be avoided, as that means "success, all done"). + */ static long gnttab_copy( XEN_GUEST_HANDLE_PARAM(gnttab_copy_t) uop, unsigned int count) @@ -2226,10 +2239,11 @@ gnttab_copy( for ( i = 0; i < count; i++ ) { if (i && hypercall_preempt_check()) - return i; + return count - i; if ( unlikely(__copy_from_guest(&op, uop, 1)) ) return -EFAULT; - __gnttab_copy(&op); + if ( !__gnttab_copy(&op) ) + return count - i; if ( unlikely(__copy_field_to_guest(uop, &op, status)) ) return -EFAULT; guest_handle_add_offset(uop, 1); @@ -2727,6 +2741,7 @@ do_grant_table_op( rc = gnttab_copy(copy, count); if ( rc > 0 ) { + rc = count - rc; guest_handle_add_offset(copy, rc); uop = guest_handle_cast(copy, void); } -- generated by git-patchbot for /home/xen/git/xen.git#stable-4.5 _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |