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.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)
57static int d_namespace_path(struct path *path, char *buf, int buflen, 57static int d_namespace_path(struct path *path, char *buf, int buflen,
58 char **name, int flags) 58 char **name, int flags)
59{ 59{
60 struct path root, tmp;
61 char *res; 60 char *res;
62 int connected, error = 0; 61 int error = 0;
62 int connected = 1;
63
64 if (path->mnt->mnt_flags & MNT_INTERNAL) {
65 /* it's not mounted anywhere */
66 res = dentry_path(path->dentry, buf, buflen);
67 *name = res;
68 if (IS_ERR(res)) {
69 *name = buf;
70 return PTR_ERR(res);
71 }
72 if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
73 strncmp(*name, "/sys/", 5) == 0) {
74 /* TODO: convert over to using a per namespace
75 * control instead of hard coded /proc
76 */
77 return prepend(name, *name - buf, "/proc", 5);
78 }
79 return 0;
80 }
63 81
64 /* Get the root we want to resolve too, released below */ 82 /* resolve paths relative to chroot?*/
65 if (flags & PATH_CHROOT_REL) { 83 if (flags & PATH_CHROOT_REL) {
66 /* resolve paths relative to chroot */ 84 struct path root;
67 get_fs_root(current->fs, &root); 85 get_fs_root(current->fs, &root);
68 } else { 86 res = __d_path(path, &root, buf, buflen);
69 /* resolve paths relative to namespace */ 87 if (res && !IS_ERR(res)) {
70 root.mnt = current->nsproxy->mnt_ns->root; 88 /* everything's fine */
71 root.dentry = root.mnt->mnt_root; 89 *name = res;
72 path_get(&root); 90 path_put(&root);
91 goto ok;
92 }
93 path_put(&root);
94 connected = 0;
73 } 95 }
74 96
75 tmp = root; 97 res = d_absolute_path(path, buf, buflen);
76 res = __d_path(path, &tmp, buf, buflen);
77 98
78 *name = res; 99 *name = res;
79 /* handle error conditions - and still allow a partial path to 100 /* 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,
84 *name = buf; 105 *name = buf;
85 goto out; 106 goto out;
86 } 107 }
108 if (!our_mnt(path->mnt))
109 connected = 0;
87 110
111ok:
88 /* Handle two cases: 112 /* Handle two cases:
89 * 1. A deleted dentry && profile is not allowing mediation of deleted 113 * 1. A deleted dentry && profile is not allowing mediation of deleted
90 * 2. On some filesystems, newly allocated dentries appear to the 114 * 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,
97 goto out; 121 goto out;
98 } 122 }
99 123
100 /* Determine if the path is connected to the expected root */ 124 /* If the path is not connected to the expected root,
101 connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt;
102
103 /* If the path is not connected,
104 * check if it is a sysctl and handle specially else remove any 125 * check if it is a sysctl and handle specially else remove any
105 * leading / that __d_path may have returned. 126 * leading / that __d_path may have returned.
106 * Unless 127 * Unless
@@ -112,17 +133,9 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
112 * namespace root. 133 * namespace root.
113 */ 134 */
114 if (!connected) { 135 if (!connected) {
115 /* is the disconnect path a sysctl? */ 136 if (!(flags & PATH_CONNECT_PATH) &&
116 if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
117 strncmp(*name, "/sys/", 5) == 0) {
118 /* TODO: convert over to using a per namespace
119 * control instead of hard coded /proc
120 */
121 error = prepend(name, *name - buf, "/proc", 5);
122 } else if (!(flags & PATH_CONNECT_PATH) &&
123 !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && 137 !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
124 (tmp.mnt == current->nsproxy->mnt_ns->root && 138 our_mnt(path->mnt))) {
125 tmp.dentry == tmp.mnt->mnt_root))) {
126 /* disconnected path, don't return pathname starting 139 /* disconnected path, don't return pathname starting
127 * with '/' 140 * with '/'
128 */ 141 */
@@ -133,8 +146,6 @@ static int d_namespace_path(struct path *path, char *buf, int buflen,
133 } 146 }
134 147
135out: 148out:
136 path_put(&root);
137
138 return error; 149 return error;
139} 150}
140 151