1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
From bb43a10fefe494ab747b020fef3e823b63fc566d Mon Sep 17 00:00:00 2001
From: Jan Beulich <jbeulich@suse.com>
Date: Tue, 11 Oct 2022 15:11:01 +0200
Subject: [PATCH 055/126] gnttab: correct locking on transitive grant copy
error path
While the comment next to the lock dropping in preparation of
recursively calling acquire_grant_for_copy() mistakenly talks about the
rd == td case (excluded a few lines further up), the same concerns apply
to the calling of release_grant_for_copy() on a subsequent error path.
This is CVE-2022-33748 / XSA-411.
Fixes: ad48fb963dbf ("gnttab: fix transitive grant handling")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
master commit: 6e3aab858eef614a21a782a3b73acc88e74690ea
master date: 2022-10-11 14:29:30 +0200
---
xen/common/grant_table.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/xen/common/grant_table.c b/xen/common/grant_table.c
index 77bba9806937..0523beb9b734 100644
--- a/xen/common/grant_table.c
+++ b/xen/common/grant_table.c
@@ -2608,9 +2608,8 @@ acquire_grant_for_copy(
trans_domid);
/*
- * acquire_grant_for_copy() could take the lock on the
- * remote table (if rd == td), so we have to drop the lock
- * here and reacquire.
+ * acquire_grant_for_copy() will take the lock on the remote table,
+ * so we have to drop the lock here and reacquire.
*/
active_entry_release(act);
grant_read_unlock(rgt);
@@ -2647,11 +2646,25 @@ acquire_grant_for_copy(
act->trans_gref != trans_gref ||
!act->is_sub_page)) )
{
+ /*
+ * Like above for acquire_grant_for_copy() we need to drop and then
+ * re-acquire the locks here to prevent lock order inversion issues.
+ * Unlike for acquire_grant_for_copy() we don't need to re-check
+ * anything, as release_grant_for_copy() doesn't depend on the grant
+ * table entry: It only updates internal state and the status flags.
+ */
+ active_entry_release(act);
+ grant_read_unlock(rgt);
+
release_grant_for_copy(td, trans_gref, readonly);
rcu_unlock_domain(td);
+
+ grant_read_lock(rgt);
+ act = active_entry_acquire(rgt, gref);
reduce_status_for_pin(rd, act, status, readonly);
active_entry_release(act);
grant_read_unlock(rgt);
+
put_page(*page);
*page = NULL;
return ERESTART;
--
2.37.4
|