mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 18:17:09 +00:00
61 lines
1.9 KiB
Diff
61 lines
1.9 KiB
Diff
|
From: Andreas Gruenbacher <agruen@suse.de>
|
||
|
Subject: Make d_path() consistent across mount operations
|
||
|
|
||
|
The path that __d_path() computes can become slightly inconsistent when it
|
||
|
races with mount operations: it grabs the vfsmount_lock when traversing mount
|
||
|
points but immediately drops it again, only to re-grab it when it reaches the
|
||
|
next mount point. The result is that the filename computed is not always
|
||
|
consisent, and the file may never have had that name. (This is unlikely, but
|
||
|
still possible.)
|
||
|
|
||
|
Fix this by grabbing the vfsmount_lock when the first mount point is reached,
|
||
|
and holding onto it until the d_cache lookup is completed.
|
||
|
|
||
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
||
|
Signed-off-by: John Johansen <jjohansen@suse.de>
|
||
|
|
||
|
---
|
||
|
fs/dcache.c | 14 ++++++++------
|
||
|
1 file changed, 8 insertions(+), 6 deletions(-)
|
||
|
|
||
|
--- a/fs/dcache.c
|
||
|
+++ b/fs/dcache.c
|
||
|
@@ -1786,7 +1786,7 @@ static char *__d_path(struct dentry *den
|
||
|
struct dentry *root, struct vfsmount *rootmnt,
|
||
|
char *buffer, int buflen, int fail_deleted)
|
||
|
{
|
||
|
- int namelen, is_slash;
|
||
|
+ int namelen, is_slash, vfsmount_locked = 0;
|
||
|
|
||
|
if (buflen < 2)
|
||
|
return ERR_PTR(-ENAMETOOLONG);
|
||
|
@@ -1809,14 +1809,14 @@ static char *__d_path(struct dentry *den
|
||
|
struct dentry * parent;
|
||
|
|
||
|
if (dentry == vfsmnt->mnt_root || IS_ROOT(dentry)) {
|
||
|
- spin_lock(&vfsmount_lock);
|
||
|
- if (vfsmnt->mnt_parent == vfsmnt) {
|
||
|
- spin_unlock(&vfsmount_lock);
|
||
|
- goto global_root;
|
||
|
+ if (!vfsmount_locked) {
|
||
|
+ spin_lock(&vfsmount_lock);
|
||
|
+ vfsmount_locked = 1;
|
||
|
}
|
||
|
+ if (vfsmnt->mnt_parent == vfsmnt)
|
||
|
+ goto global_root;
|
||
|
dentry = vfsmnt->mnt_mountpoint;
|
||
|
vfsmnt = vfsmnt->mnt_parent;
|
||
|
- spin_unlock(&vfsmount_lock);
|
||
|
continue;
|
||
|
}
|
||
|
parent = dentry->d_parent;
|
||
|
@@ -1835,6 +1835,8 @@ static char *__d_path(struct dentry *den
|
||
|
*--buffer = '/';
|
||
|
|
||
|
out:
|
||
|
+ if (vfsmount_locked)
|
||
|
+ spin_unlock(&vfsmount_lock);
|
||
|
spin_unlock(&dcache_lock);
|
||
|
return buffer;
|
||
|
|