LCOV - code coverage report
Current view: top level - fs/btrfs - xattr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 147 0.0 %
Date: 2014-02-18 Functions: 0 10 0.0 %
Branches: 0 104 0.0 %

           Branch data     Line data    Source code
       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                 :            : 
      32                 :          0 : ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
      33                 :            :                                 void *buffer, size_t size)
      34                 :            : {
      35                 :            :         struct btrfs_dir_item *di;
      36                 :          0 :         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                 :          0 :         path = btrfs_alloc_path();
      43         [ #  # ]:          0 :         if (!path)
      44                 :            :                 return -ENOMEM;
      45                 :            : 
      46                 :            :         /* lookup the xattr by name */
      47                 :          0 :         di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), name,
      48                 :          0 :                                 strlen(name), 0);
      49         [ #  # ]:          0 :         if (!di) {
      50                 :            :                 ret = -ENODATA;
      51                 :            :                 goto out;
      52         [ #  # ]:          0 :         } else if (IS_ERR(di)) {
      53                 :            :                 ret = PTR_ERR(di);
      54                 :          0 :                 goto out;
      55                 :            :         }
      56                 :            : 
      57                 :          0 :         leaf = path->nodes[0];
      58                 :            :         /* if size is 0, that means we want the size of the attr */
      59         [ #  # ]:          0 :         if (!size) {
      60                 :          0 :                 ret = btrfs_dir_data_len(leaf, di);
      61                 :          0 :                 goto out;
      62                 :            :         }
      63                 :            : 
      64                 :            :         /* now get the data out of our dir_item */
      65         [ #  # ]:          0 :         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                 :          0 :         data_ptr = (unsigned long)((char *)(di + 1) +
      78                 :            :                                    btrfs_dir_name_len(leaf, di));
      79                 :          0 :         read_extent_buffer(leaf, buffer, data_ptr,
      80                 :            :                            btrfs_dir_data_len(leaf, di));
      81                 :          0 :         ret = btrfs_dir_data_len(leaf, di);
      82                 :            : 
      83                 :            : out:
      84                 :          0 :         btrfs_free_path(path);
      85                 :          0 :         return ret;
      86                 :            : }
      87                 :            : 
      88                 :          0 : static 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                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
      94                 :            :         struct btrfs_path *path;
      95                 :          0 :         size_t name_len = strlen(name);
      96                 :            :         int ret = 0;
      97                 :            : 
      98         [ #  # ]:          0 :         if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
      99                 :            :                 return -ENOSPC;
     100                 :            : 
     101                 :          0 :         path = btrfs_alloc_path();
     102         [ #  # ]:          0 :         if (!path)
     103                 :            :                 return -ENOMEM;
     104                 :            : 
     105         [ #  # ]:          0 :         if (flags & XATTR_REPLACE) {
     106                 :          0 :                 di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
     107                 :            :                                         name_len, -1);
     108         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     109                 :            :                         ret = PTR_ERR(di);
     110                 :          0 :                         goto out;
     111         [ #  # ]:          0 :                 } else if (!di) {
     112                 :            :                         ret = -ENODATA;
     113                 :            :                         goto out;
     114                 :            :                 }
     115                 :          0 :                 ret = btrfs_delete_one_dir_name(trans, root, path, di);
     116         [ #  # ]:          0 :                 if (ret)
     117                 :            :                         goto out;
     118                 :          0 :                 btrfs_release_path(path);
     119                 :            : 
     120                 :            :                 /*
     121                 :            :                  * remove the attribute
     122                 :            :                  */
     123         [ #  # ]:          0 :                 if (!value)
     124                 :            :                         goto out;
     125                 :            :         } else {
     126                 :          0 :                 di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode),
     127                 :            :                                         name, name_len, 0);
     128         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     129                 :            :                         ret = PTR_ERR(di);
     130                 :          0 :                         goto out;
     131                 :            :                 }
     132         [ #  # ]:          0 :                 if (!di && !value)
     133                 :            :                         goto out;
     134                 :          0 :                 btrfs_release_path(path);
     135                 :            :         }
     136                 :            : 
     137                 :            : again:
     138                 :          0 :         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         [ #  # ]:          0 :         if (ret == -EOVERFLOW)
     149                 :            :                 ret = -EEXIST;
     150                 :            : 
     151         [ #  # ]:          0 :         if (ret == -EEXIST) {
     152         [ #  # ]:          0 :                 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                 :          0 :                 btrfs_release_path(path);
     160                 :          0 :                 di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode),
     161                 :            :                                         name, name_len, -1);
     162         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     163                 :            :                         ret = PTR_ERR(di);
     164                 :          0 :                         goto out;
     165         [ #  # ]:          0 :                 } else if (!di) {
     166                 :            :                         /* Shouldn't happen but just in case... */
     167                 :          0 :                         btrfs_release_path(path);
     168                 :          0 :                         goto again;
     169                 :            :                 }
     170                 :            : 
     171                 :          0 :                 ret = btrfs_delete_one_dir_name(trans, root, path, di);
     172         [ #  # ]:          0 :                 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         [ #  # ]:          0 :                 if (value) {
     179                 :          0 :                         btrfs_release_path(path);
     180                 :          0 :                         goto again;
     181                 :            :                 }
     182                 :            :         }
     183                 :            : out:
     184                 :          0 :         btrfs_free_path(path);
     185                 :          0 :         return ret;
     186                 :            : }
     187                 :            : 
     188                 :            : /*
     189                 :            :  * @value: "" makes the attribute to empty, NULL removes it
     190                 :            :  */
     191                 :          0 : int __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                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
     196                 :            :         int ret;
     197                 :            : 
     198         [ #  # ]:          0 :         if (trans)
     199                 :          0 :                 return do_setxattr(trans, inode, name, value, size, flags);
     200                 :            : 
     201                 :          0 :         trans = btrfs_start_transaction(root, 2);
     202         [ #  # ]:          0 :         if (IS_ERR(trans))
     203                 :          0 :                 return PTR_ERR(trans);
     204                 :            : 
     205                 :          0 :         ret = do_setxattr(trans, inode, name, value, size, flags);
     206         [ #  # ]:          0 :         if (ret)
     207                 :            :                 goto out;
     208                 :            : 
     209                 :            :         inode_inc_iversion(inode);
     210                 :          0 :         inode->i_ctime = CURRENT_TIME;
     211                 :          0 :         set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
     212                 :          0 :         ret = btrfs_update_inode(trans, root, inode);
     213         [ #  # ]:          0 :         BUG_ON(ret);
     214                 :            : out:
     215                 :          0 :         btrfs_end_transaction(trans, root);
     216                 :          0 :         return ret;
     217                 :            : }
     218                 :            : 
     219                 :          0 : ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
     220                 :            : {
     221                 :            :         struct btrfs_key key, found_key;
     222                 :          0 :         struct inode *inode = dentry->d_inode;
     223                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
     224                 :            :         struct btrfs_path *path;
     225                 :          0 :         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                 :          0 :         key.objectid = btrfs_ino(inode);
     238                 :            :         btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
     239                 :          0 :         key.offset = 0;
     240                 :            : 
     241                 :          0 :         path = btrfs_alloc_path();
     242         [ #  # ]:          0 :         if (!path)
     243                 :            :                 return -ENOMEM;
     244                 :          0 :         path->reada = 2;
     245                 :            : 
     246                 :            :         /* search for our xattrs */
     247                 :          0 :         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
     248         [ #  # ]:          0 :         if (ret < 0)
     249                 :            :                 goto err;
     250                 :            : 
     251                 :            :         while (1) {
     252                 :          0 :                 leaf = path->nodes[0];
     253                 :          0 :                 slot = path->slots[0];
     254                 :            : 
     255                 :            :                 /* this is where we start walking through the path */
     256         [ #  # ]:          0 :                 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                 :          0 :                         ret = btrfs_next_leaf(root, path);
     262         [ #  # ]:          0 :                         if (ret < 0)
     263                 :            :                                 goto err;
     264         [ #  # ]:          0 :                         else if (ret > 0)
     265                 :            :                                 break;
     266                 :          0 :                         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         [ #  # ]:          0 :                 if (found_key.objectid != key.objectid)
     273                 :            :                         break;
     274         [ #  # ]:          0 :                 if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
     275                 :            :                         break;
     276                 :            : 
     277                 :          0 :                 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
     278         [ #  # ]:          0 :                 if (verify_dir_item(root, leaf, di))
     279                 :            :                         goto next;
     280                 :            : 
     281                 :          0 :                 name_len = btrfs_dir_name_len(leaf, di);
     282                 :          0 :                 total_size += name_len + 1;
     283                 :            : 
     284                 :            :                 /* we are just looking for how big our buffer needs to be */
     285         [ #  # ]:          0 :                 if (!size)
     286                 :            :                         goto next;
     287                 :            : 
     288 [ #  # ][ #  # ]:          0 :                 if (!buffer || (name_len + 1) > size_left) {
     289                 :            :                         ret = -ERANGE;
     290                 :            :                         goto err;
     291                 :            :                 }
     292                 :            : 
     293                 :          0 :                 name_ptr = (unsigned long)(di + 1);
     294                 :          0 :                 read_extent_buffer(leaf, buffer, name_ptr, name_len);
     295                 :          0 :                 buffer[name_len] = '\0';
     296                 :            : 
     297                 :          0 :                 size_left -= name_len + 1;
     298                 :          0 :                 buffer += name_len + 1;
     299                 :            : next:
     300                 :          0 :                 path->slots[0]++;
     301                 :            :         }
     302                 :          0 :         ret = total_size;
     303                 :            : 
     304                 :            : err:
     305                 :          0 :         btrfs_free_path(path);
     306                 :            : 
     307                 :          0 :         return ret;
     308                 :            : }
     309                 :            : 
     310                 :            : /*
     311                 :            :  * List of handlers for synthetic system.* attributes.  All real ondisk
     312                 :            :  * attributes are handled directly.
     313                 :            :  */
     314                 :            : const 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                 :            :  */
     328                 :          0 : static bool btrfs_is_valid_xattr(const char *name)
     329                 :            : {
     330                 :          0 :         return !strncmp(name, XATTR_SECURITY_PREFIX,
     331         [ #  # ]:          0 :                         XATTR_SECURITY_PREFIX_LEN) ||
     332         [ #  # ]:          0 :                !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
     333 [ #  # ][ #  # ]:          0 :                !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
     334                 :          0 :                !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
     335                 :            : }
     336                 :            : 
     337                 :          0 : ssize_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         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     346                 :          0 :                 return generic_getxattr(dentry, name, buffer, size);
     347                 :            : 
     348         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     349                 :            :                 return -EOPNOTSUPP;
     350                 :          0 :         return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
     351                 :            : }
     352                 :            : 
     353                 :          0 : int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
     354                 :            :                    size_t size, int flags)
     355                 :            : {
     356                 :          0 :         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         [ #  # ]:          0 :         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         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     371                 :          0 :                 return generic_setxattr(dentry, name, value, size, flags);
     372                 :            : 
     373         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     374                 :            :                 return -EOPNOTSUPP;
     375                 :            : 
     376         [ #  # ]:          0 :         if (size == 0)
     377                 :            :                 value = "";  /* empty EA, do not remove */
     378                 :            : 
     379                 :          0 :         return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
     380                 :            :                                 flags);
     381                 :            : }
     382                 :            : 
     383                 :          0 : int btrfs_removexattr(struct dentry *dentry, const char *name)
     384                 :            : {
     385                 :          0 :         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         [ #  # ]:          0 :         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         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     400                 :          0 :                 return generic_removexattr(dentry, name);
     401                 :            : 
     402         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     403                 :            :                 return -EOPNOTSUPP;
     404                 :            : 
     405                 :          0 :         return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
     406                 :            :                                 XATTR_REPLACE);
     407                 :            : }
     408                 :            : 
     409                 :          0 : static 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         [ #  # ]:          0 :         for (xattr = xattr_array; xattr->name != NULL; xattr++) {
     418                 :          0 :                 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
     419                 :          0 :                                strlen(xattr->name) + 1, GFP_NOFS);
     420         [ #  # ]:          0 :                 if (!name) {
     421                 :            :                         err = -ENOMEM;
     422                 :            :                         break;
     423                 :            :                 }
     424                 :          0 :                 strcpy(name, XATTR_SECURITY_PREFIX);
     425                 :          0 :                 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
     426                 :          0 :                 err = __btrfs_setxattr(trans, inode, name,
     427                 :          0 :                                        xattr->value, xattr->value_len, 0);
     428                 :          0 :                 kfree(name);
     429         [ #  # ]:          0 :                 if (err < 0)
     430                 :            :                         break;
     431                 :            :         }
     432                 :          0 :         return err;
     433                 :            : }
     434                 :            : 
     435                 :          0 : int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
     436                 :            :                               struct inode *inode, struct inode *dir,
     437                 :            :                               const struct qstr *qstr)
     438                 :            : {
     439                 :          0 :         return security_inode_init_security(inode, dir, qstr,
     440                 :            :                                             &btrfs_initxattrs, trans);
     441                 :            : }

Generated by: LCOV version 1.9