1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2015-2018 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#undef _FILE_OFFSET_BITS /* prevent #define open open64 */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include <string.h> 27bf215546Sopenharmony_ci#include <stdlib.h> 28bf215546Sopenharmony_ci#include <stdio.h> 29bf215546Sopenharmony_ci#include <stdint.h> 30bf215546Sopenharmony_ci#include <stdarg.h> 31bf215546Sopenharmony_ci#include <fcntl.h> 32bf215546Sopenharmony_ci#include <unistd.h> 33bf215546Sopenharmony_ci#include <sys/ioctl.h> 34bf215546Sopenharmony_ci#include <sys/stat.h> 35bf215546Sopenharmony_ci#include <sys/mman.h> 36bf215546Sopenharmony_ci#include <sys/sysmacros.h> 37bf215546Sopenharmony_ci#include <dlfcn.h> 38bf215546Sopenharmony_ci#include <pthread.h> 39bf215546Sopenharmony_ci#include "drm-uapi/i915_drm.h" 40bf215546Sopenharmony_ci 41bf215546Sopenharmony_ci#include "util/hash_table.h" 42bf215546Sopenharmony_ci#include "util/u_math.h" 43bf215546Sopenharmony_ci 44bf215546Sopenharmony_ci#define MESA_LOG_TAG "INTEL-SANITIZE-GPU" 45bf215546Sopenharmony_ci#include "util/log.h" 46bf215546Sopenharmony_ci#include "common/intel_clflush.h" 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_cistatic int (*libc_open)(const char *pathname, int flags, mode_t mode); 49bf215546Sopenharmony_cistatic int (*libc_close)(int fd); 50bf215546Sopenharmony_cistatic int (*libc_ioctl)(int fd, unsigned long request, void *argp); 51bf215546Sopenharmony_cistatic int (*libc_fcntl)(int fd, int cmd, int param); 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_ci#define DRM_MAJOR 226 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/* TODO: we want to make sure that the padding forces 56bf215546Sopenharmony_ci * the BO to take another page on the (PP)GTT; 4KB 57bf215546Sopenharmony_ci * may or may not be the page size for the BO. Indeed, 58bf215546Sopenharmony_ci * depending on GPU, kernel version and GEM size, the 59bf215546Sopenharmony_ci * page size can be one of 4KB, 64KB or 2M. 60bf215546Sopenharmony_ci */ 61bf215546Sopenharmony_ci#define PADDING_SIZE 4096 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_cistruct refcnt_hash_table { 64bf215546Sopenharmony_ci struct hash_table *t; 65bf215546Sopenharmony_ci int refcnt; 66bf215546Sopenharmony_ci}; 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cipthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 69bf215546Sopenharmony_ci#define MUTEX_LOCK() do { \ 70bf215546Sopenharmony_ci if (unlikely(pthread_mutex_lock(&mutex))) { \ 71bf215546Sopenharmony_ci mesa_loge("mutex_lock failed"); \ 72bf215546Sopenharmony_ci abort(); \ 73bf215546Sopenharmony_ci } \ 74bf215546Sopenharmony_ci} while (0) 75bf215546Sopenharmony_ci#define MUTEX_UNLOCK() do { \ 76bf215546Sopenharmony_ci if (unlikely(pthread_mutex_unlock(&mutex))) { \ 77bf215546Sopenharmony_ci mesa_loge("mutex_unlock failed"); \ 78bf215546Sopenharmony_ci abort(); \ 79bf215546Sopenharmony_ci } \ 80bf215546Sopenharmony_ci} while (0) 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_cistatic struct hash_table *fds_to_bo_sizes = NULL; 83bf215546Sopenharmony_ci 84bf215546Sopenharmony_cistatic inline struct hash_table* 85bf215546Sopenharmony_cibo_size_table(int fd) 86bf215546Sopenharmony_ci{ 87bf215546Sopenharmony_ci struct hash_entry *e = _mesa_hash_table_search(fds_to_bo_sizes, 88bf215546Sopenharmony_ci (void*)(uintptr_t)fd); 89bf215546Sopenharmony_ci return e ? ((struct refcnt_hash_table*)e->data)->t : NULL; 90bf215546Sopenharmony_ci} 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_cistatic inline uint64_t 93bf215546Sopenharmony_cibo_size(int fd, uint32_t handle) 94bf215546Sopenharmony_ci{ 95bf215546Sopenharmony_ci struct hash_table *t = bo_size_table(fd); 96bf215546Sopenharmony_ci if (!t) 97bf215546Sopenharmony_ci return UINT64_MAX; 98bf215546Sopenharmony_ci struct hash_entry *e = _mesa_hash_table_search(t, (void*)(uintptr_t)handle); 99bf215546Sopenharmony_ci return e ? (uint64_t)(uintptr_t)e->data : UINT64_MAX; 100bf215546Sopenharmony_ci} 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_cistatic inline bool 103bf215546Sopenharmony_ciis_drm_fd(int fd) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci return !!bo_size_table(fd); 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_cistatic inline void 109bf215546Sopenharmony_ciadd_drm_fd(int fd) 110bf215546Sopenharmony_ci{ 111bf215546Sopenharmony_ci struct refcnt_hash_table *r = malloc(sizeof(*r)); 112bf215546Sopenharmony_ci r->refcnt = 1; 113bf215546Sopenharmony_ci r->t = _mesa_pointer_hash_table_create(NULL); 114bf215546Sopenharmony_ci _mesa_hash_table_insert(fds_to_bo_sizes, (void*)(uintptr_t)fd, 115bf215546Sopenharmony_ci (void*)(uintptr_t)r); 116bf215546Sopenharmony_ci} 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_cistatic inline void 119bf215546Sopenharmony_cidup_drm_fd(int old_fd, int new_fd) 120bf215546Sopenharmony_ci{ 121bf215546Sopenharmony_ci struct hash_entry *e = _mesa_hash_table_search(fds_to_bo_sizes, 122bf215546Sopenharmony_ci (void*)(uintptr_t)old_fd); 123bf215546Sopenharmony_ci struct refcnt_hash_table *r = e->data; 124bf215546Sopenharmony_ci r->refcnt++; 125bf215546Sopenharmony_ci _mesa_hash_table_insert(fds_to_bo_sizes, (void*)(uintptr_t)new_fd, 126bf215546Sopenharmony_ci (void*)(uintptr_t)r); 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_cistatic inline void 130bf215546Sopenharmony_cidel_drm_fd(int fd) 131bf215546Sopenharmony_ci{ 132bf215546Sopenharmony_ci struct hash_entry *e = _mesa_hash_table_search(fds_to_bo_sizes, 133bf215546Sopenharmony_ci (void*)(uintptr_t)fd); 134bf215546Sopenharmony_ci struct refcnt_hash_table *r = e->data; 135bf215546Sopenharmony_ci if (!--r->refcnt) { 136bf215546Sopenharmony_ci _mesa_hash_table_remove(fds_to_bo_sizes, e); 137bf215546Sopenharmony_ci _mesa_hash_table_destroy(r->t, NULL); 138bf215546Sopenharmony_ci free(r); 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci} 141bf215546Sopenharmony_ci 142bf215546Sopenharmony_ci/* Our goal is not to have noise good enough for crypto, 143bf215546Sopenharmony_ci * but instead values that are unique-ish enough that 144bf215546Sopenharmony_ci * it is incredibly unlikely that a buffer overwrite 145bf215546Sopenharmony_ci * will produce the exact same values. 146bf215546Sopenharmony_ci */ 147bf215546Sopenharmony_cistatic uint8_t 148bf215546Sopenharmony_cinext_noise_value(uint8_t prev_noise) 149bf215546Sopenharmony_ci{ 150bf215546Sopenharmony_ci uint32_t v = prev_noise; 151bf215546Sopenharmony_ci return (v * 103u + 227u) & 0xFF; 152bf215546Sopenharmony_ci} 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_cistatic void 155bf215546Sopenharmony_cifill_noise_buffer(uint8_t *dst, uint8_t start, uint32_t length) 156bf215546Sopenharmony_ci{ 157bf215546Sopenharmony_ci for(uint32_t i = 0; i < length; ++i) { 158bf215546Sopenharmony_ci dst[i] = start; 159bf215546Sopenharmony_ci start = next_noise_value(start); 160bf215546Sopenharmony_ci } 161bf215546Sopenharmony_ci} 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_cistatic bool 164bf215546Sopenharmony_cipadding_is_good(int fd, uint32_t handle) 165bf215546Sopenharmony_ci{ 166bf215546Sopenharmony_ci struct drm_i915_gem_mmap mmap_arg = { 167bf215546Sopenharmony_ci .handle = handle, 168bf215546Sopenharmony_ci .offset = align64(bo_size(fd, handle), 4096), 169bf215546Sopenharmony_ci .size = PADDING_SIZE, 170bf215546Sopenharmony_ci .flags = 0, 171bf215546Sopenharmony_ci }; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci /* Unknown bo, maybe prime or userptr. Ignore */ 174bf215546Sopenharmony_ci if (mmap_arg.offset == UINT64_MAX) 175bf215546Sopenharmony_ci return true; 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci uint8_t *mapped; 178bf215546Sopenharmony_ci int ret; 179bf215546Sopenharmony_ci uint8_t expected_value; 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci ret = libc_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg); 182bf215546Sopenharmony_ci if (ret != 0) { 183bf215546Sopenharmony_ci mesa_logd("Unable to map buffer %d for pad checking.", handle); 184bf215546Sopenharmony_ci return false; 185bf215546Sopenharmony_ci } 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci mapped = (uint8_t*) (uintptr_t) mmap_arg.addr_ptr; 188bf215546Sopenharmony_ci /* bah-humbug, we need to see the latest contents and 189bf215546Sopenharmony_ci * if the bo is not cache coherent we likely need to 190bf215546Sopenharmony_ci * invalidate the cache lines to get it. 191bf215546Sopenharmony_ci */ 192bf215546Sopenharmony_ci intel_invalidate_range(mapped, PADDING_SIZE); 193bf215546Sopenharmony_ci 194bf215546Sopenharmony_ci expected_value = handle & 0xFF; 195bf215546Sopenharmony_ci for (uint32_t i = 0; i < PADDING_SIZE; ++i) { 196bf215546Sopenharmony_ci if (expected_value != mapped[i]) { 197bf215546Sopenharmony_ci munmap(mapped, PADDING_SIZE); 198bf215546Sopenharmony_ci return false; 199bf215546Sopenharmony_ci } 200bf215546Sopenharmony_ci expected_value = next_noise_value(expected_value); 201bf215546Sopenharmony_ci } 202bf215546Sopenharmony_ci munmap(mapped, PADDING_SIZE); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci return true; 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_cistatic int 208bf215546Sopenharmony_cicreate_with_padding(int fd, struct drm_i915_gem_create *create) 209bf215546Sopenharmony_ci{ 210bf215546Sopenharmony_ci uint64_t original_size = create->size; 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ci create->size = align64(original_size, 4096) + PADDING_SIZE; 213bf215546Sopenharmony_ci int ret = libc_ioctl(fd, DRM_IOCTL_I915_GEM_CREATE, create); 214bf215546Sopenharmony_ci create->size = original_size; 215bf215546Sopenharmony_ci 216bf215546Sopenharmony_ci if (ret != 0) 217bf215546Sopenharmony_ci return ret; 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci uint8_t *noise_values; 220bf215546Sopenharmony_ci struct drm_i915_gem_mmap mmap_arg = { 221bf215546Sopenharmony_ci .handle = create->handle, 222bf215546Sopenharmony_ci .offset = align64(create->size, 4096), 223bf215546Sopenharmony_ci .size = PADDING_SIZE, 224bf215546Sopenharmony_ci .flags = 0, 225bf215546Sopenharmony_ci }; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci ret = libc_ioctl(fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg); 228bf215546Sopenharmony_ci if (ret != 0) { 229bf215546Sopenharmony_ci mesa_logd("Unable to map buffer %d for pad creation.\n", create->handle); 230bf215546Sopenharmony_ci return 0; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci 233bf215546Sopenharmony_ci noise_values = (uint8_t*) (uintptr_t) mmap_arg.addr_ptr; 234bf215546Sopenharmony_ci fill_noise_buffer(noise_values, create->handle & 0xFF, 235bf215546Sopenharmony_ci PADDING_SIZE); 236bf215546Sopenharmony_ci munmap(noise_values, PADDING_SIZE); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci _mesa_hash_table_insert(bo_size_table(fd), (void*)(uintptr_t)create->handle, 239bf215546Sopenharmony_ci (void*)(uintptr_t)create->size); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci return 0; 242bf215546Sopenharmony_ci} 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_cistatic int 245bf215546Sopenharmony_ciexec_and_check_padding(int fd, unsigned long request, 246bf215546Sopenharmony_ci struct drm_i915_gem_execbuffer2 *exec) 247bf215546Sopenharmony_ci{ 248bf215546Sopenharmony_ci int ret = libc_ioctl(fd, request, exec); 249bf215546Sopenharmony_ci if (ret != 0) 250bf215546Sopenharmony_ci return ret; 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci struct drm_i915_gem_exec_object2 *objects = 253bf215546Sopenharmony_ci (void*)(uintptr_t)exec->buffers_ptr; 254bf215546Sopenharmony_ci uint32_t batch_bo = exec->flags & I915_EXEC_BATCH_FIRST ? objects[0].handle : 255bf215546Sopenharmony_ci objects[exec->buffer_count - 1].handle; 256bf215546Sopenharmony_ci 257bf215546Sopenharmony_ci struct drm_i915_gem_wait wait = { 258bf215546Sopenharmony_ci .bo_handle = batch_bo, 259bf215546Sopenharmony_ci .timeout_ns = -1, 260bf215546Sopenharmony_ci }; 261bf215546Sopenharmony_ci ret = libc_ioctl(fd, DRM_IOCTL_I915_GEM_WAIT, &wait); 262bf215546Sopenharmony_ci if (ret != 0) 263bf215546Sopenharmony_ci return ret; 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci bool detected_out_of_bounds_write = false; 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci for (int i = 0; i < exec->buffer_count; i++) { 268bf215546Sopenharmony_ci uint32_t handle = objects[i].handle; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci if (!padding_is_good(fd, handle)) { 271bf215546Sopenharmony_ci detected_out_of_bounds_write = true; 272bf215546Sopenharmony_ci mesa_loge("Detected buffer out-of-bounds write in bo %d", handle); 273bf215546Sopenharmony_ci } 274bf215546Sopenharmony_ci } 275bf215546Sopenharmony_ci 276bf215546Sopenharmony_ci if (unlikely(detected_out_of_bounds_write)) { 277bf215546Sopenharmony_ci abort(); 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci return 0; 281bf215546Sopenharmony_ci} 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_cistatic int 284bf215546Sopenharmony_cigem_close(int fd, struct drm_gem_close *close) 285bf215546Sopenharmony_ci{ 286bf215546Sopenharmony_ci int ret = libc_ioctl(fd, DRM_IOCTL_GEM_CLOSE, close); 287bf215546Sopenharmony_ci if (ret != 0) 288bf215546Sopenharmony_ci return ret; 289bf215546Sopenharmony_ci 290bf215546Sopenharmony_ci struct hash_table *t = bo_size_table(fd); 291bf215546Sopenharmony_ci struct hash_entry *e = 292bf215546Sopenharmony_ci _mesa_hash_table_search(t, (void*)(uintptr_t)close->handle); 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (e) 295bf215546Sopenharmony_ci _mesa_hash_table_remove(t, e); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci return 0; 298bf215546Sopenharmony_ci} 299bf215546Sopenharmony_ci 300bf215546Sopenharmony_cistatic bool 301bf215546Sopenharmony_ciis_i915(int fd) { 302bf215546Sopenharmony_ci struct stat stat; 303bf215546Sopenharmony_ci if (fstat(fd, &stat)) 304bf215546Sopenharmony_ci return false; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci if (!S_ISCHR(stat.st_mode) || major(stat.st_rdev) != DRM_MAJOR) 307bf215546Sopenharmony_ci return false; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci char name[5] = ""; 310bf215546Sopenharmony_ci drm_version_t version = { 311bf215546Sopenharmony_ci .name = name, 312bf215546Sopenharmony_ci .name_len = sizeof(name) - 1, 313bf215546Sopenharmony_ci }; 314bf215546Sopenharmony_ci if (libc_ioctl(fd, DRM_IOCTL_VERSION, &version)) 315bf215546Sopenharmony_ci return false; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci return strcmp("i915", name) == 0; 318bf215546Sopenharmony_ci} 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int 321bf215546Sopenharmony_ciopen(const char *path, int flags, ...) 322bf215546Sopenharmony_ci{ 323bf215546Sopenharmony_ci va_list args; 324bf215546Sopenharmony_ci mode_t mode; 325bf215546Sopenharmony_ci 326bf215546Sopenharmony_ci va_start(args, flags); 327bf215546Sopenharmony_ci mode = va_arg(args, int); 328bf215546Sopenharmony_ci va_end(args); 329bf215546Sopenharmony_ci 330bf215546Sopenharmony_ci int fd = libc_open(path, flags, mode); 331bf215546Sopenharmony_ci 332bf215546Sopenharmony_ci MUTEX_LOCK(); 333bf215546Sopenharmony_ci 334bf215546Sopenharmony_ci if (fd >= 0 && is_i915(fd)) 335bf215546Sopenharmony_ci add_drm_fd(fd); 336bf215546Sopenharmony_ci 337bf215546Sopenharmony_ci MUTEX_UNLOCK(); 338bf215546Sopenharmony_ci 339bf215546Sopenharmony_ci return fd; 340bf215546Sopenharmony_ci} 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci__attribute__ ((visibility ("default"), alias ("open"))) int 343bf215546Sopenharmony_ciopen64(const char *path, int flags, ...); 344bf215546Sopenharmony_ci 345bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int 346bf215546Sopenharmony_ciclose(int fd) 347bf215546Sopenharmony_ci{ 348bf215546Sopenharmony_ci MUTEX_LOCK(); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci if (is_drm_fd(fd)) 351bf215546Sopenharmony_ci del_drm_fd(fd); 352bf215546Sopenharmony_ci 353bf215546Sopenharmony_ci MUTEX_UNLOCK(); 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci return libc_close(fd); 356bf215546Sopenharmony_ci} 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int 359bf215546Sopenharmony_cifcntl(int fd, int cmd, ...) 360bf215546Sopenharmony_ci{ 361bf215546Sopenharmony_ci va_list args; 362bf215546Sopenharmony_ci int param; 363bf215546Sopenharmony_ci 364bf215546Sopenharmony_ci va_start(args, cmd); 365bf215546Sopenharmony_ci param = va_arg(args, int); 366bf215546Sopenharmony_ci va_end(args); 367bf215546Sopenharmony_ci 368bf215546Sopenharmony_ci int res = libc_fcntl(fd, cmd, param); 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci MUTEX_LOCK(); 371bf215546Sopenharmony_ci 372bf215546Sopenharmony_ci if (is_drm_fd(fd) && cmd == F_DUPFD_CLOEXEC) 373bf215546Sopenharmony_ci dup_drm_fd(fd, res); 374bf215546Sopenharmony_ci 375bf215546Sopenharmony_ci MUTEX_UNLOCK(); 376bf215546Sopenharmony_ci 377bf215546Sopenharmony_ci return res; 378bf215546Sopenharmony_ci} 379bf215546Sopenharmony_ci 380bf215546Sopenharmony_ci__attribute__ ((visibility ("default"))) int 381bf215546Sopenharmony_ciioctl(int fd, unsigned long request, ...) 382bf215546Sopenharmony_ci{ 383bf215546Sopenharmony_ci int res; 384bf215546Sopenharmony_ci va_list args; 385bf215546Sopenharmony_ci void *argp; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci MUTEX_LOCK(); 388bf215546Sopenharmony_ci 389bf215546Sopenharmony_ci va_start(args, request); 390bf215546Sopenharmony_ci argp = va_arg(args, void *); 391bf215546Sopenharmony_ci va_end(args); 392bf215546Sopenharmony_ci 393bf215546Sopenharmony_ci if (_IOC_TYPE(request) == DRM_IOCTL_BASE && !is_drm_fd(fd) && is_i915(fd)) { 394bf215546Sopenharmony_ci mesa_loge("missed drm fd %d", fd); 395bf215546Sopenharmony_ci add_drm_fd(fd); 396bf215546Sopenharmony_ci } 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci if (is_drm_fd(fd)) { 399bf215546Sopenharmony_ci switch (request) { 400bf215546Sopenharmony_ci case DRM_IOCTL_GEM_CLOSE: 401bf215546Sopenharmony_ci res = gem_close(fd, (struct drm_gem_close*)argp); 402bf215546Sopenharmony_ci goto out; 403bf215546Sopenharmony_ci 404bf215546Sopenharmony_ci case DRM_IOCTL_I915_GEM_CREATE: 405bf215546Sopenharmony_ci res = create_with_padding(fd, (struct drm_i915_gem_create*)argp); 406bf215546Sopenharmony_ci goto out; 407bf215546Sopenharmony_ci 408bf215546Sopenharmony_ci case DRM_IOCTL_I915_GEM_EXECBUFFER2: 409bf215546Sopenharmony_ci case DRM_IOCTL_I915_GEM_EXECBUFFER2_WR: 410bf215546Sopenharmony_ci res = exec_and_check_padding(fd, request, 411bf215546Sopenharmony_ci (struct drm_i915_gem_execbuffer2*)argp); 412bf215546Sopenharmony_ci goto out; 413bf215546Sopenharmony_ci 414bf215546Sopenharmony_ci default: 415bf215546Sopenharmony_ci break; 416bf215546Sopenharmony_ci } 417bf215546Sopenharmony_ci } 418bf215546Sopenharmony_ci res = libc_ioctl(fd, request, argp); 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci out: 421bf215546Sopenharmony_ci MUTEX_UNLOCK(); 422bf215546Sopenharmony_ci return res; 423bf215546Sopenharmony_ci} 424bf215546Sopenharmony_ci 425bf215546Sopenharmony_cistatic void __attribute__ ((constructor)) 426bf215546Sopenharmony_ciinit(void) 427bf215546Sopenharmony_ci{ 428bf215546Sopenharmony_ci fds_to_bo_sizes = _mesa_pointer_hash_table_create(NULL); 429bf215546Sopenharmony_ci libc_open = dlsym(RTLD_NEXT, "open"); 430bf215546Sopenharmony_ci libc_close = dlsym(RTLD_NEXT, "close"); 431bf215546Sopenharmony_ci libc_fcntl = dlsym(RTLD_NEXT, "fcntl"); 432bf215546Sopenharmony_ci libc_ioctl = dlsym(RTLD_NEXT, "ioctl"); 433bf215546Sopenharmony_ci} 434