Skip to content

Commit 1af9777

Browse files
Ming Leigregkh
Ming Lei
authored andcommitted
blk-mq: fix buffer overflow when reading sysfs file of 'pending'
commit 596f5aa upstream. There may be lots of pending requests so that the buffer of PAGE_SIZE can't hold them at all. One typical example is scsi-mq, the queue depth(.can_queue) of scsi_host and blk-mq is quite big but scsi_device's queue_depth is a bit small(.cmd_per_lun), then it is quite easy to have lots of pending requests in hw queue. This patch fixes the following warning and the related memory destruction. [ 359.025101] fill_read_buffer: blk_mq_hw_sysfs_show+0x0/0x7d returned bad count^M [ 359.055595] irq event stamp: 15537^M [ 359.055606] general protection fault: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC ^M [ 359.055614] Dumping ftrace buffer:^M [ 359.055660] (ftrace buffer empty)^M [ 359.055672] Modules linked in: nbd ipv6 kvm_intel kvm serio_raw^M [ 359.055678] CPU: 4 PID: 21631 Comm: stress-ng-sysfs Not tainted 4.2.0-rc5-next-20150805 #434^M [ 359.055679] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011^M [ 359.055682] task: ffff8802161cc000 ti: ffff88021b4a8000 task.ti: ffff88021b4a8000^M [ 359.055693] RIP: 0010:[<ffffffff811541c5>] [<ffffffff811541c5>] __kmalloc+0xe8/0x152^M Signed-off-by: Ming Lei <[email protected]> Signed-off-by: Jens Axboe <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 4fbdb44 commit 1af9777

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

block/blk-mq-sysfs.c

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,26 @@ static ssize_t blk_mq_sysfs_completed_show(struct blk_mq_ctx *ctx, char *page)
141141

142142
static ssize_t sysfs_list_show(char *page, struct list_head *list, char *msg)
143143
{
144-
char *start_page = page;
145144
struct request *rq;
145+
int len = snprintf(page, PAGE_SIZE - 1, "%s:\n", msg);
146+
147+
list_for_each_entry(rq, list, queuelist) {
148+
const int rq_len = 2 * sizeof(rq) + 2;
149+
150+
/* if the output will be truncated */
151+
if (PAGE_SIZE - 1 < len + rq_len) {
152+
/* backspacing if it can't hold '\t...\n' */
153+
if (PAGE_SIZE - 1 < len + 5)
154+
len -= rq_len;
155+
len += snprintf(page + len, PAGE_SIZE - 1 - len,
156+
"\t...\n");
157+
break;
158+
}
159+
len += snprintf(page + len, PAGE_SIZE - 1 - len,
160+
"\t%p\n", rq);
161+
}
146162

147-
page += sprintf(page, "%s:\n", msg);
148-
149-
list_for_each_entry(rq, list, queuelist)
150-
page += sprintf(page, "\t%p\n", rq);
151-
152-
return page - start_page;
163+
return len;
153164
}
154165

155166
static ssize_t blk_mq_sysfs_rq_list_show(struct blk_mq_ctx *ctx, char *page)

0 commit comments

Comments
 (0)