All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yousef Alhouseen <alhouseenyousef@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-staging@lists.linux.dev, linux-kernel@vger.kernel.org,
	Yousef Alhouseen <alhouseenyousef@gmail.com>
Subject: [PATCH] staging: vme_user: bound slave windows to DMA buffers
Date: Thu, 25 Jun 2026 11:31:37 +0200	[thread overview]
Message-ID: <20260625093137.6589-1-alhouseenyousef@gmail.com> (raw)

vme_user allocates a fixed PCI_BUF_SIZE coherent DMA buffer for each
slave image, but VME_SET_SLAVE passes the user-supplied size to
vme_slave_set() unchanged. An enabled window larger than PCI_BUF_SIZE lets
the bridge expose DMA addresses beyond the allocation.

The character device read/write paths also derive their bounds from
vme_get_size(), so the oversized programmed window can make
buffer_to_user() and buffer_from_user() access past
image[minor].kern_buf.

Reject enabled slave windows that do not fit in the backing buffer and use
the same capped size for slave read/write/llseek bounds. Also convert the
read/write limit checks to subtraction-based form so offset + count cannot
wrap around the image size check.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@gmail.com>
---
 drivers/staging/vme_user/vme_user.c | 38 ++++++++++++++++++++++-------
 1 file changed, 29 insertions(+), 9 deletions(-)

diff --git a/drivers/staging/vme_user/vme_user.c b/drivers/staging/vme_user/vme_user.c
index 11e25c2f6..24d3c6ec3 100644
--- a/drivers/staging/vme_user/vme_user.c
+++ b/drivers/staging/vme_user/vme_user.c
@@ -175,11 +175,22 @@ static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
 	return count;
 }
 
+static size_t vme_user_get_image_size(unsigned int minor)
+{
+	size_t image_size = vme_get_size(image[minor].resource);
+
+	if (type[minor] == SLAVE_MINOR)
+		image_size = min_t(size_t, image_size, image[minor].size_buf);
+
+	return image_size;
+}
+
 static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
 			     loff_t *ppos)
 {
 	unsigned int minor = iminor(file_inode(file));
 	ssize_t retval;
+	size_t offset;
 	size_t image_size;
 
 	if (minor == CONTROL_MINOR)
@@ -188,17 +199,19 @@ static ssize_t vme_user_read(struct file *file, char __user *buf, size_t count,
 	mutex_lock(&image[minor].mutex);
 
 	/* XXX Do we *really* want this helper - we can use vme_*_get ? */
-	image_size = vme_get_size(image[minor].resource);
+	image_size = vme_user_get_image_size(minor);
 
 	/* Ensure we are starting at a valid location */
-	if ((*ppos < 0) || (*ppos > (image_size - 1))) {
+	if ((*ppos < 0) || ((u64)*ppos >= image_size)) {
 		mutex_unlock(&image[minor].mutex);
 		return 0;
 	}
 
+	offset = *ppos;
+
 	/* Ensure not reading past end of the image */
-	if (*ppos + count > image_size)
-		count = image_size - *ppos;
+	if (count > image_size - offset)
+		count = image_size - offset;
 
 	switch (type[minor]) {
 	case MASTER_MINOR:
@@ -223,6 +236,7 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
 {
 	unsigned int minor = iminor(file_inode(file));
 	ssize_t retval;
+	size_t offset;
 	size_t image_size;
 
 	if (minor == CONTROL_MINOR)
@@ -230,17 +244,19 @@ static ssize_t vme_user_write(struct file *file, const char __user *buf,
 
 	mutex_lock(&image[minor].mutex);
 
-	image_size = vme_get_size(image[minor].resource);
+	image_size = vme_user_get_image_size(minor);
 
 	/* Ensure we are starting at a valid location */
-	if ((*ppos < 0) || (*ppos > (image_size - 1))) {
+	if ((*ppos < 0) || ((u64)*ppos >= image_size)) {
 		mutex_unlock(&image[minor].mutex);
 		return 0;
 	}
 
+	offset = *ppos;
+
 	/* Ensure not reading past end of the image */
-	if (*ppos + count > image_size)
-		count = image_size - *ppos;
+	if (count > image_size - offset)
+		count = image_size - offset;
 
 	switch (type[minor]) {
 	case MASTER_MINOR:
@@ -271,7 +287,7 @@ static loff_t vme_user_llseek(struct file *file, loff_t off, int whence)
 	case MASTER_MINOR:
 	case SLAVE_MINOR:
 		mutex_lock(&image[minor].mutex);
-		image_size = vme_get_size(image[minor].resource);
+		image_size = vme_user_get_image_size(minor);
 		res = fixed_size_llseek(file, off, whence, image_size);
 		mutex_unlock(&image[minor].mutex);
 		return res;
@@ -394,6 +410,10 @@ static int vme_user_ioctl(struct inode *inode, struct file *file,
 				return -EFAULT;
 			}
 
+			if (slave.enable &&
+			    (!slave.size || slave.size > image[minor].size_buf))
+				return -EINVAL;
+
 			/* XXX	We do not want to push aspace, cycle and width
 			 *	to userspace as they are
 			 */
-- 
2.54.0


             reply	other threads:[~2026-06-25  9:32 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-25  9:31 Yousef Alhouseen [this message]
2026-06-25  9:47 ` [PATCH] staging: vme_user: bound slave windows to DMA buffers Greg Kroah-Hartman
2026-06-25 11:51 ` Dan Carpenter
2026-06-25 11:58   ` Dan Carpenter
2026-06-25 13:54     ` Yousef Alhouseen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260625093137.6589-1-alhouseenyousef@gmail.com \
    --to=alhouseenyousef@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-staging@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.