aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuergen Gross <jgross@suse.com>2018-11-01 08:33:07 -0400
committerJuergen Gross <jgross@suse.com>2018-11-09 10:38:34 -0500
commit3941552aec1e04d63999988a057ae09a1c56ebeb (patch)
tree3f9521547989145ad1ae2b36900845c9ac160d76
parentd3132b3860f6cf35ff7609a76bbcdbb814bd027c (diff)
xen: remove size limit of privcmd-buf mapping interface
Currently the size of hypercall buffers allocated via /dev/xen/hypercall is limited to a default of 64 memory pages. For live migration of guests this might be too small as the page dirty bitmask needs to be sized according to the size of the guest. This means migrating a 8GB sized guest is already exhausting the default buffer size for the dirty bitmap. There is no sensible way to set a sane limit, so just remove it completely. The device node's usage is limited to root anyway, so there is no additional DOS scenario added by allowing unlimited buffers. While at it make the error path for the -ENOMEM case a little bit cleaner by setting n_pages to the number of successfully allocated pages instead of the target size. Fixes: c51b3c639e01f2 ("xen: add new hypercall buffer mapping device") Cc: <stable@vger.kernel.org> #4.18 Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Boris Ostrovsky <boris.ostrovsky@oracle.com> Signed-off-by: Juergen Gross <jgross@suse.com>
-rw-r--r--drivers/xen/privcmd-buf.c22
1 files changed, 4 insertions, 18 deletions
diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c
index df1ed37c3269..de01a6d0059d 100644
--- a/drivers/xen/privcmd-buf.c
+++ b/drivers/xen/privcmd-buf.c
@@ -21,15 +21,9 @@
21 21
22MODULE_LICENSE("GPL"); 22MODULE_LICENSE("GPL");
23 23
24static unsigned int limit = 64;
25module_param(limit, uint, 0644);
26MODULE_PARM_DESC(limit, "Maximum number of pages that may be allocated by "
27 "the privcmd-buf device per open file");
28
29struct privcmd_buf_private { 24struct privcmd_buf_private {
30 struct mutex lock; 25 struct mutex lock;
31 struct list_head list; 26 struct list_head list;
32 unsigned int allocated;
33}; 27};
34 28
35struct privcmd_buf_vma_private { 29struct privcmd_buf_vma_private {
@@ -60,13 +54,10 @@ static void privcmd_buf_vmapriv_free(struct privcmd_buf_vma_private *vma_priv)
60{ 54{
61 unsigned int i; 55 unsigned int i;
62 56
63 vma_priv->file_priv->allocated -= vma_priv->n_pages;
64
65 list_del(&vma_priv->list); 57 list_del(&vma_priv->list);
66 58
67 for (i = 0; i < vma_priv->n_pages; i++) 59 for (i = 0; i < vma_priv->n_pages; i++)
68 if (vma_priv->pages[i]) 60 __free_page(vma_priv->pages[i]);
69 __free_page(vma_priv->pages[i]);
70 61
71 kfree(vma_priv); 62 kfree(vma_priv);
72} 63}
@@ -146,8 +137,7 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)
146 unsigned int i; 137 unsigned int i;
147 int ret = 0; 138 int ret = 0;
148 139
149 if (!(vma->vm_flags & VM_SHARED) || count > limit || 140 if (!(vma->vm_flags & VM_SHARED))
150 file_priv->allocated + count > limit)
151 return -EINVAL; 141 return -EINVAL;
152 142
153 vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *), 143 vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *),
@@ -155,19 +145,15 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)
155 if (!vma_priv) 145 if (!vma_priv)
156 return -ENOMEM; 146 return -ENOMEM;
157 147
158 vma_priv->n_pages = count; 148 for (i = 0; i < count; i++) {
159 count = 0;
160 for (i = 0; i < vma_priv->n_pages; i++) {
161 vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO); 149 vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
162 if (!vma_priv->pages[i]) 150 if (!vma_priv->pages[i])
163 break; 151 break;
164 count++; 152 vma_priv->n_pages++;
165 } 153 }
166 154
167 mutex_lock(&file_priv->lock); 155 mutex_lock(&file_priv->lock);
168 156
169 file_priv->allocated += count;
170
171 vma_priv->file_priv = file_priv; 157 vma_priv->file_priv = file_priv;
172 vma_priv->users = 1; 158 vma_priv->users = 1;
173 159