From: Stanley Jhu <stanleyjhu@google.com>
To: Jens Axboe <axboe@kernel.dk>,
"James E . J . Bottomley"
<James.Bottomley@HansenPartnership.com>,
"Martin K . Petersen" <mkp@kernel.org>,
Bart Van Assche <bvanassche@acm.org>,
Alim Akhtar <alim.akhtar@samsung.com>
Cc: Sathya Prakash Veerichetty <sathya.prakash@broadcom.com>,
Kashyap Desai <kashyap.desai@broadcom.com>,
Sumit Saxena <sumit.saxena@broadcom.com>,
Sreekanth Reddy <sreekanth.reddy@broadcom.com>,
Lee Duncan <lduncan@suse.com>, Chris Leech <cleech@redhat.com>,
Mike Christie <michael.christie@oracle.com>,
Bean Huo <beanhuo@micron.com>, Christoph Hellwig <hch@lst.de>,
linux-block@vger.kernel.org, linux-scsi@vger.kernel.org,
mpi3mr-linuxdrv.pdl@broadcom.com, open-iscsi@googlegroups.com,
linux-kernel@vger.kernel.org, stable@vger.kernel.org
Subject: [PATCH] scsi: bsg: Pass reply_len to bsg_setup_queue() to fit UFS ARPMB replies
Date: Tue, 13 Oct 2026 21:27:08 +0800 [thread overview]
Message-ID: <20261013132708.1669415-1-stanleyjhu@google.com> (raw)
bsg-lib allocates a 96-byte (SCSI_SENSE_BUFFERSIZE) reply buffer per
job, but struct ufs_rpmb_reply is 104 bytes: a 40-byte struct
ufs_bsg_reply followed by a 64-byte EHS. When an Advanced RPMB command
returns an EHS, ufshcd_advanced_rpmb_req_handler() copies it right
after the 40-byte header and writes 8 bytes past the end of the buffer.
Let each BSG transport pass its reply buffer size to bsg_setup_queue()
and have ufs_bsg request sizeof(struct ufs_rpmb_reply), so the full
reply reaches user space. Other transports keep SCSI_SENSE_BUFFERSIZE.
Fixes: 6ff265fc5ef6 ("scsi: ufs: core: bsg: Add advanced RPMB support in ufs_bsg")
Cc: stable@vger.kernel.org
Signed-off-by: Stanley Jhu <stanleyjhu@google.com>
---
Tested on QEMU arm64 with KASAN: the reproducer no longer triggers.
block/bsg-lib.c | 13 ++++++++++---
drivers/scsi/mpi3mr/mpi3mr_app.c | 2 +-
drivers/scsi/scsi_transport_fc.c | 6 ++++--
drivers/scsi/scsi_transport_iscsi.c | 2 +-
drivers/scsi/scsi_transport_sas.c | 6 ++++--
drivers/ufs/core/ufs_bsg.c | 2 +-
include/linux/bsg-lib.h | 3 ++-
7 files changed, 23 insertions(+), 11 deletions(-)
diff --git a/block/bsg-lib.c b/block/bsg-lib.c
index 895db30a7033..536cee4430a7 100644
--- a/block/bsg-lib.c
+++ b/block/bsg-lib.c
@@ -23,11 +23,14 @@ struct bsg_set {
struct bsg_device *bd;
bsg_job_fn *job_fn;
bsg_timeout_fn *timeout_fn;
+ unsigned int reply_len;
};
static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
bool open_for_write, unsigned int timeout)
{
+ struct bsg_set *bset =
+ container_of(q->tag_set, struct bsg_set, tag_set);
struct bsg_job *job;
struct request *rq;
struct bio *bio;
@@ -50,7 +53,7 @@ static int bsg_transport_sg_io_fn(struct request_queue *q, struct sg_io_v4 *hdr,
reply = job->reply;
memset(job, 0, sizeof(*job));
job->reply = reply;
- job->reply_len = SCSI_SENSE_BUFFERSIZE;
+ job->reply_len = bset->reply_len;
job->dd_data = job + 1;
job->request_len = hdr->request_len;
@@ -301,9 +304,10 @@ static blk_status_t bsg_queue_rq(struct blk_mq_hw_ctx *hctx,
static int bsg_init_rq(struct blk_mq_tag_set *set, struct request *req,
unsigned int hctx_idx, int numa_node)
{
+ struct bsg_set *bset = container_of(set, struct bsg_set, tag_set);
struct bsg_job *job = blk_mq_rq_to_pdu(req);
- job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);
+ job->reply = kzalloc(bset->reply_len, GFP_KERNEL);
if (!job->reply)
return -ENOMEM;
return 0;
@@ -358,10 +362,12 @@ static const struct blk_mq_ops bsg_mq_ops = {
* @job_fn: bsg job handler
* @timeout: timeout handler function pointer
* @dd_job_size: size of LLD data needed for each job
+ * @reply_len: size of the reply buffer needed for each job
*/
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
struct queue_limits *lim, bsg_job_fn *job_fn,
- bsg_timeout_fn *timeout, int dd_job_size)
+ bsg_timeout_fn *timeout, int dd_job_size,
+ unsigned int reply_len)
{
struct bsg_set *bset;
struct blk_mq_tag_set *set;
@@ -374,6 +380,7 @@ struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
bset->job_fn = job_fn;
bset->timeout_fn = timeout;
+ bset->reply_len = reply_len;
set = &bset->tag_set;
set->ops = &bsg_mq_ops;
diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
index 1353a8ff9c85..094490713d69 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -3053,7 +3053,7 @@ void mpi3mr_bsg_init(struct mpi3mr_ioc *mrioc)
}
q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), &lim,
- mpi3mr_bsg_request, NULL, 0);
+ mpi3mr_bsg_request, NULL, 0, SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q)) {
ioc_err(mrioc, "%s: bsg registration failed\n",
dev_name(bsg_dev));
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 173ed6373f04..b66365a382c7 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -4345,7 +4345,8 @@ fc_bsg_hostadd(struct Scsi_Host *shost, struct fc_host_attrs *fc_host)
scsi_init_limits(shost, &lim);
lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
q = bsg_setup_queue(dev, bsg_name, &lim, fc_bsg_dispatch,
- fc_bsg_job_timeout, i->f->dd_bsg_size);
+ fc_bsg_job_timeout, i->f->dd_bsg_size,
+ SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q)) {
dev_err(dev,
"fc_host%d: bsg interface failed to initialize - setup queue\n",
@@ -4378,7 +4379,8 @@ fc_bsg_rportadd(struct Scsi_Host *shost, struct fc_rport *rport)
scsi_init_limits(shost, &lim);
lim.max_segments = min_not_zero(lim.max_segments, i->f->max_bsg_segments);
q = bsg_setup_queue(dev, dev_name(dev), &lim, fc_bsg_dispatch_prep,
- fc_bsg_job_timeout, i->f->dd_bsg_size);
+ fc_bsg_job_timeout, i->f->dd_bsg_size,
+ SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q)) {
dev_err(dev, "failed to setup bsg queue\n");
return PTR_ERR(q);
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 8aa76f813bcd..b50ff8a1d0a9 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -1545,7 +1545,7 @@ iscsi_bsg_host_add(struct Scsi_Host *shost, struct iscsi_cls_host *ihost)
snprintf(bsg_name, sizeof(bsg_name), "iscsi_host%d", shost->host_no);
scsi_init_limits(shost, &lim);
q = bsg_setup_queue(dev, bsg_name, &lim, iscsi_bsg_host_dispatch, NULL,
- 0);
+ 0, SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q)) {
shost_printk(KERN_ERR, shost, "bsg interface failed to "
"initialize - no request queue\n");
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c
index d689b9ed08a6..a825966f60e5 100644
--- a/drivers/scsi/scsi_transport_sas.c
+++ b/drivers/scsi/scsi_transport_sas.c
@@ -199,7 +199,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
if (rphy) {
q = bsg_setup_queue(&rphy->dev, dev_name(&rphy->dev), NULL,
- sas_smp_dispatch, NULL, 0);
+ sas_smp_dispatch, NULL, 0,
+ SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q))
return PTR_ERR(q);
rphy->q = q;
@@ -208,7 +209,8 @@ static int sas_bsg_initialize(struct Scsi_Host *shost, struct sas_rphy *rphy)
snprintf(name, sizeof(name), "sas_host%d", shost->host_no);
q = bsg_setup_queue(&shost->shost_gendev, name, NULL,
- sas_smp_dispatch, NULL, 0);
+ sas_smp_dispatch, NULL, 0,
+ SCSI_SENSE_BUFFERSIZE);
if (IS_ERR(q))
return PTR_ERR(q);
to_sas_host_attrs(shost)->q = q;
diff --git a/drivers/ufs/core/ufs_bsg.c b/drivers/ufs/core/ufs_bsg.c
index 7a66917b3fc0..156637dd76c8 100644
--- a/drivers/ufs/core/ufs_bsg.c
+++ b/drivers/ufs/core/ufs_bsg.c
@@ -258,7 +258,7 @@ int ufs_bsg_probe(struct ufs_hba *hba)
goto out;
q = bsg_setup_queue(bsg_dev, dev_name(bsg_dev), NULL, ufs_bsg_request,
- NULL, 0);
+ NULL, 0, sizeof(struct ufs_rpmb_reply));
if (IS_ERR(q)) {
ret = PTR_ERR(q);
device_del(bsg_dev);
diff --git a/include/linux/bsg-lib.h b/include/linux/bsg-lib.h
index 14fa93268630..a697246feeac 100644
--- a/include/linux/bsg-lib.h
+++ b/include/linux/bsg-lib.h
@@ -66,7 +66,8 @@ void bsg_job_done(struct bsg_job *job, int result,
unsigned int reply_payload_rcv_len);
struct request_queue *bsg_setup_queue(struct device *dev, const char *name,
struct queue_limits *lim, bsg_job_fn *job_fn,
- bsg_timeout_fn *timeout, int dd_job_size);
+ bsg_timeout_fn *timeout, int dd_job_size,
+ unsigned int reply_len);
void bsg_remove_queue(struct request_queue *q);
void bsg_job_put(struct bsg_job *job);
int __must_check bsg_job_get(struct bsg_job *job);
--
2.56.0.385.gd3acb90ef8-goog
reply other threads:[~2026-10-13 13:27 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20261013132708.1669415-1-stanleyjhu@google.com \
--to=stanleyjhu@google.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=alim.akhtar@samsung.com \
--cc=axboe@kernel.dk \
--cc=beanhuo@micron.com \
--cc=bvanassche@acm.org \
--cc=cleech@redhat.com \
--cc=hch@lst.de \
--cc=kashyap.desai@broadcom.com \
--cc=lduncan@suse.com \
--cc=linux-block@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=michael.christie@oracle.com \
--cc=mkp@kernel.org \
--cc=mpi3mr-linuxdrv.pdl@broadcom.com \
--cc=open-iscsi@googlegroups.com \
--cc=sathya.prakash@broadcom.com \
--cc=sreekanth.reddy@broadcom.com \
--cc=stable@vger.kernel.org \
--cc=sumit.saxena@broadcom.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®