mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00
59 lines
1.9 KiB
Diff
59 lines
1.9 KiB
Diff
Make d_path() consistent across mount operations
|
|
|
|
Right now, 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 the
|
|
lock 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 extremely unlikely, but
|
|
still possible.)
|
|
|
|
This can easily be fixed by grabbing the vfsmount_lock when the first
|
|
mount point is reached, and holding onto it until the d_cache lookup is
|
|
completed. As a bonus, this makes __d_path() slightly more efficient
|
|
when traversing a number of mount points.
|
|
|
|
Signed-off-by: Andreas Gruenbacher <agruen@suse.de>
|
|
|
|
Index: b/fs/dcache.c
|
|
===================================================================
|
|
--- a/fs/dcache.c
|
|
+++ b/fs/dcache.c
|
|
@@ -1754,7 +1754,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);
|
|
@@ -1777,14 +1777,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;
|
|
@@ -1803,6 +1803,8 @@ static char *__d_path(struct dentry *den
|
|
*--buffer = '/';
|
|
|
|
out:
|
|
+ if (vfsmount_locked)
|
|
+ spin_unlock(&vfsmount_lock);
|
|
spin_unlock(&dcache_lock);
|
|
return buffer;
|
|
|