[RFC PATCH v1 3/3] tests: add tests for DRM ioctl decoding
Zhibin Li
haoyouab at gmail.com
Mon Jun 3 13:24:35 UTC 2019
* tests/ioctl_drm.c: New file.
* tests/ioctl_drm-success.c: Likewise.
* tests/ioctl_drm-success.tests: New test.
* tests/pure_executables.list : Add ioctl_drm.
* tests/gen_tests.in (ioctl_drm): New entry.
* tests/Makefile.am (check_PROGRAMS): Add ioctl_drm-success.
(DECODER_TESTS): Add ioctl_drm-success.test.
* tests/.gitignore: Add ioctl_drm and ioctl_drm-success.
---
tests/.gitignore | 2 +
tests/Makefile.am | 2 +
tests/gen_tests.in | 1 +
tests/ioctl_drm-success.c | 881 +++++++++++++++++++++++++++++++++++
tests/ioctl_drm-success.test | 18 +
tests/ioctl_drm.c | 90 ++++
tests/pure_executables.list | 1 +
7 files changed, 995 insertions(+)
create mode 100644 tests/ioctl_drm-success.c
create mode 100755 tests/ioctl_drm-success.test
create mode 100644 tests/ioctl_drm.c
diff --git a/tests/.gitignore b/tests/.gitignore
index fb3fa928..a30bdb5b 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -150,6 +150,8 @@ ioctl
ioctl_block
ioctl_dm
ioctl_dm-v
+ioctl_drm
+ioctl_drm-success
ioctl_evdev
ioctl_evdev-success
ioctl_evdev-success-v
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9e99aff2..b63e4e0c 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -97,6 +97,7 @@ check_PROGRAMS = $(PURE_EXECUTABLES) \
inject-nf \
int_0x80 \
ioctl_dm-v \
+ ioctl_drm-success \
ioctl_evdev-success \
ioctl_evdev-success-v \
ioctl_evdev-v \
@@ -234,6 +235,7 @@ DECODER_TESTS = \
getuid.test \
int_0x80.test \
ioctl.test \
+ ioctl_drm-success.test \
ioctl_evdev-success-v.test \
ioctl_evdev-success.test \
ioctl_perf-success.test \
diff --git a/tests/gen_tests.in b/tests/gen_tests.in
index 487b9608..9d22ca47 100644
--- a/tests/gen_tests.in
+++ b/tests/gen_tests.in
@@ -124,6 +124,7 @@ io_uring_setup -a26 -y
ioctl_block +ioctl.test
ioctl_dm +ioctl.test -s9
ioctl_dm-v +ioctl.test -v -s9
+ioctl_drm +ioctl.test
ioctl_evdev +ioctl.test
ioctl_evdev-v +ioctl.test -v
ioctl_inotify +ioctl.test
diff --git a/tests/ioctl_drm-success.c b/tests/ioctl_drm-success.c
new file mode 100644
index 00000000..8e88bb10
--- /dev/null
+++ b/tests/ioctl_drm-success.c
@@ -0,0 +1,881 @@
+#include "tests.h"
+
+#if defined(HAVE_DRM_H) || defined(HAVE_DRM_DRM_H)
+
+# include <errno.h>
+# include <inttypes.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/ioctl.h>
+# include "print_fields.h"
+
+# ifdef HAVE_DRM_H
+# include <drm.h>
+# else
+# include <drm/drm.h>
+# endif
+
+static const char *errstr;
+
+struct drm_check {
+ unsigned long cmd;
+ const char *cmd_str;
+ void *arg_ptr;
+ void (*print_arg)(long rc, void *ptr, void *arg);
+};
+
+struct drm_mode_rm_fb_wrap {
+ unsigned int fb_id;
+};
+
+static long
+invoke_test_syscall(unsigned long cmd, void *p)
+{
+ long rc = ioctl(-1, cmd, p);
+ errstr = sprintrc(rc);
+ static char inj_errstr[4096];
+
+ snprintf(inj_errstr, sizeof(inj_errstr), "%s (INJECTED)", errstr);
+ errstr = inj_errstr;
+ return rc;
+}
+
+static void
+test_drm(struct drm_check *check, void *arg)
+{
+
+ long rc = invoke_test_syscall(check->cmd, check->arg_ptr);
+ printf("ioctl(-1, %s, ", check->cmd_str);
+ if (check->print_arg)
+ check->print_arg(rc, check->arg_ptr, arg);
+ else
+ printf("%p", check->arg_ptr);
+ printf(") = %s\n", errstr);
+}
+
+static void
+print_drm_version(long rc, void *ptr, void *arg)
+{
+ struct drm_version *ver = ptr;
+
+ if (rc < 0) {
+ printf("%p", ver);
+ return;
+ }
+ PRINT_FIELD_U("{", *ver, version_major);
+ PRINT_FIELD_U(", ", *ver, version_minor);
+ PRINT_FIELD_U(", ", *ver, version_patchlevel);
+ PRINT_FIELD_U(", ", *ver, name_len);
+ printf(", name=\"%s\"", ver->name);
+ PRINT_FIELD_U(", ", *ver, date_len);
+ printf(", date=\"%s\"", ver->date);
+ PRINT_FIELD_U(", ", *ver, desc_len);
+ printf(", desc=\"%s\"", ver->desc);
+ printf("}");
+}
+
+static void
+print_drm_set_version(long rc, void *ptr, void *arg)
+{
+ struct drm_set_version *ver = ptr;
+
+ if (rc < 0) {
+ printf("%p", ver);
+ return;
+ }
+ PRINT_FIELD_D("write:{", *ver, drm_di_major);
+ PRINT_FIELD_D(", ", *ver, drm_di_minor);
+ PRINT_FIELD_D(", ", *ver, drm_dd_major);
+ PRINT_FIELD_D(", ", *ver, drm_dd_minor);
+ printf("}");
+ PRINT_FIELD_D(", read:{", *ver, drm_di_major);
+ PRINT_FIELD_D(", ", *ver, drm_di_minor);
+ PRINT_FIELD_D(", ", *ver, drm_dd_major);
+ PRINT_FIELD_D(", ", *ver, drm_dd_minor);
+ printf("}");
+
+}
+
+static void
+print_drm_get_unique(long rc, void *ptr, void *arg)
+{
+ struct drm_unique *unique = ptr;
+
+ if (rc < 0) {
+ printf("%p", unique);
+ return;
+ }
+ PRINT_FIELD_U("{", *unique, unique_len);
+ printf(", unique=\"%s\"", unique->unique);
+ printf("}");
+}
+
+static void
+print_drm_get_magic(long rc, void *ptr, void *arg)
+{
+ struct drm_auth *auth = ptr;
+
+ if (rc < 0) {
+ printf("%p", auth);
+ return;
+ }
+ PRINT_FIELD_U("{", *auth, magic);
+ printf("}");
+}
+
+static void
+print_drm_wait_vblank(long rc, void *ptr, void *arg)
+{
+ union drm_wait_vblank *vblank = ptr;
+
+ if (rc < 0) {
+ printf("%p", vblank);
+ return;
+ }
+ PRINT_FIELD_U("{request={", vblank->request, type);
+ PRINT_FIELD_U(", ", vblank->request, sequence);
+ PRINT_FIELD_U(", ", vblank->request, signal);
+ printf("}");
+
+
+ PRINT_FIELD_U(", reply={", vblank->reply, type);
+ PRINT_FIELD_U(", ", vblank->reply, sequence);
+ PRINT_FIELD_U(", ", vblank->reply, tval_sec);
+ PRINT_FIELD_U(", ", vblank->reply, tval_usec);
+ printf("}}");
+}
+
+static void
+print_drm_mode_get_resources(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_card_res *res = ptr;
+
+ if (rc < 0) {
+ printf("%p", res);
+ return;
+ }
+ printf("{fb_id_ptr=%#llx, ", (unsigned long long) res->fb_id_ptr);
+ printf("crtc_id_ptr=%#llx, ", (unsigned long long) res->crtc_id_ptr);
+ printf("connector_id_ptr=%#llx, ", (unsigned long long) res->connector_id_ptr);
+ printf("encoder_id_ptr=%#llx", (unsigned long long) res->encoder_id_ptr);
+ PRINT_FIELD_U(", ", *res, count_fbs);
+ PRINT_FIELD_U(", ", *res, count_crtcs);
+ PRINT_FIELD_U(", ", *res, count_connectors);
+ PRINT_FIELD_U(", ", *res, count_encoders);
+ PRINT_FIELD_U(", ", *res, min_width);
+ PRINT_FIELD_U(", ", *res, max_width);
+ PRINT_FIELD_U(", ", *res, min_height);
+ PRINT_FIELD_U(", ", *res, max_height);
+ printf("}");
+}
+
+static void
+drm_mode_print_modeinfo(struct drm_mode_modeinfo *info)
+{
+ PRINT_FIELD_U("", *info, clock);
+ PRINT_FIELD_U(", ", *info, hdisplay);
+ PRINT_FIELD_U(", ", *info, hsync_start);
+ PRINT_FIELD_U(", ", *info, hsync_end);
+ PRINT_FIELD_U(", ", *info, htotal);
+ PRINT_FIELD_U(", ", *info, hskew);
+ PRINT_FIELD_U(", ", *info, vdisplay);
+ PRINT_FIELD_U(", ", *info, vsync_start);
+ PRINT_FIELD_U(", ", *info, vsync_end);
+ PRINT_FIELD_U(", ", *info, vtotal);
+ PRINT_FIELD_U(", ", *info, vscan);
+ PRINT_FIELD_U(", ", *info, vrefresh);
+ PRINT_FIELD_X(", ", *info, flags);
+ PRINT_FIELD_U(", ", *info, type);
+ printf(", name=\"%s\"", info->name);
+}
+
+static void
+print_drm_mode_get_crtc(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_crtc *crtc = ptr;
+
+ if (rc < 0) {
+ printf("%p", crtc);
+ return;
+ }
+ PRINT_FIELD_U("{", *crtc, crtc_id);
+ printf(", set_connectors_ptr=%#llx", (unsigned long long) crtc->set_connectors_ptr);
+ PRINT_FIELD_U(", ", *crtc, count_connectors);
+ PRINT_FIELD_U(", ", *crtc, fb_id);
+ PRINT_FIELD_U(", ", *crtc, x);
+ PRINT_FIELD_U(", ", *crtc, y);
+ PRINT_FIELD_U(", ", *crtc, gamma_size);
+ PRINT_FIELD_U(", ", *crtc, mode_valid);
+ printf("mode={");
+ drm_mode_print_modeinfo(&crtc->mode);
+ printf("}}");
+}
+
+static void
+print_drm_mode_set_crtc(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_crtc *crtc = ptr;
+
+ if (rc < 0) {
+ printf("%p", crtc);
+ return;
+ }
+ printf("{set_connectors_ptr=%#llx", (unsigned long long) crtc->set_connectors_ptr);
+ PRINT_FIELD_U(", ", *crtc, count_connectors);
+ PRINT_FIELD_U(", ", *crtc, crtc_id);
+ PRINT_FIELD_U(", ", *crtc, fb_id);
+ PRINT_FIELD_U(", ", *crtc, x);
+ PRINT_FIELD_U(", ", *crtc, y);
+ PRINT_FIELD_U(", ", *crtc, gamma_size);
+ PRINT_FIELD_U(", ", *crtc, mode_valid);
+ printf("mode={");
+ drm_mode_print_modeinfo(&crtc->mode);
+ printf("}}");
+}
+
+static void
+print_drm_mode_cursor(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_cursor *cursor = ptr;
+
+ if (rc < 0) {
+ printf("%p", cursor);
+ return;
+ }
+ PRINT_FIELD_X("{", *cursor, flags);
+ PRINT_FIELD_U(", ", *cursor, crtc_id);
+ PRINT_FIELD_D(", ", *cursor, x);
+ PRINT_FIELD_D(", ", *cursor, y);
+ PRINT_FIELD_U(", ", *cursor, width);
+ PRINT_FIELD_U(", ", *cursor, height);
+ PRINT_FIELD_U(", ", *cursor, handle);
+ printf("}");
+}
+
+static void
+print_drm_mode_cursor2(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_cursor2 *cursor2 = ptr;
+
+ if (rc < 0) {
+ printf("%p", cursor2);
+ return;
+ }
+ PRINT_FIELD_X("{", *cursor2, flags);
+ PRINT_FIELD_U(", ", *cursor2, crtc_id);
+ PRINT_FIELD_D(", ", *cursor2, x);
+ PRINT_FIELD_D(", ", *cursor2, y);
+ PRINT_FIELD_U(", ", *cursor2, width);
+ PRINT_FIELD_U(", ", *cursor2, height);
+ PRINT_FIELD_U(", ", *cursor2, handle);
+ PRINT_FIELD_D(", ", *cursor2, hot_x);
+ PRINT_FIELD_D(", ", *cursor2, hot_y);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_gamma(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_crtc_lut *lut = ptr;
+
+ if (rc < 0) {
+ printf("%p", lut);
+ return;
+ }
+ PRINT_FIELD_U("{", *lut, crtc_id);
+ PRINT_FIELD_U(", ", *lut, gamma_size);
+ printf(", red=%#llx", (unsigned long long) lut->red);
+ printf(", green=%#llx", (unsigned long long) lut->green);
+ printf(", blue=%#llx", (unsigned long long) lut->blue);
+ printf("}");
+}
+
+static void
+print_drm_mode_set_gamma(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_crtc_lut *lut = ptr;
+
+ if (rc < 0) {
+ printf("%p", lut);
+ return;
+ }
+ PRINT_FIELD_U("{", *lut, crtc_id);
+ PRINT_FIELD_U(", ", *lut, gamma_size);
+ printf(", red=%#llx", (unsigned long long) lut->red);
+ printf(", green=%#llx", (unsigned long long) lut->green);
+ printf(", blue=%#llx", (unsigned long long) lut->blue);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_encoder(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_get_encoder *enc = ptr;
+
+ if (rc < 0) {
+ printf("%p", enc);
+ return;
+ }
+ PRINT_FIELD_U("{", *enc, encoder_id);
+ PRINT_FIELD_U(", ", *enc, encoder_type);
+ PRINT_FIELD_U(", ", *enc, crtc_id);
+ PRINT_FIELD_X(", ", *enc, possible_crtcs);
+ PRINT_FIELD_X(", ", *enc, possible_clones);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_connector(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_get_connector *con = ptr;
+
+ if (rc < 0) {
+ printf("%p", con);
+ return;
+ }
+ PRINT_FIELD_U("{", *con, connector_id);
+ printf(", encoders_ptr=%#llx", (unsigned long long) con->encoders_ptr);
+ printf(", modes_ptr=%#llx", (unsigned long long) con->modes_ptr);
+ printf(", props_ptr=%#llx", (unsigned long long) con->props_ptr);
+ printf(", prop_values_ptr=%#llx", (unsigned long long) con->prop_values_ptr);
+ PRINT_FIELD_U(", ", *con, count_modes);
+ PRINT_FIELD_U(", ", *con, count_props);
+ PRINT_FIELD_U(", ", *con, count_encoders);
+ PRINT_FIELD_U(", ", *con, encoder_id);
+ PRINT_FIELD_U(", ", *con, connector_type);
+ PRINT_FIELD_U(", ", *con, connector_type_id);
+ PRINT_FIELD_U(", ", *con, connection);
+ PRINT_FIELD_U(", ", *con, mm_width);
+ PRINT_FIELD_U(", ", *con, mm_height);
+ PRINT_FIELD_U(", ", *con, subpixel);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_property(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_get_property *prop = ptr;
+
+ if (rc < 0) {
+ printf("%p", prop);
+ return;
+ }
+ PRINT_FIELD_U("{", *prop, prop_id);
+ printf(", values_ptr=%#llx", prop->values_ptr);
+ printf(", enum_blob_ptr=%#llx", prop->enum_blob_ptr);
+ PRINT_FIELD_X(", ", *prop, flags);
+ PRINT_FIELD_CSTRING(", ", *prop, name);
+ PRINT_FIELD_U(", ", *prop, count_values);
+ PRINT_FIELD_U(", ", *prop, count_enum_blobs);
+ printf("}");
+}
+
+static void
+print_drm_mode_set_property(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_connector_set_property *prop = ptr;
+
+ if (rc < 0) {
+ printf("%p", prop);
+ return;
+ }
+ PRINT_FIELD_U("{", *prop, value);
+ PRINT_FIELD_U(", ", *prop, prop_id);
+ PRINT_FIELD_U(", ", *prop, connector_id);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_prop_blob(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_get_blob *blob = ptr;
+
+ if (rc < 0) {
+ printf("%p", blob);
+ return;
+ }
+ PRINT_FIELD_U("{", *blob, blob_id);
+ PRINT_FIELD_U(", ", *blob, length);
+ PRINT_FIELD_U(", ", *blob, data);
+ printf("}");
+}
+
+static void
+print_drm_mode_add_fb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_fb_cmd *cmd = ptr;
+
+ if (rc < 0) {
+ printf("%p", cmd);
+ return;
+ }
+ PRINT_FIELD_U("{", *cmd, width);
+ PRINT_FIELD_U(", ", *cmd, height);
+ PRINT_FIELD_U(", ", *cmd, pitch);
+ PRINT_FIELD_U(", ", *cmd, bpp);
+ PRINT_FIELD_U(", ", *cmd, depth);
+ PRINT_FIELD_U(", ", *cmd, handle);
+ PRINT_FIELD_U(", ", *cmd, fb_id);
+ printf("}");
+}
+
+static void
+print_drm_mode_add_fb2(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_fb_cmd2 *cmd = ptr;
+
+ if (rc < 0) {
+ printf("%p", cmd);
+ return;
+ }
+ PRINT_FIELD_U("{", *cmd, width);
+ PRINT_FIELD_U(", ", *cmd, height);
+ PRINT_FIELD_X(", ", *cmd, pixel_format);
+ PRINT_FIELD_U(", ", *cmd, flags);
+ printf(", handles={%u, %u, %u, %u}, "
+ "pitches={%u, %u, %u, %u}, "
+ "offsets={%u, %u, %u, %u}",
+ cmd->handles[0], cmd->handles[1], cmd->handles[2],
+ cmd->handles[3], cmd->pitches[0], cmd->pitches[1],
+ cmd->pitches[2], cmd->pitches[3], cmd->offsets[0],
+ cmd->offsets[1], cmd->offsets[2], cmd->offsets[3]);
+#ifdef HAVE_STRUCT_DRM_MODE_FB_CMD2_MODIFIER
+ printf(", modifiers={%" PRIu64 ", %" PRIu64 ", %" PRIu64 ", %" PRIu64 "}",
+ (uint64_t) cmd->modifier[0], (uint64_t) cmd->modifier[1],
+ (uint64_t) cmd->modifier[2], (uint64_t) cmd->modifier[3]);
+#endif
+ PRINT_FIELD_U(", ", *cmd, fb_id);
+ printf("}");
+}
+
+static void
+print_drm_mode_get_fb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_fb_cmd *cmd = ptr;
+
+ if (rc < 0) {
+ printf("%p", cmd);
+ return;
+ }
+ PRINT_FIELD_U("{", *cmd, fb_id);
+ PRINT_FIELD_U(", ", *cmd, width);
+ PRINT_FIELD_U(", ", *cmd, height);
+ PRINT_FIELD_U(", ", *cmd, pitch);
+ PRINT_FIELD_U(", ", *cmd, bpp);
+ PRINT_FIELD_U(", ", *cmd, depth);
+ PRINT_FIELD_U(", ", *cmd, handle);
+ printf("}");
+
+}
+
+static void
+print_drm_mode_rm_fb(long rc, void *ptr, void *arg)
+{
+ //unsigned int *handle = ptr;
+ struct drm_mode_rm_fb_wrap *wrap = ptr;
+
+ if (rc < 0) {
+ printf("%p", wrap);
+ return;
+ }
+ printf("%u", wrap->fb_id);
+}
+
+static void
+print_drm_mode_page_flip(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_crtc_page_flip *flip = ptr;
+
+ if (rc < 0) {
+ printf("%p", flip);
+ return;
+ }
+ PRINT_FIELD_U("{", *flip, crtc_id);
+ PRINT_FIELD_U(", ", *flip, fb_id);
+ PRINT_FIELD_X(", ", *flip, flags);
+ PRINT_FIELD_X(", ", *flip, user_data);
+ printf("}");
+}
+
+static void
+print_drm_mode_dirty_fb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_fb_dirty_cmd *cmd = ptr;
+
+ if (rc < 0) {
+ printf("%p", cmd);
+ return;
+ }
+ PRINT_FIELD_U("{", *cmd, fb_id);
+ PRINT_FIELD_X(", ", *cmd, flags);
+ PRINT_FIELD_X(", ", *cmd, color);
+ PRINT_FIELD_U(", ", *cmd, num_clips);
+ printf(", clips_ptr=%#llx", cmd->clips_ptr);
+ printf("}");
+}
+
+static void
+print_drm_mode_create_dumb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_create_dumb *dumb = ptr;
+
+ if (rc < 0) {
+ printf("%p", dumb);
+ return;
+ }
+ PRINT_FIELD_U("{", *dumb, width);
+ PRINT_FIELD_U(", ", *dumb, height);
+ PRINT_FIELD_U(", ", *dumb, bpp);
+ PRINT_FIELD_X(", ", *dumb, flags);
+ PRINT_FIELD_U(", ", *dumb, handle);
+ PRINT_FIELD_U(", ", *dumb, pitch);
+ PRINT_FIELD_U(", ", *dumb, size);
+ printf("}");
+}
+
+static void
+print_drm_mode_map_dumb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_map_dumb *dumb = ptr;
+
+ if (rc < 0) {
+ printf("%p", dumb);
+ return;
+ }
+ PRINT_FIELD_U("{", *dumb, handle);
+ PRINT_FIELD_U(", ", *dumb, offset);
+ printf("}");
+}
+
+static void
+print_drm_mode_destroy_dumb(long rc, void *ptr, void *arg)
+{
+ struct drm_mode_destroy_dumb *dumb = ptr;
+
+ if (rc < 0) {
+ printf("%p", dumb);
+ return;
+ }
+ PRINT_FIELD_U("{", *dumb, handle);
+ printf("}");
+}
+
+static void
+print_drm_gem_close(long rc, void *ptr, void *arg)
+{
+ struct drm_gem_close *close = ptr;
+
+ if (rc < 0) {
+ printf("%p", close);
+ return;
+ }
+ PRINT_FIELD_U("{", *close, handle);
+ printf("}");
+}
+
+int
+main(int argc, char **argv)
+{
+ unsigned long num_skip;
+ long inject_retval;
+ bool locked = false;
+
+ if (argc == 1)
+ return 0;
+
+ if (argc < 3)
+ error_msg_and_fail("Usage: %s NUM_SKIP INJECT_RETVAL", argv[0]);
+
+ num_skip = strtoul(argv[1], NULL, 0);
+ inject_retval = strtol(argv[2], NULL, 0);
+
+ if (inject_retval < 0)
+ error_msg_and_fail("Expected non-negative INJECT_RETVAL, "
+ "but got %ld", inject_retval);
+
+ for (unsigned int i = 0; i < num_skip; i++) {
+ long rc = ioctl(-1, DRM_IOCTL_VERSION, NULL);
+ printf("ioctl(-1, DRM_IOCTL_VERSION, NULL) = %s%s\n",
+ sprintrc(rc),
+ rc == inject_retval ? " (INJECTED)" : "");
+
+ if (rc != inject_retval)
+ continue;
+
+ locked = true;
+ break;
+ }
+
+ if (!locked)
+ error_msg_and_fail("Hasn't locked on ioctl(-1"
+ ", DRM_IOCTL_VERSION, NULL) returning %lu",
+ inject_retval);
+
+ /* drm_version */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_version, ver);
+ char bogus_name[4096] = "bogus_name";
+ char bogus_date[4096] = "bogus_date";
+ char bogus_desc[4096] = "bogus_desc";
+ ver->version_major = 1;
+ ver->version_minor = 2;
+ ver->version_patchlevel = 3;
+ ver->name_len = strlen(bogus_name);
+ ver->name = bogus_name;
+ ver->date_len = strlen(bogus_date);
+ ver->date = bogus_date;
+ ver->desc_len = strlen(bogus_desc);
+ ver->desc = bogus_desc;
+
+ /* drm_set_version */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_set_version, set_ver);
+ set_ver->drm_di_major = 1;
+ set_ver->drm_di_minor = 2;
+ set_ver->drm_dd_major = 3;
+ set_ver->drm_dd_minor = 4;
+
+ /* drm_unique */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_unique, unique);
+ char bogus_unique[4096] = "bogus_unique";
+ unique->unique_len = strlen(bogus_unique);
+ unique->unique = bogus_unique;
+
+ /* drm_auth */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_auth, auth);
+ auth->magic = 123;
+
+ /* drm_wait_vblank */
+ TAIL_ALLOC_OBJECT_CONST_PTR(union drm_wait_vblank, vblank);
+ vblank->request.type = 1;
+ vblank->request.sequence = 2;
+ vblank->request.signal = 3;
+ vblank->reply.tval_usec = 4;
+
+ /* drm_mode_card_res */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_card_res, res);
+ res->fb_id_ptr = 0xffffffff;
+ res->crtc_id_ptr = 0xffffffff;
+ res->connector_id_ptr = 0xffffffff;
+ res->encoder_id_ptr = 0xffffffff;
+ res->count_fbs = 1;
+ res->count_crtcs = 1;
+ res->count_connectors = 1;
+ res->count_encoders = 1;
+ res->min_width = 1;
+ res->max_width = 1;
+ res->min_height = 1;
+ res->max_height = 1;
+
+ /* drm_mode_crtc */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_crtc, crtc);
+ char bogus_mode_name[DRM_DISPLAY_MODE_LEN] = "bogus_mode_name";
+ crtc->crtc_id = 123;
+ crtc->set_connectors_ptr = 0xffffffff;
+ crtc->count_connectors = 1;
+ crtc->fb_id = 1;
+ crtc->x = 1;
+ crtc->y = 1;
+ crtc->gamma_size = 1;
+ crtc->mode_valid = 1;
+ snprintf(crtc->mode.name, sizeof(bogus_mode_name), "%s", bogus_mode_name);
+
+ /* drm_mode_cursor */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_cursor, cursor);
+ cursor->flags = 1;
+ cursor->crtc_id = 1;
+ cursor->x = 1;
+ cursor->y = 1;
+ cursor->width = 1;
+ cursor->height = 1;
+ cursor->handle = 1;
+
+ /* drm_mode_cursor2 */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_cursor2, cursor2);
+ cursor2->flags = 1;
+ cursor2->crtc_id = 1;
+ cursor2->x = 1;
+ cursor2->y = 1;
+ cursor2->width = 1;
+ cursor2->height = 1;
+ cursor2->handle = 1;
+ cursor2->hot_x = 1;
+ cursor2->hot_y = 1;
+
+ /* drm_mode_crtc_lut */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_crtc_lut, lut);
+ lut->crtc_id = 1;
+ lut->gamma_size = 1;
+ lut->red = 255;
+ lut->green = 255;
+ lut->blue = 255;
+
+ /* drm_mode_get_encoder */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_get_encoder, enc);
+ enc->encoder_id = 1;
+ enc->encoder_type = 1;
+ enc->crtc_id = 1;
+ enc->possible_crtcs = 1;
+ enc->possible_clones = 1;
+
+ /* drm_mode_get_connector */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_get_connector, con);
+ char con_str[4096];
+ snprintf(con_str, sizeof(con_str), "DRM_IOWR(0xa7, %#lx) /* DRM_IOCTL_MODE_GETCONNECTOR */",
+ (long unsigned int) _IOC_SIZE(DRM_IOCTL_MODE_GETCONNECTOR));
+ con->connector_id = 1;
+ con->encoders_ptr = 0xffffffff;
+ con->modes_ptr = 0xffffffff;
+ con->props_ptr = 0xffffffff;
+ con->prop_values_ptr = 0xffffffff;
+ con->count_modes = 1;
+ con->count_props = 1;
+ con->count_encoders = 1;
+ con->encoder_id = 1;
+ con->connector_type = 1;
+ con->connector_type_id = 1;
+ con->connection = 1;
+ con->mm_width = 1;
+ con->mm_height = 1;
+ con->subpixel = 1;
+
+ /* drm_mode_get_property */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_get_property, prop);
+ char bogus_property_name[DRM_PROP_NAME_LEN] = "bogus_property_name";
+ prop->prop_id = 1;
+ prop->values_ptr = 0xffffffff;
+ prop->enum_blob_ptr = 0xffffffff;
+ prop->flags = 0x1;
+ snprintf(prop->name, sizeof(bogus_property_name), "%s", bogus_property_name);
+
+ /* drm_mode_connector_set_property */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_connector_set_property, set_prop);
+ set_prop->value = 1;
+ set_prop->prop_id = 1;
+ set_prop->connector_id = 1;
+
+ /* drm_mode_get_blob */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_get_blob, blob);
+ blob->blob_id = 1;
+ blob->length = 1;
+ blob->data = 1;
+
+ /* drm_mode_fb_cmd */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_fb_cmd, cmd);
+ cmd->width = 1;
+ cmd->height = 1;
+ cmd->pitch = 1;
+ cmd->bpp = 1;
+ cmd->depth = 1;
+ cmd->handle = 1;
+ cmd->fb_id = 1;
+
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_fb_cmd2, cmd2);
+ cmd2->width = 1;
+ cmd2->height = 1;
+ cmd2->pixel_format = 0x1;
+ cmd2->flags = 1;
+ for (unsigned int i = 0; i < 4; i++) {
+ cmd2->handles[i] = 1;
+ cmd2->pitches[i] = 1;
+ cmd2->offsets[i] = 1;
+#ifdef HAVE_STRUCT_DRM_MODE_FB_CMD2_MODIFIER
+ cmd2->modifier[i] = 1;
+#endif
+ }
+ cmd2->fb_id = 1;
+
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_rm_fb_wrap, wrap);
+ wrap->fb_id = 3;
+
+ /* struct drm_mode_crtc_page_flip */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_crtc_page_flip, flip);
+ flip->crtc_id = 1;
+ flip->fb_id = 1;
+ flip->flags = 0x1;
+ flip->user_data = 1;
+
+ /* struct drm_mode_fb_dirty_cmd */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_fb_dirty_cmd, dirty_cmd);
+ dirty_cmd->fb_id = 1;
+ dirty_cmd->flags = 0x1;
+ dirty_cmd->color = 0x1;
+ dirty_cmd->num_clips = 1;
+ dirty_cmd->clips_ptr = 0xffffffff;
+
+ /* struct drm_mode_create_dumb */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_create_dumb, dumb);
+ dumb->width = 1;
+ dumb->height = 1;
+ dumb->bpp = 1;
+ dumb->flags = 0x1;
+ dumb->handle = 1;
+ dumb->pitch = 1;
+ dumb->size = 1;
+
+ /* struct drm_mode_map_dumb */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_map_dumb, map_dumb);
+ map_dumb->handle = 1;
+ map_dumb->offset = 1;
+
+ /* struct drm_mode_destroy_dumb */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_mode_destroy_dumb, destroy_dumb);
+ destroy_dumb->handle = 1;
+
+ /* struct drm_gem_close */
+ TAIL_ALLOC_OBJECT_CONST_PTR(struct drm_gem_close, close);
+ close->handle = 1;
+
+ struct drm_check a[] = {
+ { ARG_STR(DRM_IOCTL_VERSION), ver, print_drm_version },
+ { ARG_STR(DRM_IOCTL_SET_VERSION), set_ver, print_drm_set_version },
+ { ARG_STR(DRM_IOCTL_GET_UNIQUE), unique, print_drm_get_unique },
+ { ARG_STR(DRM_IOCTL_GET_MAGIC), auth, print_drm_get_magic },
+ { ARG_STR(DRM_IOCTL_WAIT_VBLANK), vblank, print_drm_wait_vblank },
+ { ARG_STR(DRM_IOCTL_MODE_GETRESOURCES), res, print_drm_mode_get_resources },
+ { ARG_STR(DRM_IOCTL_MODE_GETCRTC), crtc, print_drm_mode_get_crtc },
+ { ARG_STR(DRM_IOCTL_MODE_SETCRTC), crtc, print_drm_mode_set_crtc },
+ { ARG_STR(DRM_IOCTL_MODE_CURSOR), cursor, print_drm_mode_cursor },
+ { ARG_STR(DRM_IOCTL_MODE_CURSOR2), cursor2, print_drm_mode_cursor2 },
+ { ARG_STR(DRM_IOCTL_MODE_GETGAMMA), lut, print_drm_mode_get_gamma },
+ { ARG_STR(DRM_IOCTL_MODE_SETGAMMA), lut, print_drm_mode_set_gamma },
+ { ARG_STR(DRM_IOCTL_MODE_GETENCODER), enc, print_drm_mode_get_encoder },
+ { ARG_STR(DRM_IOCTL_MODE_GETPROPERTY), prop, print_drm_mode_get_property },
+ { ARG_STR(DRM_IOCTL_MODE_SETPROPERTY), set_prop, print_drm_mode_set_property },
+ { ARG_STR(DRM_IOCTL_MODE_GETPROPBLOB), blob, print_drm_mode_get_prop_blob },
+ { ARG_STR(DRM_IOCTL_MODE_ADDFB), cmd, print_drm_mode_add_fb },
+ { ARG_STR(DRM_IOCTL_MODE_ADDFB2), cmd2, print_drm_mode_add_fb2 },
+ { ARG_STR(DRM_IOCTL_MODE_GETFB), cmd, print_drm_mode_get_fb },
+ { ARG_STR(DRM_IOCTL_MODE_RMFB), wrap, print_drm_mode_rm_fb },
+ { ARG_STR(DRM_IOCTL_MODE_PAGE_FLIP), flip, print_drm_mode_page_flip },
+ { ARG_STR(DRM_IOCTL_MODE_DIRTYFB), dirty_cmd, print_drm_mode_dirty_fb },
+ { ARG_STR(DRM_IOCTL_MODE_CREATE_DUMB), dumb, print_drm_mode_create_dumb },
+ { ARG_STR(DRM_IOCTL_MODE_MAP_DUMB), map_dumb, print_drm_mode_map_dumb },
+ { ARG_STR(DRM_IOCTL_MODE_DESTROY_DUMB), destroy_dumb, print_drm_mode_destroy_dumb },
+ { ARG_STR(DRM_IOCTL_GEM_CLOSE), close, print_drm_gem_close },
+ };
+
+ for (unsigned int i = 0; i < ARRAY_SIZE(a); i++) {
+ test_drm(&a[i], NULL);
+ }
+
+ struct drm_check b = {
+ .cmd = DRM_IOCTL_MODE_GETCONNECTOR,
+ .arg_ptr = con,
+ .print_arg = print_drm_mode_get_connector,
+ };
+
+ if (_IOC_SIZE(DRM_IOCTL_MODE_GETCONNECTOR) == 0x50) {
+ b.cmd_str = "DRM_IOCTL_MODE_GETCONNECTOR";
+ } else {
+ b.cmd_str = con_str;
+ }
+ test_drm(&b, NULL);
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}
+#else
+
+SKIP_MAIN_UNDEFINED("HAVE_DRM_H && HAVE_DRM_DRM_H");
+
+#endif
diff --git a/tests/ioctl_drm-success.test b/tests/ioctl_drm-success.test
new file mode 100755
index 00000000..3dd076d5
--- /dev/null
+++ b/tests/ioctl_drm-success.test
@@ -0,0 +1,18 @@
+#!/bin/sh -efu
+#
+# Copyright (c) 2018 The strace developers.
+# All rights reserved.
+#
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+. "${srcdir=.}/scno_tampering.sh"
+
+: ${IOCTL_INJECT_START=256}
+: ${IOCTL_INJECT_RETVAL=42}
+
+run_prog
+run_strace -a16 -e trace=ioctl \
+ -e inject=ioctl:retval="${IOCTL_INJECT_RETVAL}":when="${IOCTL_INJECT_START}+" \
+ ../ioctl_drm-success "${IOCTL_INJECT_START}" "${IOCTL_INJECT_RETVAL}"> "$EXP"
+grep -v '^ioctl([012][,<]' < "$LOG" > "$OUT"
+match_diff "$OUT" "$EXP"
diff --git a/tests/ioctl_drm.c b/tests/ioctl_drm.c
new file mode 100644
index 00000000..e9d62702
--- /dev/null
+++ b/tests/ioctl_drm.c
@@ -0,0 +1,90 @@
+#include "tests.h"
+
+#if defined(HAVE_DRM_H) || defined(HAVE_DRM_DRM_H)
+
+# include <errno.h>
+# include <inttypes.h>
+# include <stdio.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/ioctl.h>
+
+# ifdef HAVE_DRM_H
+# include <drm.h>
+# else
+# include <drm/drm.h>
+# endif
+
+# define TEST_NULL_ARG_EX(cmd, str) \
+ do { \
+ ioctl(-1, cmd, 0); \
+ printf("ioctl(-1, %s, NULL) = -1 EBADF (%m)\n", str); \
+ } while(0)
+
+# define TEST_NULL_ARG(cmd) TEST_NULL_ARG_EX(cmd, #cmd)
+
+static const unsigned long lmagic = (unsigned long) 0xdeadbeefbadc0dedULL;
+
+int
+main(void)
+{
+ TEST_NULL_ARG(DRM_IOCTL_VERSION);
+ TEST_NULL_ARG(DRM_IOCTL_SET_VERSION);
+ TEST_NULL_ARG(DRM_IOCTL_GET_UNIQUE);
+ TEST_NULL_ARG(DRM_IOCTL_GET_MAGIC);
+ TEST_NULL_ARG(DRM_IOCTL_WAIT_VBLANK);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETRESOURCES);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETCRTC);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_SETCRTC);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_CURSOR);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_CURSOR2);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETGAMMA);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_SETGAMMA);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETENCODER);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETPROPERTY);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_SETPROPERTY);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETPROPBLOB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETFB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_ADDFB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_ADDFB2);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_RMFB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_PAGE_FLIP);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_DIRTYFB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_CREATE_DUMB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_MAP_DUMB);
+ TEST_NULL_ARG(DRM_IOCTL_MODE_DESTROY_DUMB);
+ TEST_NULL_ARG(DRM_IOCTL_GEM_CLOSE);
+
+ if (_IOC_SIZE(DRM_IOCTL_MODE_GETCONNECTOR) == 0x50) {
+ TEST_NULL_ARG(DRM_IOCTL_MODE_GETCONNECTOR);
+ } else {
+ ioctl(-1, DRM_IOCTL_MODE_GETCONNECTOR, 0);
+ printf("ioctl(-1, DRM_IOWR(%#lx, %#lx) /* DRM_IOCTL_MODE_GETCONNECTOR */, NULL) = -1 EBADF (%m)\n",
+ (long unsigned int) _IOC_NR(DRM_IOCTL_MODE_GETCONNECTOR),
+ (long unsigned int) _IOC_SIZE(DRM_IOCTL_MODE_GETCONNECTOR));
+ }
+
+ ioctl(-1, _IOC(_IOC_READ, 0x45, 0x1, 0xff), lmagic);
+ printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
+ "_IOC(_IOC_READ, 0x45, 0x1, 0xff)", lmagic);
+
+ ioctl(-1, _IOC(_IOC_WRITE, 0x45, 0x1, 0xff), lmagic);
+ printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
+ "_IOC(_IOC_WRITE, 0x45, 0x1, 0xff)", lmagic);
+
+ ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff), lmagic);
+ printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
+ "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0xfe, 0xff)", lmagic);
+
+ ioctl(-1, _IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0), lmagic);
+ printf("ioctl(-1, %s, %#lx) = -1 EBADF (%m)\n",
+ "_IOC(_IOC_READ|_IOC_WRITE, 0x45, 0, 0)", lmagic);
+
+ puts("+++ exited with 0 +++");
+ return 0;
+}
+#else
+
+SKIP_MAIN_UNDEFINED("HAVE_DRM_H");
+
+#endif
diff --git a/tests/pure_executables.list b/tests/pure_executables.list
index 37225209..71c33f66 100755
--- a/tests/pure_executables.list
+++ b/tests/pure_executables.list
@@ -126,6 +126,7 @@ io_uring_setup
ioctl
ioctl_block
ioctl_dm
+ioctl_drm
ioctl_evdev
ioctl_inotify
ioctl_kvm_run
--
2.21.0
More information about the Strace-devel
mailing list