diff options
author | Amir Goldstein <amir73il@gmail.com> | 2023-08-16 16:47:59 +0300 |
---|---|---|
committer | Amir Goldstein <amir73il@gmail.com> | 2023-10-31 01:12:57 +0300 |
commit | 5b02bfc1e7e3811c5bf7f0fa626a0694d0dbbd77 (patch) | |
tree | 508405693acdfdf8200f5890f4930e9a48e49cde /fs/overlayfs/util.c | |
parent | c63e56a4a6523fcb1358e1878607d77a40b534bb (diff) | |
download | linux-5b02bfc1e7e3811c5bf7f0fa626a0694d0dbbd77.tar.xz |
ovl: do not encode lower fh with upper sb_writers held
When lower fs is a nested overlayfs, calling encode_fh() on a lower
directory dentry may trigger copy up and take sb_writers on the upper fs
of the lower nested overlayfs.
The lower nested overlayfs may have the same upper fs as this overlayfs,
so nested sb_writers lock is illegal.
Move all the callers that encode lower fh to before ovl_want_write().
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Diffstat (limited to 'fs/overlayfs/util.c')
-rw-r--r-- | fs/overlayfs/util.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/fs/overlayfs/util.c b/fs/overlayfs/util.c index 12156e2091ad..f8455fcb8b07 100644 --- a/fs/overlayfs/util.c +++ b/fs/overlayfs/util.c @@ -1013,12 +1013,18 @@ static void ovl_cleanup_index(struct dentry *dentry) struct dentry *index = NULL; struct inode *inode; struct qstr name = { }; + bool got_write = false; int err; err = ovl_get_index_name(ofs, lowerdentry, &name); if (err) goto fail; + err = ovl_want_write(dentry); + if (err) + goto fail; + + got_write = true; inode = d_inode(upperdentry); if (!S_ISDIR(inode->i_mode) && inode->i_nlink != 1) { pr_warn_ratelimited("cleanup linked index (%pd2, ino=%lu, nlink=%u)\n", @@ -1056,6 +1062,8 @@ static void ovl_cleanup_index(struct dentry *dentry) goto fail; out: + if (got_write) + ovl_drop_write(dentry); kfree(name.name); dput(index); return; @@ -1135,6 +1143,8 @@ void ovl_nlink_end(struct dentry *dentry) { struct inode *inode = d_inode(dentry); + ovl_drop_write(dentry); + if (ovl_test_flag(OVL_INDEX, inode) && inode->i_nlink == 0) { const struct cred *old_cred; @@ -1143,7 +1153,6 @@ void ovl_nlink_end(struct dentry *dentry) revert_creds(old_cred); } - ovl_drop_write(dentry); ovl_inode_unlock(inode); } |