From patchwork Fri Jan 8 02:22:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jeff Layton X-Patchwork-Id: 7981991 Return-Path: X-Original-To: patchwork-linux-fsdevel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id E6BC7BEEED for ; Fri, 8 Jan 2016 02:22:48 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id DF7DC20142 for ; Fri, 8 Jan 2016 02:22:47 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F13A72014A for ; Fri, 8 Jan 2016 02:22:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753822AbcAHCWe (ORCPT ); Thu, 7 Jan 2016 21:22:34 -0500 Received: from mail-qg0-f51.google.com ([209.85.192.51]:35276 "EHLO mail-qg0-f51.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753473AbcAHCWd (ORCPT ); Thu, 7 Jan 2016 21:22:33 -0500 Received: by mail-qg0-f51.google.com with SMTP id o11so343089390qge.2 for ; Thu, 07 Jan 2016 18:22:33 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=poochiereds-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Xd1qVgqm8RnmUS4244+600caw3UIJwshyv2Bx8BrRf0=; b=wDvXEj7aJssg9X5MOowH1hRrRaE2cdhI7KMwvLHe9vn93nSKi4nAxyL0Om2jc/tuD2 A/6CiIlM8YesfrT11QqwTrUwPekIRMk/P/svyQMINOKgGzF4iurvuakuymO8XDix35un B7pyq/KMPLIvpySKxNR3FzH7OfWVqjXJdt61P1YbSFFhnCNv1ke5WxCBIXilGes3Ue1u 2bDqRANndbbqbK3Hv9ZCO2s6iu+yPg2yEI3D8/JOGx7jJvtoh/jbFWAoeYsrqoiNsh6w w9AtxtFhk2/4UJtwL2GWJBz742BjQQ/qx1Lp+luLGuzBi4Mu/Vhk6XAOala5fFFGSYXM d+QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xd1qVgqm8RnmUS4244+600caw3UIJwshyv2Bx8BrRf0=; b=f7DMdDrGirTmaFxCoqsImrl8U5NUHU9yv6T7JZoNdFoB1DWny/S/XUIWw145VLUaOY 66O4oveThU9AT4kjYRpCltpFjoG3KITN53nmFfnR2M+PveYKC/UWWRApaeiP6UhmUkoJ pVzLy7g5ikOH6/8q+FDWtjyf1OwssJ0C8R/PZ0bc1zzEZeSWorqLYPlyHBDPKzAeEcko /SFdbtaZdk7EnS05CXWeQ6x73q8CZoNUSyExrcHRy+C4mxDSxJtuFMiMp5cc73ohe61f pRNfRP9kK3lYwqLPHdXFqDU9X7iZFkWk+lpslHe0jX9aP09Rvy8eC1iQS1joCskR+Ce/ em7A== X-Gm-Message-State: ALoCoQk2dFp7PZvBRI+r7JTZqJYC+uWgWtiEv4xOSSArqyTFaKebGxv8tmWqgquiXLDZQGirShKL03RByZz6iVCJvHQt2S9o+w== X-Received: by 10.140.201.20 with SMTP id w20mr85305229qha.10.1452219752665; Thu, 07 Jan 2016 18:22:32 -0800 (PST) Received: from tlielax.poochiereds.net ([2606:a000:1125:4075::d5a]) by smtp.googlemail.com with ESMTPSA id g90sm46739706qgg.45.2016.01.07.18.22.30 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 07 Jan 2016 18:22:31 -0800 (PST) From: Jeff Layton X-Google-Original-From: Jeff Layton To: linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Dmitry Vyukov , "J. Bruce Fields" , Alexander Viro , syzkaller , Kostya Serebryany , Alexander Potapenko , Sasha Levin , Eric Dumazet Subject: [PATCH] locks: fix unlock when fcntl_setlk races with a close Date: Thu, 7 Jan 2016 21:22:22 -0500 Message-Id: <1452219742-18507-1-git-send-email-jeff.layton@primarydata.com> X-Mailer: git-send-email 2.5.0 In-Reply-To: References: Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Spam-Status: No, score=-6.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,RP_MATCHES_RCVD,T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Dmitry reported that he was able to reproduce the WARN_ON_ONCE that fires in locks_free_lock_context when the flc_posix list isn't empty. The problem turns out to be that we're basically rebuilding the file_lock from scratch in fcntl_setlk when we discover that the setlk has raced with a close. If the l_whence field is SEEK_CUR or SEEK_END, then we may end up with fl_start and fl_end values that differ from when the lock was initially set, if the file position or length of the file has changed in the interim. Fix this by just reusing the same lock request structure, and simply override fl_type value with F_UNLCK as appropriate. That ensures that we really are unlocking the lock that was initially set. While we're there, make sure that we do pop a WARN_ON_ONCE if the removal ever fails. Also return -EBADF in this event, since that's what we would have returned if the close had happened earlier. Cc: Reported-by: Dmitry Vyukov Signed-off-by: Jeff Layton --- fs/locks.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 593dca300b29..0db640e4ced4 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -2181,7 +2181,6 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, goto out; } -again: error = flock_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -2231,9 +2230,11 @@ again: spin_lock(¤t->files->file_lock); f = fcheck(fd); spin_unlock(¤t->files->file_lock); - if (!error && f != filp && flock.l_type != F_UNLCK) { - flock.l_type = F_UNLCK; - goto again; + if (!error && f != filp && file_lock->fl_type != F_UNLCK) { + file_lock->fl_type = F_UNLCK; + error = do_lock_file_wait(filp, cmd, file_lock); + WARN_ON_ONCE(error); + error = -EBADF; } out: @@ -2321,7 +2322,6 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, goto out; } -again: error = flock64_to_posix_lock(filp, file_lock, &flock); if (error) goto out; @@ -2366,11 +2366,12 @@ again: spin_lock(¤t->files->file_lock); f = fcheck(fd); spin_unlock(¤t->files->file_lock); - if (!error && f != filp && flock.l_type != F_UNLCK) { - flock.l_type = F_UNLCK; - goto again; + if (!error && f != filp && file_lock->fl_type != F_UNLCK) { + file_lock->fl_type = F_UNLCK; + error = do_lock_file_wait(filp, cmd, file_lock); + WARN_ON_ONCE(error); + error = -EBADF; } - out: locks_free_lock(file_lock); return error;