* Re: [PATCH 2/2] drm/tests: Add KUnit tests for the client mode size limits
[not found] ` <20261015212545.1989962-3-hugo@hsal.es>
@ 2026-10-15 21:34 ` sashiko-bot
0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-10-15 21:34 UTC (permalink / raw)
To: Hugo Sales, dri-devel
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] drm/tests: lockless access to connector->modes violates locking rules
- [Low] drm/tests: memory leak of cloned modes on KUnit assertion failure
--
commit 806dc20896099436a3d060ce16a4a8cb84cf8467
Author: Hugo Sales <hugo@hsal.es>
Subject: drm/tests: Add KUnit tests for the client mode size limits
This commit adds KUnit tests for various client mode pickers to ensure they
skip modes larger than the client's size. It also tests that the modeset
probe properly retains the preferred mode.
> diff --git a/drivers/gpu/drm/tests/drm_client_modeset_test.c b/drivers/gpu/drm/tests/drm_client_modeset_test.c
> index 00f43fca97954..93aa919d4f317 100644
> --- a/drivers/gpu/drm/tests/drm_client_modeset_test.c
> +++ b/drivers/gpu/drm/tests/drm_client_modeset_test.c
[ ... ]
> @@ -197,6 +213,206 @@ static struct kunit_suite drm_test_pick_cmdline_test_suite = {
>
> kunit_test_suite(drm_test_pick_cmdline_test_suite);
>
> +static void drm_test_pick_first_mode_within_limits(struct kunit *test)
> +{
[ ... ]
> + mutex_lock(&drm->mode_config.mutex);
> + ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
> + mutex_unlock(&drm->mode_config.mutex);
> + KUNIT_ASSERT_GT(test, ret, 0);
> +
> + mode = drm_connector_first_mode(connector, 1920, 1080);
[Severity: Low]
The connector->modes list is explicitly documented as being protected by
dev->mode_config.mutex. Here, the mutex is unlocked just before calling
drm_connector_first_mode(), which iterates over connector->modes.
While this is isolated test code and no concurrent modification occurs,
could this lockless iteration trigger static analysis tools or lockdep
warnings?
> + KUNIT_ASSERT_NOT_NULL(test, mode);
> + KUNIT_EXPECT_EQ(test, mode->hdisplay, 1920);
> + KUNIT_EXPECT_EQ(test, mode->vdisplay, 1080);
[ ... ]
> +static void drm_test_pick_cmdline_mode_within_limits(struct kunit *test)
> +{
[ ... ]
> + mutex_lock(&drm->mode_config.mutex);
> + ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
> + mutex_unlock(&drm->mode_config.mutex);
> + KUNIT_ASSERT_GT(test, ret, 0);
> +
> + mode = drm_connector_pick_cmdline_mode(connector, 1920, 1080);
[Severity: Low]
Similarly here, drm_connector_pick_cmdline_mode() iterates over
connector->modes outside of drm->mode_config.mutex. Does this violate
the locking rules for the connector modes list?
> + KUNIT_ASSERT_NOT_NULL(test, mode);
[ ... ]
> +static void drm_test_pick_tiled_mode_within_limits(struct kunit *test)
> +{
[ ... ]
> + mutex_lock(&drm->mode_config.mutex);
> + ret = drm_helper_probe_single_connector_modes(connector, 1920, 1080);
> + mutex_unlock(&drm->mode_config.mutex);
> + KUNIT_ASSERT_GT(test, ret, 0);
> +
> + mode = drm_connector_get_tiled_mode(connector, 1920, 1080);
[Severity: Low]
As with the previous pickers, drm_connector_get_tiled_mode() accesses
connector->modes without the required drm->mode_config.mutex held.
> + KUNIT_ASSERT_NOT_NULL(test, mode);
[ ... ]
> +static void drm_test_pick_clone_mode_within_limits(struct kunit *test)
> +{
[ ... ]
> + mutex_lock(&drm->mode_config.mutex);
> + for (i = 0; i < ARRAY_SIZE(connectors); i++) {
> + ret = drm_helper_probe_single_connector_modes(connectors[i], 1920, 1080);
> + KUNIT_EXPECT_GT(test, ret, 0);
> + }
> + mutex_unlock(&drm->mode_config.mutex);
> +
> + KUNIT_EXPECT_TRUE(test, drm_client_target_cloned(drm, connectors, ARRAY_SIZE(connectors),
> + modes, offsets, enabled, 1024, 768));
[Severity: Low]
This call to drm_client_target_cloned() also iterates over
connector->modes after the config mutex has been released.
> + for (i = 0; i < ARRAY_SIZE(connectors); i++) {
> + KUNIT_ASSERT_NOT_NULL(test, modes[i]);
[Severity: Low]
If this KUNIT_ASSERT_NOT_NULL() assertion fails, it immediately forces an
early return from the test.
Because drm_client_target_cloned() allocates new modes via mode_replace(),
would an early return here bypass the mandatory modes_destroy() cleanup
below and leak the dynamically allocated mode objects?
Could KUnit's managed allocations (like kunit_add_action) be used to ensure
modes_destroy() always runs on cleanup?
> + KUNIT_EXPECT_EQ(test, modes[i]->hdisplay, 1024);
> + KUNIT_EXPECT_EQ(test, modes[i]->vdisplay, 768);
> + }
> + modes_destroy(drm, modes, ARRAY_SIZE(connectors));
[ ... ]
> +static void drm_test_probe_keeps_modes_above_limits(struct kunit *test)
> +{
[ ... ]
> + ret = drm_client_modeset_probe(client, 1024, 768);
> + KUNIT_ASSERT_EQ(test, ret, 0);
> +
> + mode = client->modesets[0].mode;
> + KUNIT_ASSERT_NOT_NULL(test, mode);
> + KUNIT_EXPECT_EQ(test, mode->hdisplay, 1024);
> + KUNIT_EXPECT_EQ(test, mode->vdisplay, 768);
> +
> + mode = drm_connector_preferred_mode(connector, 1920, 1080);
[Severity: Low]
Once again, drm_connector_preferred_mode() is called to iterate the
connector->modes list without the config mutex held.
> + KUNIT_ASSERT_NOT_NULL(test, mode);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261015212545.1989962-1-hugo@hsal.es?part=2
^ permalink raw reply [flat|nested] 2+ messages in thread