From mboxrd@z Thu Jan 1 00:00:00 1970 From: Kees Cook Subject: [PATCH] tests: add gem_reloc_overflow to check wrapping Date: Fri, 15 Mar 2013 11:09:07 -0700 Message-ID: <20130315180907.GA9231@www.outflux.net> Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Return-path: Received: from smtp.outflux.net (smtp.outflux.net [198.145.64.163]) by gabe.freedesktop.org (Postfix) with ESMTP id 4BA21E5D16 for ; Fri, 15 Mar 2013 11:09:14 -0700 (PDT) Content-Disposition: inline List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+gcfxdi-intel-gfx=m.gmane.org@lists.freedesktop.org To: damien.lespiau@intel.com Cc: intel-gfx@lists.freedesktop.org List-Id: intel-gfx@lists.freedesktop.org This adds a test to make sure that the execbuffer validation routine is checking for invalid addresses, single entry overflow, and multi-entry wrapping overflow. Signed-off-by: Kees Cook --- tests/.gitignore | 1 + tests/Makefile.am | 1 + tests/gem_reloc_overflow.c | 154 ++++++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 156 insertions(+) create mode 100644 tests/gem_reloc_overflow.c diff --git a/tests/.gitignore b/tests/.gitignore index 7e2d901..fd30412 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -45,6 +45,7 @@ gem_pipe_control_store_loop gem_pread_after_blit gem_pwrite gem_readwrite +gem_reloc_overflow gem_reloc_vs_gpu gem_reg_read gem_render_linear_blits diff --git a/tests/Makefile.am b/tests/Makefile.am index ef68a02..2fddfe8 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -84,6 +84,7 @@ TESTS_progs =3D \ gem_pipe_control_store_loop \ gem_unfence_active_buffers \ gem_unref_active_buffers \ + gem_reloc_overflow \ gem_reloc_vs_gpu \ drm_vma_limiter \ drm_vma_limiter_cpu \ diff --git a/tests/gem_reloc_overflow.c b/tests/gem_reloc_overflow.c new file mode 100644 index 0000000..d666f4f --- /dev/null +++ b/tests/gem_reloc_overflow.c @@ -0,0 +1,154 @@ +/* + * Copyright =A9 2013 Google + * + * 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 limitati= on + * 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 ne= xt + * paragraph) shall be included in all copies or substantial portions of t= he + * 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 OT= HER + * 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 DEA= LINGS + * IN THE SOFTWARE. + * + * Authors: + * Kees Cook + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "drm.h" +#include "i915_drm.h" +#include "drmtest.h" +#include "intel_gpu_tools.h" + +/* + * Testcase: Kernel relocation overflows are caught. + */ + +int main(int argc, char *argv[]) +{ + int fd, i, entries, num; + size_t reloc_size; + size_t total_actual =3D 0; + unsigned int total_unsigned =3D 0; + int total_signed =3D 0; + uint32_t *handles; + struct drm_i915_gem_relocation_entry *reloc; + struct drm_i915_gem_exec_object2 *execobjs; + struct drm_i915_gem_execbuffer2 execbuf =3D { 0 }; + + fd =3D drm_open_any(); + + /* Create giant reloc buffer area. */ + num =3D 257; + entries =3D ((1ULL << 32) / (num - 1)); + reloc_size =3D entries * sizeof(struct drm_i915_gem_relocation_entry); + reloc =3D mmap(NULL, reloc_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (reloc =3D=3D MAP_FAILED) { + perror("mmap"); + return errno; + } + + /* Allocate the handles we'll need to wrap. */ + handles =3D calloc(num, sizeof(*handles)); + for (i =3D 0; i < num; i++) { + struct drm_i915_gem_create create_args =3D { 0 }; + create_args.size =3D 0x1000; + if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create_args)) { + perror("DRM_IOCTL_I915_GEM_CREATE"); + return errno; + } + handles[i] =3D create_args.handle; + } + + /* Create relocation objects. */ + execobjs =3D calloc(num, sizeof(*execobjs)); + execbuf.buffers_ptr =3D (uintptr_t)execobjs; + + /* Attempt unmapped single entry. */ + execobjs[0].relocation_count =3D 1; + execobjs[0].relocs_ptr =3D 0; + execbuf.buffer_count =3D 1; + + errno =3D 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno !=3D EFAULT) { + perror("DRM_IOCTL_I915_GEM_EXECBUFFER2, invalid address"); + abort(); + } + + /* Attempt single overflowed entry. */ + execobjs[0].relocation_count =3D (1 << 31); + execobjs[0].relocs_ptr =3D (uintptr_t)reloc; + execbuf.buffer_count =3D 1; + + errno =3D 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno !=3D EINVAL) { + perror("DRM_IOCTL_I915_GEM_EXECBUFFER2, single overflow"); + abort(); + } + + /* Attempt wrapped overflow entries. */ + for (i =3D 0; i < num; i++) { + struct drm_i915_gem_exec_object2 *obj =3D &execobjs[i]; + obj->handle =3D handles[i]; + + if (i =3D=3D num - 1) { + /* Wraps to 1 on last count. */ + obj->relocation_count =3D 1 - total_unsigned; + obj->relocs_ptr =3D (uintptr_t)reloc; + } else { + obj->relocation_count =3D entries; + obj->relocs_ptr =3D (uintptr_t)reloc; + } + + total_unsigned +=3D obj->relocation_count; + total_signed +=3D obj->relocation_count; + total_actual +=3D obj->relocation_count; + } + execbuf.buffer_count =3D num; + + errno =3D 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno !=3D EINVAL) { + /* ENOENT means we're subject to wrapping overflow since + * processing has continued into validating buffer contents. + */ + perror("DRM_IOCTL_I915_GEM_EXECBUFFER2, wrap overflow"); + abort(); + } + + if (close(fd)) { + perror("close"); + return errno; + } + + return 0; +} -- = 1.7.9.5 -- = Kees Cook Chrome OS Security