mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
vfs: check unlinked ancestors before mount
We check submounts before doing d_drop() on a non-empty directory dentry in NFS (have_submounts()), but we do not exclude a racing mount. Nor do we prevent mounts to be added to the disconnected subtree using relative paths after the d_drop(). This patch fixes these issues by checking for unlinked (unhashed, non-root) ancestors before proceeding with the mount. This is done with rename seqlock taken for write and with ->d_lock grabbed on each ancestor in turn, including our dentry itself. This ensures that the only one of check_submounts_and_drop() or has_unlinked_ancestor() can succeed. Signed-off-by: Miklos Szeredi <miklos@szeredi.hu> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
848ac114e8
commit
eed8100766
3 changed files with 39 additions and 6 deletions
|
@ -611,6 +611,7 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry)
|
|||
{
|
||||
struct list_head *chain = mountpoint_hashtable + hash(NULL, dentry);
|
||||
struct mountpoint *mp;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(mp, chain, m_hash) {
|
||||
if (mp->m_dentry == dentry) {
|
||||
|
@ -626,14 +627,12 @@ static struct mountpoint *new_mountpoint(struct dentry *dentry)
|
|||
if (!mp)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
spin_lock(&dentry->d_lock);
|
||||
if (d_unlinked(dentry)) {
|
||||
spin_unlock(&dentry->d_lock);
|
||||
ret = d_set_mounted(dentry);
|
||||
if (ret) {
|
||||
kfree(mp);
|
||||
return ERR_PTR(-ENOENT);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
dentry->d_flags |= DCACHE_MOUNTED;
|
||||
spin_unlock(&dentry->d_lock);
|
||||
|
||||
mp->m_dentry = dentry;
|
||||
mp->m_count = 1;
|
||||
list_add(&mp->m_hash, chain);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue