From: syzbot <syzbot+c7604c9fdd7580cca4e0@syzkaller.appspotmail.com>
To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com
Subject: Forwarded: [PATCH v2] PCI/proc: check user access return values in proc_bus_pci_{read,write}()
Date: Sun, 03 May 2026 18:22:29 -0700 [thread overview]
Message-ID: <69f7f4d5.050a0220.312cd3.003f.GAE@google.com> (raw)
In-Reply-To: <69f3f165.170a0220.5f1b.0010.GAE@google.com>
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH v2] PCI/proc: check user access return values in proc_bus_pci_{read,write}()
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
proc_bus_pci_write() ignores the return value of __get_user(). On a
faulting user pointer the extable fixup zeros the destination, and the
function writes those zeros to PCI configuration space.
syzbot triggers this with writev()-ing a NULL iov_base to
/proc/bus/pci/00/03.0 (the virtio-blk controller in the syzkaller VM):
zero is written to the Command register, clearing Bus Master Enable,
and the disk stops responding. In-flight journal writes never complete
and jbd2 hangs in wait_on_buffer() indefinitely:
INFO: task jbd2/sda1-8 blocked in I/O wait for more than 143 seconds.
__wait_on_buffer fs/buffer.c:123
jbd2_journal_commit_transaction+0x388a/0x6870 fs/jbd2/commit.c:837
kjournald2 fs/jbd2/journal.c:201
proc_bus_pci_read() has the symmetric problem with __put_user(): a
faulting user pointer silently drops config-space data and returns
success.
Switch both functions to get_user()/put_user(), which combine the
access_ok() check with the load/store and return -EFAULT on failure.
The up-front access_ok() can be removed accordingly. On error, jump to
a common label that releases the runtime-PM reference and returns
-EFAULT.
Reported-by: syzbot+c7604c9fdd7580cca4e0@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c7604c9fdd7580cca4e0
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
Changes in v2:
- Use get_user()/put_user() and drop access_ok() (Krzysztof)
- Rename label to err: per kernel convention (Krzysztof)
- Simplify error path to release runtime-PM and return -EFAULT (Krzysztof)
- Apply the same fix to proc_bus_pci_read() (Krzysztof)
---
drivers/pci/proc.c | 44 ++++++++++++++++++++++++++++----------------
1 file changed, 28 insertions(+), 16 deletions(-)
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;
buf += 2;
pos += 2;
cnt -= 2;
@@ -79,7 +78,8 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
while (cnt >= 4) {
unsigned int val;
pci_user_read_config_dword(dev, pos, &val);
- __put_user(cpu_to_le32(val), (__le32 __user *) buf);
+ if (put_user(cpu_to_le32(val), (__le32 __user *) buf))
+ goto err;
buf += 4;
pos += 4;
cnt -= 4;
@@ -89,7 +89,8 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
if (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;
buf += 2;
pos += 2;
cnt -= 2;
@@ -98,7 +99,8 @@ static ssize_t proc_bus_pci_read(struct file *file, char __user *buf,
if (cnt) {
unsigned char val;
pci_user_read_config_byte(dev, pos, &val);
- __put_user(val, buf);
+ if (put_user(val, buf))
+ goto err;
pos++;
}
@@ -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,
@@ -129,14 +135,12 @@ static ssize_t proc_bus_pci_write(struct file *file, const 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;
- __get_user(val, buf);
+ if (get_user(val, buf))
+ goto err;
pci_user_write_config_byte(dev, pos, val);
buf++;
pos++;
@@ -145,7 +149,8 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
if ((pos & 3) && cnt > 2) {
__le16 val;
- __get_user(val, (__le16 __user *) buf);
+ if (get_user(val, (__le16 __user *) buf))
+ goto err;
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
@@ -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;
@@ -163,7 +169,8 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
if (cnt >= 2) {
__le16 val;
- __get_user(val, (__le16 __user *) buf);
+ if (get_user(val, (__le16 __user *) buf))
+ goto err;
pci_user_write_config_word(dev, pos, le16_to_cpu(val));
buf += 2;
pos += 2;
@@ -172,7 +179,8 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
if (cnt) {
unsigned char val;
- __get_user(val, buf);
+ if (get_user(val, buf))
+ goto err;
pci_user_write_config_byte(dev, pos, val);
pos++;
}
@@ -182,6 +190,10 @@ static ssize_t proc_bus_pci_write(struct file *file, const char __user *buf,
*ppos = pos;
i_size_write(ino, dev->cfg_size);
return nbytes;
+
+err:
+ pci_config_pm_runtime_put(dev);
+ return -EFAULT;
}
#ifdef HAVE_PCI_MMAP
--
2.43.0
prev parent reply other threads:[~2026-05-04 1:22 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-01 0:18 [syzbot] INFO: task jbd2/sda1-NUM:NUM blocked in I/O wait for more than NUM seconds syzbot
2026-05-01 14:48 ` [syzbot] [ext4?] " syzbot
2026-05-01 23:47 ` Forwarded: [PATCH] PCI/proc: validate user buffer before touching config space syzbot
2026-05-02 0:02 ` Forwarded: [PATCH] PCI/proc: check return value of __get_user() in proc_bus_pci_write() syzbot
2026-05-04 1:22 ` syzbot [this message]
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=69f7f4d5.050a0220.312cd3.003f.GAE@google.com \
--to=syzbot+c7604c9fdd7580cca4e0@syzkaller.appspotmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=syzkaller-bugs@googlegroups.com \
/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.