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        } else {
 126                di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode),
 127                                        name, name_len, 0);
 128                if (IS_ERR(di)) {
 129                        ret = PTR_ERR(di);
 130                        goto out;
 131                }
 132                if (!di && !value)
 133                        goto out;
 134                btrfs_release_path(path);
 135        }
 136
 137again:
 138        ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
 139                                      name, name_len, value, size);
 140        /*
 141         * If we're setting an xattr to a new value but the new value is say
 142         * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting
 143         * back from split_leaf.  This is because it thinks we'll be extending
 144         * the existing item size, but we're asking for enough space to add the
 145         * item itself.  So if we get EOVERFLOW just set ret to EEXIST and let
 146         * the rest of the function figure it out.
 147         */
 148        if (ret == -EOVERFLOW)
 149                ret = -EEXIST;
 150
 151        if (ret == -EEXIST) {
 152                if (flags & XATTR_CREATE)
 153                        goto out;
 154                /*
 155                 * We can't use the path we already have since we won't have the
 156                 * proper locking for a delete, so release the path and
 157                 * re-lookup to delete the thing.
 158                 */
 159                btrfs_release_path(path);
 160                di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode),
 161                                        name, name_len, -1);
 162                if (IS_ERR(di)) {
 163                        ret = PTR_ERR(di);
 164                        goto out;
 165                } else if (!di) {
 166                        /* Shouldn't happen but just in case... */
 167                        btrfs_release_path(path);
 168                        goto again;
 169                }
 170
 171                ret = btrfs_delete_one_dir_name(trans, root, path, di);
 172                if (ret)
 173                        goto out;
 174
 175                /*
 176                 * We have a value to set, so go back and try to insert it now.
 177                 */
 178                if (value) {
 179                        btrfs_release_path(path);
 180                        goto again;
 181                }
 182        }
 183out:
 184        btrfs_free_path(path);
 185        return ret;
 186}
 187
 188/*
 189 * @value: "" makes the attribute to empty, NULL removes it
 190 */
 191int __btrfs_setxattr(struct btrfs_trans_handle *trans,
 192                     struct inode *inode, const char *name,
 193                     const void *value, size_t size, int flags)
 194{
 195        struct btrfs_root *root = BTRFS_I(inode)->root;
 196        int ret;
 197
 198        if (trans)
 199                return do_setxattr(trans, inode, name, value, size, flags);
 200
 201        trans = btrfs_start_transaction(root, 2);
 202        if (IS_ERR(trans))
 203                return PTR_ERR(trans);
 204
 205        ret = do_setxattr(trans, inode, name, value, size, flags);
 206        if (ret)
 207                goto out;
 208
 209        inode_inc_iversion(inode);
 210        inode->i_ctime = CURRENT_TIME;
 211        set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
 212        ret = btrfs_update_inode(trans, root, inode);
 213        BUG_ON(ret);
 214out:
 215        btrfs_end_transaction(trans, root);
 216        return ret;
 217}
 218
 219ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
 220{
 221        struct btrfs_key key, found_key;
 222        struct inode *inode = dentry->d_inode;
 223        struct btrfs_root *root = BTRFS_I(inode)->root;
 224        struct btrfs_path *path;
 225        struct extent_buffer *leaf;
 226        struct btrfs_dir_item *di;
 227        int ret = 0, slot;
 228        size_t total_size = 0, size_left = size;
 229        unsigned long name_ptr;
 230        size_t name_len;
 231
 232        /*
 233         * ok we want all objects associated with this id.
 234         * NOTE: we set key.offset = 0; because we want to start with the
 235         * first xattr that we find and walk forward
 236         */
 237        key.objectid = btrfs_ino(inode);
 238        btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
 239        key.offset = 0;
 240
 241        path = btrfs_alloc_path();
 242        if (!path)
 243                return -ENOMEM;
 244        path->reada = 2;
 245
 246        /* search for our xattrs */
 247        ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
 248        if (ret < 0)
 249                goto err;
 250
 251        while (1) {
 252                leaf = path->nodes[0];
 253                slot = path->slots[0];
 254
 255                /* this is where we start walking through the path */
 256                if (slot >= btrfs_header_nritems(leaf)) {
 257                        /*
 258                         * if we've reached the last slot in this leaf we need
 259                         * to go to the next leaf and reset everything
 260                         */
 261                        ret = btrfs_next_leaf(root, path);
 262                        if (ret < 0)
 263                                goto err;
 264                        else if (ret > 0)
 265                                break;
 266                        continue;
 267                }
 268
 269                btrfs_item_key_to_cpu(leaf, &found_key, slot);
 270
 271                /* check to make sure this item is what we want */
 272                if (found_key.objectid != key.objectid)
 273                        break;
 274                if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
 275                        break;
 276
 277                di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
 278                if (verify_dir_item(root, leaf, di))
 279                        goto next;
 280
 281                name_len = btrfs_dir_name_len(leaf, di);
 282                total_size += name_len + 1;
 283
 284                /* we are just looking for how big our buffer needs to be */
 285                if (!size)
 286                        goto next;
 287
 288                if (!buffer || (name_len + 1) > size_left) {
 289                        ret = -ERANGE;
 290                        goto err;
 291                }
 292
 293                name_ptr = (unsigned long)(di + 1);
 294                read_extent_buffer(leaf, buffer, name_ptr, name_len);
 295                buffer[name_len] = '\0';
 296
 297                size_left -= name_len + 1;
 298                buffer += name_len + 1;
 299next:
 300                path->slots[0]++;
 301        }
 302        ret = total_size;
 303
 304err:
 305        btrfs_free_path(path);
 306
 307        return ret;
 308}
 309
 310/*
 311 * List of handlers for synthetic system.* attributes.  All real ondisk
 312 * attributes are handled directly.
 313 */
 314const struct xattr_handler *btrfs_xattr_handlers[] = {
 315#ifdef CONFIG_BTRFS_FS_POSIX_ACL
 316        &btrfs_xattr_acl_access_handler,
 317        &btrfs_xattr_acl_default_handler,
 318#endif
 319        NULL,
 320};
 321
 322/*
 323 * Check if the attribute is in a supported namespace.
 324 *
 325 * This applied after the check for the synthetic attributes in the system
 326 * namespace.
 327 */
 328static bool btrfs_is_valid_xattr(const char *name)
 329{
 330        return !strncmp(name, XATTR_SECURITY_PREFIX,
 331                        XATTR_SECURITY_PREFIX_LEN) ||
 332               !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
 333               !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
 334               !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
 335}
 336
 337ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
 338                       void *buffer, size_t size)
 339{
 340        /*
 341         * If this is a request for a synthetic attribute in the system.*
 342         * namespace use the generic infrastructure to resolve a handler
 343         * for it via sb->s_xattr.
 344         */
 345        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 346                return generic_getxattr(dentry, name, buffer, size);
 347
 348        if (!btrfs_is_valid_xattr(name))
 349                return -EOPNOTSUPP;
 350        return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
 351}
 352
 353int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
 354                   size_t size, int flags)
 355{
 356        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
 357
 358        /*
 359         * The permission on security.* and system.* is not checked
 360         * in permission().
 361         */
 362        if (btrfs_root_readonly(root))
 363                return -EROFS;
 364
 365        /*
 366         * If this is a request for a synthetic attribute in the system.*
 367         * namespace use the generic infrastructure to resolve a handler
 368         * for it via sb->s_xattr.
 369         */
 370        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 371                return generic_setxattr(dentry, name, value, size, flags);
 372
 373        if (!btrfs_is_valid_xattr(name))
 374                return -EOPNOTSUPP;
 375
 376        if (size == 0)
 377                value = "";  /* empty EA, do not remove */
 378
 379        return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
 380                                flags);
 381}
 382
 383int btrfs_removexattr(struct dentry *dentry, const char *name)
 384{
 385        struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
 386
 387        /*
 388         * The permission on security.* and system.* is not checked
 389         * in permission().
 390         */
 391        if (btrfs_root_readonly(root))
 392                return -EROFS;
 393
 394        /*
 395         * If this is a request for a synthetic attribute in the system.*
 396         * namespace use the generic infrastructure to resolve a handler
 397         * for it via sb->s_xattr.
 398         */
 399        if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
 400                return generic_removexattr(dentry, name);
 401
 402        if (!btrfs_is_valid_xattr(name))
 403                return -EOPNOTSUPP;
 404
 405        return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
 406                                XATTR_REPLACE);
 407}
 408
 409static int btrfs_initxattrs(struct inode *inode,
 410                            const struct xattr *xattr_array, void *fs_info)
 411{
 412        const struct xattr *xattr;
 413        struct btrfs_trans_handle *trans = fs_info;
 414        char *name;
 415        int err = 0;
 416
 417        for (xattr = xattr_array; xattr->name != NULL; xattr++) {
 418                name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
 419                               strlen(xattr->name) + 1, GFP_NOFS);
 420                if (!name) {
 421                        err = -ENOMEM;
 422                        break;
 423                }
 424                strcpy(name, XATTR_SECURITY_PREFIX);
 425                strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
 426                err = __btrfs_setxattr(trans, inode, name,
 427                                       xattr->value, xattr->value_len, 0);
 428                kfree(name);
 429                if (err < 0)
 430                        break;
 431        }
 432        return err;
 433}
 434
 435int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
 436                              struct inode *inode, struct inode *dir,
 437                              const struct qstr *qstr)
 438{
 439        return security_inode_init_security(inode, dir, qstr,
 440                                            &btrfs_initxattrs, trans);
 441}
 442