All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Deepanshu Kartikey" <kartikey406@gmail.com>
Cc: linux-pci@vger.kernel.org
Subject: Re: [PATCH v2] PCI/proc: check user access return values in proc_bus_pci_{read,write}()
Date: Mon, 04 May 2026 02:44:21 +0000	[thread overview]
Message-ID: <20260504024421.D5256C2BCB4@smtp.kernel.org> (raw)
In-Reply-To: <20260504022231.15501-1-kartikey406@gmail.com>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Integer truncation in proc_bus_pci_write allows negative offsets to bypass bounds checks, leading to out-of-bounds PCI accesses and soft lockups.
- [Medium] Error handling discards partial transfers, violating POSIX semantics and risking unintended side effects on retry.
--

commit e7bdf9d788abd98223b783ee67cefeac2bfdde52
Author: Deepanshu Kartikey <kartikey406@gmail.com>

PCI/proc: check user access return values in proc_bus_pci_{read,write}()

This commit replaces __get_user() and __put_user() with get_user() and
put_user() to check for user access faults during PCI config space reads
and writes. It removes the upfront access_ok() check and adds an error
path to release the runtime PM reference and return -EFAULT on failure.

> diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
> index ce36e35681e8..8e624d829840 100644
> --- a/drivers/pci/proc.c
> +++ b/drivers/pci/proc.c
> @@ -53,15 +53,13 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
>  		nbytes = size - pos;
>  	cnt = nbytes;
>  
> -	if (!access_ok(buf, cnt))
> -		return -EINVAL;
> -
>  	pci_config_pm_runtime_get(dev);
>  
>  	if ((pos & 1) && cnt) {
>  		unsigned char val;
>  		pci_user_read_config_byte(dev, pos, &val);
> -		__put_user(val, buf);
> +		if (put_user(val, buf))
> +			goto err;
>  		buf++;
>  		pos++;
>  		cnt--;
> @@ -70,7 +68,8 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
>  	if ((pos & 3) && cnt > 2) {
>  		unsigned short val;
>  		pci_user_read_config_word(dev, pos, &val);
> -		__put_user(cpu_to_le16(val), (__le16 __user *) buf);
> +		if (put_user(cpu_to_le16(val), (__le16 __user *) buf))
> +			goto err;

If a fault happens during this put_user() call, some bytes may have already
been successfully transferred by the previous call. Unconditionally jumping
to the err label and returning -EFAULT discards this partial progress and
fails to update *ppos.

Since configuration registers can be stateful, such as Write-1-to-Clear
bits, could userspace retrying the entire operation cause unintended side
effects?

If data has been successfully processed prior to a fault, should the function
update the file offset and return the number of bytes transferred instead?

[ ... ]
> @@ -106,6 +108,10 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
>  
>  	*ppos = pos;
>  	return nbytes;
> +
> +err:
> +	pci_config_pm_runtime_put(dev);
> +	return -EFAULT;
>  }
>  
>  static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,

This issue isn't introduced by the patch, but does this function truncate
*ppos? Looking at the full function:

static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
				  size_t nbytes, loff_t *ppos)
{
	...
	int pos = *ppos;
	...

If a large positive offset is passed, such as 2294967296, the assignment to
the 32-bit int pos would truncate it to a negative value.

This bypasses the if (pos >= size) check. When checking pos + nbytes > size,
pos is promoted to a 64-bit size_t and sign-extends to a huge value, making
the condition true. nbytes is then calculated as size - pos, resulting in a
massive positive integer for cnt.

[ ... ]
> @@ -154,7 +159,8 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
>  
>  	while (cnt >= 4) {
>  		__le32 val;
> -		__get_user(val, (__le32 __user *) buf);
> +		if (get_user(val, (__le32 __user *) buf))
> +			goto err;
>  		pci_user_write_config_dword(dev, pos, le32_to_cpu(val));
>  		buf += 4;
>  		pos += 4;
>  		cnt -= 4;

The while (cnt >= 4) loop would then execute hundreds of millions of times,
passing a negative offset to the configuration accessor functions.

Since proc_bus_pci_write() lacks a cond_resched() call in this loop, could
this trigger a soft lockup?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260504022231.15501-1-kartikey406@gmail.com?part=1

  reply	other threads:[~2026-05-04  2:44 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-04  2:22 [PATCH v2] PCI/proc: check user access return values in proc_bus_pci_{read,write}() Deepanshu Kartikey
2026-05-04  2:44 ` sashiko-bot [this message]
2026-06-21  8:22 ` Deepanshu Kartikey
2026-06-22 17:19   ` Bjorn Helgaas
2026-07-25  2:06     ` Deepanshu Kartikey
2026-07-28 21:56 ` Bjorn Helgaas
2026-07-28 23:16 ` Krzysztof Wilczyński

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=20260504024421.D5256C2BCB4@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=kartikey406@gmail.com \
    --cc=linux-pci@vger.kernel.org \
    --cc=sashiko@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.