blob: 0b55faab3b328ff9aea5f3f9dcd68a9b50bcfbd6 [file] [log] [blame]
Kentaro Takedac73bd6d2009-02-05 17:18:12 +09001/*
2 * security/tomoyo/realpath.c
3 *
4 * Get the canonicalized absolute pathnames. The basis for TOMOYO.
5 *
6 * Copyright (C) 2005-2009 NTT DATA CORPORATION
7 *
Tetsuo Handa39826a12009-04-08 22:31:28 +09008 * Version: 2.2.0 2009/04/01
Kentaro Takedac73bd6d2009-02-05 17:18:12 +09009 *
10 */
11
12#include <linux/types.h>
13#include <linux/mount.h>
14#include <linux/mnt_namespace.h>
Al Viro5ad4e532009-03-29 19:50:06 -040015#include <linux/fs_struct.h>
Kentaro Takedac73bd6d2009-02-05 17:18:12 +090016#include "common.h"
17#include "realpath.h"
18
19/**
20 * tomoyo_encode: Convert binary string to ascii string.
21 *
22 * @buffer: Buffer for ASCII string.
23 * @buflen: Size of @buffer.
24 * @str: Binary string.
25 *
26 * Returns 0 on success, -ENOMEM otherwise.
27 */
28int tomoyo_encode(char *buffer, int buflen, const char *str)
29{
30 while (1) {
31 const unsigned char c = *(unsigned char *) str++;
32
33 if (tomoyo_is_valid(c)) {
34 if (--buflen <= 0)
35 break;
36 *buffer++ = (char) c;
37 if (c != '\\')
38 continue;
39 if (--buflen <= 0)
40 break;
41 *buffer++ = (char) c;
42 continue;
43 }
44 if (!c) {
45 if (--buflen <= 0)
46 break;
47 *buffer = '\0';
48 return 0;
49 }
50 buflen -= 4;
51 if (buflen <= 0)
52 break;
53 *buffer++ = '\\';
54 *buffer++ = (c >> 6) + '0';
55 *buffer++ = ((c >> 3) & 7) + '0';
56 *buffer++ = (c & 7) + '0';
57 }
58 return -ENOMEM;
59}
60
61/**
62 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
63 *
64 * @path: Pointer to "struct path".
65 * @newname: Pointer to buffer to return value in.
66 * @newname_len: Size of @newname.
67 *
68 * Returns 0 on success, negative value otherwise.
69 *
70 * If dentry is a directory, trailing '/' is appended.
71 * Characters out of 0x20 < c < 0x7F range are converted to
72 * \ooo style octal string.
73 * Character \ is converted to \\ string.
74 */
75int tomoyo_realpath_from_path2(struct path *path, char *newname,
76 int newname_len)
77{
78 int error = -ENOMEM;
79 struct dentry *dentry = path->dentry;
80 char *sp;
81
82 if (!dentry || !path->mnt || !newname || newname_len <= 2048)
83 return -EINVAL;
84 if (dentry->d_op && dentry->d_op->d_dname) {
85 /* For "socket:[\$]" and "pipe:[\$]". */
86 static const int offset = 1536;
87 sp = dentry->d_op->d_dname(dentry, newname + offset,
88 newname_len - offset);
89 } else {
90 /* Taken from d_namespace_path(). */
91 struct path root;
92 struct path ns_root = { };
93 struct path tmp;
94
95 read_lock(&current->fs->lock);
96 root = current->fs->root;
97 path_get(&root);
98 read_unlock(&current->fs->lock);
99 spin_lock(&vfsmount_lock);
100 if (root.mnt && root.mnt->mnt_ns)
101 ns_root.mnt = mntget(root.mnt->mnt_ns->root);
102 if (ns_root.mnt)
103 ns_root.dentry = dget(ns_root.mnt->mnt_root);
104 spin_unlock(&vfsmount_lock);
105 spin_lock(&dcache_lock);
106 tmp = ns_root;
107 sp = __d_path(path, &tmp, newname, newname_len);
108 spin_unlock(&dcache_lock);
109 path_put(&root);
110 path_put(&ns_root);
Eric W. Biedermana4054b62009-11-20 09:12:22 -0800111 /* Prepend "/proc" prefix if using internal proc vfs mount. */
112 if (!IS_ERR(sp) && (path->mnt->mnt_parent == path->mnt) &&
113 (strcmp(path->mnt->mnt_sb->s_type->name, "proc") == 0)) {
114 sp -= 5;
115 if (sp >= newname)
116 memcpy(sp, "/proc", 5);
117 else
118 sp = ERR_PTR(-ENOMEM);
119 }
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900120 }
121 if (IS_ERR(sp))
122 error = PTR_ERR(sp);
123 else
124 error = tomoyo_encode(newname, sp - newname, sp);
125 /* Append trailing '/' if dentry is a directory. */
126 if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
127 && *newname) {
128 sp = newname + strlen(newname);
129 if (*(sp - 1) != '/') {
130 if (sp < newname + newname_len - 4) {
131 *sp++ = '/';
132 *sp = '\0';
133 } else {
134 error = -ENOMEM;
135 }
136 }
137 }
138 if (error)
139 printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
140 return error;
141}
142
143/**
144 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
145 *
146 * @path: Pointer to "struct path".
147 *
148 * Returns the realpath of the given @path on success, NULL otherwise.
149 *
150 * These functions use tomoyo_alloc(), so the caller must call tomoyo_free()
151 * if these functions didn't return NULL.
152 */
153char *tomoyo_realpath_from_path(struct path *path)
154{
155 char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer));
156
157 BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
158 <= TOMOYO_MAX_PATHNAME_LEN - 1);
159 if (!buf)
160 return NULL;
161 if (tomoyo_realpath_from_path2(path, buf,
162 TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
163 return buf;
164 tomoyo_free(buf);
165 return NULL;
166}
167
168/**
169 * tomoyo_realpath - Get realpath of a pathname.
170 *
171 * @pathname: The pathname to solve.
172 *
173 * Returns the realpath of @pathname on success, NULL otherwise.
174 */
175char *tomoyo_realpath(const char *pathname)
176{
Al Viroe24977d2009-04-02 21:17:03 -0400177 struct path path;
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900178
Al Viroe24977d2009-04-02 21:17:03 -0400179 if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
180 char *buf = tomoyo_realpath_from_path(&path);
181 path_put(&path);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900182 return buf;
183 }
184 return NULL;
185}
186
187/**
188 * tomoyo_realpath_nofollow - Get realpath of a pathname.
189 *
190 * @pathname: The pathname to solve.
191 *
192 * Returns the realpath of @pathname on success, NULL otherwise.
193 */
194char *tomoyo_realpath_nofollow(const char *pathname)
195{
Al Viroe24977d2009-04-02 21:17:03 -0400196 struct path path;
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900197
Al Viroe24977d2009-04-02 21:17:03 -0400198 if (pathname && kern_path(pathname, 0, &path) == 0) {
199 char *buf = tomoyo_realpath_from_path(&path);
200 path_put(&path);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900201 return buf;
202 }
203 return NULL;
204}
205
206/* Memory allocated for non-string data. */
207static unsigned int tomoyo_allocated_memory_for_elements;
208/* Quota for holding non-string data. */
209static unsigned int tomoyo_quota_for_elements;
210
211/**
212 * tomoyo_alloc_element - Allocate permanent memory for structures.
213 *
214 * @size: Size in bytes.
215 *
216 * Returns pointer to allocated memory on success, NULL otherwise.
217 *
218 * Memory has to be zeroed.
219 * The RAM is chunked, so NEVER try to kfree() the returned pointer.
220 */
221void *tomoyo_alloc_element(const unsigned int size)
222{
223 static char *buf;
224 static DEFINE_MUTEX(lock);
225 static unsigned int buf_used_len = PATH_MAX;
226 char *ptr = NULL;
227 /*Assumes sizeof(void *) >= sizeof(long) is true. */
228 const unsigned int word_aligned_size
229 = roundup(size, max(sizeof(void *), sizeof(long)));
230 if (word_aligned_size > PATH_MAX)
231 return NULL;
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900232 mutex_lock(&lock);
233 if (buf_used_len + word_aligned_size > PATH_MAX) {
234 if (!tomoyo_quota_for_elements ||
235 tomoyo_allocated_memory_for_elements
236 + PATH_MAX <= tomoyo_quota_for_elements)
237 ptr = kzalloc(PATH_MAX, GFP_KERNEL);
238 if (!ptr) {
239 printk(KERN_WARNING "ERROR: Out of memory "
240 "for tomoyo_alloc_element().\n");
241 if (!tomoyo_policy_loaded)
242 panic("MAC Initialization failed.\n");
243 } else {
244 buf = ptr;
245 tomoyo_allocated_memory_for_elements += PATH_MAX;
246 buf_used_len = word_aligned_size;
247 ptr = buf;
248 }
249 } else if (word_aligned_size) {
250 int i;
251 ptr = buf + buf_used_len;
252 buf_used_len += word_aligned_size;
253 for (i = 0; i < word_aligned_size; i++) {
254 if (!ptr[i])
255 continue;
256 printk(KERN_ERR "WARNING: Reserved memory was tainted! "
257 "The system might go wrong.\n");
258 ptr[i] = '\0';
259 }
260 }
261 mutex_unlock(&lock);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900262 return ptr;
263}
264
265/* Memory allocated for string data in bytes. */
266static unsigned int tomoyo_allocated_memory_for_savename;
267/* Quota for holding string data in bytes. */
268static unsigned int tomoyo_quota_for_savename;
269
270/*
271 * TOMOYO uses this hash only when appending a string into the string
272 * table. Frequency of appending strings is very low. So we don't need
273 * large (e.g. 64k) hash size. 256 will be sufficient.
274 */
275#define TOMOYO_MAX_HASH 256
276
Tetsuo Handac3fa1092009-06-08 12:37:39 +0900277/*
278 * tomoyo_name_entry is a structure which is used for linking
279 * "struct tomoyo_path_info" into tomoyo_name_list .
280 *
281 * Since tomoyo_name_list manages a list of strings which are shared by
282 * multiple processes (whereas "struct tomoyo_path_info" inside
283 * "struct tomoyo_path_info_with_data" is not shared), a reference counter will
284 * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info"
285 * when TOMOYO starts supporting garbage collector.
286 */
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900287struct tomoyo_name_entry {
288 struct list_head list;
289 struct tomoyo_path_info entry;
290};
291
292/* Structure for available memory region. */
293struct tomoyo_free_memory_block_list {
294 struct list_head list;
295 char *ptr; /* Pointer to a free area. */
296 int len; /* Length of the area. */
297};
298
299/*
Tetsuo Handac3fa1092009-06-08 12:37:39 +0900300 * tomoyo_name_list is used for holding string data used by TOMOYO.
301 * Since same string data is likely used for multiple times (e.g.
302 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
303 * "const struct tomoyo_path_info *".
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900304 */
305static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
306
307/**
308 * tomoyo_save_name - Allocate permanent memory for string data.
309 *
310 * @name: The string to store into the permernent memory.
311 *
312 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
313 *
314 * The RAM is shared, so NEVER try to modify or kfree() the returned name.
315 */
316const struct tomoyo_path_info *tomoyo_save_name(const char *name)
317{
318 static LIST_HEAD(fmb_list);
319 static DEFINE_MUTEX(lock);
320 struct tomoyo_name_entry *ptr;
321 unsigned int hash;
322 /* fmb contains available size in bytes.
323 fmb is removed from the fmb_list when fmb->len becomes 0. */
324 struct tomoyo_free_memory_block_list *fmb;
325 int len;
326 char *cp;
327
328 if (!name)
329 return NULL;
330 len = strlen(name) + 1;
331 if (len > TOMOYO_MAX_PATHNAME_LEN) {
332 printk(KERN_WARNING "ERROR: Name too long "
333 "for tomoyo_save_name().\n");
334 return NULL;
335 }
336 hash = full_name_hash((const unsigned char *) name, len - 1);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900337 mutex_lock(&lock);
338 list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH],
339 list) {
340 if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name))
341 goto out;
342 }
343 list_for_each_entry(fmb, &fmb_list, list) {
344 if (len <= fmb->len)
345 goto ready;
346 }
347 if (!tomoyo_quota_for_savename ||
348 tomoyo_allocated_memory_for_savename + PATH_MAX
349 <= tomoyo_quota_for_savename)
350 cp = kzalloc(PATH_MAX, GFP_KERNEL);
351 else
352 cp = NULL;
353 fmb = kzalloc(sizeof(*fmb), GFP_KERNEL);
354 if (!cp || !fmb) {
355 kfree(cp);
356 kfree(fmb);
357 printk(KERN_WARNING "ERROR: Out of memory "
358 "for tomoyo_save_name().\n");
359 if (!tomoyo_policy_loaded)
360 panic("MAC Initialization failed.\n");
361 ptr = NULL;
362 goto out;
363 }
364 tomoyo_allocated_memory_for_savename += PATH_MAX;
365 list_add(&fmb->list, &fmb_list);
366 fmb->ptr = cp;
367 fmb->len = PATH_MAX;
368 ready:
369 ptr = tomoyo_alloc_element(sizeof(*ptr));
370 if (!ptr)
371 goto out;
372 ptr->entry.name = fmb->ptr;
373 memmove(fmb->ptr, name, len);
374 tomoyo_fill_path_info(&ptr->entry);
375 fmb->ptr += len;
376 fmb->len -= len;
377 list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]);
378 if (fmb->len == 0) {
379 list_del(&fmb->list);
380 kfree(fmb);
381 }
382 out:
383 mutex_unlock(&lock);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900384 return ptr ? &ptr->entry : NULL;
385}
386
387/**
388 * tomoyo_realpath_init - Initialize realpath related code.
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900389 */
Tetsuo Handa1581e7d2009-02-21 20:40:50 +0900390void __init tomoyo_realpath_init(void)
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900391{
392 int i;
393
394 BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
395 for (i = 0; i < TOMOYO_MAX_HASH; i++)
396 INIT_LIST_HEAD(&tomoyo_name_list[i]);
397 INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
398 tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME);
399 list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
400 down_read(&tomoyo_domain_list_lock);
401 if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
402 panic("Can't register tomoyo_kernel_domain");
403 up_read(&tomoyo_domain_list_lock);
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900404}
405
Kentaro Takedac73bd6d2009-02-05 17:18:12 +0900406/* Memory allocated for temporary purpose. */
407static atomic_t tomoyo_dynamic_memory_size;
408
409/**
410 * tomoyo_alloc - Allocate memory for temporary purpose.
411 *
412 * @size: Size in bytes.
413 *
414 * Returns pointer to allocated memory on success, NULL otherwise.
415 */
416void *tomoyo_alloc(const size_t size)
417{
418 void *p = kzalloc(size, GFP_KERNEL);
419 if (p)
420 atomic_add(ksize(p), &tomoyo_dynamic_memory_size);
421 return p;
422}
423
424/**
425 * tomoyo_free - Release memory allocated by tomoyo_alloc().
426 *
427 * @p: Pointer returned by tomoyo_alloc(). May be NULL.
428 *
429 * Returns nothing.
430 */
431void tomoyo_free(const void *p)
432{
433 if (p) {
434 atomic_sub(ksize(p), &tomoyo_dynamic_memory_size);
435 kfree(p);
436 }
437}
438
439/**
440 * tomoyo_read_memory_counter - Check for memory usage in bytes.
441 *
442 * @head: Pointer to "struct tomoyo_io_buffer".
443 *
444 * Returns memory usage.
445 */
446int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
447{
448 if (!head->read_eof) {
449 const unsigned int shared
450 = tomoyo_allocated_memory_for_savename;
451 const unsigned int private
452 = tomoyo_allocated_memory_for_elements;
453 const unsigned int dynamic
454 = atomic_read(&tomoyo_dynamic_memory_size);
455 char buffer[64];
456
457 memset(buffer, 0, sizeof(buffer));
458 if (tomoyo_quota_for_savename)
459 snprintf(buffer, sizeof(buffer) - 1,
460 " (Quota: %10u)",
461 tomoyo_quota_for_savename);
462 else
463 buffer[0] = '\0';
464 tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer);
465 if (tomoyo_quota_for_elements)
466 snprintf(buffer, sizeof(buffer) - 1,
467 " (Quota: %10u)",
468 tomoyo_quota_for_elements);
469 else
470 buffer[0] = '\0';
471 tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer);
472 tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic);
473 tomoyo_io_printf(head, "Total: %10u\n",
474 shared + private + dynamic);
475 head->read_eof = true;
476 }
477 return 0;
478}
479
480/**
481 * tomoyo_write_memory_quota - Set memory quota.
482 *
483 * @head: Pointer to "struct tomoyo_io_buffer".
484 *
485 * Returns 0.
486 */
487int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
488{
489 char *data = head->write_buf;
490 unsigned int size;
491
492 if (sscanf(data, "Shared: %u", &size) == 1)
493 tomoyo_quota_for_savename = size;
494 else if (sscanf(data, "Private: %u", &size) == 1)
495 tomoyo_quota_for_elements = size;
496 return 0;
497}