mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-06 17:31:01 +01: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
|
||
|
@@ -1770,7 +1770,7 @@ static char *__d_path(struct dentry *den
|
||
|
struct path *root, 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);
|
||
|
@@ -1794,14 +1794,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;
|
||
|
@@ -1820,6 +1820,8 @@ static char *__d_path(struct dentry *den
|
||
|
*--buffer = '/';
|
||
|
|
||
|
out:
|
||
|
+ if (vfsmount_locked)
|
||
|
+ spin_unlock(&vfsmount_lock);
|
||
|
spin_unlock(&dcache_lock);
|
||
|
return buffer;
|
||
|
|