From patchwork Sat May 12 09:17:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 10395847 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 4D67360390 for ; Sat, 12 May 2018 09:16:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3D65228FF8 for ; Sat, 12 May 2018 09:16:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 320122900F; Sat, 12 May 2018 09:16:04 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5C5E28FF8 for ; Sat, 12 May 2018 09:16:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751150AbeELJQB (ORCPT ); Sat, 12 May 2018 05:16:01 -0400 Received: from mail-wr0-f193.google.com ([209.85.128.193]:34698 "EHLO mail-wr0-f193.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750846AbeELJP5 (ORCPT ); Sat, 12 May 2018 05:15:57 -0400 Received: by mail-wr0-f193.google.com with SMTP id p18-v6so7485849wrm.1; Sat, 12 May 2018 02:15:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=FLtkrxZSmIgtvuRSWaWBFREk+rmm0tbsE32n1//zyaI=; b=pOXjj0hJ05x9hpp5tZkvpeWbT1mYLUVrB1xO1Rmc6KDmu9ZSUagN4Um30/h+spMuEc Pmd+rpU6/KmSos2gw1/vYEEeyTJN4KUCUkfrWeb1B8yZNObAaP8bAJmG3kyhihg8EPCp 5IBB3OEQMuMolgEiVXYk3c+vPS0w4/NeBl7qlcGcj1y7Tb3eydsoyzuPoc5CQ7ls25I9 BAH7GU4go1Mj7nlMgInBZFbuI4T+eWnkdqtBwicUUlWlKE6EhiVpsTbU+5w1Sg7g5amG gTm0hE9CocW4ucZOSaAUddbHshKFR1X9xwR8Z9sClnsN68uKqvsyo9A0KOnfGi1ono12 cISw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=FLtkrxZSmIgtvuRSWaWBFREk+rmm0tbsE32n1//zyaI=; b=spD8T/KkNCn+vyDnTlmSNrwP4u3HKaNxiVUQBHnSO5pCHb7u56vE4y5NE6xXkcPUCO 5Sl1Mrn1q8EKFt/dw61/C4i3MwiK6zRCEuNfOnaZWjT3npSJapASjWNWHnmav9tX0fUM PVMSDfS1SCJOvpXW0dxKrtZicn0zCbOAueZa6plNm1ZNUN+cCm7BC8mYNbQhyz+kgwU9 K5Rz9wOg6gEWTtl6h2aVYld4uo/aaK5+A0K7jE65S9VSIHhfC7pFhiG2LlzVpUCCGptg Hoe8ethhmPAuOZAoBSNYABwAq8RWSfMB6h1n6qQuerWtjAGCYE0q9XenwTNW2Mqqh1JT VpHA== X-Gm-Message-State: ALKqPwfmm7feoHnIR8VjF7dV9wSDUqUPhuxvOd7NZ7R2rClkOAcYq6hz i3IB2tSZgaLQ2PppiwoY9xY= X-Google-Smtp-Source: AB8JxZqQzNu0lNEP1FaVyCOojOeLGgS9L31H6WpIoupr+KmOwPZWxc5PuJu93ObI/bCtQEnaB9eWDA== X-Received: by 2002:adf:9925:: with SMTP id x34-v6mr1684042wrb.29.1526116556082; Sat, 12 May 2018 02:15:56 -0700 (PDT) Received: from localhost.localdomain ([94.230.83.122]) by smtp.gmail.com with ESMTPSA id x63-v6sm3566911wma.25.2018.05.12.02.15.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sat, 12 May 2018 02:15:55 -0700 (PDT) From: Amir Goldstein To: Miklos Szeredi Cc: Al Viro , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [PATCH v2 3/3] ovl: make ovl_create_real() cope with vfs_mkdir() safely Date: Sat, 12 May 2018 12:17:11 +0300 Message-Id: <1526116631-24186-4-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1526116631-24186-1-git-send-email-amir73il@gmail.com> References: <1526116631-24186-1-git-send-email-amir73il@gmail.com> Sender: linux-fsdevel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-fsdevel@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Al Viro vfs_mkdir() may succeed and leave the dentry passed to it unhashed and negative. ovl_create_real() is the last caller breaking when that happens. Pass newdentry to ovl_create_real() by ref, so in the case above, if lookup finds a good dentry, newdentry will be replaced by the positive hashed one. [amir: split re-factoring to prep patch and pass dentry by ref] Signed-off-by: Al Viro Signed-off-by: Amir Goldstein --- fs/overlayfs/dir.c | 24 +++++++++++++++++++++--- fs/overlayfs/overlayfs.h | 2 +- fs/overlayfs/super.c | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/fs/overlayfs/dir.c b/fs/overlayfs/dir.c index eb3fed19b1af..aeb40dcd9dd4 100644 --- a/fs/overlayfs/dir.c +++ b/fs/overlayfs/dir.c @@ -114,9 +114,10 @@ int ovl_cleanup_and_whiteout(struct dentry *workdir, struct inode *dir, goto out; } -int ovl_create_real(struct inode *dir, struct dentry *newdentry, +int ovl_create_real(struct inode *dir, struct dentry **pnewdentry, struct cattr *attr, struct dentry *hardlink, bool debug) { + struct dentry *newdentry = *pnewdentry; int err; if (newdentry->d_inode) @@ -140,6 +141,23 @@ int ovl_create_real(struct inode *dir, struct dentry *newdentry, case S_IFSOCK: err = ovl_do_mknod(dir, newdentry, attr->mode, attr->rdev, debug); + /* + * vfs_mkdir() may succeed and leave the dentry passed + * to it unhashed and negative. If that happens, try to + * lookup a new hashed and positive dentry. + */ + if (!err && unlikely(d_unhashed(newdentry))) { + struct dentry *d; + + d = lookup_one_len(newdentry->d_name.name, + newdentry->d_parent, + newdentry->d_name.len); + if (IS_ERR(d)) + return PTR_ERR(d); + + dput(newdentry); + *pnewdentry = newdentry = d; + } break; case S_IFLNK: @@ -171,7 +189,7 @@ struct dentry *ovl_create_temp(struct dentry *workdir, struct cattr *attr, if (IS_ERR(temp)) return temp; - err = ovl_create_real(wdir, temp, attr, hardlink, true); + err = ovl_create_real(wdir, &temp, attr, hardlink, true); if (err) { dput(temp); return ERR_PTR(err); @@ -256,7 +274,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode, err = PTR_ERR(newdentry); if (IS_ERR(newdentry)) goto out_unlock; - err = ovl_create_real(udir, newdentry, attr, hardlink, false); + err = ovl_create_real(udir, &newdentry, attr, hardlink, false); if (err) goto out_dput; diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h index fc0b3e876636..2fb738d3ff6a 100644 --- a/fs/overlayfs/overlayfs.h +++ b/fs/overlayfs/overlayfs.h @@ -378,7 +378,7 @@ struct cattr { umode_t mode; const char *link; }; -int ovl_create_real(struct inode *dir, struct dentry *newdentry, +int ovl_create_real(struct inode *dir, struct dentry **pnewdentry, struct cattr *attr, struct dentry *hardlink, bool debug); struct dentry *ovl_create_temp(struct dentry *workdir, struct cattr *attr, diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 492d534058ae..d83c0543c03c 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -603,7 +603,7 @@ static struct dentry *ovl_workdir_create(struct ovl_fs *ofs, goto retry; } - err = ovl_create_real(dir, work, + err = ovl_create_real(dir, &work, &(struct cattr){.mode = S_IFDIR | 0}, NULL, true); if (err)