linux/security/tomoyo/realpath.c
<<
>>
Prefs
   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   2009/04/01
   9 *
  10 */
  11
  12#include <linux/types.h>
  13#include <linux/mount.h>
  14#include <linux/mnt_namespace.h>
  15#include <linux/fs_struct.h>
  16#include <linux/hash.h>
  17#include <linux/magic.h>
  18#include <linux/slab.h>
  19#include "common.h"
  20
  21/**
  22 * tomoyo_encode: Convert binary string to ascii string.
  23 *
  24 * @buffer:  Buffer for ASCII string.
  25 * @buflen:  Size of @buffer.
  26 * @str:     Binary string.
  27 *
  28 * Returns 0 on success, -ENOMEM otherwise.
  29 */
  30int tomoyo_encode(char *buffer, int buflen, const char *str)
  31{
  32        while (1) {
  33                const unsigned char c = *(unsigned char *) str++;
  34
  35                if (tomoyo_is_valid(c)) {
  36                        if (--buflen <= 0)
  37                                break;
  38                        *buffer++ = (char) c;
  39                        if (c != '\\')
  40                                continue;
  41                        if (--buflen <= 0)
  42                                break;
  43                        *buffer++ = (char) c;
  44                        continue;
  45                }
  46                if (!c) {
  47                        if (--buflen <= 0)
  48                                break;
  49                        *buffer = '\0';
  50                        return 0;
  51                }
  52                buflen -= 4;
  53                if (buflen <= 0)
  54                        break;
  55                *buffer++ = '\\';
  56                *buffer++ = (c >> 6) + '0';
  57                *buffer++ = ((c >> 3) & 7) + '0';
  58                *buffer++ = (c & 7) + '0';
  59        }
  60        return -ENOMEM;
  61}
  62
  63/**
  64 * tomoyo_realpath_from_path2 - Returns realpath(3) of the given dentry but ignores chroot'ed root.
  65 *
  66 * @path:        Pointer to "struct path".
  67 * @newname:     Pointer to buffer to return value in.
  68 * @newname_len: Size of @newname.
  69 *
  70 * Returns 0 on success, negative value otherwise.
  71 *
  72 * If dentry is a directory, trailing '/' is appended.
  73 * Characters out of 0x20 < c < 0x7F range are converted to
  74 * \ooo style octal string.
  75 * Character \ is converted to \\ string.
  76 */
  77int tomoyo_realpath_from_path2(struct path *path, char *newname,
  78                               int newname_len)
  79{
  80        int error = -ENOMEM;
  81        struct dentry *dentry = path->dentry;
  82        char *sp;
  83
  84        if (!dentry || !path->mnt || !newname || newname_len <= 2048)
  85                return -EINVAL;
  86        if (dentry->d_op && dentry->d_op->d_dname) {
  87                /* For "socket:[\$]" and "pipe:[\$]". */
  88                static const int offset = 1536;
  89                sp = dentry->d_op->d_dname(dentry, newname + offset,
  90                                           newname_len - offset);
  91        } else {
  92                struct path ns_root = {.mnt = NULL, .dentry = NULL};
  93
  94                spin_lock(&dcache_lock);
  95                /* go to whatever namespace root we are under */
  96                sp = __d_path(path, &ns_root, newname, newname_len);
  97                spin_unlock(&dcache_lock);
  98                /* Prepend "/proc" prefix if using internal proc vfs mount. */
  99                if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) &&
 100                    (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) {
 101                        sp -= 5;
 102                        if (sp >= newname)
 103                                memcpy(sp, "/proc", 5);
 104                        else
 105                                sp = ERR_PTR(-ENOMEM);
 106                }
 107        }
 108        if (IS_ERR(sp))
 109                error = PTR_ERR(sp);
 110        else
 111                error = tomoyo_encode(newname, sp - newname, sp);
 112        /* Append trailing '/' if dentry is a directory. */
 113        if (!error && dentry->d_inode && S_ISDIR(dentry->d_inode->i_mode)
 114            && *newname) {
 115                sp = newname + strlen(newname);
 116                if (*(sp - 1) != '/') {
 117                        if (sp < newname + newname_len - 4) {
 118                                *sp++ = '/';
 119                                *sp = '\0';
 120                        } else {
 121                                error = -ENOMEM;
 122                        }
 123                }
 124        }
 125        if (error)
 126                printk(KERN_WARNING "tomoyo_realpath: Pathname too long.\n");
 127        return error;
 128}
 129
 130/**
 131 * tomoyo_realpath_from_path - Returns realpath(3) of the given pathname but ignores chroot'ed root.
 132 *
 133 * @path: Pointer to "struct path".
 134 *
 135 * Returns the realpath of the given @path on success, NULL otherwise.
 136 *
 137 * These functions use kzalloc(), so the caller must call kfree()
 138 * if these functions didn't return NULL.
 139 */
 140char *tomoyo_realpath_from_path(struct path *path)
 141{
 142        char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_NOFS);
 143
 144        BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer)
 145                     <= TOMOYO_MAX_PATHNAME_LEN - 1);
 146        if (!buf)
 147                return NULL;
 148        if (tomoyo_realpath_from_path2(path, buf,
 149                                       TOMOYO_MAX_PATHNAME_LEN - 1) == 0)
 150                return buf;
 151        kfree(buf);
 152        return NULL;
 153}
 154
 155/**
 156 * tomoyo_realpath - Get realpath of a pathname.
 157 *
 158 * @pathname: The pathname to solve.
 159 *
 160 * Returns the realpath of @pathname on success, NULL otherwise.
 161 */
 162char *tomoyo_realpath(const char *pathname)
 163{
 164        struct path path;
 165
 166        if (pathname && kern_path(pathname, LOOKUP_FOLLOW, &path) == 0) {
 167                char *buf = tomoyo_realpath_from_path(&path);
 168                path_put(&path);
 169                return buf;
 170        }
 171        return NULL;
 172}
 173
 174/**
 175 * tomoyo_realpath_nofollow - Get realpath of a pathname.
 176 *
 177 * @pathname: The pathname to solve.
 178 *
 179 * Returns the realpath of @pathname on success, NULL otherwise.
 180 */
 181char *tomoyo_realpath_nofollow(const char *pathname)
 182{
 183        struct path path;
 184
 185        if (pathname && kern_path(pathname, 0, &path) == 0) {
 186                char *buf = tomoyo_realpath_from_path(&path);
 187                path_put(&path);
 188                return buf;
 189        }
 190        return NULL;
 191}
 192
 193/* Memory allocated for non-string data. */
 194static atomic_t tomoyo_policy_memory_size;
 195/* Quota for holding policy. */
 196static unsigned int tomoyo_quota_for_policy;
 197
 198/**
 199 * tomoyo_memory_ok - Check memory quota.
 200 *
 201 * @ptr: Pointer to allocated memory.
 202 *
 203 * Returns true on success, false otherwise.
 204 *
 205 * Caller holds tomoyo_policy_lock.
 206 * Memory pointed by @ptr will be zeroed on success.
 207 */
 208bool tomoyo_memory_ok(void *ptr)
 209{
 210        int allocated_len = ptr ? ksize(ptr) : 0;
 211        atomic_add(allocated_len, &tomoyo_policy_memory_size);
 212        if (ptr && (!tomoyo_quota_for_policy ||
 213                    atomic_read(&tomoyo_policy_memory_size)
 214                    <= tomoyo_quota_for_policy)) {
 215                memset(ptr, 0, allocated_len);
 216                return true;
 217        }
 218        printk(KERN_WARNING "ERROR: Out of memory "
 219               "for tomoyo_alloc_element().\n");
 220        if (!tomoyo_policy_loaded)
 221                panic("MAC Initialization failed.\n");
 222        return false;
 223}
 224
 225/**
 226 * tomoyo_commit_ok - Check memory quota.
 227 *
 228 * @data:   Data to copy from.
 229 * @size:   Size in byte.
 230 *
 231 * Returns pointer to allocated memory on success, NULL otherwise.
 232 */
 233void *tomoyo_commit_ok(void *data, const unsigned int size)
 234{
 235        void *ptr = kzalloc(size, GFP_NOFS);
 236        if (tomoyo_memory_ok(ptr)) {
 237                memmove(ptr, data, size);
 238                memset(data, 0, size);
 239                return ptr;
 240        }
 241        return NULL;
 242}
 243
 244/**
 245 * tomoyo_memory_free - Free memory for elements.
 246 *
 247 * @ptr:  Pointer to allocated memory.
 248 */
 249void tomoyo_memory_free(void *ptr)
 250{
 251        atomic_sub(ksize(ptr), &tomoyo_policy_memory_size);
 252        kfree(ptr);
 253}
 254
 255/*
 256 * tomoyo_name_list is used for holding string data used by TOMOYO.
 257 * Since same string data is likely used for multiple times (e.g.
 258 * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of
 259 * "const struct tomoyo_path_info *".
 260 */
 261struct list_head tomoyo_name_list[TOMOYO_MAX_HASH];
 262
 263/**
 264 * tomoyo_get_name - Allocate permanent memory for string data.
 265 *
 266 * @name: The string to store into the permernent memory.
 267 *
 268 * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise.
 269 */
 270const struct tomoyo_path_info *tomoyo_get_name(const char *name)
 271{
 272        struct tomoyo_name_entry *ptr;
 273        unsigned int hash;
 274        int len;
 275        int allocated_len;
 276        struct list_head *head;
 277
 278        if (!name)
 279                return NULL;
 280        len = strlen(name) + 1;
 281        hash = full_name_hash((const unsigned char *) name, len - 1);
 282        head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)];
 283        if (mutex_lock_interruptible(&tomoyo_policy_lock))
 284                return NULL;
 285        list_for_each_entry(ptr, head, list) {
 286                if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name))
 287                        continue;
 288                atomic_inc(&ptr->users);
 289                goto out;
 290        }
 291        ptr = kzalloc(sizeof(*ptr) + len, GFP_NOFS);
 292        allocated_len = ptr ? ksize(ptr) : 0;
 293        if (!ptr || (tomoyo_quota_for_policy &&
 294                     atomic_read(&tomoyo_policy_memory_size) + allocated_len
 295                     > tomoyo_quota_for_policy)) {
 296                kfree(ptr);
 297                printk(KERN_WARNING "ERROR: Out of memory "
 298                       "for tomoyo_get_name().\n");
 299                if (!tomoyo_policy_loaded)
 300                        panic("MAC Initialization failed.\n");
 301                ptr = NULL;
 302                goto out;
 303        }
 304        atomic_add(allocated_len, &tomoyo_policy_memory_size);
 305        ptr->entry.name = ((char *) ptr) + sizeof(*ptr);
 306        memmove((char *) ptr->entry.name, name, len);
 307        atomic_set(&ptr->users, 1);
 308        tomoyo_fill_path_info(&ptr->entry);
 309        list_add_tail(&ptr->list, head);
 310 out:
 311        mutex_unlock(&tomoyo_policy_lock);
 312        return ptr ? &ptr->entry : NULL;
 313}
 314
 315/**
 316 * tomoyo_realpath_init - Initialize realpath related code.
 317 */
 318void __init tomoyo_realpath_init(void)
 319{
 320        int i;
 321
 322        BUILD_BUG_ON(TOMOYO_MAX_PATHNAME_LEN > PATH_MAX);
 323        for (i = 0; i < TOMOYO_MAX_HASH; i++)
 324                INIT_LIST_HEAD(&tomoyo_name_list[i]);
 325        INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list);
 326        tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME);
 327        /*
 328         * tomoyo_read_lock() is not needed because this function is
 329         * called before the first "delete" request.
 330         */
 331        list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list);
 332        if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain)
 333                panic("Can't register tomoyo_kernel_domain");
 334}
 335
 336/**
 337 * tomoyo_read_memory_counter - Check for memory usage in bytes.
 338 *
 339 * @head: Pointer to "struct tomoyo_io_buffer".
 340 *
 341 * Returns memory usage.
 342 */
 343int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head)
 344{
 345        if (!head->read_eof) {
 346                const unsigned int policy
 347                        = atomic_read(&tomoyo_policy_memory_size);
 348                char buffer[64];
 349
 350                memset(buffer, 0, sizeof(buffer));
 351                if (tomoyo_quota_for_policy)
 352                        snprintf(buffer, sizeof(buffer) - 1,
 353                                 "   (Quota: %10u)",
 354                                 tomoyo_quota_for_policy);
 355                else
 356                        buffer[0] = '\0';
 357                tomoyo_io_printf(head, "Policy:  %10u%s\n", policy, buffer);
 358                tomoyo_io_printf(head, "Total:   %10u\n", policy);
 359                head->read_eof = true;
 360        }
 361        return 0;
 362}
 363
 364/**
 365 * tomoyo_write_memory_quota - Set memory quota.
 366 *
 367 * @head: Pointer to "struct tomoyo_io_buffer".
 368 *
 369 * Returns 0.
 370 */
 371int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head)
 372{
 373        char *data = head->write_buf;
 374        unsigned int size;
 375
 376        if (sscanf(data, "Policy: %u", &size) == 1)
 377                tomoyo_quota_for_policy = size;
 378        return 0;
 379}
 380