From patchwork Thu Nov 10 22:44:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amir Goldstein X-Patchwork-Id: 9422189 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 080096022E for ; Thu, 10 Nov 2016 22:45:26 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0B47D29844 for ; Thu, 10 Nov 2016 22:45:26 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F2B7F29849; Thu, 10 Nov 2016 22:45:25 +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=-6.3 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, RCVD_IN_SORBS_SPAM, T_DKIM_INVALID 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 78A8E29844 for ; Thu, 10 Nov 2016 22:45:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756049AbcKJWpX (ORCPT ); Thu, 10 Nov 2016 17:45:23 -0500 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34927 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755895AbcKJWpU (ORCPT ); Thu, 10 Nov 2016 17:45:20 -0500 Received: by mail-wm0-f68.google.com with SMTP id a20so5881234wme.2; Thu, 10 Nov 2016 14:45:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=5HtmCPRbZbGvLYWkVYRjdx9Hv/IAHvI6CgggBzBnTYo=; b=WTSW2FNvpX4zlWm9M/AuF7qwJR95TikCOSkIdiI/8XVb5Y/0xF1Q5bC8Ta1+WBTFDw Nj/epn2i3LcKGTy6IIo2et7URrrR50YfAyge13PDNu1ZjyMBcZtqPSy1s/o7JXlNZetW GLcdJ2awZ9pgjh/4wQGFsKdOn9GXF2niAS5nvEME7bmcs/lO9yIXkzkqkjWdiQkOGYuD A3pQFUFk3YsaXA0JC0COsAq7Ln8yW69n3xvvYwLcGjogL+ndkmz+LLKD3IJ8XSF9GWSl 23/ARbj0gP2ymCErhQ4o35MLdK1UbNuDCXvv+WvKnJOVUPj0iCgWWI4DN80Giknz1dfq JZUg== 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=5HtmCPRbZbGvLYWkVYRjdx9Hv/IAHvI6CgggBzBnTYo=; b=VSbC4LhMaBNWFeKczqwo5b36QqT84aD+Si4G2k84QimozY13fOzRhltZny05xehcFD s/mbNWuvB3lTlU0mEVdqzPH1xYEKUZbdVow5+6c4DRvLCWlfO0XvgzbwBPfUjnW2nWXJ NHQ9+0OzOf2TJpRcrHJV49ub6yX5pzmA2TF7xsh1BTKQlJLz+2J21BKk/uff7GNRH9jb IYeP53vb/THJpKSmfk7vkH1jVpEW//8HyhEL7CsWan+8gr/NON5IOWsTgED+ADLtGuh3 fApQzVoprWZuwj0YisVRRKqgZirSqN6aJUzvj8dMrJkddXhh7NqzMeAGG0gWVlq0rd91 6+fA== X-Gm-Message-State: ABUngve41O558TL6NWeN8VjKfLeCkP/n6fMXhKwIR/w8Kt99GekoP4jNF2cEyXiEhEv7UQ== X-Received: by 10.194.179.135 with SMTP id dg7mr6324197wjc.219.1478817917565; Thu, 10 Nov 2016 14:45:17 -0800 (PST) Received: from amir-VirtualBox.Home (bzq-79-177-89-54.red.bezeqint.net. [79.177.89.54]) by smtp.gmail.com with ESMTPSA id n72sm15444310wmd.11.2016.11.10.14.45.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 10 Nov 2016 14:45:16 -0800 (PST) From: Amir Goldstein To: Miklos Szeredi Cc: Konstantin Khlebnikov , Al Viro , linux-unionfs@vger.kernel.org, linux-fsdevel@vger.kernel.org Subject: [RFC][PATH 3/4] ovl: delete lock upper dir and work dir Date: Fri, 11 Nov 2016 00:44:42 +0200 Message-Id: <1478817883-27662-4-git-send-email-amir73il@gmail.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1478817883-27662-1-git-send-email-amir73il@gmail.com> References: <1478817883-27662-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 Attempt to take a delete lock on both upper dir and work dir after verifying that they are not ancestors of each other. Fail the mount with -EBUSY on failure to take the locks, as it indicates that those directories may be in use by another overlay mount. The delete lock guaranties that upper/work dir can't be moved into each other while the overlay is mounted. The "work" directory created inside the workdir path is also delete locked, so it can't be moved into upper dir while overlay is mounted. Signed-off-by: Amir Goldstein --- fs/overlayfs/super.c | 63 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 11 deletions(-) diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 625fa705..4f4eb16 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -142,8 +142,15 @@ static void ovl_put_super(struct super_block *sb) struct ovl_fs *ufs = sb->s_fs_info; unsigned i; - dput(ufs->workdir); - mntput(ufs->upper_mnt); + if (ufs->workdir) { + delete_unlock(ufs->workdir->d_parent); + delete_unlock(ufs->workdir); + dput(ufs->workdir); + } + if (ufs->upper_mnt) { + delete_unlock(ufs->upper_mnt->mnt_root); + mntput(ufs->upper_mnt); + } for (i = 0; i < ufs->numlower; i++) mntput(ufs->lower_mnt[i]); kfree(ufs->lower_mnt); @@ -384,6 +391,11 @@ static struct dentry *ovl_workdir_create(struct vfsmount *mnt, inode_unlock(work->d_inode); if (err) goto out_dput; + + err = -EBUSY; + /* Lock work dir to its parent */ + if (!delete_trylock(work)) + goto out_dput; } out_unlock: inode_unlock(dir); @@ -490,16 +502,34 @@ static int ovl_lower_dir(const char *name, struct path *path, long *namelen, return err; } -/* Workdir should not be subdir of upperdir and vice versa */ -static bool ovl_workdir_ok(struct dentry *workdir, struct dentry *upperdir) +/* + * Workdir should not be subdir of upperdir and vice versa. + * Delete lock both upper and workdir to their parent under lock_rename(), + * so if they are siblings, they remain siblings throughout the overlay mount + */ +static int ovl_workdir_trylock(struct dentry *workdir, struct dentry *upperdir) { - bool ok = false; + int ret; + + if (workdir == upperdir) + return -EINVAL; + + ret = -EINVAL; + if (lock_rename(workdir, upperdir) != NULL) + goto out_unlock_rename; - if (workdir != upperdir) { - ok = (lock_rename(workdir, upperdir) == NULL); - unlock_rename(workdir, upperdir); + ret = -EBUSY; + if (!delete_trylock(upperdir)) + goto out_unlock_rename; + if (!delete_trylock(workdir)) { + delete_unlock(upperdir); + goto out_unlock_rename; } - return ok; + ret = 0; + +out_unlock_rename: + unlock_rename(workdir, upperdir); + return ret; } static unsigned int ovl_split_lowerdirs(char *str) @@ -717,16 +747,20 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) pr_err("overlayfs: workdir and upperdir must reside under the same mount\n"); goto out_put_workpath; } - if (!ovl_workdir_ok(workpath.dentry, upperpath.dentry)) { + err = ovl_workdir_trylock(workpath.dentry, upperpath.dentry); + if (err == -EINVAL) { pr_err("overlayfs: workdir and upperdir must be separate subtrees\n"); goto out_put_workpath; + } else if (err == -EBUSY) { + pr_err("overlayfs: workdir/upperdir may be in use by another overlay\n"); + goto out_put_workpath; } sb->s_stack_depth = upperpath.mnt->mnt_sb->s_stack_depth; } err = -ENOMEM; lowertmp = kstrdup(ufs->config.lowerdir, GFP_KERNEL); if (!lowertmp) - goto out_put_workpath; + goto out_unlock_workpath; err = -EINVAL; stacklen = ovl_split_lowerdirs(lowertmp); @@ -885,6 +919,8 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) mntput(ufs->lower_mnt[i]); kfree(ufs->lower_mnt); out_put_workdir: + if (ufs->workdir) + delete_unlock(ufs->workdir); dput(ufs->workdir); mntput(ufs->upper_mnt); out_put_lowerpath: @@ -893,6 +929,11 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent) kfree(stack); out_free_lowertmp: kfree(lowertmp); +out_unlock_workpath: + if (workpath.dentry) + delete_unlock(workpath.dentry); + if (upperpath.dentry) + delete_unlock(upperpath.dentry); out_put_workpath: path_put(&workpath); out_put_upperpath: