@@ -21,7 +21,7 @@
ACLOCAL_AMFLAGS = ${ACLOCAL_FLAGS} -I m4
-SUBDIRS = lib tools scripts benchmarks
+SUBDIRS = lib tools scripts benchmarks cve
if BUILD_TESTS
SUBDIRS += tests
@@ -311,6 +311,7 @@ AC_CONFIG_FILES([
tools/null_state_gen/Makefile
tools/registers/Makefile
overlay/Makefile
+ cve/Makefile
])
AC_CONFIG_FILES([tools/intel_aubdump], [chmod +x tools/intel_aubdump])
new file mode 100644
@@ -0,0 +1,14 @@
+include Makefile.sources
+
+cve_PROGRAMS = $(cve_prog_list)
+
+AM_CPPFLAGS = \
+ -I$(top_srcdir) \
+ -I$(top_srcdir)/include/drm-uapi \
+ -I$(top_srcdir)/lib \
+ -I$(top_srcdir)/lib/stubs/syscalls
+
+AM_CFLAGS = -I$(top_srcdir)/include/drm-uapi \
+ $(DRM_CFLAGS) $(CWARNFLAGS) $(CAIRO_CFLAGS) $(LIBUNWIND_CFLAGS) \
+ $(WERROR_CFLAGS) -D_GNU_SOURCE
+LDADD = $(top_builddir)/lib/libintel_tools.la
new file mode 100644
@@ -0,0 +1,5 @@
+cvedir=$(libexecdir)/igt-gpu-tools/cve
+
+cve_prog_list = \
+ cve-2019-0155
+ $(NULL)
new file mode 100644
@@ -0,0 +1,470 @@
+/*
+ * Copyright © 2019 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * Can be compiled with:
+ * gcc -Wall -static -o cve-2019-0155 cve-2019-0155.c
+*/
+
+#define VERSION 1
+#define CHECK_WRITE_BLOCK_WITHOUT_PARSER 0
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define ASSERT(x, s) do { \
+ if (!(x)) { \
+ printf("Failed to %s, %s (%d)\n", (s), \
+ strerror(errno), errno); \
+ exit(EXIT_FAILURE); \
+ } \
+ } while(0)
+
+static int do_ioctl(const int fd, const unsigned long nr, void *arg)
+{
+ int ret;
+
+ do
+ ret = ioctl(fd, nr, arg);
+ while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+
+ return ret;
+}
+
+static int is_driver_i915(const int fd)
+{
+ struct _drm_version {
+ int version_major;
+ int version_minor;
+ int version_patchlevel;
+
+ size_t name_len;
+ char *name;
+ size_t date_len;
+ char *date;
+ size_t desc_len;
+ char *desc;
+ } v = { 0, };
+ char name[256] = { 0, };
+ int ret;
+
+ v.name_len = sizeof(name) - 1;
+ v.name = name;
+
+ ret = do_ioctl(fd, _IOWR(0x40, 0x00, struct _drm_version), &v);
+ ASSERT(ret == 0, "get name");
+
+ name[v.name_len] = 0;
+
+ return !strcmp(name, "i915");
+}
+
+static int cmd_parser_version(const int fd)
+{
+ int ret, version = 0;
+ struct _drm_i915_getparam_t {
+ int32_t param;
+ uint64_t value;
+ } q = { 28,
+ (uint64_t)&version };
+
+ ret = do_ioctl(fd, _IOWR(0x40, 0x40 + 0x06, struct _drm_i915_getparam_t), &q);
+ ASSERT(ret == 0, "get param");
+
+ return version;
+}
+
+#define MI_INSTR(opcode, flags) (((opcode) << 23) | (flags))
+#define MI_BATCH_BUFFER_END MI_INSTR(0x0a, 0)
+#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, (3-2))
+
+static int is_write_blocked(const int fd)
+{
+ int ret;
+ uint32_t handle;
+
+ struct _drm_i915_gem_execbuffer2 {
+ uint64_t buffers_ptr;
+ uint32_t buffer_count;
+ uint32_t batch_start_offset;
+ uint32_t batch_len;
+ uint32_t DR1;
+ uint32_t DR4;
+ uint32_t num_cliprects;
+ uint64_t cliprects_ptr;
+ uint64_t flags;
+ uint64_t rsvd1;
+ uint64_t rsvd2;
+ } execbuf = { 0, };
+
+ struct _drm_i915_gem_exec_object2 {
+ uint32_t handle;
+ uint32_t relocation_count;
+ uint64_t relocs_ptr;
+ uint64_t alignment;
+ uint64_t offset;
+ uint64_t flags;
+ uint64_t rsvd1;
+ uint64_t rsvd2;
+ } execobj[1] = { { 0, } };
+
+ struct _drm_i915_gem_create {
+ uint64_t size;
+ uint32_t handle;
+ uint32_t pad;
+ } createobj = { 0, };
+
+ struct _drm_i915_gem_pwrite {
+ uint32_t handle;
+ uint32_t pad;
+ uint64_t offset;
+ uint64_t size;
+ uint64_t data_ptr;
+ } pwrite = { 0, };
+
+ const uint32_t batch[] = {
+ MI_LOAD_REGISTER_IMM,
+ 0x2221c,
+ 0x0,
+ 0,
+ MI_BATCH_BUFFER_END,
+ };
+
+ createobj.handle = 0;
+ createobj.size = 4096;
+
+ ret = do_ioctl(fd, _IOWR(0x40, 0x40+0x1b, struct _drm_i915_gem_create), &createobj);
+ ASSERT(ret == 0, "create object");
+
+ handle = createobj.handle;
+
+ pwrite.handle = handle;
+ pwrite.size = sizeof(batch);
+ pwrite.data_ptr = (uintptr_t)batch;
+
+ ret = do_ioctl(fd, _IOWR(0x40, 0x40+0x1d, struct _drm_i915_gem_pwrite), &pwrite);
+ ASSERT(ret == 0, "write object");
+
+ execobj[0].handle = handle;
+
+ execbuf.buffers_ptr = (uintptr_t)execobj;
+ execbuf.buffer_count = 1;
+ execbuf.flags = 3; /* select blitter engine (bcs0) */
+
+ ret = do_ioctl(fd, _IOWR(0x40, 0x40+0x29, struct _drm_i915_gem_execbuffer2), &execbuf);
+ if (ret) {
+ if (errno == EACCES || errno == EINVAL)
+ return 1;
+ }
+
+ return 0;
+}
+
+#define INTEL_VGA_DEVICE(x, y) (x)
+
+static const uint32_t gen9_ids[] = {
+
+ INTEL_VGA_DEVICE(0x1906, info), /* ULT GT1 */
+
+ INTEL_VGA_DEVICE(0x190E, info), /* ULX GT1 */
+
+ INTEL_VGA_DEVICE(0x1902, info), /* DT GT1 */
+ INTEL_VGA_DEVICE(0x190B, info), /* Halo GT1 */
+ INTEL_VGA_DEVICE(0x190A, info), /* SRV GT1 */
+
+ INTEL_VGA_DEVICE(0x1916, info), /* ULT GT2 */
+ INTEL_VGA_DEVICE(0x1921, info), /* ULT GT2F */
+
+ INTEL_VGA_DEVICE(0x191E, info), /* ULX GT2 */
+
+ INTEL_VGA_DEVICE(0x1912, info), /* DT GT2 */
+ INTEL_VGA_DEVICE(0x191B, info), /* Halo GT2 */
+ INTEL_VGA_DEVICE(0x191A, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x191D, info), /* WKS GT2 */
+
+ INTEL_VGA_DEVICE(0x1926, info), /* ULT GT3 */
+
+ INTEL_VGA_DEVICE(0x1923, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x1927, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x192B, info), /* Halo GT3 */
+ INTEL_VGA_DEVICE(0x192D, info), /* SRV GT3 */
+
+ INTEL_VGA_DEVICE(0x1932, info), /* DT GT4 */
+ INTEL_VGA_DEVICE(0x193B, info), /* Halo GT4 */
+ INTEL_VGA_DEVICE(0x193D, info), /* WKS GT4 */
+ INTEL_VGA_DEVICE(0x192A, info), /* SRV GT4 */
+ INTEL_VGA_DEVICE(0x193A, info), /* SRV GT4e */
+
+ INTEL_VGA_DEVICE(0x0A84, info),
+ INTEL_VGA_DEVICE(0x1A84, info),
+ INTEL_VGA_DEVICE(0x1A85, info),
+ INTEL_VGA_DEVICE(0x5A84, info), /* APL HD Graphics 505 */
+ INTEL_VGA_DEVICE(0x5A85, info), /* APL HD Graphics 500 */
+
+ INTEL_VGA_DEVICE(0x3184, info),
+ INTEL_VGA_DEVICE(0x3185, info),
+
+ INTEL_VGA_DEVICE(0x5906, info), /* ULT GT1 */
+ INTEL_VGA_DEVICE(0x5913, info), /* ULT GT1.5 */
+
+ INTEL_VGA_DEVICE(0x590E, info), /* ULX GT1 */
+ INTEL_VGA_DEVICE(0x5915, info), /* ULX GT1.5 */
+
+ INTEL_VGA_DEVICE(0x5902, info), /* DT GT1 */
+ INTEL_VGA_DEVICE(0x5908, info), /* Halo GT1 */
+ INTEL_VGA_DEVICE(0x590B, info), /* Halo GT1 */
+ INTEL_VGA_DEVICE(0x590A, info), /* SRV GT1 */
+
+ INTEL_VGA_DEVICE(0x5916, info), /* ULT GT2 */
+ INTEL_VGA_DEVICE(0x5921, info), /* ULT GT2F */
+
+ INTEL_VGA_DEVICE(0x591E, info), /* ULX GT2 */
+
+ INTEL_VGA_DEVICE(0x5917, info), /* Mobile GT2 */
+ INTEL_VGA_DEVICE(0x5912, info), /* DT GT2 */
+ INTEL_VGA_DEVICE(0x591B, info), /* Halo GT2 */
+ INTEL_VGA_DEVICE(0x591A, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x591D, info), /* WKS GT2 */
+
+ INTEL_VGA_DEVICE(0x5926, info), /* ULT GT3 */
+
+ INTEL_VGA_DEVICE(0x5923, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x5927, info), /* ULT GT3 */
+
+ INTEL_VGA_DEVICE(0x593B, info), /* Halo GT4 */
+
+ INTEL_VGA_DEVICE(0x591C, info), /* ULX GT2 */
+ INTEL_VGA_DEVICE(0x87C0, info), /* ULX GT2 */
+
+ INTEL_VGA_DEVICE(0x87CA, info),
+
+ INTEL_VGA_DEVICE(0x9B21, info),
+ INTEL_VGA_DEVICE(0x9BAA, info),
+ INTEL_VGA_DEVICE(0x9BAB, info),
+ INTEL_VGA_DEVICE(0x9BAC, info),
+ INTEL_VGA_DEVICE(0x9BA0, info),
+ INTEL_VGA_DEVICE(0x9BA5, info),
+ INTEL_VGA_DEVICE(0x9BA8, info),
+ INTEL_VGA_DEVICE(0x9BA4, info),
+ INTEL_VGA_DEVICE(0x9BA2, info),
+
+ INTEL_VGA_DEVICE(0x9B41, info),
+ INTEL_VGA_DEVICE(0x9BCA, info),
+ INTEL_VGA_DEVICE(0x9BCB, info),
+ INTEL_VGA_DEVICE(0x9BCC, info),
+ INTEL_VGA_DEVICE(0x9BC0, info),
+ INTEL_VGA_DEVICE(0x9BC5, info),
+ INTEL_VGA_DEVICE(0x9BC8, info),
+ INTEL_VGA_DEVICE(0x9BC4, info),
+ INTEL_VGA_DEVICE(0x9BC2, info),
+ INTEL_VGA_DEVICE(0x9BC6, info),
+ INTEL_VGA_DEVICE(0x9BE6, info),
+ INTEL_VGA_DEVICE(0x9BF6, info),
+
+ INTEL_VGA_DEVICE(0x3E90, info), /* SRV GT1 */
+ INTEL_VGA_DEVICE(0x3E93, info), /* SRV GT1 */
+ INTEL_VGA_DEVICE(0x3E99, info), /* SRV GT1 */
+
+ INTEL_VGA_DEVICE(0x3E91, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x3E92, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x3E96, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x3E98, info), /* SRV GT2 */
+ INTEL_VGA_DEVICE(0x3E9A, info), /* SRV GT2 */
+
+ INTEL_VGA_DEVICE(0x3E9C, info),
+
+ INTEL_VGA_DEVICE(0x3E9B, info), /* Halo GT2 */
+ INTEL_VGA_DEVICE(0x3E94, info), /* Halo GT2 */
+
+ INTEL_VGA_DEVICE(0x3EA9, info),
+
+ INTEL_VGA_DEVICE(0x3EA5, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x3EA6, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x3EA7, info), /* ULT GT3 */
+ INTEL_VGA_DEVICE(0x3EA8, info), /* ULT GT3 */
+
+ INTEL_VGA_DEVICE(0x3EA1, info),
+ INTEL_VGA_DEVICE(0x3EA4, info),
+
+ INTEL_VGA_DEVICE(0x3EA0, info),
+ INTEL_VGA_DEVICE(0x3EA3, info),
+
+ INTEL_VGA_DEVICE(0x3EA2, info),
+};
+
+static int is_platform_gen9(void)
+{
+ const char * const id_file =
+ "/sys/bus/pci/drivers/i915/0000:00:02.0/device";
+ char idstr[32] = {0, };
+ uint32_t id = 0;
+ int fd, ret, i;
+
+ fd = open(id_file, O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ ret = read(fd, idstr, 6);
+ if (ret != 6)
+ return -1;
+
+ close(fd);
+
+ idstr[6] = 0;
+
+ id = strtol(idstr, NULL, 16);
+
+ for (i = 0; i < sizeof(gen9_ids)/sizeof(uint32_t); i++)
+ if (id == gen9_ids[i])
+ return 1;
+
+ return 0;
+}
+
+static int is_fd_safe(const int fd)
+{
+ int parser_version = -1;
+ int write_block = 0;
+
+ parser_version = cmd_parser_version(fd);
+ printf(" Command parser version: %d\n", parser_version);
+ if (parser_version >= 10) {
+ printf(" Command parsing for blt engine supported\n");
+ } else if (!CHECK_WRITE_BLOCK_WITHOUT_PARSER) {
+ printf(" There is no blitter command parser\n");
+ return 0;
+ }
+
+ write_block = is_write_blocked(fd);
+
+ printf(" Unsafe write %s\n", write_block ? "blocked" : "possible!");
+
+ return write_block;
+}
+
+struct stats {
+ int checked;
+ int safe;
+ int failed;
+};
+
+static void check_path(const char *path, struct stats *stats)
+{
+ int fd;
+ int is_safe;
+
+ fd = open(path, O_RDWR);
+ if (fd == -1) {
+ if (errno != ENOENT) {
+ printf("Opening %s failed with %s (%d)\n",
+ path, strerror(errno), errno);
+ stats->failed++;
+ }
+
+ return;
+ }
+
+ if (!is_driver_i915(fd)) {
+ close(fd);
+ return;
+ }
+
+ printf("Checking %s:\n", path);
+
+ is_safe = is_fd_safe(fd);
+ printf(" Device %s : %s\n\n", path, is_safe ? "SAFE" : "VULNERABLE");
+ if (is_safe)
+ stats->safe++;
+
+ stats->checked++;
+
+ close (fd);
+}
+
+static int check_devices(void)
+{
+ const char * const cardbase = "/dev/dri/card";
+ const char * const renderbase = "/dev/dri/renderD";
+ char path[256];
+ int i;
+ struct stats s = { 0, 0, 0 };
+
+ for (i = 0; i < 16; i++) {
+ sprintf(path, "%s%d", cardbase, i);
+ check_path(path, &s);
+
+ sprintf(path, "%s%d", renderbase, i + 128);
+ check_path(path, &s);
+ }
+
+ if (s.failed && !s.checked) {
+ printf("Failed to open devices, need root?\n");
+ return -1;
+ }
+
+ if (!s.checked) {
+ printf ("Didn't find anything to check\n");
+ return -1;
+ }
+
+ return s.checked == s.safe;
+}
+
+int main(int argc, char *argv[])
+{
+ int safe = 0;
+ int ret;
+
+ printf("Intel cve-2019-0155 (blt mmio vulnerability) checker version %d\n\n", VERSION);
+
+ sync();
+
+ ret = is_platform_gen9();
+ if (ret == 0) {
+ safe = 1;
+ printf("Your platform is not affected\n");
+ } else if (ret == -1) {
+ printf("Unable to determine platform type\n");
+ }
+
+ if (safe != 1)
+ safe = check_devices();
+
+ if (safe < 0) {
+ printf("Unable to determine system state due to errors\n");
+ return EXIT_FAILURE;
+ }
+
+ printf("\nYour system is %s against cve-2019-0155\n", safe ? "SAFE" : "VULNERABLE");
+
+ return safe ? EXIT_SUCCESS : EXIT_FAILURE;
+}
new file mode 100644
@@ -0,0 +1,12 @@
+cve_progs = [
+ 'cve-2019-0155',
+]
+
+cvedir = join_paths(libexecdir, 'cve')
+
+foreach prog : cve_progs
+ executable(prog, prog + '.c',
+ install : true,
+ install_dir : cvedir,
+ dependencies : igt_deps)
+endforeach
@@ -302,6 +302,7 @@ if libdrm_intel.found()
endif
subdir('overlay')
subdir('man')
+subdir('cve')
gtk_doc = dependency('gtk-doc', required : build_docs)
python3 = find_program('python3', required : build_docs)
Add vulnerability checker for cve-2019-0155 v2: sync, bailout early if no parser (Chris) Cc: Chris Wilson <chris@chris-wilson.co.uk> Cc: Jon Bloomfield <jon.bloomfield@intel.com> Cc: Joonas Lahtinen <joonas.lahtinen@intel.com> References: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-0155 References: https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00242.html Signed-off-by: Mika Kuoppala <mika.kuoppala@linux.intel.com> --- Makefile.am | 2 +- configure.ac | 1 + cve/Makefile.am | 14 ++ cve/Makefile.sources | 5 + cve/cve-2019-0155.c | 470 +++++++++++++++++++++++++++++++++++++++++++ cve/meson.build | 12 ++ meson.build | 1 + 7 files changed, 504 insertions(+), 1 deletion(-) create mode 100644 cve/Makefile.am create mode 100644 cve/Makefile.sources create mode 100644 cve/cve-2019-0155.c create mode 100644 cve/meson.build