Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp981125imm; Fri, 13 Jul 2018 09:26:08 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdRi3z9UMGO8WnJXwGsZ4nxjYCDeQo3Q0u2I4p+YGle8rAPBtKQhUe+mzlbplwzFZxVe+Bn X-Received: by 2002:a62:9f16:: with SMTP id g22-v6mr7678446pfe.207.1531499168766; Fri, 13 Jul 2018 09:26:08 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531499168; cv=none; d=google.com; s=arc-20160816; b=RJiPE7GPjiGWDC3f/l8O11dMaslhn7+BrclSynfiBhJVIMV3P0+s3lxt3iXrIZi+YD ipJbU/5/A575OEuoCugsWa2BTrrtvYFzoX/MBxS75tw9BxNk0gyRbyE+5Kz95jYHMvDQ he8wfKRcTdAmPKDeLU/F48a0G5fVnd025po5rJSer0uSZ0EZvSM8ws9Qexiq+v8XCHlV zupM4sAderc30ENRTm+y0wY/ZC0l0f6vqVgnGdv9seG/vJ9VoUuFsIK0qEw0/jRe4jxx 0fiINIJ6RexDvPHcAJyieo5lFDs976A4pRwUOiZvl0X+eqKXYlyNuxMqWj4ro6qgjOcF +GRA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:arc-authentication-results; bh=qt999mLXHT0JWVqUeaB2Lou64tM45Xlm7Y5T/isIzCc=; b=BX7HhPCVLGRvg4E2wvTZ1KcsK+dbxcIp58gwSnIBABeUKujRu2H4i5xDhImbZGVA5h MlLxFpGbyFBGX46z8oBKKMwAuYk+P8tYmuzlvOv0w30HAYwt5kKpgxFZJ+rU+rUeppWa wjPEhd8H3RPoUoqedEVoMYmhJo+n6KxBPMFDwxEYDeQjf/rEx+7aUJazaQL2rlXlJAEl H1WlXK9n48tH+DfuqJkW11Gts18m8qvCI6JFWwxKYIoLCfY7LWj0TOe+AVIHVfz58EgK M5s2EZmLkhvSm5juWUVsLL19cHEhSaV964LEQ5erzGXRMN3DdvhEpeGdoChjsUx2BLFm 0ksQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id q129-v6si23157451pga.217.2018.07.13.09.25.54; Fri, 13 Jul 2018 09:26:08 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=redhat.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2387611AbeGMQkV (ORCPT + 99 others); Fri, 13 Jul 2018 12:40:21 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:33610 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1729735AbeGMQkU (ORCPT ); Fri, 13 Jul 2018 12:40:20 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 37DDA7A7F1; Fri, 13 Jul 2018 16:24:59 +0000 (UTC) Received: from whitewolf.lyude.net.com (ovpn-125-176.rdu2.redhat.com [10.10.125.176]) by smtp.corp.redhat.com (Postfix) with ESMTP id C45FF1C67B; Fri, 13 Jul 2018 16:24:58 +0000 (UTC) From: Lyude Paul To: nouveau@lists.freedesktop.org Cc: stable@vger.kernel.org, Karol Herbst , Ben Skeggs , David Airlie , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/2] drm/nouveau: Use drm_connector_list_iter_* for iterating connectors Date: Fri, 13 Jul 2018 12:24:40 -0400 Message-Id: <20180713162442.22522-2-lyude@redhat.com> In-Reply-To: <20180713162442.22522-1-lyude@redhat.com> References: <20180713162442.22522-1-lyude@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 13 Jul 2018 16:24:59 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.2]); Fri, 13 Jul 2018 16:24:59 +0000 (UTC) for IP:'10.11.54.5' DOMAIN:'int-mx05.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'lyude@redhat.com' RCPT:'' Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Every codepath in nouveau that loops through the connector list currently does so using the old method, which is prone to race conditions from MST connectors being created and destroyed. This has been causing a multitude of problems, including memory corruption from trying to access connectors that have already been freed! Signed-off-by: Lyude Paul Cc: stable@vger.kernel.org Cc: Karol Herbst --- drivers/gpu/drm/nouveau/nouveau_backlight.c | 6 ++++-- drivers/gpu/drm/nouveau/nouveau_connector.c | 9 +++++++-- drivers/gpu/drm/nouveau/nouveau_connector.h | 14 ++++++++++---- drivers/gpu/drm/nouveau/nouveau_display.c | 10 ++++++++-- 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_backlight.c b/drivers/gpu/drm/nouveau/nouveau_backlight.c index debbbf0fd4bd..408b955e5c39 100644 --- a/drivers/gpu/drm/nouveau/nouveau_backlight.c +++ b/drivers/gpu/drm/nouveau/nouveau_backlight.c @@ -267,6 +267,7 @@ nouveau_backlight_init(struct drm_device *dev) struct nouveau_drm *drm = nouveau_drm(dev); struct nvif_device *device = &drm->client.device; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; INIT_LIST_HEAD(&drm->bl_connectors); @@ -275,7 +276,8 @@ nouveau_backlight_init(struct drm_device *dev) return 0; } - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->connector_type != DRM_MODE_CONNECTOR_LVDS && connector->connector_type != DRM_MODE_CONNECTOR_eDP) continue; @@ -292,7 +294,7 @@ nouveau_backlight_init(struct drm_device *dev) break; } } - + drm_connector_list_iter_end(&conn_iter); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 7b557c354307..7dc380449232 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1208,14 +1208,19 @@ nouveau_connector_create(struct drm_device *dev, int index) struct nouveau_display *disp = nouveau_display(dev); struct nouveau_connector *nv_connector = NULL; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; int type, ret = 0; bool dummy; - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { nv_connector = nouveau_connector(connector); - if (nv_connector->index == index) + if (nv_connector->index == index) { + drm_connector_list_iter_end(&conn_iter); return connector; + } } + drm_connector_list_iter_end(&conn_iter); nv_connector = kzalloc(sizeof(*nv_connector), GFP_KERNEL); if (!nv_connector) diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index a4d1a059bd3d..a8cbb4b56fc7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -65,14 +65,20 @@ nouveau_crtc_connector_get(struct nouveau_crtc *nv_crtc) { struct drm_device *dev = nv_crtc->base.dev; struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; + struct nouveau_connector *nv_connector = NULL; struct drm_crtc *crtc = to_drm_crtc(nv_crtc); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { - if (connector->encoder && connector->encoder->crtc == crtc) - return nouveau_connector(connector); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->encoder && connector->encoder->crtc == crtc) { + nv_connector = nouveau_connector(connector); + break; + } } + drm_connector_list_iter_end(&conn_iter); - return NULL; + return nv_connector; } struct drm_connector * diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 774b429142bc..46b8430ef4aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -404,6 +404,7 @@ nouveau_display_init(struct drm_device *dev) struct nouveau_display *disp = nouveau_display(dev); struct nouveau_drm *drm = nouveau_drm(dev); struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; int ret; ret = disp->init(dev); @@ -411,10 +412,12 @@ nouveau_display_init(struct drm_device *dev) return ret; /* enable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct nouveau_connector *conn = nouveau_connector(connector); nvif_notify_get(&conn->hpd); } + drm_connector_list_iter_end(&conn_iter); /* enable flip completion events */ nvif_notify_get(&drm->flip); @@ -427,6 +430,7 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) struct nouveau_display *disp = nouveau_display(dev); struct nouveau_drm *drm = nouveau_drm(dev); struct drm_connector *connector; + struct drm_connector_list_iter conn_iter; if (!suspend) { if (drm_drv_uses_atomic_modeset(dev)) @@ -439,10 +443,12 @@ nouveau_display_fini(struct drm_device *dev, bool suspend) nvif_notify_put(&drm->flip); /* disable hotplug interrupts */ - list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct nouveau_connector *conn = nouveau_connector(connector); nvif_notify_put(&conn->hpd); } + drm_connector_list_iter_end(&conn_iter); drm_kms_helper_poll_disable(dev); disp->fini(dev); -- 2.17.1