Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756790AbcDDX66 (ORCPT ); Mon, 4 Apr 2016 19:58:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41280 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752510AbcDDX64 (ORCPT ); Mon, 4 Apr 2016 19:58:56 -0400 From: Lyude To: dri-devel@lists.freedesktop.org Cc: Lyude , stable@vger.kernel.org, David Airlie , linux-kernel@vger.kernel.org (open list) Subject: [PATCH RESEND] drm/dp/mst: Validate port in drm_dp_payload_send_msg() Date: Mon, 4 Apr 2016 19:58:47 -0400 Message-Id: <1459814327-25039-1-git-send-email-cpaul@redhat.com> In-Reply-To: <1459812826-20760-1-git-send-email-cpaul@redhat.com> References: <1459812826-20760-1-git-send-email-cpaul@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 04 Apr 2016 23:58:55 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 3310 Lines: 83 With the joys of things running concurrently, there's always a chance that the port we get passed in drm_dp_payload_send_msg() isn't actually valid anymore. Because of this, we need to make sure we validate the reference to the port before we use it otherwise we risk running into various race conditions. For instance, on the Dell MST monitor I have here for testing, hotplugging it enough times causes us to kernel panic: [drm:intel_mst_enable_dp] 1 [drm:drm_dp_update_payload_part2] payload 0 1 [drm:intel_get_hpd_pins] hotplug event received, stat 0x00200000, dig 0x10101011, pins 0x00000020 [drm:intel_hpd_irq_handler] digital hpd port B - short [drm:intel_dp_hpd_pulse] got hpd irq on port B - short [drm:intel_dp_check_mst_status] got esi 00 10 00 [drm:drm_dp_update_payload_part2] payload 1 1 general protection fault: 0000 [#1] SMP … Call Trace: [] drm_dp_update_payload_part2+0xc2/0x130 [drm_kms_helper] [] intel_mst_enable_dp+0xf8/0x180 [i915] [] haswell_crtc_enable+0x3ed/0x8c0 [i915] [] intel_atomic_commit+0x5ad/0x1590 [i915] [] ? drm_atomic_set_crtc_for_connector+0x57/0xe0 [drm] [] drm_atomic_commit+0x37/0x60 [drm] [] drm_atomic_helper_set_config+0x7a/0xb0 [drm_kms_helper] [] drm_mode_set_config_internal+0x62/0x100 [drm] [] drm_mode_setcrtc+0x3cd/0x4e0 [drm] [] drm_ioctl+0x143/0x510 [drm] [] ? drm_mode_setplane+0x1b0/0x1b0 [drm] [] ? hrtimer_start_range_ns+0x1b7/0x3a0 [] do_vfs_ioctl+0x92/0x570 [] ? __sys_recvmsg+0x42/0x80 [] SyS_ioctl+0x79/0x90 [] entry_SYSCALL_64_fastpath+0x1a/0xa4 RIP [] drm_dp_payload_send_msg+0x146/0x1f0 [drm_kms_helper] Which occurs because of the hotplug event shown in the log, which ends up causing DRM's dp helpers to drop the port we're updating the payload on and panic. CC: stable@vger.kernel.org Signed-off-by: Lyude Reviewed-by: David Airlie --- Resending since I forgot to CC stable on this patch the first time drivers/gpu/drm/drm_dp_mst_topology.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 27fbd79..e17fbda 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1672,13 +1672,19 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, u8 sinks[DRM_DP_MAX_SDP_STREAMS]; int i; + port = drm_dp_get_validated_port_ref(mgr, port); + if (!port) + return -EINVAL; + port_num = port->port_num; mstb = drm_dp_get_validated_mstb_ref(mgr, port->parent); if (!mstb) { mstb = drm_dp_get_last_connected_port_and_mstb(mgr, port->parent, &port_num); - if (!mstb) + if (!mstb) { + drm_dp_put_port(port); return -EINVAL; + } } txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); @@ -1707,6 +1713,7 @@ static int drm_dp_payload_send_msg(struct drm_dp_mst_topology_mgr *mgr, kfree(txmsg); fail_put: drm_dp_put_mst_branch_device(mstb); + drm_dp_put_port(port); return ret; } -- 2.5.5