]> git.ipfire.org Git - people/teissler/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.xen/863-blktap-vma-close.patch
Updated xen patches taken from suse.
[people/teissler/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.xen / 863-blktap-vma-close.patch
CommitLineData
00e5a55c
BS
1From: http://xenbits.xensource.com/linux-2.6.18-xen.hg?rev/464a925d73f1
2# HG changeset 863 patch
3# User Keir Fraser <keir.fraser@citrix.com>
4# Date 1239969802 -3600
5# Node ID 464a925d73f141d8ca568026ee2e6635489affa2
6# Parent dfd2adc5874021b52c13d317df1f55b46ec38e3d
7Subject: blktap: don't access deallocated data
8References: bnc#484210, bnc#485652
9Patch-mainline: obsolete
10
11Dereferencing filp->private_data->vma in the file_operations.release
12actor isn't permitted, as the vma generally has been destroyed by that
13time. The kfree()ing of vma->vm_private_data must be done in the
14vm_operations.close actor, and the call to zap_page_range() seems
15redundant with the caller of that actor altogether.
16
17Signed-off-by: Jan Beulich <jbeulich@novell.com>
18
19--- sle11-2009-04-20.orig/drivers/xen/blktap/blktap.c 2009-04-20 11:35:28.000000000 +0200
20+++ sle11-2009-04-20/drivers/xen/blktap/blktap.c 2009-04-20 11:35:40.000000000 +0200
21@@ -293,6 +293,10 @@ static inline int OFFSET_TO_SEG(int offs
22 /******************************************************************
23 * BLKTAP VM OPS
24 */
25+struct tap_vma_priv {
26+ tap_blkif_t *info;
27+ struct page *map[];
28+};
29
30 static struct page *blktap_nopage(struct vm_area_struct *vma,
31 unsigned long address,
32@@ -315,7 +319,7 @@ static pte_t blktap_clear_pte(struct vm_
33 int offset, seg, usr_idx, pending_idx, mmap_idx;
34 unsigned long uvstart = vma->vm_start + (RING_PAGES << PAGE_SHIFT);
35 unsigned long kvaddr;
36- struct page **map;
37+ struct tap_vma_priv *priv;
38 struct page *pg;
39 struct grant_handle_pair *khandle;
40 struct gnttab_unmap_grant_ref unmap[2];
41@@ -330,12 +334,12 @@ static pte_t blktap_clear_pte(struct vm_
42 ptep, is_fullmm);
43
44 info = vma->vm_file->private_data;
45- map = vma->vm_private_data;
46+ priv = vma->vm_private_data;
47
48 /* TODO Should these be changed to if statements? */
49 BUG_ON(!info);
50 BUG_ON(!info->idx_map);
51- BUG_ON(!map);
52+ BUG_ON(!priv);
53
54 offset = (int) ((uvaddr - uvstart) >> PAGE_SHIFT);
55 usr_idx = OFFSET_TO_USR_IDX(offset);
56@@ -347,7 +351,7 @@ static pte_t blktap_clear_pte(struct vm_
57 kvaddr = idx_to_kaddr(mmap_idx, pending_idx, seg);
58 pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
59 ClearPageReserved(pg);
60- map[offset + RING_PAGES] = NULL;
61+ priv->map[offset + RING_PAGES] = NULL;
62
63 khandle = &pending_handle(mmap_idx, pending_idx, seg);
64
65@@ -388,9 +392,20 @@ static pte_t blktap_clear_pte(struct vm_
66 return copy;
67 }
68
69+static void blktap_vma_close(struct vm_area_struct *vma)
70+{
71+ struct tap_vma_priv *priv = vma->vm_private_data;
72+
73+ if (priv) {
74+ priv->info->vma = NULL;
75+ kfree(priv);
76+ }
77+}
78+
79 struct vm_operations_struct blktap_vm_ops = {
80 nopage: blktap_nopage,
81 zap_pte: blktap_clear_pte,
82+ close: blktap_vma_close,
83 };
84
85 /******************************************************************
86@@ -609,21 +624,6 @@ static int blktap_release(struct inode *
87 ClearPageReserved(virt_to_page(info->ufe_ring.sring));
88 free_page((unsigned long) info->ufe_ring.sring);
89
90- /* Clear any active mappings and free foreign map table */
91- if (info->vma) {
92- struct mm_struct *mm = info->vma->vm_mm;
93-
94- down_write(&mm->mmap_sem);
95- zap_page_range(
96- info->vma, info->vma->vm_start,
97- info->vma->vm_end - info->vma->vm_start, NULL);
98- up_write(&mm->mmap_sem);
99-
100- kfree(info->vma->vm_private_data);
101-
102- info->vma = NULL;
103- }
104-
105 if (info->idx_map) {
106 kfree(info->idx_map);
107 info->idx_map = NULL;
108@@ -662,8 +662,7 @@ static int blktap_release(struct inode *
109 static int blktap_mmap(struct file *filp, struct vm_area_struct *vma)
110 {
111 int size;
112- struct page **map;
113- int i;
114+ struct tap_vma_priv *priv;
115 tap_blkif_t *info = filp->private_data;
116 int ret;
117
118@@ -700,18 +699,16 @@ static int blktap_mmap(struct file *filp
119 }
120
121 /* Mark this VM as containing foreign pages, and set up mappings. */
122- map = kzalloc(((vma->vm_end - vma->vm_start) >> PAGE_SHIFT)
123- * sizeof(struct page *),
124- GFP_KERNEL);
125- if (map == NULL) {
126+ priv = kzalloc(sizeof(*priv) + ((vma->vm_end - vma->vm_start)
127+ >> PAGE_SHIFT) * sizeof(*priv->map),
128+ GFP_KERNEL);
129+ if (priv == NULL) {
130 WPRINTK("Couldn't alloc VM_FOREIGN map.\n");
131 goto fail;
132 }
133+ priv->info = info;
134
135- for (i = 0; i < ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT); i++)
136- map[i] = NULL;
137-
138- vma->vm_private_data = map;
139+ vma->vm_private_data = priv;
140 vma->vm_flags |= VM_FOREIGN;
141 vma->vm_flags |= VM_DONTCOPY;
142
143@@ -1190,7 +1187,7 @@ static int blktap_read_ufe_ring(tap_blki
144 for (j = 0; j < pending_req->nr_pages; j++) {
145
146 unsigned long kvaddr, uvaddr;
147- struct page **map = info->vma->vm_private_data;
148+ struct tap_vma_priv *priv = info->vma->vm_private_data;
149 struct page *pg;
150 int offset;
151
152@@ -1201,7 +1198,7 @@ static int blktap_read_ufe_ring(tap_blki
153 ClearPageReserved(pg);
154 offset = (uvaddr - info->vma->vm_start)
155 >> PAGE_SHIFT;
156- map[offset] = NULL;
157+ priv->map[offset] = NULL;
158 }
159 fast_flush_area(pending_req, pending_idx, usr_idx, info->minor);
160 info->idx_map[usr_idx] = INVALID_REQ;
161@@ -1359,6 +1356,7 @@ static void dispatch_rw_block_io(blkif_t
162 unsigned int nseg;
163 int ret, i, nr_sects = 0;
164 tap_blkif_t *info;
165+ struct tap_vma_priv *priv;
166 blkif_request_t *target;
167 int pending_idx = RTN_PEND_IDX(pending_req,pending_req->mem_idx);
168 int usr_idx;
169@@ -1407,6 +1405,7 @@ static void dispatch_rw_block_io(blkif_t
170 pending_req->status = BLKIF_RSP_OKAY;
171 pending_req->nr_pages = nseg;
172 op = 0;
173+ priv = info->vma->vm_private_data;
174 mm = info->vma->vm_mm;
175 if (!xen_feature(XENFEAT_auto_translated_physmap))
176 down_write(&mm->mmap_sem);
177@@ -1490,8 +1489,7 @@ static void dispatch_rw_block_io(blkif_t
178 >> PAGE_SHIFT));
179 offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT;
180 pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
181- ((struct page **)info->vma->vm_private_data)[offset] =
182- pg;
183+ priv->map[offset] = pg;
184 }
185 } else {
186 for (i = 0; i < nseg; i++) {
187@@ -1518,8 +1516,7 @@ static void dispatch_rw_block_io(blkif_t
188
189 offset = (uvaddr - info->vma->vm_start) >> PAGE_SHIFT;
190 pg = pfn_to_page(__pa(kvaddr) >> PAGE_SHIFT);
191- ((struct page **)info->vma->vm_private_data)[offset] =
192- pg;
193+ priv->map[offset] = pg;
194 }
195 }
196