[RFC i-g-t] tests/intel/sec_xe_exec_queue_timeslice_abuse: Validate the Impact of Timeslice Abuse on Exec Queues

Peter Senna Tschudin peter.senna at linux.intel.com
Sun May 4 20:28:06 UTC 2025


DO NOT MERGE!

This is an RFC for a new kind of security-related test.

The objective is to test the behavior of the GPU scheduler under
conditions where one execution queue ("attacker") is configured with an
abnormally large timeslice, potentially disrupting the normal execution
of another queue ("attacked").

The proposed steps are:

For each GPU engine (drm_xe_engine_class_instance?):
  	1. Determine the values for the following parameters:
  		- `timeslice_duration_us`: Default timeslice duration in
  		   microseconds.
  		- `timeslice_duration_min`: Minimum allowable timeslice duration.
  		- `timeslice_duration_max`: Maximum allowable timeslice duration.

  	2. Create two execution queues with the following configurations:
  		- `attacked`: Queue with standard/default settings.
  		- `attacker`: Queue configured with an extended timeslice
  			      duration. The goal is to:
  			a) First attempt to set a timeslice greater than
  			   `timeslice_duration_max`.
  			b) If setting a timeslice above `timeslice_duration_max`
  			   fails, fallback to setting the timeslice to
  			   `timeslice_duration_max`.

  	3. Submit tasks to both queues:
  		- Submit a workload to the `attacked` queue with normal
  		   operations.
  		- Submit a workload to the `attacker` queue designed to
  		  maximize its timeslice and potentially disrupt the GPU
  		  scheduler.

  	4. Verify the behavior of the `attacked` queue:
  		- Ensure that tasks in the `attacked` queue execute within the
  		  expected time constraints and are not delayed or blocked due
  		  to the extended timeslice of the `attacker` queue.
  		- Specifically, confirm that tasks in the `attacked` queue do
  		  not exceed `timeslice_duration_max` in terms of execution
  		  delays or interruptions.

This RFC implements the first step that is reading timeslice values for
each engine.

Signed-off-by: Peter Senna Tschudin <peter.senna at linux.intel.com>
---
 .../intel/sec_xe_exec_queue_timeslice_abuse.c | 296 ++++++++++++++++++
 tests/meson.build                             |   1 +
 2 files changed, 297 insertions(+)
 create mode 100644 tests/intel/sec_xe_exec_queue_timeslice_abuse.c

diff --git a/tests/intel/sec_xe_exec_queue_timeslice_abuse.c b/tests/intel/sec_xe_exec_queue_timeslice_abuse.c
new file mode 100644
index 000000000..bc00a0cd5
--- /dev/null
+++ b/tests/intel/sec_xe_exec_queue_timeslice_abuse.c
@@ -0,0 +1,296 @@
+// SPDX-License-Identifier: MIT
+/*
+ * Copyright © 2025 Intel Corporation
+ */
+
+/*
+ * Test Specification: Validate the Impact of Timeslice Abuse on Exec Queues
+ *
+ * Objective
+ * Test the behavior of the GPU scheduler under conditions where one execution
+ * queue ("attacker") is configured with an abnormally large timeslice,
+ * potentially disrupting the normal execution of another queue ("attacked").
+ *
+ * Steps:
+ *
+ * For each GPU engine available:
+ *	1. Determine the values for the following parameters:
+ *		- `timeslice_duration_us`: Default timeslice duration in
+ *		   microseconds.
+ *		- `timeslice_duration_min`: Minimum allowable timeslice duration.
+ *		- `timeslice_duration_max`: Maximum allowable timeslice duration.
+ *
+ *	2. Create two execution queues with the following configurations:
+ *		- `attacked`: Queue with standard/default settings.
+ *		- `attacker`: Queue configured with an extended timeslice
+ *			      duration. The goal is to:
+ *			a) First attempt to set a timeslice greater than
+ *			   `timeslice_duration_max`.
+ *			b) If setting a timeslice above `timeslice_duration_max`
+ *			   fails, fallback to setting the timeslice to
+ *			   `timeslice_duration_max`.
+ *
+ *	3. Submit tasks to both queues:
+ *		- Submit a workload to the `attacked` queue with normal
+ *		   operations.
+ *		- Submit a workload to the `attacker` queue designed to
+ *		  maximize its timeslice and potentially disrupt the GPU
+ *		  scheduler.
+ *
+ *	4. Verify the behavior of the `attacked` queue:
+ *		- Ensure that tasks in the `attacked` queue execute within the
+ *		  expected time constraints and are not delayed or blocked due
+ *		  to the extended timeslice of the `attacker` queue.
+ *		- Specifically, confirm that tasks in the `attacked` queue do
+ *		  not exceed `timeslice_duration_max` in terms of execution
+ *		  delays or interruptions.
+ *
+ */
+
+#include <dirent.h>
+#include <fcntl.h>
+
+#include "igt.h"
+#include "igt_list.h"
+#include "igt_sysfs.h"
+#include "xe/xe_query.h"
+
+static struct igt_list_head engines_list;
+
+/*
+ * Struct to Hold Data for Each Engine
+ */
+struct engines_timeslice_test_data {
+	/* Name of the GPU engine (e.g., "CCS", "VCS", "RCS", "BCS", "VECS") */
+	const char *engine_name;
+
+	/* Minimum allowable timeslice duration (microseconds) */
+	uint32_t timeslice_min;
+
+	/* Maximum allowable timeslice duration (microseconds) */
+	uint32_t timeslice_max;
+
+	/* Timeslice value set for the attacker queue (microseconds) */
+	uint32_t timeslice_set;
+
+	/* Pointer to the attacked execution queue */
+	struct xe_exec_queue *attacked_queue;
+
+	/* Pointer to the attacker execution queue */
+	struct xe_exec_queue *attacker_queue;
+
+	/* Linked list node */
+	struct igt_list_head link;
+};
+
+/**
+ * engine_list_add_timeslices: Check if there is already an entry in the list
+ *			       for the engine and add timeslices.
+ * @engine: name of the engine
+ * @set: timeslice duration set for the attacker queue
+ * @max: maximum allowable timeslice duration
+ * @min: minimum allowable timeslice duration
+ *
+ * Returns: bool indicating if timeslices were added to the list
+ *
+ */
+static bool engines_list_add_timeslices(const char *engine, uint32_t set,
+					uint32_t min, uint32_t max)
+{
+	struct engines_timeslice_test_data *engine_data = NULL;
+
+	/* Check if the engine already exists in the list. If it does
+	 * add the timeslice values to the existing entry
+	 */
+	igt_list_for_each_entry(engine_data, &engines_list, link) {
+		if (strcmp(engine_data->engine_name, engine) == 0) {
+			engine_data->timeslice_set = set;
+			engine_data->timeslice_min = min;
+			engine_data->timeslice_max = max;
+			return true;
+		}
+	}
+	/* If the engine does not exist, create a new entry */
+	engine_data = malloc(sizeof(*engine_data));
+	if (!engine_data)
+		return false;
+
+	engine_data->engine_name = strdup(engine);
+	engine_data->timeslice_set = set;
+	engine_data->timeslice_min = min;
+	engine_data->timeslice_max = max;
+	engine_data->attacked_queue = NULL;
+	engine_data->attacker_queue = NULL;
+
+	igt_list_add(&engine_data->link, &engines_list);
+	return true;
+}
+
+/**
+ * engine_list_print_all: Print all engines in the list
+ *
+ * Returns: void
+ *
+ */
+static void engines_list_print_all(void)
+{
+	struct engines_timeslice_test_data *engine_data = NULL;
+
+	igt_list_for_each_entry(engine_data, &engines_list, link) {
+		igt_info("Engine: %s, Set: %u, Min: %u, Max: %u\n",
+			 engine_data->engine_name,
+			 engine_data->timeslice_set,
+			 engine_data->timeslice_min,
+			 engine_data->timeslice_max);
+	}
+}
+
+/**
+ * engine_free_all: Free all engines in the list
+ *
+ * Returns: void
+ *
+ */
+static void engines_list_free_all(void)
+{
+	struct engines_timeslice_test_data *engine_data = NULL, *tmp = NULL;
+
+	igt_list_for_each_entry_safe(engine_data, tmp, &engines_list, link) {
+		free((void *)engine_data->engine_name);
+		free(engine_data);
+	}
+}
+
+/**
+ * get_queue_timeslice_properties: Get the timeslice properties for an engine
+ * @xe: xe device file descriptor
+ * @engine: engine file descriptor
+ * @set: pointer to store the timeslice duration set for the attacker queue
+ * @min: pointer to store the minimum allowable timeslice duration
+ * @max: pointer to store the maximum allowable timeslice duration
+ *
+ * Returns: 0 on success, -1 on failure
+ */
+static int get_queue_timeslice_properties(int xe, int engine,
+	unsigned int *set, unsigned int *min, unsigned int *max)
+{
+	int defaults;
+
+	defaults = openat(engine, ".defaults", O_DIRECTORY);
+	if (defaults == -1)
+		return -1; /* Failure: Unable to open the defaults directory */
+
+	/* Read the max, min, and set values from the sysfs */
+	if (igt_sysfs_scanf(defaults, "timeslice_duration_max", "%u", max) != 1 ||
+	    igt_sysfs_scanf(defaults, "timeslice_duration_min", "%u", min) != 1 ||
+	    igt_sysfs_scanf(engine, "timeslice_duration_us", "%u", set) != 1) {
+		close(defaults);
+		return -1; /* Failure: Unable to read sysfs values */
+	}
+	close(defaults);
+
+	return 0; /* Success */
+}
+
+/**
+ * TEST: Validate the Impact of Timeslice Abuse on Exec Queues
+ * Category: Security
+ * Mega feature: Security Validation Plan
+ * Sub-category: Security Validation Plan
+ * Functionality: Test if exec queue timeslice property can be used as an
+ *		  attack to prevent other queues from running
+ * Test category: security test
+ *
+ * SUBTEST: get-timeslice-properties
+ * Description: Test to check if timeslice properties are available and
+ *		read them.
+ * Test category: functionality test
+ */
+
+/**
+ * engine_list_add_timeslices: Check if there is already an entry in the list
+ *			       for the engine and add timeslices.
+ * @engine: name of the engine
+ * @set: timeslice duration set for the attacker queue
+ * @max: maximum allowable timeslice duration
+ * @min: minimum allowable timeslice duration
+ *
+ * Returns: bool indicating if timeslices were added to the list
+ *
+ */
+igt_main
+{
+	int gt = -1;
+	bool has_sysfs;
+	unsigned int max = -1;
+	unsigned int min = -1;
+	unsigned int set = -1;
+	int sys_fd = -1;
+	int xe = -1;
+
+	igt_fixture {
+		/* Initialize the list of engines */
+		IGT_INIT_LIST_HEAD(&engines_list);
+
+		xe = drm_open_driver(DRIVER_XE);
+		sys_fd = igt_sysfs_open(xe);
+
+		if (sys_fd != -1) {
+			close(sys_fd);
+			has_sysfs = true;
+		} else {
+			has_sysfs = false;
+		}
+	}
+
+	igt_subtest("get-timeslice-properties") {
+		xe_for_each_gt(xe, gt) {
+			int engines = -1;
+			int gt_fd = -1;
+			DIR *dir;
+			struct dirent *de;
+
+			igt_require(has_sysfs);
+
+			gt_fd = xe_sysfs_gt_open(xe, gt);
+			igt_require(gt_fd != -1);
+
+			engines = openat(gt_fd, "engines", O_RDONLY);
+			igt_require(engines != -1);
+
+			lseek(engines, 0, SEEK_SET);
+
+			dir = fdopendir(engines);
+			if (!dir)
+				close(engines);
+
+			while ((de = readdir(dir))) {
+				int engine_fd = -1;
+
+				if (*de->d_name == '.')
+					continue;
+
+				engine_fd = openat(engines, de->d_name, O_RDONLY);
+				if (engine_fd < 0)
+					continue;
+
+				/* Check if the timeslice properties are available */
+				if (get_queue_timeslice_properties(xe, engine_fd, &set, &min, &max) == 0)
+					engines_list_add_timeslices(de->d_name, set, min, max);
+				else
+					igt_warn("Failed to get timeslice properties\n");
+
+				close(engine_fd);
+			}
+			close(gt_fd);
+		}
+		engines_list_print_all();
+	}
+
+	igt_fixture {
+		engines_list_free_all();
+		close(sys_fd);
+		xe_device_put(xe);
+		drm_close_driver(xe);
+	}
+}
diff --git a/tests/meson.build b/tests/meson.build
index 20ddddb89..560b74ceb 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -273,6 +273,7 @@ intel_kms_progs = [
 ]
 
 intel_xe_progs = [
+	'sec_xe_exec_queue_timeslice_abuse',
 	'xe_wedged',
 	'xe_ccs',
 	'xe_create',
-- 
2.43.0



More information about the igt-dev mailing list