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.c56
1 files changed, 34 insertions, 22 deletions
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 9d070a7c3ffc..2daeea4f9266 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -83,31 +83,29 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
83 struct path root; 83 struct path root;
84 get_fs_root(current->fs, &root); 84 get_fs_root(current->fs, &root);
85 res = __d_path(path, &root, buf, buflen); 85 res = __d_path(path, &root, buf, buflen);
86 if (res && !IS_ERR(res)) {
87 /* everything's fine */
88 *name = res;
89 path_put(&root);
90 goto ok;
91 }
92 path_put(&root); 86 path_put(&root);
93 connected = 0; 87 } else {
88 res = d_absolute_path(path, buf, buflen);
89 if (!our_mnt(path->mnt))
90 connected = 0;
94 } 91 }
95 92
96 res = d_absolute_path(path, buf, buflen);
97
98 *name = res;
99 /* handle error conditions - and still allow a partial path to 93 /* handle error conditions - and still allow a partial path to
100 * be returned. 94 * be returned.
101 */ 95 */
102 if (IS_ERR(res)) { 96 if (!res || IS_ERR(res)) {
103 error = PTR_ERR(res);
104 *name = buf;
105 goto out;
106 }
107 if (!our_mnt(path->mnt))
108 connected = 0; 97 connected = 0;
98 res = dentry_path_raw(path->dentry, buf, buflen);
99 if (IS_ERR(res)) {
100 error = PTR_ERR(res);
101 *name = buf;
102 goto out;
103 };
104 } else if (!our_mnt(path->mnt))
105 connected = 0;
106
107 *name = res;
109 108
110ok:
111 /* Handle two cases: 109 /* Handle two cases:
112 * 1. A deleted dentry && profile is not allowing mediation of deleted 110 * 1. A deleted dentry && profile is not allowing mediation of deleted
113 * 2. On some filesystems, newly allocated dentries appear to the 111 * 2. On some filesystems, newly allocated dentries appear to the
@@ -138,7 +136,7 @@ ok:
138 /* disconnected path, don't return pathname starting 136 /* disconnected path, don't return pathname starting
139 * with '/' 137 * with '/'
140 */ 138 */
141 error = -ESTALE; 139 error = -EACCES;
142 if (*res == '/') 140 if (*res == '/')
143 *name = res + 1; 141 *name = res + 1;
144 } 142 }
@@ -159,7 +157,7 @@ out:
159 * Returns: %0 else error on failure 157 * Returns: %0 else error on failure
160 */ 158 */
161static int get_name_to_buffer(struct path *path, int flags, char *buffer, 159static int get_name_to_buffer(struct path *path, int flags, char *buffer,
162 int size, char **name) 160 int size, char **name, const char **info)
163{ 161{
164 int adjust = (flags & PATH_IS_DIR) ? 1 : 0; 162 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
165 int error = d_namespace_path(path, buffer, size - adjust, name, flags); 163 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
@@ -171,15 +169,27 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
171 */ 169 */
172 strcpy(&buffer[size - 2], "/"); 170 strcpy(&buffer[size - 2], "/");
173 171
172 if (info && error) {
173 if (error == -ENOENT)
174 *info = "Failed name lookup - deleted entry";
175 else if (error == -ESTALE)
176 *info = "Failed name lookup - disconnected path";
177 else if (error == -ENAMETOOLONG)
178 *info = "Failed name lookup - name too long";
179 else
180 *info = "Failed name lookup";
181 }
182
174 return error; 183 return error;
175} 184}
176 185
177/** 186/**
178 * aa_get_name - compute the pathname of a file 187 * aa_path_name - compute the pathname of a file
179 * @path: path the file (NOT NULL) 188 * @path: path the file (NOT NULL)
180 * @flags: flags controlling path name generation 189 * @flags: flags controlling path name generation
181 * @buffer: buffer that aa_get_name() allocated (NOT NULL) 190 * @buffer: buffer that aa_get_name() allocated (NOT NULL)
182 * @name: Returns - the generated path name if !error (NOT NULL) 191 * @name: Returns - the generated path name if !error (NOT NULL)
192 * @info: Returns - information on why the path lookup failed (MAYBE NULL)
183 * 193 *
184 * @name is a pointer to the beginning of the pathname (which usually differs 194 * @name is a pointer to the beginning of the pathname (which usually differs
185 * from the beginning of the buffer), or NULL. If there is an error @name 195 * from the beginning of the buffer), or NULL. If there is an error @name
@@ -192,7 +202,8 @@ static int get_name_to_buffer(struct path *path, int flags, char *buffer,
192 * 202 *
193 * Returns: %0 else error code if could retrieve name 203 * Returns: %0 else error code if could retrieve name
194 */ 204 */
195int aa_get_name(struct path *path, int flags, char **buffer, const char **name) 205int aa_path_name(struct path *path, int flags, char **buffer, const char **name,
206 const char **info)
196{ 207{
197 char *buf, *str = NULL; 208 char *buf, *str = NULL;
198 int size = 256; 209 int size = 256;
@@ -206,7 +217,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
206 if (!buf) 217 if (!buf)
207 return -ENOMEM; 218 return -ENOMEM;
208 219
209 error = get_name_to_buffer(path, flags, buf, size, &str); 220 error = get_name_to_buffer(path, flags, buf, size, &str, info);
210 if (error != -ENAMETOOLONG) 221 if (error != -ENAMETOOLONG)
211 break; 222 break;
212 223
@@ -214,6 +225,7 @@ int aa_get_name(struct path *path, int flags, char **buffer, const char **name)
214 size <<= 1; 225 size <<= 1;
215 if (size > aa_g_path_max) 226 if (size > aa_g_path_max)
216 return -ENAMETOOLONG; 227 return -ENAMETOOLONG;
228 *info = NULL;
217 } 229 }
218 *buffer = buf; 230 *buffer = buf;
219 *name = str; 231 *name = str;