Date: Sat, 9 May 2020 06:25:21 +0000 (UTC) From: Toomas Soome <tsoome@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r360836 - head/stand/libsa/zfs Message-ID: <202005090625.0496PLvc091232@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: tsoome Date: Sat May 9 06:25:20 2020 New Revision: 360836 URL: https://svnweb.freebsd.org/changeset/base/360836 Log: loader: vdev_read() can corrupt memory When reading less than sector size but from sector boundary, the vdev_read() will read full sector into the provided buffer and therefore corrupting memory past buffer end. MFC after: 2 days Modified: head/stand/libsa/zfs/zfs.c Modified: head/stand/libsa/zfs/zfs.c ============================================================================== --- head/stand/libsa/zfs/zfs.c Sat May 9 05:04:02 2020 (r360835) +++ head/stand/libsa/zfs/zfs.c Sat May 9 06:25:20 2020 (r360836) @@ -418,7 +418,7 @@ vdev_read(vdev_t *vdev, void *priv, off_t offset, void full_sec_size -= secsz; /* Return of partial sector data requires a bounce buffer. */ - if ((head > 0) || do_tail_read) { + if ((head > 0) || do_tail_read || bytes < secsz) { bouncebuf = malloc(secsz); if (bouncebuf == NULL) { printf("vdev_read: out of memory\n"); @@ -442,14 +442,28 @@ vdev_read(vdev_t *vdev, void *priv, off_t offset, void outbuf += min(secsz - head, bytes); } - /* Full data return from read sectors */ + /* + * Full data return from read sectors. + * Note, there is still corner case where we read + * from sector boundary, but less than sector size, e.g. reading 512B + * from 4k sector. + */ if (full_sec_size > 0) { - res = read(fd, outbuf, full_sec_size); - if (res != full_sec_size) { - ret = EIO; - goto error; + if (bytes < full_sec_size) { + res = read(fd, bouncebuf, secsz); + if (res != secsz) { + ret = EIO; + goto error; + } + memcpy(outbuf, bouncebuf, bytes); + } else { + res = read(fd, outbuf, full_sec_size); + if (res != full_sec_size) { + ret = EIO; + goto error; + } + outbuf += full_sec_size; } - outbuf += full_sec_size; } /* Partial data return from last sector */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202005090625.0496PLvc091232>