Skip to content

Commit 9da6743

Browse files
committed
drm/tidss: fix crash related to accessing freed memory
tidss uses devm_kzalloc to allocate DRM plane, encoder and crtc objects. This is not correct as the lifetime of those objects should be longer than the underlying device's. When unloading tidss module, the devm_kzalloc'ed objects have already been freed when tidss_release() is called, and the driver will accesses freed memory possibly causing a crash, a kernel WARN, or other undefined behavior, and also KASAN will give a bug. Signed-off-by: Tomi Valkeinen <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected] Acked-by: Daniel Vetter <[email protected]>
1 parent 7bfc1fe commit 9da6743

File tree

3 files changed

+42
-12
lines changed

3 files changed

+42
-12
lines changed

drivers/gpu/drm/tidss/tidss_crtc.c

+13-3
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,17 @@ static struct drm_crtc_state *tidss_crtc_duplicate_state(struct drm_crtc *crtc)
379379
return &state->base;
380380
}
381381

382+
static void tidss_crtc_destroy(struct drm_crtc *crtc)
383+
{
384+
struct tidss_crtc *tcrtc = to_tidss_crtc(crtc);
385+
386+
drm_crtc_cleanup(crtc);
387+
kfree(tcrtc);
388+
}
389+
382390
static const struct drm_crtc_funcs tidss_crtc_funcs = {
383391
.reset = tidss_crtc_reset,
384-
.destroy = drm_crtc_cleanup,
392+
.destroy = tidss_crtc_destroy,
385393
.set_config = drm_atomic_helper_set_config,
386394
.page_flip = drm_atomic_helper_page_flip,
387395
.atomic_duplicate_state = tidss_crtc_duplicate_state,
@@ -400,7 +408,7 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
400408
bool has_ctm = tidss->feat->vp_feat.color.has_ctm;
401409
int ret;
402410

403-
tcrtc = devm_kzalloc(tidss->dev, sizeof(*tcrtc), GFP_KERNEL);
411+
tcrtc = kzalloc(sizeof(*tcrtc), GFP_KERNEL);
404412
if (!tcrtc)
405413
return ERR_PTR(-ENOMEM);
406414

@@ -411,8 +419,10 @@ struct tidss_crtc *tidss_crtc_create(struct tidss_device *tidss,
411419

412420
ret = drm_crtc_init_with_planes(&tidss->ddev, crtc, primary,
413421
NULL, &tidss_crtc_funcs, NULL);
414-
if (ret < 0)
422+
if (ret < 0) {
423+
kfree(tcrtc);
415424
return ERR_PTR(ret);
425+
}
416426

417427
drm_crtc_helper_add(crtc, &tidss_crtc_helper_funcs);
418428

drivers/gpu/drm/tidss/tidss_encoder.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,18 @@ static int tidss_encoder_atomic_check(struct drm_encoder *encoder,
5555
return 0;
5656
}
5757

58+
static void tidss_encoder_destroy(struct drm_encoder *encoder)
59+
{
60+
drm_encoder_cleanup(encoder);
61+
kfree(encoder);
62+
}
63+
5864
static const struct drm_encoder_helper_funcs encoder_helper_funcs = {
5965
.atomic_check = tidss_encoder_atomic_check,
6066
};
6167

6268
static const struct drm_encoder_funcs encoder_funcs = {
63-
.destroy = drm_encoder_cleanup,
69+
.destroy = tidss_encoder_destroy,
6470
};
6571

6672
struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
@@ -69,16 +75,18 @@ struct drm_encoder *tidss_encoder_create(struct tidss_device *tidss,
6975
struct drm_encoder *enc;
7076
int ret;
7177

72-
enc = devm_kzalloc(tidss->dev, sizeof(*enc), GFP_KERNEL);
78+
enc = kzalloc(sizeof(*enc), GFP_KERNEL);
7379
if (!enc)
7480
return ERR_PTR(-ENOMEM);
7581

7682
enc->possible_crtcs = possible_crtcs;
7783

7884
ret = drm_encoder_init(&tidss->ddev, enc, &encoder_funcs,
7985
encoder_type, NULL);
80-
if (ret < 0)
86+
if (ret < 0) {
87+
kfree(enc);
8188
return ERR_PTR(ret);
89+
}
8290

8391
drm_encoder_helper_add(enc, &encoder_helper_funcs);
8492

drivers/gpu/drm/tidss/tidss_plane.c

+18-6
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ static void tidss_plane_atomic_disable(struct drm_plane *plane,
141141
dispc_plane_enable(tidss->dispc, tplane->hw_plane_id, false);
142142
}
143143

144+
static void drm_plane_destroy(struct drm_plane *plane)
145+
{
146+
struct tidss_plane *tplane = to_tidss_plane(plane);
147+
148+
drm_plane_cleanup(plane);
149+
kfree(tplane);
150+
}
151+
144152
static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
145153
.atomic_check = tidss_plane_atomic_check,
146154
.atomic_update = tidss_plane_atomic_update,
@@ -151,7 +159,7 @@ static const struct drm_plane_funcs tidss_plane_funcs = {
151159
.update_plane = drm_atomic_helper_update_plane,
152160
.disable_plane = drm_atomic_helper_disable_plane,
153161
.reset = drm_atomic_helper_plane_reset,
154-
.destroy = drm_plane_cleanup,
162+
.destroy = drm_plane_destroy,
155163
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
156164
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
157165
};
@@ -175,7 +183,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
175183
BIT(DRM_MODE_BLEND_COVERAGE));
176184
int ret;
177185

178-
tplane = devm_kzalloc(tidss->dev, sizeof(*tplane), GFP_KERNEL);
186+
tplane = kzalloc(sizeof(*tplane), GFP_KERNEL);
179187
if (!tplane)
180188
return ERR_PTR(-ENOMEM);
181189

@@ -190,7 +198,7 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
190198
formats, num_formats,
191199
NULL, type, NULL);
192200
if (ret < 0)
193-
return ERR_PTR(ret);
201+
goto err;
194202

195203
drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
196204

@@ -203,15 +211,19 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
203211
default_encoding,
204212
default_range);
205213
if (ret)
206-
return ERR_PTR(ret);
214+
goto err;
207215

208216
ret = drm_plane_create_alpha_property(&tplane->plane);
209217
if (ret)
210-
return ERR_PTR(ret);
218+
goto err;
211219

212220
ret = drm_plane_create_blend_mode_property(&tplane->plane, blend_modes);
213221
if (ret)
214-
return ERR_PTR(ret);
222+
goto err;
215223

216224
return tplane;
225+
226+
err:
227+
kfree(tplane);
228+
return ERR_PTR(ret);
217229
}

0 commit comments

Comments
 (0)