aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/path.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/path.c')
-rw-r--r--security/apparmor/path.c47
1 files changed, 13 insertions, 34 deletions
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 96bab9469d48..82396050f186 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -59,39 +59,22 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
59{ 59{
60 struct path root, tmp; 60 struct path root, tmp;
61 char *res; 61 char *res;
62 int deleted, connected; 62 int connected, error = 0;
63 int error = 0;
64 63
65 /* Get the root we want to resolve too */ 64 /* Get the root we want to resolve too, released below */
66 if (flags & PATH_CHROOT_REL) { 65 if (flags & PATH_CHROOT_REL) {
67 /* resolve paths relative to chroot */ 66 /* resolve paths relative to chroot */
68 read_lock(&current->fs->lock); 67 get_fs_root(current->fs, &root);
69 root = current->fs->root;
70 /* released below */
71 path_get(&root);
72 read_unlock(&current->fs->lock);
73 } else { 68 } else {
74 /* resolve paths relative to namespace */ 69 /* resolve paths relative to namespace */
75 root.mnt = current->nsproxy->mnt_ns->root; 70 root.mnt = current->nsproxy->mnt_ns->root;
76 root.dentry = root.mnt->mnt_root; 71 root.dentry = root.mnt->mnt_root;
77 /* released below */
78 path_get(&root); 72 path_get(&root);
79 } 73 }
80 74
81 spin_lock(&dcache_lock); 75 spin_lock(&dcache_lock);
82 /* There is a race window between path lookup here and the 76 tmp = root;
83 * need to strip the " (deleted) string that __d_path applies 77 res = __d_path(path, &tmp, buf, buflen);
84 * Detect the race and relookup the path
85 *
86 * The stripping of (deleted) is a hack that could be removed
87 * with an updated __d_path
88 */
89 do {
90 tmp = root;
91 deleted = d_unlinked(path->dentry);
92 res = __d_path(path, &tmp, buf, buflen);
93
94 } while (deleted != d_unlinked(path->dentry));
95 spin_unlock(&dcache_lock); 78 spin_unlock(&dcache_lock);
96 79
97 *name = res; 80 *name = res;
@@ -103,21 +86,17 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
103 *name = buf; 86 *name = buf;
104 goto out; 87 goto out;
105 } 88 }
106 if (deleted) {
107 /* On some filesystems, newly allocated dentries appear to the
108 * security_path hooks as a deleted dentry except without an
109 * inode allocated.
110 *
111 * Remove the appended deleted text and return as string for
112 * normal mediation, or auditing. The (deleted) string is
113 * guaranteed to be added in this case, so just strip it.
114 */
115 buf[buflen - 11] = 0; /* - (len(" (deleted)") +\0) */
116 89
117 if (path->dentry->d_inode && !(flags & PATH_MEDIATE_DELETED)) { 90 /* Handle two cases:
91 * 1. A deleted dentry && profile is not allowing mediation of deleted
92 * 2. On some filesystems, newly allocated dentries appear to the
93 * security_path hooks as a deleted dentry except without an inode
94 * allocated.
95 */
96 if (d_unlinked(path->dentry) && path->dentry->d_inode &&
97 !(flags & PATH_MEDIATE_DELETED)) {
118 error = -ENOENT; 98 error = -ENOENT;
119 goto out; 99 goto out;
120 }
121 } 100 }
122 101
123 /* Determine if the path is connected to the expected root */ 102 /* Determine if the path is connected to the expected root */