[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v2] hvc/xen: lock console list traversal


  • To: linux-kernel@xxxxxxxxxxxxxxx
  • From: Roger Pau Monne <roger.pau@xxxxxxxxxx>
  • Date: Wed, 30 Nov 2022 17:36:02 +0100
  • Arc-authentication-results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=citrix.com; dmarc=pass action=none header.from=citrix.com; dkim=pass header.d=citrix.com; arc=none
  • Arc-message-signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=TEk6iK5GvuVMLVelUUxiis8clwrCKUaO8K0CKeMME58=; b=Fql3cSUfTvkH2EgyWXKoe7FKwby3AyLKSyFj8eO5vlSCljT2Amck684NgwfbOVCPTvOT3OLoFAVz5vPW/ECMLpQ4/zPq9ziJtd1smXVK+XAaXFld26UkAMSVgDAecQZWd+uCfT7YXljp4sHz14ReicalHzJnykXpTbEr7bud+HiNvyHsqDdLjsMXTBUqsRZvPQ0gjjDpQ4UWubht963WYsGewQqCGedBNVUigI77CyohzTy45TagM3ZfIERfrw+VNzfWx2Qsjl7jDUxB6XJmOC1jVSc3IkalMIQGMOGCFJtVngFgu6n45n18FGnsoBbXuF/uoi6nC14mXnPioQHhmQ==
  • Arc-seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=c209cZJox8fbDBdJi9CeYWU6m7FTrqY3+WhVSsoFPei1/P1qXtDAN2+bajTlphWPlN2Y0/VNUTnxYtC8T6UQ2PaqxXxFbjmLC7Eu2bPJ6hhpw5mOGSbLz8OscRH29d6cGGLoP0rHds30c/FJ/xz0Bnbr78NNUn4kiTA9BPmkZxjX+TlHqNylGkVUCVds8oLmydZPP/mDJUmBGHG2MwjpAGcz7TMXfXykNlljcocz6NRP8kHVeTVxsdj7jx3Nv3W7ZRyAPt4qmUUnGzKMjfdrUrtniWf5KAaPPCayUChXireV8En/rhq60ZAtxHessSriLhExXNXqD4K48WK42PvoAQ==
  • Authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=citrix.com;
  • Cc: xen-devel@xxxxxxxxxxxxxxxxxxxx, Roger Pau Monne <roger.pau@xxxxxxxxxx>, Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>, Jiri Slaby <jirislaby@xxxxxxxxxx>, Juergen Gross <jgross@xxxxxxxx>, Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>, Jan Beulich <jbeulich@xxxxxxxx>, Stefano Stabellini <sstabellini@xxxxxxxxxx>, Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>, linuxppc-dev@xxxxxxxxxxxxxxxx
  • Delivery-date: Wed, 30 Nov 2022 16:37:26 +0000
  • Ironport-data: A9a23:gJeZBK1xsdz1zXPmt/bD5bRxkn2cJEfYwER7XKvMYLTBsI5bpzMOy 2NLCG/UOv2IMzT2LoxyYYy+ox4HvpXSzoQ3SVNppC1hF35El5HIVI+TRqvS04F+DeWYFR46s J9OAjXkBJppJpMJjk71atANlVEliefTAOK5ULSfUsxIbVcMYD87jh5+kPIOjIdtgNyoayuAo tq3qMDEULOf82cc3lk8tuTS9nuDgNyo4GlC5wVlPagR1LPjvyJ94Kw3dPnZw0TQGuG4LsbiL 87fwbew+H/u/htFIrtJRZ6iLyXm6paLVeS/oiI+t5qK23CulQRrukoPD9IOaF8/ttm8t4sZJ OOhF3CHYVxB0qXkwIzxWvTDes10FfUuFLTveRBTvSEPpqFvnrSFL/hGVSkL0YMkFulfAV9tz /cxFBo2YFORodqtkIyiFORnv5F2RCXrFNt3VnBI6xj8VK9jareaBqLA6JlfwSs6gd1IEbDGf c0FZDFzbRPGJRpSJlMQD5F4l+Ct7pX9W2QA9BTJ+uxqvS6KklwZPLvFabI5fvSQQspYhACAr 3/u9GXlGBAKcteYzFJp91r82LSXx3qkA+r+EpXj/Ll4jWGO2VUWIx8bU2HrnamyhnaxDoc3x 0s8v3BGQbIJ3EiqSMTtGh61uniJujYCVNdKVe438geAzuzT+QnxLngJSHtNZcIrsOcyRCc2z RmZktXxHzttvbaJD3WH+d+8oim/NisVBWsDYzIUQwwY5dXqvIA0iFTIVNkLOKy0lNzuHTj60 hiJoTI4irFVitQEv4258krAmCmEvYXSQ0g+4QC/dmii9AJiIom+e5av90PY/N5HNo+SSlTHt 38B8+Cc5u0TCZCGlASWXf4AWrqu4p6tKybAiFRiG50g8TWF+HO5e41UpjZkKy9BMcECYzblJ lDSvQB544VaN3+nK6RwZuqZD8Us0Lj4Dd+gWv3KRt5PeYRqMgiV+ChkfgiXxW+FraQ3uaQ2O JPeesH1C38fUP1j1GDvGbdb1qI3zCcjw2+VXYr80xmszbuZYjiSVKsBN1yNKOs+6ctovTnoz jqWDOPSoz03bQE0SnC/HVI7RbzSEUUGOA==
  • Ironport-hdrordr: A9a23:ZPSbV6NantNhHMBcTgajsMiBIKoaSvp037By7TEJdfRUGvb4qy ncpoVi6faUskduZJhOo6HkBEDtexzhHNtOkO8s1NSZLXjbUQmTXeVfBOLZqlWKcUCTygce79 YGT0EUMr3N5C1B/KTHCX6DYrUdKbe8npxAzt2utEuFBTsaEZ1I/kN1AhuSCU1tRgNCDYAiFJ Wd7MJbpzymEE5nE/hTKEN1INQqELfw5e7bXSI=
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

The currently lockless access to the xen console list in
vtermno_to_xencons() is incorrect, as additions and removals from the
list can happen anytime, and as such the traversal of the list to get
the private console data for a given termno needs to happen with the
lock held.  Note users that modify the list already do so with the
lock taken.

Adjust current lock takers to use the _irq{save,restore} helpers,
since the context in which vtermno_to_xencons() is called can have
interrupts disabled.  Use the _irq{save,restore} set of helpers to
switch the current callers to disable interrupts in the locked region.
I haven't checked if existing users could instead use the _irq
variant, as I think it's safer to use _irq{save,restore} upfront.

While there switch from using list_for_each_entry_safe to
list_for_each_entry: the current entry cursor won't be removed as
part of the code in the loop body, so using the _safe variant is
pointless.

Fixes: 02e19f9c7cac ('hvc_xen: implement multiconsole support')
Signed-off-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
Changes since v1:
 - Switch current lock users to disable interrupts in the locked
   region.
---
 drivers/tty/hvc/hvc_xen.c | 46 ++++++++++++++++++++++++---------------
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/drivers/tty/hvc/hvc_xen.c b/drivers/tty/hvc/hvc_xen.c
index e63c1761a361..d9d023275328 100644
--- a/drivers/tty/hvc/hvc_xen.c
+++ b/drivers/tty/hvc/hvc_xen.c
@@ -53,17 +53,22 @@ static DEFINE_SPINLOCK(xencons_lock);
 
 static struct xencons_info *vtermno_to_xencons(int vtermno)
 {
-       struct xencons_info *entry, *n, *ret = NULL;
+       struct xencons_info *entry, *ret = NULL;
+       unsigned long flags;
 
-       if (list_empty(&xenconsoles))
-                       return NULL;
+       spin_lock_irqsave(&xencons_lock, flags);
+       if (list_empty(&xenconsoles)) {
+               spin_unlock_irqrestore(&xencons_lock, flags);
+               return NULL;
+       }
 
-       list_for_each_entry_safe(entry, n, &xenconsoles, list) {
+       list_for_each_entry(entry, &xenconsoles, list) {
                if (entry->vtermno == vtermno) {
                        ret  = entry;
                        break;
                }
        }
+       spin_unlock_irqrestore(&xencons_lock, flags);
 
        return ret;
 }
@@ -234,7 +239,7 @@ static int xen_hvm_console_init(void)
 {
        int r;
        uint64_t v = 0;
-       unsigned long gfn;
+       unsigned long gfn, flags;
        struct xencons_info *info;
 
        if (!xen_hvm_domain())
@@ -270,9 +275,9 @@ static int xen_hvm_console_init(void)
                goto err;
        info->vtermno = HVC_COOKIE;
 
-       spin_lock(&xencons_lock);
+       spin_lock_irqsave(&xencons_lock, flags);
        list_add_tail(&info->list, &xenconsoles);
-       spin_unlock(&xencons_lock);
+       spin_unlock_irqrestore(&xencons_lock, flags);
 
        return 0;
 err:
@@ -296,6 +301,7 @@ static int xencons_info_pv_init(struct xencons_info *info, 
int vtermno)
 static int xen_pv_console_init(void)
 {
        struct xencons_info *info;
+       unsigned long flags;
 
        if (!xen_pv_domain())
                return -ENODEV;
@@ -312,9 +318,9 @@ static int xen_pv_console_init(void)
                /* already configured */
                return 0;
        }
-       spin_lock(&xencons_lock);
+       spin_lock_irqsave(&xencons_lock, flags);
        xencons_info_pv_init(info, HVC_COOKIE);
-       spin_unlock(&xencons_lock);
+       spin_unlock_irqrestore(&xencons_lock, flags);
 
        return 0;
 }
@@ -322,6 +328,7 @@ static int xen_pv_console_init(void)
 static int xen_initial_domain_console_init(void)
 {
        struct xencons_info *info;
+       unsigned long flags;
 
        if (!xen_initial_domain())
                return -ENODEV;
@@ -337,9 +344,9 @@ static int xen_initial_domain_console_init(void)
        info->irq = bind_virq_to_irq(VIRQ_CONSOLE, 0, false);
        info->vtermno = HVC_COOKIE;
 
-       spin_lock(&xencons_lock);
+       spin_lock_irqsave(&xencons_lock, flags);
        list_add_tail(&info->list, &xenconsoles);
-       spin_unlock(&xencons_lock);
+       spin_unlock_irqrestore(&xencons_lock, flags);
 
        return 0;
 }
@@ -394,10 +401,12 @@ static void xencons_free(struct xencons_info *info)
 
 static int xen_console_remove(struct xencons_info *info)
 {
+       unsigned long flags;
+
        xencons_disconnect_backend(info);
-       spin_lock(&xencons_lock);
+       spin_lock_irqsave(&xencons_lock, flags);
        list_del(&info->list);
-       spin_unlock(&xencons_lock);
+       spin_unlock_irqrestore(&xencons_lock, flags);
        if (info->xbdev != NULL)
                xencons_free(info);
        else {
@@ -478,6 +487,7 @@ static int xencons_probe(struct xenbus_device *dev,
 {
        int ret, devid;
        struct xencons_info *info;
+       unsigned long flags;
 
        devid = dev->nodename[strlen(dev->nodename) - 1] - '0';
        if (devid == 0)
@@ -497,9 +507,9 @@ static int xencons_probe(struct xenbus_device *dev,
        ret = xencons_connect_backend(dev, info);
        if (ret < 0)
                goto error;
-       spin_lock(&xencons_lock);
+       spin_lock_irqsave(&xencons_lock, flags);
        list_add_tail(&info->list, &xenconsoles);
-       spin_unlock(&xencons_lock);
+       spin_unlock_irqrestore(&xencons_lock, flags);
 
        return 0;
 
@@ -599,10 +609,12 @@ static int __init xen_hvc_init(void)
 
        info->hvc = hvc_alloc(HVC_COOKIE, info->irq, ops, 256);
        if (IS_ERR(info->hvc)) {
+               unsigned long flags;
+
                r = PTR_ERR(info->hvc);
-               spin_lock(&xencons_lock);
+               spin_lock_irqsave(&xencons_lock, flags);
                list_del(&info->list);
-               spin_unlock(&xencons_lock);
+               spin_unlock_irqrestore(&xencons_lock, flags);
                if (info->irq)
                        unbind_from_irqhandler(info->irq, NULL);
                kfree(info);
-- 
2.37.3




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.