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