LCOV - code coverage report
Current view: top level - fs/btrfs - xattr.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 152 0.0 %
Date: 2014-04-16 Functions: 0 10 0.0 %
Branches: 0 110 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 <linux/posix_acl_xattr.h>
      26                 :            : #include "ctree.h"
      27                 :            : #include "btrfs_inode.h"
      28                 :            : #include "transaction.h"
      29                 :            : #include "xattr.h"
      30                 :            : #include "disk-io.h"
      31                 :            : #include "props.h"
      32                 :            : 
      33                 :            : 
      34                 :          0 : ssize_t __btrfs_getxattr(struct inode *inode, const char *name,
      35                 :            :                                 void *buffer, size_t size)
      36                 :            : {
      37                 :            :         struct btrfs_dir_item *di;
      38                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
      39                 :            :         struct btrfs_path *path;
      40                 :            :         struct extent_buffer *leaf;
      41                 :            :         int ret = 0;
      42                 :            :         unsigned long data_ptr;
      43                 :            : 
      44                 :          0 :         path = btrfs_alloc_path();
      45         [ #  # ]:          0 :         if (!path)
      46                 :            :                 return -ENOMEM;
      47                 :            : 
      48                 :            :         /* lookup the xattr by name */
      49                 :          0 :         di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode), name,
      50                 :          0 :                                 strlen(name), 0);
      51         [ #  # ]:          0 :         if (!di) {
      52                 :            :                 ret = -ENODATA;
      53                 :            :                 goto out;
      54         [ #  # ]:          0 :         } else if (IS_ERR(di)) {
      55                 :            :                 ret = PTR_ERR(di);
      56                 :          0 :                 goto out;
      57                 :            :         }
      58                 :            : 
      59                 :          0 :         leaf = path->nodes[0];
      60                 :            :         /* if size is 0, that means we want the size of the attr */
      61         [ #  # ]:          0 :         if (!size) {
      62                 :          0 :                 ret = btrfs_dir_data_len(leaf, di);
      63                 :          0 :                 goto out;
      64                 :            :         }
      65                 :            : 
      66                 :            :         /* now get the data out of our dir_item */
      67         [ #  # ]:          0 :         if (btrfs_dir_data_len(leaf, di) > size) {
      68                 :            :                 ret = -ERANGE;
      69                 :            :                 goto out;
      70                 :            :         }
      71                 :            : 
      72                 :            :         /*
      73                 :            :          * The way things are packed into the leaf is like this
      74                 :            :          * |struct btrfs_dir_item|name|data|
      75                 :            :          * where name is the xattr name, so security.foo, and data is the
      76                 :            :          * content of the xattr.  data_ptr points to the location in memory
      77                 :            :          * where the data starts in the in memory leaf
      78                 :            :          */
      79                 :          0 :         data_ptr = (unsigned long)((char *)(di + 1) +
      80                 :            :                                    btrfs_dir_name_len(leaf, di));
      81                 :          0 :         read_extent_buffer(leaf, buffer, data_ptr,
      82                 :            :                            btrfs_dir_data_len(leaf, di));
      83                 :          0 :         ret = btrfs_dir_data_len(leaf, di);
      84                 :            : 
      85                 :            : out:
      86                 :          0 :         btrfs_free_path(path);
      87                 :          0 :         return ret;
      88                 :            : }
      89                 :            : 
      90                 :          0 : static int do_setxattr(struct btrfs_trans_handle *trans,
      91                 :            :                        struct inode *inode, const char *name,
      92                 :            :                        const void *value, size_t size, int flags)
      93                 :            : {
      94                 :            :         struct btrfs_dir_item *di;
      95                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
      96                 :            :         struct btrfs_path *path;
      97                 :          0 :         size_t name_len = strlen(name);
      98                 :            :         int ret = 0;
      99                 :            : 
     100         [ #  # ]:          0 :         if (name_len + size > BTRFS_MAX_XATTR_SIZE(root))
     101                 :            :                 return -ENOSPC;
     102                 :            : 
     103                 :          0 :         path = btrfs_alloc_path();
     104         [ #  # ]:          0 :         if (!path)
     105                 :            :                 return -ENOMEM;
     106                 :            : 
     107         [ #  # ]:          0 :         if (flags & XATTR_REPLACE) {
     108                 :          0 :                 di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode), name,
     109                 :            :                                         name_len, -1);
     110         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     111                 :            :                         ret = PTR_ERR(di);
     112                 :          0 :                         goto out;
     113         [ #  # ]:          0 :                 } else if (!di) {
     114                 :            :                         ret = -ENODATA;
     115                 :            :                         goto out;
     116                 :            :                 }
     117                 :          0 :                 ret = btrfs_delete_one_dir_name(trans, root, path, di);
     118         [ #  # ]:          0 :                 if (ret)
     119                 :            :                         goto out;
     120                 :          0 :                 btrfs_release_path(path);
     121                 :            : 
     122                 :            :                 /*
     123                 :            :                  * remove the attribute
     124                 :            :                  */
     125         [ #  # ]:          0 :                 if (!value)
     126                 :            :                         goto out;
     127                 :            :         } else {
     128                 :          0 :                 di = btrfs_lookup_xattr(NULL, root, path, btrfs_ino(inode),
     129                 :            :                                         name, name_len, 0);
     130         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     131                 :            :                         ret = PTR_ERR(di);
     132                 :          0 :                         goto out;
     133                 :            :                 }
     134         [ #  # ]:          0 :                 if (!di && !value)
     135                 :            :                         goto out;
     136                 :          0 :                 btrfs_release_path(path);
     137                 :            :         }
     138                 :            : 
     139                 :            : again:
     140                 :          0 :         ret = btrfs_insert_xattr_item(trans, root, path, btrfs_ino(inode),
     141                 :            :                                       name, name_len, value, size);
     142                 :            :         /*
     143                 :            :          * If we're setting an xattr to a new value but the new value is say
     144                 :            :          * exactly BTRFS_MAX_XATTR_SIZE, we could end up with EOVERFLOW getting
     145                 :            :          * back from split_leaf.  This is because it thinks we'll be extending
     146                 :            :          * the existing item size, but we're asking for enough space to add the
     147                 :            :          * item itself.  So if we get EOVERFLOW just set ret to EEXIST and let
     148                 :            :          * the rest of the function figure it out.
     149                 :            :          */
     150         [ #  # ]:          0 :         if (ret == -EOVERFLOW)
     151                 :            :                 ret = -EEXIST;
     152                 :            : 
     153         [ #  # ]:          0 :         if (ret == -EEXIST) {
     154         [ #  # ]:          0 :                 if (flags & XATTR_CREATE)
     155                 :            :                         goto out;
     156                 :            :                 /*
     157                 :            :                  * We can't use the path we already have since we won't have the
     158                 :            :                  * proper locking for a delete, so release the path and
     159                 :            :                  * re-lookup to delete the thing.
     160                 :            :                  */
     161                 :          0 :                 btrfs_release_path(path);
     162                 :          0 :                 di = btrfs_lookup_xattr(trans, root, path, btrfs_ino(inode),
     163                 :            :                                         name, name_len, -1);
     164         [ #  # ]:          0 :                 if (IS_ERR(di)) {
     165                 :            :                         ret = PTR_ERR(di);
     166                 :          0 :                         goto out;
     167         [ #  # ]:          0 :                 } else if (!di) {
     168                 :            :                         /* Shouldn't happen but just in case... */
     169                 :          0 :                         btrfs_release_path(path);
     170                 :          0 :                         goto again;
     171                 :            :                 }
     172                 :            : 
     173                 :          0 :                 ret = btrfs_delete_one_dir_name(trans, root, path, di);
     174         [ #  # ]:          0 :                 if (ret)
     175                 :            :                         goto out;
     176                 :            : 
     177                 :            :                 /*
     178                 :            :                  * We have a value to set, so go back and try to insert it now.
     179                 :            :                  */
     180         [ #  # ]:          0 :                 if (value) {
     181                 :          0 :                         btrfs_release_path(path);
     182                 :          0 :                         goto again;
     183                 :            :                 }
     184                 :            :         }
     185                 :            : out:
     186                 :          0 :         btrfs_free_path(path);
     187                 :          0 :         return ret;
     188                 :            : }
     189                 :            : 
     190                 :            : /*
     191                 :            :  * @value: "" makes the attribute to empty, NULL removes it
     192                 :            :  */
     193                 :          0 : int __btrfs_setxattr(struct btrfs_trans_handle *trans,
     194                 :            :                      struct inode *inode, const char *name,
     195                 :            :                      const void *value, size_t size, int flags)
     196                 :            : {
     197                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
     198                 :            :         int ret;
     199                 :            : 
     200         [ #  # ]:          0 :         if (trans)
     201                 :          0 :                 return do_setxattr(trans, inode, name, value, size, flags);
     202                 :            : 
     203                 :          0 :         trans = btrfs_start_transaction(root, 2);
     204         [ #  # ]:          0 :         if (IS_ERR(trans))
     205                 :          0 :                 return PTR_ERR(trans);
     206                 :            : 
     207                 :          0 :         ret = do_setxattr(trans, inode, name, value, size, flags);
     208         [ #  # ]:          0 :         if (ret)
     209                 :            :                 goto out;
     210                 :            : 
     211                 :            :         inode_inc_iversion(inode);
     212                 :          0 :         inode->i_ctime = CURRENT_TIME;
     213                 :          0 :         set_bit(BTRFS_INODE_COPY_EVERYTHING, &BTRFS_I(inode)->runtime_flags);
     214                 :          0 :         ret = btrfs_update_inode(trans, root, inode);
     215         [ #  # ]:          0 :         BUG_ON(ret);
     216                 :            : out:
     217                 :          0 :         btrfs_end_transaction(trans, root);
     218                 :          0 :         return ret;
     219                 :            : }
     220                 :            : 
     221                 :          0 : ssize_t btrfs_listxattr(struct dentry *dentry, char *buffer, size_t size)
     222                 :            : {
     223                 :            :         struct btrfs_key key, found_key;
     224                 :          0 :         struct inode *inode = dentry->d_inode;
     225                 :          0 :         struct btrfs_root *root = BTRFS_I(inode)->root;
     226                 :            :         struct btrfs_path *path;
     227                 :          0 :         struct extent_buffer *leaf;
     228                 :            :         struct btrfs_dir_item *di;
     229                 :            :         int ret = 0, slot;
     230                 :            :         size_t total_size = 0, size_left = size;
     231                 :            :         unsigned long name_ptr;
     232                 :            :         size_t name_len;
     233                 :            : 
     234                 :            :         /*
     235                 :            :          * ok we want all objects associated with this id.
     236                 :            :          * NOTE: we set key.offset = 0; because we want to start with the
     237                 :            :          * first xattr that we find and walk forward
     238                 :            :          */
     239                 :          0 :         key.objectid = btrfs_ino(inode);
     240                 :            :         btrfs_set_key_type(&key, BTRFS_XATTR_ITEM_KEY);
     241                 :          0 :         key.offset = 0;
     242                 :            : 
     243                 :          0 :         path = btrfs_alloc_path();
     244         [ #  # ]:          0 :         if (!path)
     245                 :            :                 return -ENOMEM;
     246                 :          0 :         path->reada = 2;
     247                 :            : 
     248                 :            :         /* search for our xattrs */
     249                 :          0 :         ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
     250         [ #  # ]:          0 :         if (ret < 0)
     251                 :            :                 goto err;
     252                 :            : 
     253                 :            :         while (1) {
     254                 :          0 :                 leaf = path->nodes[0];
     255                 :          0 :                 slot = path->slots[0];
     256                 :            : 
     257                 :            :                 /* this is where we start walking through the path */
     258         [ #  # ]:          0 :                 if (slot >= btrfs_header_nritems(leaf)) {
     259                 :            :                         /*
     260                 :            :                          * if we've reached the last slot in this leaf we need
     261                 :            :                          * to go to the next leaf and reset everything
     262                 :            :                          */
     263                 :          0 :                         ret = btrfs_next_leaf(root, path);
     264         [ #  # ]:          0 :                         if (ret < 0)
     265                 :            :                                 goto err;
     266         [ #  # ]:          0 :                         else if (ret > 0)
     267                 :            :                                 break;
     268                 :          0 :                         continue;
     269                 :            :                 }
     270                 :            : 
     271                 :            :                 btrfs_item_key_to_cpu(leaf, &found_key, slot);
     272                 :            : 
     273                 :            :                 /* check to make sure this item is what we want */
     274         [ #  # ]:          0 :                 if (found_key.objectid != key.objectid)
     275                 :            :                         break;
     276         [ #  # ]:          0 :                 if (btrfs_key_type(&found_key) != BTRFS_XATTR_ITEM_KEY)
     277                 :            :                         break;
     278                 :            : 
     279                 :          0 :                 di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
     280         [ #  # ]:          0 :                 if (verify_dir_item(root, leaf, di))
     281                 :            :                         goto next;
     282                 :            : 
     283                 :          0 :                 name_len = btrfs_dir_name_len(leaf, di);
     284                 :          0 :                 total_size += name_len + 1;
     285                 :            : 
     286                 :            :                 /* we are just looking for how big our buffer needs to be */
     287         [ #  # ]:          0 :                 if (!size)
     288                 :            :                         goto next;
     289                 :            : 
     290 [ #  # ][ #  # ]:          0 :                 if (!buffer || (name_len + 1) > size_left) {
     291                 :            :                         ret = -ERANGE;
     292                 :            :                         goto err;
     293                 :            :                 }
     294                 :            : 
     295                 :          0 :                 name_ptr = (unsigned long)(di + 1);
     296                 :          0 :                 read_extent_buffer(leaf, buffer, name_ptr, name_len);
     297                 :          0 :                 buffer[name_len] = '\0';
     298                 :            : 
     299                 :          0 :                 size_left -= name_len + 1;
     300                 :          0 :                 buffer += name_len + 1;
     301                 :            : next:
     302                 :          0 :                 path->slots[0]++;
     303                 :            :         }
     304                 :          0 :         ret = total_size;
     305                 :            : 
     306                 :            : err:
     307                 :          0 :         btrfs_free_path(path);
     308                 :            : 
     309                 :          0 :         return ret;
     310                 :            : }
     311                 :            : 
     312                 :            : /*
     313                 :            :  * List of handlers for synthetic system.* attributes.  All real ondisk
     314                 :            :  * attributes are handled directly.
     315                 :            :  */
     316                 :            : const struct xattr_handler *btrfs_xattr_handlers[] = {
     317                 :            : #ifdef CONFIG_BTRFS_FS_POSIX_ACL
     318                 :            :         &posix_acl_access_xattr_handler,
     319                 :            :         &posix_acl_default_xattr_handler,
     320                 :            : #endif
     321                 :            :         NULL,
     322                 :            : };
     323                 :            : 
     324                 :            : /*
     325                 :            :  * Check if the attribute is in a supported namespace.
     326                 :            :  *
     327                 :            :  * This applied after the check for the synthetic attributes in the system
     328                 :            :  * namespace.
     329                 :            :  */
     330                 :          0 : static bool btrfs_is_valid_xattr(const char *name)
     331                 :            : {
     332                 :          0 :         return !strncmp(name, XATTR_SECURITY_PREFIX,
     333         [ #  # ]:          0 :                         XATTR_SECURITY_PREFIX_LEN) ||
     334         [ #  # ]:          0 :                !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN) ||
     335         [ #  # ]:          0 :                !strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) ||
     336 [ #  # ][ #  # ]:          0 :                !strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) ||
     337                 :          0 :                 !strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN);
     338                 :            : }
     339                 :            : 
     340                 :          0 : ssize_t btrfs_getxattr(struct dentry *dentry, const char *name,
     341                 :            :                        void *buffer, size_t size)
     342                 :            : {
     343                 :            :         /*
     344                 :            :          * If this is a request for a synthetic attribute in the system.*
     345                 :            :          * namespace use the generic infrastructure to resolve a handler
     346                 :            :          * for it via sb->s_xattr.
     347                 :            :          */
     348         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     349                 :          0 :                 return generic_getxattr(dentry, name, buffer, size);
     350                 :            : 
     351         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     352                 :            :                 return -EOPNOTSUPP;
     353                 :          0 :         return __btrfs_getxattr(dentry->d_inode, name, buffer, size);
     354                 :            : }
     355                 :            : 
     356                 :          0 : int btrfs_setxattr(struct dentry *dentry, const char *name, const void *value,
     357                 :            :                    size_t size, int flags)
     358                 :            : {
     359                 :          0 :         struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
     360                 :            : 
     361                 :            :         /*
     362                 :            :          * The permission on security.* and system.* is not checked
     363                 :            :          * in permission().
     364                 :            :          */
     365         [ #  # ]:          0 :         if (btrfs_root_readonly(root))
     366                 :            :                 return -EROFS;
     367                 :            : 
     368                 :            :         /*
     369                 :            :          * If this is a request for a synthetic attribute in the system.*
     370                 :            :          * namespace use the generic infrastructure to resolve a handler
     371                 :            :          * for it via sb->s_xattr.
     372                 :            :          */
     373         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     374                 :          0 :                 return generic_setxattr(dentry, name, value, size, flags);
     375                 :            : 
     376         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     377                 :            :                 return -EOPNOTSUPP;
     378                 :            : 
     379         [ #  # ]:          0 :         if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
     380                 :          0 :                 return btrfs_set_prop(dentry->d_inode, name,
     381                 :            :                                       value, size, flags);
     382                 :            : 
     383         [ #  # ]:          0 :         if (size == 0)
     384                 :            :                 value = "";  /* empty EA, do not remove */
     385                 :            : 
     386                 :          0 :         return __btrfs_setxattr(NULL, dentry->d_inode, name, value, size,
     387                 :            :                                 flags);
     388                 :            : }
     389                 :            : 
     390                 :          0 : int btrfs_removexattr(struct dentry *dentry, const char *name)
     391                 :            : {
     392                 :          0 :         struct btrfs_root *root = BTRFS_I(dentry->d_inode)->root;
     393                 :            : 
     394                 :            :         /*
     395                 :            :          * The permission on security.* and system.* is not checked
     396                 :            :          * in permission().
     397                 :            :          */
     398         [ #  # ]:          0 :         if (btrfs_root_readonly(root))
     399                 :            :                 return -EROFS;
     400                 :            : 
     401                 :            :         /*
     402                 :            :          * If this is a request for a synthetic attribute in the system.*
     403                 :            :          * namespace use the generic infrastructure to resolve a handler
     404                 :            :          * for it via sb->s_xattr.
     405                 :            :          */
     406         [ #  # ]:          0 :         if (!strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
     407                 :          0 :                 return generic_removexattr(dentry, name);
     408                 :            : 
     409         [ #  # ]:          0 :         if (!btrfs_is_valid_xattr(name))
     410                 :            :                 return -EOPNOTSUPP;
     411                 :            : 
     412         [ #  # ]:          0 :         if (!strncmp(name, XATTR_BTRFS_PREFIX, XATTR_BTRFS_PREFIX_LEN))
     413                 :          0 :                 return btrfs_set_prop(dentry->d_inode, name,
     414                 :            :                                       NULL, 0, XATTR_REPLACE);
     415                 :            : 
     416                 :          0 :         return __btrfs_setxattr(NULL, dentry->d_inode, name, NULL, 0,
     417                 :            :                                 XATTR_REPLACE);
     418                 :            : }
     419                 :            : 
     420                 :          0 : static int btrfs_initxattrs(struct inode *inode,
     421                 :            :                             const struct xattr *xattr_array, void *fs_info)
     422                 :            : {
     423                 :            :         const struct xattr *xattr;
     424                 :            :         struct btrfs_trans_handle *trans = fs_info;
     425                 :            :         char *name;
     426                 :            :         int err = 0;
     427                 :            : 
     428         [ #  # ]:          0 :         for (xattr = xattr_array; xattr->name != NULL; xattr++) {
     429                 :          0 :                 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
     430                 :          0 :                                strlen(xattr->name) + 1, GFP_NOFS);
     431         [ #  # ]:          0 :                 if (!name) {
     432                 :            :                         err = -ENOMEM;
     433                 :            :                         break;
     434                 :            :                 }
     435                 :          0 :                 strcpy(name, XATTR_SECURITY_PREFIX);
     436                 :          0 :                 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
     437                 :          0 :                 err = __btrfs_setxattr(trans, inode, name,
     438                 :          0 :                                        xattr->value, xattr->value_len, 0);
     439                 :          0 :                 kfree(name);
     440         [ #  # ]:          0 :                 if (err < 0)
     441                 :            :                         break;
     442                 :            :         }
     443                 :          0 :         return err;
     444                 :            : }
     445                 :            : 
     446                 :          0 : int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
     447                 :            :                               struct inode *inode, struct inode *dir,
     448                 :            :                               const struct qstr *qstr)
     449                 :            : {
     450                 :          0 :         return security_inode_init_security(inode, dir, qstr,
     451                 :            :                                             &btrfs_initxattrs, trans);
     452                 :            : }

Generated by: LCOV version 1.9