linux/fs/btrfs/xattr.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2007 Red Hat.  All rights reserved.
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public
   6 * License v2 as published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11 * General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public
  14 * License along with this program; if not, write to the
  15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  16 * Boston, MA 021110-1307, USA.
  17 */
  18
  19#include <linux/init.h>
  20#include <linux/fs.h>
  21#include <linux/slab.h>
  22#include <linux/rwsem.h>
  23#include <linux/xattr.h>
  24#include <linux/security.h>
  25#include "ctree.h"
  26#include "btrfs_inode.h"
  27#include "transaction.h"
  28#include "xattr.h"
  29#include "disk-io.h"
  30
  31
  32ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
  33                                void *buffer, size_t size)
  34{
  35        struct btrfs_dir_item *di;
  36        struct btrfs_root *root = BTRFS_I(inode)->root;
  37        struct btrfs_path *path;
  38        struct extent_buffer *leaf;
  39        int ret = 0;
  40        unsigned long data_ptr;
  41
  42        path = btrfs_alloc_path();
  43        if (!path)
  44                return -ENOMEM;
  45
  46        /* lookup the xattr by name */
  47        di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), name,
  48                                strlen(name), 0);
  49        if (!di) {
  50                ret = -ENODATA;
  51                goto out;
  52        } else if (IS_ERR(di)) {
  53                ret = PTR_ERR(di);
  54                goto out;
  55        }
  56
  57        leaf = path->nodes[0];
  58        /* if size is 0, that means we want the size of the attr */
  59        if (!size) {
  60                ret = btrfs_dir_data_len(leaf, di);
  61                goto out;
  62        }
  63
  64        /* now get the data out of our dir_item */
  65        if (btrfs_dir_data_len(leaf, di) > size) {
  66                ret = -ERANGE;
  67                goto out;
  68        }
  69
  70        /*
  71         * The way things are packed into the leaf is like this
  72         * |struct btrfs_dir_item|name|data|
  73         * where name is the xattr name, so security.foo, and data is the
  74         * content of the xattr.  data_ptr points to the location in memory
  75         * where the data starts in the in memory leaf
  76         */
  77        data_ptr = (unsigned long)((char *)(di + 1) +
  78                                   btrfs_dir_name_len(leaf, di));
  79        read_extent_buffer(leaf, buffer, data_ptr,
  80                           btrfs_dir_data_len(leaf, di));
  81        ret = btrfs_dir_data_len(leaf, di);
  82
  83out:
  84        btrfs_free_path(path);
  85        return ret;
  86}
  87
  88static int do_setxattr(struct btrfs_trans_handle *trans,
  89                       struct inode *inode, const char *name,
  90                       const void *value, size_t size, int flags)
  91{
  92        struct btrfs_dir_item *di;
  93        struct btrfs_root *root = BTRFS_I(inode)->root;
  94        struct btrfs_path *path;
  95        size_t name_len = strlen(name);
  96        int ret = 0;
  97
  98        if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
  99                return -ENOSPC;
 100
 101        path = btrfs_alloc_path();
 102        if (!path)
 103                return -ENOMEM;
 104
 105        if (flags & XATTR_REPLACE) {
 106                di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
 107                                        name_len, -1);
 108                if (IS_ERR(di)) {
 109                        ret = PTR_ERR(di);
 110                        goto out;
 111                } else if (!di) {
 112                        ret = -ENODATA;
 113                        goto out;
 114                }
 115                ret = btrfs_delete_one_dir_name(trans, root, path, di);
 116                if (ret)
 117                        goto out;
 118                btrfs_release_path(path);
 119
 120                /*
 121                 * remove the attribute
 122                 */
 123                if (!value)
 124                        goto out;
 125        }
 126
 127again:
 128        ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
 129                                      name, name_len, value, size);
 130        if (ret == -EEXIST) {
 131                if (flags & XATTR_CREATE)
 132                        goto out;
 133                /*
 134                 * We can't use the path we already have since we won't have the
 135                 * proper locking for a delete, so release the path and
 136                 * re-lookup to delete the thing.
 137                 */
 138                btrfs_release_path(path);
 139                di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode),
 140                                        name, name_len, -1);
 141                if (IS_ERR(di)) {
 142                        ret = PTR_ERR(di);
 143                        goto out;
 144                } else if (!di) {
 145                        /* Shouldn't happen but just in case... */
 146                        btrfs_release_path(path);
 147                        goto again;
 148                }
 149
 150                ret = btrfs_delete_one_dir_name(trans, root, path, di);
 151                if (ret)
 152                        goto out;
 153
 154                /*
 155                 * We have a value to set, so go back and try to insert it now.
 156                 */
 157                if (value) {
 158                        btrfs_release_path(path);
 159                        goto again;
 160                }
 161        }
 162out:
 163        btrfs_free_path(path);
 164        return ret;
 165}
 166
 167/*
 168 * @value: "" makes the attribute to empty, NULL removes it
 169 */
 170int __btrfs_setxattr(struct btrfs_trans_handle *trans,
 171                     struct inode *inode, const char *name,
 172                     const void *value, size_t size, int flags)
 173{
 174        struct btrfs_root *root = BTRFS_I(inode)->root;
 175        int ret;
 176
 177        if (trans)
 178                return do_setxattr(trans, inode, name, value, size, flags);
 179
 180        trans = btrfs_start_transaction(root, 2);
 181        if (IS_ERR(trans))
 182                return PTR_ERR(trans);
 183
 184        ret = do_setxattr(trans, inode, name, value, size, flags);
 185        if (ret)
 186                goto out;
 187
 188        inode->i_ctime = CURRENT_TIME;
 189        ret = btrfs_update_inode(trans, root, inode);
 190        BUG_ON(ret);
 191out:
 192        btrfs_end_transaction_throttle(trans, root);
 193        return ret;
 194}
 195
 196ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 197{
 198        struct btrfs_key key, found_key;
 199        struct inode *inode = dentry->d_inode;
 200        struct btrfs_root *root = BTRFS_I(inode)->root;
 201        struct btrfs_path *path;
 202        struct extent_buffer *leaf;
 203        struct btrfs_dir_item *di;
 204        int ret = 0, slot;
 205        size_t total_size = 0, size_left = size;
 206        unsigned long name_ptr;
 207        size_t name_len;
 208
 209        /*
 210         * ok we want all objects associated with this id.
 211         * NOTE: we set key.offset = 0; because we want to start with the
 212         * first xattr that we find and walk forward
 213         */
 214        key.objectid = btrfs_ino(inode);
 215        btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
 216        key.offset = 0;
 217
 218        path = btrfs_alloc_path();
 219        if (!path)
 220                return -ENOMEM;
 221        path->reada = 2;
 222
 223        /* search for our xattrs */
 224        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 225        if (ret < 0)
 226                goto err;
 227
 228        while (1) {
 229                leaf = path->nodes[0];
 230                slot = path->slots[0];
 231
 232                /* this is where we start walking through the path */
 233                if (slot >= btrfs_header_nritems(leaf)) {
 234                        /*
 235                         * if we've reached the last slot in this leaf we need
 236                         * to go to the next leaf and reset everything
 237                         */
 238                        ret = btrfs_next_leaf(root, path);
 239                        if (ret < 0)
 240                                goto err;
 241                        else if (ret > 0)
 242                                break;
 243                        continue;
 244                }
 245
 246                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 247
 248                /* check to make sure this item is what we want */
 249                if (found_key.objectid != key.objectid)
 250                        break;
 251                if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
 252                        break;
 253
 254                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
 255                if (verify_dir_item(root, leaf, di))
 256                        continue;
 257
 258                name_len = btrfs_dir_name_len(leaf, di);
 259                total_size += name_len + 1;
 260
 261                /* we are just looking for how big our buffer needs to be */
 262                if (!size)
 263                        goto next;
 264
 265                if (!buffer || (name_len + 1) > size_left) {
 266                        ret = -ERANGE;
 267                        goto err;
 268                }
 269
 270                name_ptr = (unsigned long)(di + 1);
 271                read_extent_buffer(leaf, buffer, name_ptr, name_len);
 272                buffer[name_len] = '\0';
 273
 274                size_left -= name_len + 1;
 275                buffer += name_len + 1;
 276next:
 277                path->slots[0]++;
 278        }
 279        ret = total_size;
 280
 281err:
 282        btrfs_free_path(path);
 283
 284        return ret;
 285}
 286
 287/*
 288 * List of handlers for synthetic system.* attributes.  All real ondisk
 289 * attributes are handled directly.
 290 */
 291const struct xattr_handler *btrfs_xattr_handlers[] = {
 292#ifdef CONFIG_BTRFS_FS_POSIX_ACL
 293        &btrfs_xattr_acl_access_handler,
 294        &btrfs_xattr_acl_default_handler,
 295#endif
 296        NULL,
 297};
 298
 299/*
 300 * Check if the attribute is in a supported namespace.
 301 *
 302 * This applied after the check for the synthetic attributes in the system
 303 * namespace.
 304 */
 305static bool btrfs_is_valid_xattr(const char *name)
 306{
 307        return !strncmp(name, XATTR_SECURITY_PREFIX,
 308                        XATTR_SECURITY_PREFIX_LEN) ||
 309               !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
 310               !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
 311               !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 312}
 313
 314ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
 315                       void *buffer, size_t size)
 316{
 317        /*
 318         * If this is a request for a synthetic attribute in the system.*
 319         * namespace use the generic infrastructure to resolve a handler
 320         * for it via sb->s_xattr.
 321         */
 322        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 323                return generic_getxattr(dentry, name, buffer, size);
 324
 325        if (!btrfs_is_valid_xattr(name))
 326                return -EOPNOTSUPP;
 327        return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
 328}
 329
 330int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 331                   size_t size, int flags)
 332{
 333        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
 334
 335        /*
 336         * The permission on security.* and system.* is not checked
 337         * in permission().
 338         */
 339        if (btrfs_root_readonly(root))
 340                return -EROFS;
 341
 342        /*
 343         * If this is a request for a synthetic attribute in the system.*
 344         * namespace use the generic infrastructure to resolve a handler
 345         * for it via sb->s_xattr.
 346         */
 347        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 348                return generic_setxattr(dentry, name, value, size, flags);
 349
 350        if (!btrfs_is_valid_xattr(name))
 351                return -EOPNOTSUPP;
 352
 353        if (size == 0)
 354                value = "";  /* empty EA, do not remove */
 355
 356        return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
 357                                flags);
 358}
 359
 360int btrfs_removexattr(struct dentry *dentry, const char *name)
 361{
 362        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
 363
 364        /*
 365         * The permission on security.* and system.* is not checked
 366         * in permission().
 367         */
 368        if (btrfs_root_readonly(root))
 369                return -EROFS;
 370
 371        /*
 372         * If this is a request for a synthetic attribute in the system.*
 373         * namespace use the generic infrastructure to resolve a handler
 374         * for it via sb->s_xattr.
 375         */
 376        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 377                return generic_removexattr(dentry, name);
 378
 379        if (!btrfs_is_valid_xattr(name))
 380                return -EOPNOTSUPP;
 381
 382        return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
 383                                XATTR_REPLACE);
 384}
 385
 386int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
 387                              struct inode *inode, struct inode *dir,
 388                              const struct qstr *qstr)
 389{
 390        int err;
 391        size_t len;
 392        void *value;
 393        char *suffix;
 394        char *name;
 395
 396        err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
 397                                           &len);
 398        if (err) {
 399                if (err == -EOPNOTSUPP)
 400                        return 0;
 401                return err;
 402        }
 403
 404        name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
 405                       GFP_NOFS);
 406        if (!name) {
 407                err = -ENOMEM;
 408        } else {
 409                strcpy(name, XATTR_SECURITY_PREFIX);
 410                strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
 411                err = __btrfs_setxattr(trans, inode, name, value, len, 0);
 412                kfree(name);
 413        }
 414
 415        kfree(suffix);
 416        kfree(value);
 417        return err;
 418}
 419