[Bug 210864] ggatel(8) BIO_DELETE implementation is broken

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Wed Jul 6 02:22:05 UTC 2016


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=210864

            Bug ID: 210864
           Summary: ggatel(8) BIO_DELETE implementation is broken
           Product: Base System
           Version: 11.0-CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: bin
          Assignee: freebsd-bugs at FreeBSD.org
          Reporter: julian at hsiao.email

md(4) simulates BIO_DELETE by writing zeros, and I infer ggatel(8) is
trying to do the same based on the code structure similarity. However, the
latter's implementation is actually broken. If
g_gate_ioctl(G_GATE_CMD_START, ...) returns with a BIO_DELETE request, only
gctl_length and gctl_offset are updated, and gctl_data still points to the
original buffer. ggatel(8) then proceeds to service BIO_DELETE as if it
were BIO_WRITE, so it writes "garbage" to disk, and (hopefully) EFAULT if
gctl_length is greater than gctl_data's actual length.

PoC:

# cd /tmp
# clang -x c -o bug - <<'BUG'
#include <assert.h>

#include <fcntl.h>
#include <sys/disk.h>
#include <sys/ioctl.h>

int main()
{
    const int fd = open("/dev/ggate0", O_RDWR | O_CLOEXEC | O_DIRECT);
    assert(fd != -1);

    off_t ol[2] = { 40960, 4096 };
    assert(ioctl(fd, DIOCGDELETE, ol) != -1);

    return(0);
}
BUG
# truncate -s 10m test
# ggatel create -s 4096 test
# dd if=/dev/zero   bs=4096 count=1 | LC_ALL=C tr '\0' '\252' |
  dd of=/dev/ggate0 bs=4096
# ./bug
# hexdump -C /dev/ggate0
00000000  aa aa aa aa aa aa aa aa  aa aa aa aa aa aa aa aa  |................|
*
00001000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0000a000  aa aa aa aa aa aa aa aa  aa aa aa aa aa aa aa aa  |................|
*
0000b000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00a00000

I'm not sure of the security implication of this bug, since to trigger the
bug directly requires elevated privileges. However, there may be clever
ways to trigger it by proxy.

IMHO, simulating BIO_DELETE by writing zeros is questionable, however not
everyone agrees[0]. That said, you can always use md(4) instead, so I
suggest ggatel(8) should just return EOPNOTSUPP for BIO_DELETE.

[0] http://thread.gmane.org/gmane.os.freebsd.devel.hackers/57688/focus=57689

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list