summaryrefslogtreecommitdiff
path: root/security/apparmor
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor')
-rw-r--r--security/apparmor/path.c65
1 files changed, 38 insertions, 27 deletions
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 36cc0cc39e78..b566eba4a65c 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -57,23 +57,44 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen)
static int d_namespace_path(struct path *path, char *buf, int buflen,
char **name, int flags)
{
- struct path root, tmp;
char *res;
- int connected, error = 0;
+ int error = 0;
+ int connected = 1;
+
+ if (path->mnt->mnt_flags & MNT_INTERNAL) {
+ /* it's not mounted anywhere */
+ res = dentry_path(path->dentry, buf, buflen);
+ *name = res;
+ if (IS_ERR(res)) {
+ *name = buf;
+ return PTR_ERR(res);
+ }
+ if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
+ strncmp(*name, "/sys/", 5) == 0) {
+ /* TODO: convert over to using a per namespace
+ * control instead of hard coded /proc
+ */
+ return prepend(name, *name - buf, "/proc", 5);
+ }
+ return 0;
+ }
- /* Get the root we want to resolve too, released below */
+ /* resolve paths relative to chroot?*/
if (flags & PATH_CHROOT_REL) {
- /* resolve paths relative to chroot */
+ struct path root;
get_fs_root(current->fs, &root);
- } else {
- /* resolve paths relative to namespace */
- root.mnt = current->nsproxy->mnt_ns->root;
- root.dentry = root.mnt->mnt_root;
- path_get(&root);
+ res = __d_path(path, &root, buf, buflen);
+ if (res && !IS_ERR(res)) {
+ /* everything's fine */
+ *name = res;
+ path_put(&root);
+ goto ok;
+ }
+ path_put(&root);
+ connected = 0;
}
- tmp = root;
- res = __d_path(path, &tmp, buf, buflen);
+ res = d_absolute_path(path, buf, buflen);
*name = res;
/* handle error conditions - and still allow a partial path to
@@ -84,7 +105,10 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
*name = buf;
goto out;
}
+ if (!our_mnt(path->mnt))
+ connected = 0;
+ok:
/* Handle two cases:
* 1. A deleted dentry && profile is not allowing mediation of deleted
* 2. On some filesystems, newly allocated dentries appear to the
@@ -97,10 +121,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
goto out;
}
- /* Determine if the path is connected to the expected root */
- connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
-
- /* If the path is not connected,
+ /* If the path is not connected to the expected root,
* check if it is a sysctl and handle specially else remove any
* leading / that __d_path may have returned.
* Unless
@@ -112,17 +133,9 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
* namespace root.
*/
if (!connected) {
- /* is the disconnect path a sysctl? */
- if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
- strncmp(*name, "/sys/", 5) == 0) {
- /* TODO: convert over to using a per namespace
- * control instead of hard coded /proc
- */
- error = prepend(name, *name - buf, "/proc", 5);
- } else if (!(flags & PATH_CONNECT_PATH) &&
+ if (!(flags & PATH_CONNECT_PATH) &&
!(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
- (tmp.mnt == current->nsproxy->mnt_ns->root &&
- tmp.dentry == tmp.mnt->mnt_root))) {
+ our_mnt(path->mnt))) {
/* disconnected path, don't return pathname starting
* with '/'
*/
@@ -133,8 +146,6 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
}
out:
- path_put(&root);
-
return error;
}