aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_dp_mst_topology.c
diff options
context:
space:
mode:
authorcpaul@redhat.com <cpaul@redhat.com>2016-04-22 16:08:46 -0400
committerDave Airlie <airlied@redhat.com>2016-04-26 19:26:12 -0400
commit263efde31f97c498e1ebad30e4d2906609d7ad6b (patch)
tree6ff9bf957b91ec23409fe866ef5a43deb8aa884a /drivers/gpu/drm/drm_dp_mst_topology.c
parentbd0b560a75bcebdcb48d82ed81f6b77c12771107 (diff)
drm/dp/mst: Get validated port ref in drm_dp_update_payload_part1()
We can thank KASAN for finding this, otherwise I probably would have spent hours on it. This fixes a somewhat harder to trigger kernel panic, occuring while enabling MST where the port we were currently updating the payload on would have all of it's refs dropped before we finished what we were doing: ================================================================== BUG: KASAN: use-after-free in drm_dp_update_payload_part1+0xb3f/0xdb0 [drm_kms_helper] at addr ffff8800d29de018 Read of size 4 by task Xorg/973 ============================================================================= BUG kmalloc-2048 (Tainted: G B W ): kasan: bad access detected ----------------------------------------------------------------------------- INFO: Allocated in drm_dp_add_port+0x1aa/0x1ed0 [drm_kms_helper] age=16477 cpu=0 pid=2175 ___slab_alloc+0x472/0x490 __slab_alloc+0x20/0x40 kmem_cache_alloc_trace+0x151/0x190 drm_dp_add_port+0x1aa/0x1ed0 [drm_kms_helper] drm_dp_send_link_address+0x526/0x960 [drm_kms_helper] drm_dp_check_and_send_link_address+0x1ac/0x210 [drm_kms_helper] drm_dp_mst_link_probe_work+0x77/0xd0 [drm_kms_helper] process_one_work+0x562/0x1350 worker_thread+0xd9/0x1390 kthread+0x1c5/0x260 ret_from_fork+0x22/0x40 INFO: Freed in drm_dp_free_mst_port+0x50/0x60 [drm_kms_helper] age=7521 cpu=0 pid=2175 __slab_free+0x17f/0x2d0 kfree+0x169/0x180 drm_dp_free_mst_port+0x50/0x60 [drm_kms_helper] drm_dp_destroy_connector_work+0x2b8/0x490 [drm_kms_helper] process_one_work+0x562/0x1350 worker_thread+0xd9/0x1390 kthread+0x1c5/0x260 ret_from_fork+0x22/0x40 which on this T460s, would eventually lead to kernel panics in somewhat random places later in intel_mst_enable_dp() if we got lucky enough. Signed-off-by: Lyude <cpaul@redhat.com> Cc: stable@vger.kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_dp_mst_topology.c')
-rw-r--r--drivers/gpu/drm/drm_dp_mst_topology.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c
index e17fbdaf874b..935d8cc46841 100644
--- a/drivers/gpu/drm/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/drm_dp_mst_topology.c
@@ -1796,6 +1796,11 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
1796 req_payload.start_slot = cur_slots; 1796 req_payload.start_slot = cur_slots;
1797 if (mgr->proposed_vcpis[i]) { 1797 if (mgr->proposed_vcpis[i]) {
1798 port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi); 1798 port = container_of(mgr->proposed_vcpis[i], struct drm_dp_mst_port, vcpi);
1799 port = drm_dp_get_validated_port_ref(mgr, port);
1800 if (!port) {
1801 mutex_unlock(&mgr->payload_lock);
1802 return -EINVAL;
1803 }
1799 req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots; 1804 req_payload.num_slots = mgr->proposed_vcpis[i]->num_slots;
1800 req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi; 1805 req_payload.vcpi = mgr->proposed_vcpis[i]->vcpi;
1801 } else { 1806 } else {
@@ -1823,6 +1828,9 @@ int drm_dp_update_payload_part1(struct drm_dp_mst_topology_mgr *mgr)
1823 mgr->payloads[i].payload_state = req_payload.payload_state; 1828 mgr->payloads[i].payload_state = req_payload.payload_state;
1824 } 1829 }
1825 cur_slots += req_payload.num_slots; 1830 cur_slots += req_payload.num_slots;
1831
1832 if (port)
1833 drm_dp_put_port(port);
1826 } 1834 }
1827 1835
1828 for (i = 0; i < mgr->max_payloads; i++) { 1836 for (i = 0; i < mgr->max_payloads; i++) {