Skip to content

Commit f4f19c0

Browse files
committed
Merge tag 'drm-misc-fixes-2023-07-20' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
Memory leak fixes in drm/client, memory access/leak fixes for accel/qaic, another leak fix in dma-buf and three nouveau fixes around hotplugging. Signed-off-by: Dave Airlie <[email protected]> From: Maxime Ripard <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/fmj5nok7zggux2lcpdtls2iknweba54wfc6o4zxq6i6s3dgi2r@7z3eawwhyhen
2 parents 78e9b21 + ea293f8 commit f4f19c0

File tree

7 files changed

+73
-31
lines changed

7 files changed

+73
-31
lines changed

drivers/accel/qaic/qaic_control.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/mm.h>
1515
#include <linux/moduleparam.h>
1616
#include <linux/mutex.h>
17+
#include <linux/overflow.h>
1718
#include <linux/pci.h>
1819
#include <linux/scatterlist.h>
1920
#include <linux/types.h>
@@ -366,7 +367,7 @@ static int encode_passthrough(struct qaic_device *qdev, void *trans, struct wrap
366367
if (in_trans->hdr.len % 8 != 0)
367368
return -EINVAL;
368369

369-
if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_EXT_MSG_LENGTH)
370+
if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_EXT_MSG_LENGTH)
370371
return -ENOSPC;
371372

372373
trans_wrapper = add_wrapper(wrappers,
@@ -418,9 +419,12 @@ static int find_and_map_user_pages(struct qaic_device *qdev,
418419
}
419420

420421
ret = get_user_pages_fast(xfer_start_addr, nr_pages, 0, page_list);
421-
if (ret < 0 || ret != nr_pages) {
422-
ret = -EFAULT;
422+
if (ret < 0)
423423
goto free_page_list;
424+
if (ret != nr_pages) {
425+
nr_pages = ret;
426+
ret = -EFAULT;
427+
goto put_pages;
424428
}
425429

426430
sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
@@ -557,11 +561,8 @@ static int encode_dma(struct qaic_device *qdev, void *trans, struct wrapper_list
557561
msg = &wrapper->msg;
558562
msg_hdr_len = le32_to_cpu(msg->hdr.len);
559563

560-
if (msg_hdr_len > (UINT_MAX - QAIC_MANAGE_EXT_MSG_LENGTH))
561-
return -EINVAL;
562-
563564
/* There should be enough space to hold at least one ASP entry. */
564-
if (msg_hdr_len + sizeof(*out_trans) + sizeof(struct wire_addr_size_pair) >
565+
if (size_add(msg_hdr_len, sizeof(*out_trans) + sizeof(struct wire_addr_size_pair)) >
565566
QAIC_MANAGE_EXT_MSG_LENGTH)
566567
return -ENOMEM;
567568

@@ -634,7 +635,7 @@ static int encode_activate(struct qaic_device *qdev, void *trans, struct wrapper
634635
msg = &wrapper->msg;
635636
msg_hdr_len = le32_to_cpu(msg->hdr.len);
636637

637-
if (msg_hdr_len + sizeof(*out_trans) > QAIC_MANAGE_MAX_MSG_LENGTH)
638+
if (size_add(msg_hdr_len, sizeof(*out_trans)) > QAIC_MANAGE_MAX_MSG_LENGTH)
638639
return -ENOSPC;
639640

640641
if (!in_trans->queue_size)
@@ -718,7 +719,7 @@ static int encode_status(struct qaic_device *qdev, void *trans, struct wrapper_l
718719
msg = &wrapper->msg;
719720
msg_hdr_len = le32_to_cpu(msg->hdr.len);
720721

721-
if (msg_hdr_len + in_trans->hdr.len > QAIC_MANAGE_MAX_MSG_LENGTH)
722+
if (size_add(msg_hdr_len, in_trans->hdr.len) > QAIC_MANAGE_MAX_MSG_LENGTH)
722723
return -ENOSPC;
723724

724725
trans_wrapper = add_wrapper(wrappers, sizeof(*trans_wrapper));
@@ -748,7 +749,8 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
748749
int ret;
749750
int i;
750751

751-
if (!user_msg->count) {
752+
if (!user_msg->count ||
753+
user_msg->len < sizeof(*trans_hdr)) {
752754
ret = -EINVAL;
753755
goto out;
754756
}
@@ -765,12 +767,13 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
765767
}
766768

767769
for (i = 0; i < user_msg->count; ++i) {
768-
if (user_len >= user_msg->len) {
770+
if (user_len > user_msg->len - sizeof(*trans_hdr)) {
769771
ret = -EINVAL;
770772
break;
771773
}
772774
trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len);
773-
if (user_len + trans_hdr->len > user_msg->len) {
775+
if (trans_hdr->len < sizeof(trans_hdr) ||
776+
size_add(user_len, trans_hdr->len) > user_msg->len) {
774777
ret = -EINVAL;
775778
break;
776779
}
@@ -953,15 +956,23 @@ static int decode_message(struct qaic_device *qdev, struct manage_msg *user_msg,
953956
int ret;
954957
int i;
955958

956-
if (msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
959+
if (msg_hdr_len < sizeof(*trans_hdr) ||
960+
msg_hdr_len > QAIC_MANAGE_MAX_MSG_LENGTH)
957961
return -EINVAL;
958962

959963
user_msg->len = 0;
960964
user_msg->count = le32_to_cpu(msg->hdr.count);
961965

962966
for (i = 0; i < user_msg->count; ++i) {
967+
u32 hdr_len;
968+
969+
if (msg_len > msg_hdr_len - sizeof(*trans_hdr))
970+
return -EINVAL;
971+
963972
trans_hdr = (struct wire_trans_hdr *)(msg->data + msg_len);
964-
if (msg_len + le32_to_cpu(trans_hdr->len) > msg_hdr_len)
973+
hdr_len = le32_to_cpu(trans_hdr->len);
974+
if (hdr_len < sizeof(*trans_hdr) ||
975+
size_add(msg_len, hdr_len) > msg_hdr_len)
965976
return -EINVAL;
966977

967978
switch (le32_to_cpu(trans_hdr->type)) {

drivers/dma-buf/dma-resv.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
571571
dma_resv_for_each_fence_unlocked(&cursor, fence) {
572572

573573
if (dma_resv_iter_is_restarted(&cursor)) {
574+
struct dma_fence **new_fences;
574575
unsigned int count;
575576

576577
while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
579580
count = cursor.num_fences + 1;
580581

581582
/* Eventually re-allocate the array */
582-
*fences = krealloc_array(*fences, count,
583-
sizeof(void *),
584-
GFP_KERNEL);
585-
if (count && !*fences) {
583+
new_fences = krealloc_array(*fences, count,
584+
sizeof(void *),
585+
GFP_KERNEL);
586+
if (count && !new_fences) {
587+
kfree(*fences);
588+
*fences = NULL;
589+
*num_fences = 0;
586590
dma_resv_iter_end(&cursor);
587591
return -ENOMEM;
588592
}
593+
*fences = new_fences;
589594
}
590595

591596
(*fences)[(*num_fences)++] = dma_fence_get(fence);

drivers/gpu/drm/drm_client_modeset.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@ static bool drm_client_target_cloned(struct drm_device *dev,
311311
can_clone = true;
312312
dmt_mode = drm_mode_find_dmt(dev, 1024, 768, 60, false);
313313

314+
if (!dmt_mode)
315+
goto fail;
316+
314317
for (i = 0; i < connector_count; i++) {
315318
if (!enabled[i])
316319
continue;
@@ -326,11 +329,13 @@ static bool drm_client_target_cloned(struct drm_device *dev,
326329
if (!modes[i])
327330
can_clone = false;
328331
}
332+
kfree(dmt_mode);
329333

330334
if (can_clone) {
331335
DRM_DEBUG_KMS("can clone using 1024x768\n");
332336
return true;
333337
}
338+
fail:
334339
DRM_INFO("kms: can't enable cloning when we probably wanted to.\n");
335340
return false;
336341
}
@@ -862,6 +867,7 @@ int drm_client_modeset_probe(struct drm_client_dev *client, unsigned int width,
862867
break;
863868
}
864869

870+
kfree(modeset->mode);
865871
modeset->mode = drm_mode_duplicate(dev, mode);
866872
drm_connector_get(connector);
867873
modeset->connectors[modeset->num_connectors++] = connector;

drivers/gpu/drm/nouveau/dispnv50/disp.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,8 @@ nv50_pior_destroy(struct drm_encoder *encoder)
18771877
nvif_outp_dtor(&nv_encoder->outp);
18781878

18791879
drm_encoder_cleanup(encoder);
1880+
1881+
mutex_destroy(&nv_encoder->dp.hpd_irq_lock);
18801882
kfree(encoder);
18811883
}
18821884

@@ -1921,6 +1923,8 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe)
19211923
nv_encoder->i2c = ddc;
19221924
nv_encoder->aux = aux;
19231925

1926+
mutex_init(&nv_encoder->dp.hpd_irq_lock);
1927+
19241928
encoder = to_drm_encoder(nv_encoder);
19251929
encoder->possible_crtcs = dcbe->heads;
19261930
encoder->possible_clones = 0;

drivers/gpu/drm/nouveau/include/nvkm/subdev/i2c.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ struct nvkm_i2c_bus {
1616
const struct nvkm_i2c_bus_func *func;
1717
struct nvkm_i2c_pad *pad;
1818
#define NVKM_I2C_BUS_CCB(n) /* 'n' is ccb index */ (n)
19-
#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
19+
#define NVKM_I2C_BUS_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10)
2020
#define NVKM_I2C_BUS_PRI /* ccb primary comm. port */ -1
2121
#define NVKM_I2C_BUS_SEC /* ccb secondary comm. port */ -2
2222
int id;
@@ -38,7 +38,7 @@ struct nvkm_i2c_aux {
3838
const struct nvkm_i2c_aux_func *func;
3939
struct nvkm_i2c_pad *pad;
4040
#define NVKM_I2C_AUX_CCB(n) /* 'n' is ccb index */ (n)
41-
#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x100)
41+
#define NVKM_I2C_AUX_EXT(n) /* 'n' is dcb external encoder type */ ((n) + 0x10)
4242
int id;
4343

4444
struct mutex mutex;

drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,29 @@ nvkm_uconn_uevent(struct nvkm_object *object, void *argv, u32 argc, struct nvkm_
8181
return -ENOSYS;
8282

8383
list_for_each_entry(outp, &conn->disp->outps, head) {
84-
if (outp->info.connector == conn->index && outp->dp.aux) {
85-
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG;
86-
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
87-
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ;
84+
if (outp->info.connector == conn->index)
85+
break;
86+
}
8887

89-
return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
90-
nvkm_uconn_uevent_aux);
91-
}
88+
if (&outp->head == &conn->disp->outps)
89+
return -EINVAL;
90+
91+
if (outp->dp.aux && !outp->info.location) {
92+
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_I2C_PLUG;
93+
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_I2C_UNPLUG;
94+
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ ) bits |= NVKM_I2C_IRQ;
95+
96+
return nvkm_uevent_add(uevent, &device->i2c->event, outp->dp.aux->id, bits,
97+
nvkm_uconn_uevent_aux);
9298
}
9399

94100
if (args->v0.types & NVIF_CONN_EVENT_V0_PLUG ) bits |= NVKM_GPIO_HI;
95101
if (args->v0.types & NVIF_CONN_EVENT_V0_UNPLUG) bits |= NVKM_GPIO_LO;
96-
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ)
97-
return -EINVAL;
102+
if (args->v0.types & NVIF_CONN_EVENT_V0_IRQ) {
103+
/* TODO: support DP IRQ on ANX9805 and remove this hack. */
104+
if (!outp->info.location)
105+
return -EINVAL;
106+
}
98107

99108
return nvkm_uevent_add(uevent, &device->gpio->event, conn->info.hpd, bits,
100109
nvkm_uconn_uevent_gpio);

drivers/gpu/drm/nouveau/nvkm/subdev/i2c/base.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
260260
{
261261
struct nvkm_bios *bios = device->bios;
262262
struct nvkm_i2c *i2c;
263+
struct nvkm_i2c_aux *aux;
263264
struct dcb_i2c_entry ccbE;
264265
struct dcb_output dcbE;
265266
u8 ver, hdr;
266-
int ret, i;
267+
int ret, i, ids;
267268

268269
if (!(i2c = *pi2c = kzalloc(sizeof(*i2c), GFP_KERNEL)))
269270
return -ENOMEM;
@@ -406,5 +407,11 @@ nvkm_i2c_new_(const struct nvkm_i2c_func *func, struct nvkm_device *device,
406407
}
407408
}
408409

409-
return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, i, &i2c->event);
410+
ids = 0;
411+
list_for_each_entry(aux, &i2c->aux, head)
412+
ids = max(ids, aux->id + 1);
413+
if (!ids)
414+
return 0;
415+
416+
return nvkm_event_init(&nvkm_i2c_intr_func, &i2c->subdev, 4, ids, &i2c->event);
410417
}

0 commit comments

Comments
 (0)