1
2
3
4
5
6
7
8
9
10
11
12
13
14
15#include <linux/magic.h>
16#include <linux/mount.h>
17#include <linux/namei.h>
18#include <linux/nsproxy.h>
19#include <linux/path.h>
20#include <linux/sched.h>
21#include <linux/slab.h>
22#include <linux/fs_struct.h>
23
24#include "include/apparmor.h"
25#include "include/path.h"
26#include "include/policy.h"
27
28
29static int prepend(char **buffer, int buflen, const char *str, int namelen)
30{
31 buflen -= namelen;
32 if (buflen < 0)
33 return -ENAMETOOLONG;
34 *buffer -= namelen;
35 memcpy(*buffer, str, namelen);
36 return 0;
37}
38
39#define CHROOT_NSCONNECT (PATH_CHROOT_REL | PATH_CHROOT_NSCONNECT)
40
41
42
43
44
45
46
47
48
49
50
51
52static int disconnect(const struct path *path, char *buf, char **name,
53 int flags)
54{
55 int error = 0;
56
57 if (!(flags & PATH_CONNECT_PATH) &&
58 !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) &&
59 our_mnt(path->mnt))) {
60
61
62
63 error = -EACCES;
64 if (**name == '/')
65 *name = *name + 1;
66 } else if (**name != '/')
67
68 error = prepend(name, *name - buf, "/", 1);
69
70 return error;
71}
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87static int d_namespace_path(const struct path *path, char *buf, int buflen,
88 char **name, int flags)
89{
90 char *res;
91 int error = 0;
92 int connected = 1;
93
94 if (path->mnt->mnt_flags & MNT_INTERNAL) {
95
96 res = dentry_path(path->dentry, buf, buflen);
97 *name = res;
98 if (IS_ERR(res)) {
99 *name = buf;
100 return PTR_ERR(res);
101 }
102 if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC &&
103 strncmp(*name, "/sys/", 5) == 0) {
104
105
106
107 return prepend(name, *name - buf, "/proc", 5);
108 } else
109 return disconnect(path, buf, name, flags);
110 return 0;
111 }
112
113
114 if (flags & PATH_CHROOT_REL) {
115 struct path root;
116 get_fs_root(current->fs, &root);
117 res = __d_path(path, &root, buf, buflen);
118 path_put(&root);
119 } else {
120 res = d_absolute_path(path, buf, buflen);
121 if (!our_mnt(path->mnt))
122 connected = 0;
123 }
124
125
126
127
128 if (!res || IS_ERR(res)) {
129 if (PTR_ERR(res) == -ENAMETOOLONG)
130 return -ENAMETOOLONG;
131 connected = 0;
132 res = dentry_path_raw(path->dentry, buf, buflen);
133 if (IS_ERR(res)) {
134 error = PTR_ERR(res);
135 *name = buf;
136 goto out;
137 };
138 } else if (!our_mnt(path->mnt))
139 connected = 0;
140
141 *name = res;
142
143
144
145
146
147
148
149 if (d_unlinked(path->dentry) && d_is_positive(path->dentry) &&
150 !(flags & PATH_MEDIATE_DELETED)) {
151 error = -ENOENT;
152 goto out;
153 }
154
155 if (!connected)
156 error = disconnect(path, buf, name, flags);
157
158out:
159 return error;
160}
161
162
163
164
165
166
167
168
169
170
171
172static int get_name_to_buffer(const struct path *path, int flags, char *buffer,
173 int size, char **name, const char **info)
174{
175 int adjust = (flags & PATH_IS_DIR) ? 1 : 0;
176 int error = d_namespace_path(path, buffer, size - adjust, name, flags);
177
178 if (!error && (flags & PATH_IS_DIR) && (*name)[1] != '\0')
179
180
181
182
183 strcpy(&buffer[size - 2], "/");
184
185 if (info && error) {
186 if (error == -ENOENT)
187 *info = "Failed name lookup - deleted entry";
188 else if (error == -EACCES)
189 *info = "Failed name lookup - disconnected path";
190 else if (error == -ENAMETOOLONG)
191 *info = "Failed name lookup - name too long";
192 else
193 *info = "Failed name lookup";
194 }
195
196 return error;
197}
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218int aa_path_name(const struct path *path, int flags, char **buffer,
219 const char **name, const char **info)
220{
221 char *buf, *str = NULL;
222 int size = 256;
223 int error;
224
225 *name = NULL;
226 *buffer = NULL;
227 for (;;) {
228
229 buf = kmalloc(size, GFP_KERNEL);
230 if (!buf)
231 return -ENOMEM;
232
233 error = get_name_to_buffer(path, flags, buf, size, &str, info);
234 if (error != -ENAMETOOLONG)
235 break;
236
237 kfree(buf);
238 size <<= 1;
239 if (size > aa_g_path_max)
240 return -ENAMETOOLONG;
241 *info = NULL;
242 }
243 *buffer = buf;
244 *name = str;
245
246 return error;
247}
248