mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] xen/gntalloc: validate grant count before allocation
@ 2026-06-24 12:47 Yousef Alhouseen
  2026-06-26 12:14 ` Juergen Gross
  2026-06-26 22:38 ` [PATCH v2 0/2] " Yousef Alhouseen
  0 siblings, 2 replies; 7+ messages in thread
From: Yousef Alhouseen @ 2026-06-24 12:47 UTC (permalink / raw)
  To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel, Yousef Alhouseen

gntalloc_ioctl_alloc() allocates the grant-id array before checking
whether the requested count can fit within the global grant limit.
Counts above the limit cannot succeed, so reject them before the
user-controlled allocation size reaches kcalloc().

The locked limit check also adds a u32 count to signed global counters.
Rewrite it as a subtraction-based range check so the arithmetic cannot
wrap around the limit.

While there, cast the count before advancing the per-file index so the
page-size multiplication is done in 64-bit arithmetic.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
 drivers/xen/gntalloc.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
index eadedd1e9..ba6a25a09 100644
--- a/drivers/xen/gntalloc.c
+++ b/drivers/xen/gntalloc.c
@@ -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;
+	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 (limit_snapshot < 0 || op.count > (uint32_t)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 (limit_snapshot < 0 || gref_size > limit_snapshot ||
+	    op.count > (uint32_t)(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);
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] xen/gntalloc: validate grant count before allocation
  2026-06-24 12:47 [PATCH] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
@ 2026-06-26 12:14 ` Juergen Gross
  2026-06-26 22:38 ` [PATCH v2 0/2] " Yousef Alhouseen
  1 sibling, 0 replies; 7+ messages in thread
From: Juergen Gross @ 2026-06-26 12:14 UTC (permalink / raw)
  To: Yousef Alhouseen, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel


[-- Attachment #1.1.1: Type: text/plain, Size: 2707 bytes --]

On 24.06.26 14:47, Yousef Alhouseen wrote:
> gntalloc_ioctl_alloc() allocates the grant-id array before checking
> whether the requested count can fit within the global grant limit.
> Counts above the limit cannot succeed, so reject them before the
> user-controlled allocation size reaches kcalloc().
> 
> The locked limit check also adds a u32 count to signed global counters.
> Rewrite it as a subtraction-based range check so the arithmetic cannot
> wrap around the limit.
> 
> While there, cast the count before advancing the per-file index so the
> page-size multiplication is done in 64-bit arithmetic.
> 
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
> ---
>   drivers/xen/gntalloc.c | 13 +++++++++++--
>   1 file changed, 11 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
> index eadedd1e9..ba6a25a09 100644
> --- a/drivers/xen/gntalloc.c
> +++ b/drivers/xen/gntalloc.c
> @@ -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;
> +	int limit_snapshot;

This needs to be an unsigned int, same applies to the already existing
"limit" and "gref_ids".

Could you please create a small series with patch 1 changing "limit" and
"gref_ids" to unsigned int and let this patch be patch 2?

The rest of this patch (with the "< 0" tests and some type casts removed)
is looking fine to me.


Juergen

>   
>   	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 (limit_snapshot < 0 || op.count > (uint32_t)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 (limit_snapshot < 0 || gref_size > limit_snapshot ||
> +	    op.count > (uint32_t)(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);


[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 0/2] xen/gntalloc: validate grant count before allocation
  2026-06-24 12:47 [PATCH] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
  2026-06-26 12:14 ` Juergen Gross
@ 2026-06-26 22:38 ` Yousef Alhouseen
  2026-06-26 22:38   ` [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned Yousef Alhouseen
  2026-06-26 22:38   ` [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
  1 sibling, 2 replies; 7+ messages in thread
From: Yousef Alhouseen @ 2026-06-26 22:38 UTC (permalink / raw)
  To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel, Yousef Alhouseen

The allocation ioctl currently allocates a user-sized grant-id array
before checking the global grant limit.  It also adds the requested count
when enforcing that limit, which makes the check harder to reason about
in the presence of mixed signed and unsigned types.

Make the grant counters unsigned first, then reject impossible requests
before allocation and use subtraction for the locked limit check.

Changes in v2:
- Split the unsigned type changes into a prerequisite patch.
- Remove the signed checks and unnecessary casts.

Yousef Alhouseen (2):
  xen/gntalloc: make grant counters unsigned
  xen/gntalloc: validate grant count before allocation

 drivers/xen/gntalloc.c | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

-- 
2.54.0

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned
  2026-06-26 22:38 ` [PATCH v2 0/2] " Yousef Alhouseen
@ 2026-06-26 22:38   ` Yousef Alhouseen
  2026-07-01  7:52     ` Jürgen Groß
  2026-06-26 22:38   ` [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
  1 sibling, 1 reply; 7+ messages in thread
From: Yousef Alhouseen @ 2026-06-26 22:38 UTC (permalink / raw)
  To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel, Yousef Alhouseen

The module limit and current allocation count cannot validly be
negative. Give both variables unsigned types so their representation
matches the u32 grant count supplied through the ioctl and negative
module parameter values are rejected by parameter parsing.

This also prepares the limit check for overflow-safe unsigned
arithmetic.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
 drivers/xen/gntalloc.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
index eadedd1e9..9279f1521 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 */
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation
  2026-06-26 22:38 ` [PATCH v2 0/2] " Yousef Alhouseen
  2026-06-26 22:38   ` [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned Yousef Alhouseen
@ 2026-06-26 22:38   ` Yousef Alhouseen
  2026-07-01  7:53     ` Jürgen Groß
  1 sibling, 1 reply; 7+ messages in thread
From: Yousef Alhouseen @ 2026-06-26 22:38 UTC (permalink / raw)
  To: Juergen Gross, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel, Yousef Alhouseen

gntalloc_ioctl_alloc() allocates the grant-id array before checking
whether the requested count fits within the global grant limit. Counts
above that limit cannot succeed, so reject them before the
user-controlled allocation reaches kcalloc().

Use a subtraction-based check while holding gref_mutex so adding the
requested count cannot wrap. Also cast the count before advancing the
per-file index so the page-size multiplication is performed in 64-bit
arithmetic.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
 drivers/xen/gntalloc.c | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/xen/gntalloc.c b/drivers/xen/gntalloc.c
index 9279f1521..3218686be 100644
--- a/drivers/xen/gntalloc.c
+++ b/drivers/xen/gntalloc.c
@@ -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);
-- 
2.54.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned
  2026-06-26 22:38   ` [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned Yousef Alhouseen
@ 2026-07-01  7:52     ` Jürgen Groß
  0 siblings, 0 replies; 7+ messages in thread
From: Jürgen Groß @ 2026-07-01  7:52 UTC (permalink / raw)
  To: Yousef Alhouseen, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel


[-- Attachment #1.1.1: Type: text/plain, Size: 528 bytes --]

On 27.06.26 00:38, Yousef Alhouseen wrote:
> The module limit and current allocation count cannot validly be
> negative. Give both variables unsigned types so their representation
> matches the u32 grant count supplied through the ioctl and negative
> module parameter values are rejected by parameter parsing.
> 
> This also prepares the limit check for overflow-safe unsigned
> arithmetic.
> 
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation
  2026-06-26 22:38   ` [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
@ 2026-07-01  7:53     ` Jürgen Groß
  0 siblings, 0 replies; 7+ messages in thread
From: Jürgen Groß @ 2026-07-01  7:53 UTC (permalink / raw)
  To: Yousef Alhouseen, Stefano Stabellini, Oleksandr Tyshchenko
  Cc: xen-devel, linux-kernel


[-- Attachment #1.1.1: Type: text/plain, Size: 665 bytes --]

On 27.06.26 00:38, Yousef Alhouseen wrote:
> gntalloc_ioctl_alloc() allocates the grant-id array before checking
> whether the requested count fits within the global grant limit. Counts
> above that limit cannot succeed, so reject them before the
> user-controlled allocation reaches kcalloc().
> 
> Use a subtraction-based check while holding gref_mutex so adding the
> requested count cannot wrap. Also cast the count before advancing the
> per-file index so the page-size multiplication is performed in 64-bit
> arithmetic.
> 
> Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>

Reviewed-by: Juergen Gross <jgross@suse.com>


Juergen

[-- Attachment #1.1.2: OpenPGP public key --]
[-- Type: application/pgp-keys, Size: 3743 bytes --]

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-07-01  7:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-24 12:47 [PATCH] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
2026-06-26 12:14 ` Juergen Gross
2026-06-26 22:38 ` [PATCH v2 0/2] " Yousef Alhouseen
2026-06-26 22:38   ` [PATCH v2 1/2] xen/gntalloc: make grant counters unsigned Yousef Alhouseen
2026-07-01  7:52     ` Jürgen Groß
2026-06-26 22:38   ` [PATCH v2 2/2] xen/gntalloc: validate grant count before allocation Yousef Alhouseen
2026-07-01  7:53     ` Jürgen Groß

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox