Linux kernel staging patches
 help / color / mirror / Atom feed
  • * [PATCH v2] staging: vme_user: bound slave read/write to the kern_buf size
           [not found] <20260614195318.40397-1-tautschn@amazon.com>
           [not found] ` <2026061535-hardened-presuming-96b2@gregkh>
    @ 2026-06-18 11:47 ` Michael Tautschnig
      1 sibling, 0 replies; 2+ messages in thread
    From: Michael Tautschnig @ 2026-06-18 11:47 UTC (permalink / raw)
      To: gregkh; +Cc: linux-staging, linux-kernel, stable, Michael Tautschnig
    
    The SLAVE-path helpers buffer_to_user() and buffer_from_user() copy
    'count' bytes into/out of the fixed-size kern_buf (size_buf ==
    PCI_BUF_SIZE == 0x20000, 128 KiB) using *ppos as the offset, without
    bounding *ppos + count against size_buf.
    
    vme_user_write()/vme_user_read() only clamp count to the VME window size
    (image_size = vme_get_size(resource)), which VME_SET_SLAVE sets from the
    user-supplied slave.size -- validated against the VME address space (up
    to VME_A32_MAX = 4 GiB), not against PCI_BUF_SIZE.  When the window
    exceeds 128 KiB, a write()/read() copies past the kern_buf allocation.
    
    Clamp count against size_buf in both helpers, with an early return when
    *ppos is already at/after the buffer end.  *ppos is >= 0 here (the caller
    rejects negative offsets), so size_buf - *ppos cannot wrap.  This mirrors
    the existing clamp in the MASTER-path helpers resource_to_user() /
    resource_from_user(), and matches the read()/write() convention of a
    short transfer at end-of-buffer.
    
    Found by static analysis (CodeQL taint tracking + CBMC bounded model
    checking) and confirmed dynamically under KASAN with the vme_fake bridge:
    
      BUG: KASAN: slab-out-of-bounds in _copy_from_user+0x2d/0x80
      Write of size 262144 at addr ffff888004100000 by task trigger/68
        _copy_from_user+0x2d/0x80
        vme_user_write+0x13e/0x240 [vme_user]
        vfs_write+0x1b8/0x7a0
        ksys_write+0xb8/0x150
    
    Fixes: f00a86d98a1e ("Staging: vme: add VME userspace driver")
    Cc: stable@vger.kernel.org
    Signed-off-by: Michael Tautschnig <tautschn@amazon.com>
    ---
    v1 -> v2:
     - Cc the staging list and LKML per get_maintainer.pl (v1 reached only
       Greg KH).
     - Switch the added comment to normal (non-networking) kernel style.
     - Keep the clamp + early return: this matches the read()/write()
       short-transfer / EOF convention already used by vme_user_read() /
       vme_user_write() (which clamp count and return 0 past the window) and
       by the MASTER-path resource_*() helpers (which clamp count to
       size_buf).  Documented that *ppos >= 0 here, so the subtraction is
       wrap-free.
    
    Link to v1: https://lore.kernel.org/all/20260614195318.40397-1-tautschn@amazon.com/
    
     drivers/staging/vme_user/vme_user.c | 22 ++++++++++++++++++++++
     1 file changed, 22 insertions(+)
    
    diff --git a/drivers/staging/vme_user/vme_user.c b/drivers/staging/vme_user/vme_user.c
    index 11e25c2f6b0a..a472a38ef613 100644
    --- a/drivers/staging/vme_user/vme_user.c
    +++ b/drivers/staging/vme_user/vme_user.c
    @@ -156,6 +156,17 @@ static ssize_t buffer_to_user(unsigned int minor, char __user *buf,
     {
     	void *image_ptr;
     
    +	/*
    +	 * The slave window (image_size) can exceed the fixed kern_buf
    +	 * (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf.
    +	 * *ppos is >= 0 here (checked by the caller), so the
    +	 * subtraction below cannot wrap.
    +	 */
    +	if (*ppos >= image[minor].size_buf)
    +		return 0;
    +	if (count > image[minor].size_buf - *ppos)
    +		count = image[minor].size_buf - *ppos;
    +
     	image_ptr = image[minor].kern_buf + *ppos;
     	if (copy_to_user(buf, image_ptr, (unsigned long)count))
     		return -EFAULT;
    @@ -168,6 +179,17 @@ static ssize_t buffer_from_user(unsigned int minor, const char __user *buf,
     {
     	void *image_ptr;
     
    +	/*
    +	 * The slave window (image_size) can exceed the fixed kern_buf
    +	 * (size_buf == PCI_BUF_SIZE), so bound the copy to kern_buf.
    +	 * *ppos is >= 0 here (checked by the caller), so the
    +	 * subtraction below cannot wrap.
    +	 */
    +	if (*ppos >= image[minor].size_buf)
    +		return 0;
    +	if (count > image[minor].size_buf - *ppos)
    +		count = image[minor].size_buf - *ppos;
    +
     	image_ptr = image[minor].kern_buf + *ppos;
     	if (copy_from_user(image_ptr, buf, (unsigned long)count))
     		return -EFAULT;
    -- 
    2.34.1
    
    
    
    Amazon Development Center Austria GmbH
    Brueckenkopfgasse 1
    8020 Graz
    Oesterreich
    Sitz in Graz
    Firmenbuchnummer: FN 439453 f
    Firmenbuchgericht: Landesgericht fuer Zivilrechtssachen Graz
    
    
    
    
    ^ permalink raw reply related	[flat|nested] 2+ messages in thread

  • end of thread, other threads:[~2026-06-18 11:47 UTC | newest]
    
    Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
    -- links below jump to the message on this page --
         [not found] <20260614195318.40397-1-tautschn@amazon.com>
         [not found] ` <2026061535-hardened-presuming-96b2@gregkh>
    2026-06-18 11:46   ` [PATCH] staging: vme_user: fix heap OOB in buffer_from_user and buffer_to_user Michael Tautschnig
    2026-06-18 11:47 ` [PATCH v2] staging: vme_user: bound slave read/write to the kern_buf size Michael Tautschnig
    

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