mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Douglas Gilbert <dgilbert@interlog.com>
To: Dmitry Vyukov <dvyukov@google.com>,
	jejb@linux.vnet.ibm.com,
	"Martin K. Petersen" <martin.petersen@oracle.com>,
	linux-scsi <linux-scsi@vger.kernel.org>,
	LKML <linux-kernel@vger.kernel.org>, Jens Axboe <axboe@kernel.dk>,
	linux-block@vger.kernel.org,
	syzkaller <syzkaller@googlegroups.com>
Subject: Re: scsi: memory leak in sg_start_req
Date: Thu, 11 Jan 2018 01:04:03 -0500	[thread overview]
Message-ID: <f30afef5-5123-72c2-aa41-4fbbde334fb4@interlog.com> (raw)
In-Reply-To: <CACT4Y+aqgtL37SkUAro4dKqxp4GynmfTLio1qGUbGTChFU7fpA@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 3874 bytes --]

On 2018-01-09 11:05 AM, Dmitry Vyukov wrote:
> Hello,
> 
> syzkaller has found the following memory leak:
> 
> unreferenced object 0xffff88004c190000 (size 8328):
>    comm "syz-executor", pid 4627, jiffies 4294749150 (age 45.507s)
>    hex dump (first 32 bytes):
>      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
>      20 00 00 00 22 01 00 00 00 00 00 00 04 00 00 00   ..."...........
>    backtrace:
>      [<000000005955b5a9>] kmalloc_order+0x59/0x80 mm/slab_common.c:1124
>      [<0000000043ae006e>] kmalloc_order_trace+0x1f/0x160 mm/slab_common.c:1133
>      [<00000000d33b2e16>] kmalloc_large include/linux/slab.h:433 [inline]
>      [<00000000d33b2e16>] __kmalloc+0x2c4/0x340 mm/slub.c:3751
>      [<00000000e7430040>] kmalloc include/linux/slab.h:504 [inline]
>      [<00000000e7430040>] bio_alloc_bioset+0x4d5/0x7e0 block/bio.c:450
>      [<00000000f370e717>] bio_kmalloc include/linux/bio.h:410 [inline]
>      [<00000000f370e717>] bio_copy_user_iov+0x2be/0xcb0 block/bio.c:1226
>      [<000000001d0b79ed>] __blk_rq_map_user_iov block/blk-map.c:67 [inline]
>      [<000000001d0b79ed>] blk_rq_map_user_iov+0x2b6/0x7d0 block/blk-map.c:136
>      [<000000004200a869>] blk_rq_map_user+0x11e/0x170 block/blk-map.c:166
>      [<000000008f21739e>] sg_start_req drivers/scsi/sg.c:1794 [inline]
>      [<000000008f21739e>] sg_common_write.isra.16+0x14df/0x1ed0
> drivers/scsi/sg.c:777
>      [<00000000093f61e3>] sg_write+0x8a7/0xd7b drivers/scsi/sg.c:677
>      [<00000000b67dafdc>] __vfs_write+0x10d/0x8f0 fs/read_write.c:480
>      [<000000000638f16f>] vfs_write+0x1fd/0x570 fs/read_write.c:544
>      [<000000006a7e6867>] SYSC_write fs/read_write.c:589 [inline]
>      [<000000006a7e6867>] SyS_write+0xfa/0x250 fs/read_write.c:581
> 
> can be reproduced with the following program:
> 
> // autogenerated by syzkaller (http://github.com/google/syzkaller)
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <fcntl.h>
> #include <unistd.h>
> 
> int main()
> {
>    int fd = open("/dev/sg1", O_RDWR);
>    const char *data =
>           "\xb6\x3d\xb8\x5e\x1e\x8d\x22\x00\x00\x00\x00\x00\x00\x08\xaf\xd6\x1d"
>           "\xcc\x43\x6a\xed\x5e\xd2\xbc\x70\x18\xce\xbc\x9b\x97\xae\x21\x91\x4d"
>           "\x87\x2c\x67\x8c\xe2\x2c\x9b\x16\x0e\x96\xaa\x1f\xae\x1a";
>    write(fd, data, 0x30);
>    return 0;
> }
> 
> if executed in a loop, memory consumption grows infinitely.
> 
> on upstream commit b2cd1df66037e7c4697c7e40496bf7e4a5e16a2d
> 
The seemingly random data that program is sending is asking for
a buffer of 2,264,314 bytes which the sg driver procures and waits
for the caller to either issue a read() or close() the file
or shutdown the program. The test program does none of those
expected operations, it simply asks for the same resources again.

In my version of your test code (attached), that happens 1,021 times
at which point the file handles in that process are exhausted and
all subsequent open()s fail with EBADF (as do the write()s). The
output from my program was this on one run:

# ./sg_syzk_grow
First errno=9 [Bad file descriptor] index=1021
done_count=50000, err_count=48979, last_errno=9 [Bad file descriptor]

# lsscsi -gs
[0:0:0:0]  disk  Linux  scsi_debug  0186  /dev/sda  /dev/sg0  2.14GB

Monitoring that program with 'free' from another terminal I see
about 2.5 GBytes of ram "swallowed" almost immediately when the test
program runs. When the program exits (about 50 seconds later) as far
as I can see all that ram is given back.


If you used the same program and wrote to a regular file rather than
a sg device, then that program would eventually fill any file system,
at the rate of 48 bytes per iteration (given enough file descriptor
resources). The sg driver, using its original 1994 interface,
deprecated for around 18 years, just gets a system to resource
exhaustion quicker.

Doug Gilbert





[-- Attachment #2: sg_syzk_grow.c --]
[-- Type: text/x-csrc, Size: 2204 bytes --]

// autogenerated by syzkaller (http://github.com/google/syzkaller)
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <string.h>

static const char * sg_dev = "/dev/sg0";

int main()
{
  const char *data =
         "\xb6\x3d\xb8\x5e\x1e\x8d\x22\x00\x00\x00\x00\x00\x00\x08\xaf\xd6\x1d"
         "\xcc\x43\x6a\xed\x5e\xd2\xbc\x70\x18\xce\xbc\x9b\x97\xae\x21\x91\x4d"
         "\x87\x2c\x67\x8c\xe2\x2c\x9b\x16\x0e\x96\xaa\x1f\xae\x1a";
    int k, res, first_errno, prev_errno, first_err_index;
    int err_count = 0;
    int done_count = 0;
    bool got_1st_errno = false;

    for (k = 0; k < 10000; ++k) {
        int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0) {
	    if (! got_1st_errno) {
		got_1st_errno = true;
		first_errno = errno;
		first_err_index = done_count + k;
		printf("First errno=%d [%s] index=%d\n", first_errno,
		       strerror(first_errno), first_err_index);
	    }
	    ++err_count;
	}
    }
    done_count += k;
    sleep(10);
    for (k = 0; k < 10000; ++k) {
        int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0) {
	    if (! got_1st_errno) {
		got_1st_errno = true;
		first_errno = errno;
		printf("First errno=%d [%s] index=%d\n", first_errno,
		       strerror(first_errno), first_err_index);
		first_err_index = done_count + k;
	    }
	    ++err_count;
	}
    }
    done_count += k;
    sleep(10);
    for (k = 0; k < 10000; ++k) {
        int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0)
	    ++err_count;
    }
    done_count += k;
    sleep(10);
    for (k = 0; k < 10000; ++k) {
        int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0)
	    ++err_count;
    }
    done_count += k;
    sleep(10);
    for (k = 0; k < 10000; ++k) {
        int fd = open(sg_dev, O_RDWR);

  	res = write(fd, data, 0x30);
	if (res < 0) {
	    prev_errno = errno;
	    ++err_count;
	}
    }
    done_count += k;
    sleep(10);
    printf("done_count=%d, err_count=%d, last_errno=%d [%s]\n", done_count,
	   err_count, prev_errno, strerror(prev_errno));

  return 0;

}

  reply	other threads:[~2018-01-11  6:13 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-01-09 16:05 Dmitry Vyukov
2018-01-11  6:04 ` Douglas Gilbert [this message]
2018-01-11  8:23   ` Dmitry Vyukov
2018-01-11 16:28   ` Bart Van Assche

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=f30afef5-5123-72c2-aa41-4fbbde334fb4@interlog.com \
    --to=dgilbert@interlog.com \
    --cc=axboe@kernel.dk \
    --cc=dvyukov@google.com \
    --cc=jejb@linux.vnet.ibm.com \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-scsi@vger.kernel.org \
    --cc=martin.petersen@oracle.com \
    --cc=syzkaller@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 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®