Received: by 2002:ac0:a5a7:0:0:0:0:0 with SMTP id m36-v6csp1112826imm; Wed, 1 Aug 2018 10:23:18 -0700 (PDT) X-Google-Smtp-Source: AAOMgpdDSElmvHnT6618Nm6vtXO+/XeuwhrldFjnCVU1zPQ+OQ/MuxZy6PxEbFm5zy1ADQe+1+MQ X-Received: by 2002:a63:1722:: with SMTP id x34-v6mr25582146pgl.268.1533144198868; Wed, 01 Aug 2018 10:23:18 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1533144198; cv=none; d=google.com; s=arc-20160816; b=nZtWRAt48BXefPCqm+eUuKAI9Fq3QFXlJe52mJwOfL+5O8NPApoSfJfgaXz0Sjo5I1 Umj8V14IMbjYio/eWkqAS2vd0ErXUF9iEsXAatgTPm+4XO7/yPEXhmv5L7FhRyZwlYBb NtCarWd3OIszzToupg5320Nl5v730Npr1LdqsCfWiPtNRIiJOeYODSzP5nRiadvQ5H6Z x/jZ+1qy9/zT39/eOUgUUN/XBvTIge1Zzzw5nGXvGgh34m0gRjZO7lD8BtWWm+BJyk3G +tqal/WxkReaoJOhzCeAXkY2KggFr7V+sH/2K3fvIzGpTUOYPQEXhqaA0kMyW4dPjLPt POyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:mime-version:user-agent:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=uYN4+5MTMlnosvbmjHhLJHl9iWVDNu50n0ExBkz1AlQ=; b=clqDzhQ4xqdlGBuNcs7CjuAH1RgmQUIsgI/dO8vZack3RN3Cbs6YpFkvVE1hIagbUw 5YQ7sI5JDMaR7/zjWgbaRk4iva3N5lJ8MyH6w98IKzHjOXRNMTqt2noA9QqH2rwOTc4E PdcnFhPus9hS+kSyQP/+CMvEpEpxrF5e+EsZ5aGdjK3tKQ3ZHm7frF1tjdK5eApa8Ta0 HT1IUCByx5ejCjVyLeJvVNSNwaDp3FGGDW+UKGQwrgkAX/KSGndKV/hAwJk093kCfVE9 QyfHG9/uanECBtNuJpZ2ATr7LhDkE4luUxGjnWbotpNVY/yQiZqY5tC21D3+11SM5FPJ ryBg== 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 29-v6si16775737pgv.292.2018.08.01.10.23.04; Wed, 01 Aug 2018 10:23:18 -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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405499AbeHATH3 (ORCPT + 99 others); Wed, 1 Aug 2018 15:07:29 -0400 Received: from mail.linuxfoundation.org ([140.211.169.12]:49202 "EHLO mail.linuxfoundation.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2404995AbeHATH3 (ORCPT ); Wed, 1 Aug 2018 15:07:29 -0400 Received: from localhost (D57E6652.static.ziggozakelijk.nl [213.126.102.82]) by mail.linuxfoundation.org (Postfix) with ESMTPSA id 3E1FBCC2; Wed, 1 Aug 2018 17:20:47 +0000 (UTC) From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Kirill Tkhai , Jeff Layton , Sasha Levin Subject: [PATCH 4.14 179/246] fasync: Fix deadlock between task-context and interrupt-context kill_fasync() Date: Wed, 1 Aug 2018 18:51:29 +0200 Message-Id: <20180801165020.297656999@linuxfoundation.org> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180801165011.700991984@linuxfoundation.org> References: <20180801165011.700991984@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.14-stable review patch. If anyone has any objections, please let me know. ------------------ From: Kirill Tkhai [ Upstream commit 7a107c0f55a3b4c6f84a4323df5610360bde1684 ] I observed the following deadlock between them: [task 1] [task 2] [task 3] kill_fasync() mm_update_next_owner() copy_process() spin_lock_irqsave(&fa->fa_lock) read_lock(&tasklist_lock) write_lock_irq(&tasklist_lock) send_sigio() ... read_lock(&fown->lock) kill_fasync() ... read_lock(&tasklist_lock) spin_lock_irqsave(&fa->fa_lock) ... Task 1 can't acquire read locked tasklist_lock, since there is already task 3 expressed its wish to take the lock exclusive. Task 2 holds the read locked lock, but it can't take the spin lock. Also, there is possible another deadlock (which I haven't observed): [task 1] [task 2] f_getown() kill_fasync() read_lock(&f_own->lock) spin_lock_irqsave(&fa->fa_lock,) send_sigio() write_lock_irq(&f_own->lock) kill_fasync() read_lock(&fown->lock) spin_lock_irqsave(&fa->fa_lock,) Actually, we do not need exclusive fa->fa_lock in kill_fasync_rcu(), as it guarantees fa->fa_file->f_owner integrity only. It may seem, that it used to give a task a small possibility to receive two sequential signals, if there are two parallel kill_fasync() callers, and task handles the first signal fastly, but the behaviour won't become different, since there is exclusive sighand lock in do_send_sig_info(). The patch converts fa_lock into rwlock_t, and this fixes two above deadlocks, as rwlock is allowed to be taken from interrupt handler by qrwlock design. Signed-off-by: Kirill Tkhai Signed-off-by: Jeff Layton Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- fs/fcntl.c | 15 +++++++-------- include/linux/fs.h | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) --- a/fs/fcntl.c +++ b/fs/fcntl.c @@ -864,9 +864,9 @@ int fasync_remove_entry(struct file *fil if (fa->fa_file != filp) continue; - spin_lock_irq(&fa->fa_lock); + write_lock_irq(&fa->fa_lock); fa->fa_file = NULL; - spin_unlock_irq(&fa->fa_lock); + write_unlock_irq(&fa->fa_lock); *fp = fa->fa_next; call_rcu(&fa->fa_rcu, fasync_free_rcu); @@ -911,13 +911,13 @@ struct fasync_struct *fasync_insert_entr if (fa->fa_file != filp) continue; - spin_lock_irq(&fa->fa_lock); + write_lock_irq(&fa->fa_lock); fa->fa_fd = fd; - spin_unlock_irq(&fa->fa_lock); + write_unlock_irq(&fa->fa_lock); goto out; } - spin_lock_init(&new->fa_lock); + rwlock_init(&new->fa_lock); new->magic = FASYNC_MAGIC; new->fa_file = filp; new->fa_fd = fd; @@ -980,14 +980,13 @@ static void kill_fasync_rcu(struct fasyn { while (fa) { struct fown_struct *fown; - unsigned long flags; if (fa->magic != FASYNC_MAGIC) { printk(KERN_ERR "kill_fasync: bad magic number in " "fasync_struct!\n"); return; } - spin_lock_irqsave(&fa->fa_lock, flags); + read_lock(&fa->fa_lock); if (fa->fa_file) { fown = &fa->fa_file->f_owner; /* Don't send SIGURG to processes which have not set a @@ -996,7 +995,7 @@ static void kill_fasync_rcu(struct fasyn if (!(sig == SIGURG && fown->signum == 0)) send_sigio(fown, fa->fa_fd, band); } - spin_unlock_irqrestore(&fa->fa_lock, flags); + read_unlock(&fa->fa_lock); fa = rcu_dereference(fa->fa_next); } } --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1245,7 +1245,7 @@ static inline int locks_lock_file_wait(s } struct fasync_struct { - spinlock_t fa_lock; + rwlock_t fa_lock; int magic; int fa_fd; struct fasync_struct *fa_next; /* singly linked list */