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