summaryrefslogtreecommitdiff
path: root/drivers/xen/gntalloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/xen/gntalloc.c')
-rw-r--r--drivers/xen/gntalloc.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
index eadedd1e963e..3218686be45b 100644
--- a/drivers/xen/gntalloc.c
+++ b/drivers/xen/gntalloc.c
@@ -70,14 +70,14 @@
#include <xen/gntalloc.h>
#include <xen/events.h>
-static int limit = 1024;
-module_param(limit, int, 0644);
+static unsigned int limit = 1024;
+module_param(limit, uint, 0644);
MODULE_PARM_DESC(limit, "Maximum number of grants that may be allocated by "
"the gntalloc device");
static LIST_HEAD(gref_list);
static DEFINE_MUTEX(gref_mutex);
-static int gref_size;
+static unsigned int gref_size;
struct notify_info {
uint16_t pgoff:12; /* Bits 0-11: Offset of the byte to clear */
@@ -272,6 +272,7 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
int rc = 0;
struct ioctl_gntalloc_alloc_gref op;
uint32_t *gref_ids;
+ unsigned int limit_snapshot;
pr_debug("%s: priv %p\n", __func__, priv);
@@ -280,6 +281,12 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
goto out;
}
+ limit_snapshot = READ_ONCE(limit);
+ if (op.count > limit_snapshot) {
+ rc = -ENOSPC;
+ goto out;
+ }
+
gref_ids = kcalloc(op.count, sizeof(gref_ids[0]), GFP_KERNEL);
if (!gref_ids) {
rc = -ENOMEM;
@@ -292,14 +299,16 @@ static long gntalloc_ioctl_alloc(struct gntalloc_file_private_data *priv,
* are about to enforce, removing them here is a good idea.
*/
do_cleanup();
- if (gref_size + op.count > limit) {
+ limit_snapshot = READ_ONCE(limit);
+ if (gref_size > limit_snapshot ||
+ op.count > limit_snapshot - gref_size) {
mutex_unlock(&gref_mutex);
rc = -ENOSPC;
goto out_free;
}
gref_size += op.count;
op.index = priv->index;
- priv->index += op.count * PAGE_SIZE;
+ priv->index += (uint64_t)op.count * PAGE_SIZE;
mutex_unlock(&gref_mutex);
rc = add_grefs(&op, gref_ids, priv);