From patchwork Fri Mar 15 18:09:07 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Kees Cook X-Patchwork-Id: 2279901 Return-Path: X-Original-To: patchwork-intel-gfx@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork2.kernel.org (Postfix) with ESMTP id 5C8D7DF24C for ; Fri, 15 Mar 2013 18:09:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 56EAFE5FE5 for ; Fri, 15 Mar 2013 11:09:25 -0700 (PDT) X-Original-To: intel-gfx@lists.freedesktop.org Delivered-To: intel-gfx@lists.freedesktop.org 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) Received: from www.outflux.net (serenity-end.outflux.net [10.2.0.2]) by vinyl.outflux.net (8.14.4/8.14.4/Debian-2ubuntu2) with ESMTP id r2FI97rw015726; Fri, 15 Mar 2013 11:09:07 -0700 Date: Fri, 15 Mar 2013 11:09:07 -0700 From: Kees Cook To: damien.lespiau@intel.com Message-ID: <20130315180907.GA9231@www.outflux.net> MIME-Version: 1.0 Content-Disposition: inline X-MIMEDefang-Filter: outflux$Revision: 1.316 $ X-HELO: www.outflux.net X-Scanned-By: MIMEDefang 2.71 on 10.2.0.1 Cc: intel-gfx@lists.freedesktop.org Subject: [Intel-gfx] [PATCH] tests: add gem_reloc_overflow to check wrapping X-BeenThere: intel-gfx@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Intel graphics driver community testing & development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@lists.freedesktop.org Errors-To: intel-gfx-bounces+patchwork-intel-gfx=patchwork.kernel.org@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 = \ 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 © 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 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. + * + * 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 = 0; + unsigned int total_unsigned = 0; + int total_signed = 0; + uint32_t *handles; + struct drm_i915_gem_relocation_entry *reloc; + struct drm_i915_gem_exec_object2 *execobjs; + struct drm_i915_gem_execbuffer2 execbuf = { 0 }; + + fd = drm_open_any(); + + /* Create giant reloc buffer area. */ + num = 257; + entries = ((1ULL << 32) / (num - 1)); + reloc_size = entries * sizeof(struct drm_i915_gem_relocation_entry); + reloc = mmap(NULL, reloc_size, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (reloc == MAP_FAILED) { + perror("mmap"); + return errno; + } + + /* Allocate the handles we'll need to wrap. */ + handles = calloc(num, sizeof(*handles)); + for (i = 0; i < num; i++) { + struct drm_i915_gem_create create_args = { 0 }; + create_args.size = 0x1000; + if (ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, &create_args)) { + perror("DRM_IOCTL_I915_GEM_CREATE"); + return errno; + } + handles[i] = create_args.handle; + } + + /* Create relocation objects. */ + execobjs = calloc(num, sizeof(*execobjs)); + execbuf.buffers_ptr = (uintptr_t)execobjs; + + /* Attempt unmapped single entry. */ + execobjs[0].relocation_count = 1; + execobjs[0].relocs_ptr = 0; + execbuf.buffer_count = 1; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno != EFAULT) { + perror("DRM_IOCTL_I915_GEM_EXECBUFFER2, invalid address"); + abort(); + } + + /* Attempt single overflowed entry. */ + execobjs[0].relocation_count = (1 << 31); + execobjs[0].relocs_ptr = (uintptr_t)reloc; + execbuf.buffer_count = 1; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno != EINVAL) { + perror("DRM_IOCTL_I915_GEM_EXECBUFFER2, single overflow"); + abort(); + } + + /* Attempt wrapped overflow entries. */ + for (i = 0; i < num; i++) { + struct drm_i915_gem_exec_object2 *obj = &execobjs[i]; + obj->handle = handles[i]; + + if (i == num - 1) { + /* Wraps to 1 on last count. */ + obj->relocation_count = 1 - total_unsigned; + obj->relocs_ptr = (uintptr_t)reloc; + } else { + obj->relocation_count = entries; + obj->relocs_ptr = (uintptr_t)reloc; + } + + total_unsigned += obj->relocation_count; + total_signed += obj->relocation_count; + total_actual += obj->relocation_count; + } + execbuf.buffer_count = num; + + errno = 0; + ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &execbuf); + if (errno != 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; +}