11e51764aSArtem Bityutskiy /* 21e51764aSArtem Bityutskiy * This file is part of UBIFS. 31e51764aSArtem Bityutskiy * 41e51764aSArtem Bityutskiy * Copyright (C) 2006-2008 Nokia Corporation. 51e51764aSArtem Bityutskiy * 61e51764aSArtem Bityutskiy * This program is free software; you can redistribute it and/or modify it 71e51764aSArtem Bityutskiy * under the terms of the GNU General Public License version 2 as published by 81e51764aSArtem Bityutskiy * the Free Software Foundation. 91e51764aSArtem Bityutskiy * 101e51764aSArtem Bityutskiy * This program is distributed in the hope that it will be useful, but WITHOUT 111e51764aSArtem Bityutskiy * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 121e51764aSArtem Bityutskiy * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 131e51764aSArtem Bityutskiy * more details. 141e51764aSArtem Bityutskiy * 151e51764aSArtem Bityutskiy * You should have received a copy of the GNU General Public License along with 161e51764aSArtem Bityutskiy * this program; if not, write to the Free Software Foundation, Inc., 51 171e51764aSArtem Bityutskiy * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 181e51764aSArtem Bityutskiy * 191e51764aSArtem Bityutskiy * Authors: Artem Bityutskiy (Битюцкий Артём) 201e51764aSArtem Bityutskiy * Adrian Hunter 211e51764aSArtem Bityutskiy */ 221e51764aSArtem Bityutskiy 231e51764aSArtem Bityutskiy /* 241e51764aSArtem Bityutskiy * This file implements UBIFS extended attributes support. 251e51764aSArtem Bityutskiy * 261e51764aSArtem Bityutskiy * Extended attributes are implemented as regular inodes with attached data, 271e51764aSArtem Bityutskiy * which limits extended attribute size to UBIFS block size (4KiB). Names of 281e51764aSArtem Bityutskiy * extended attributes are described by extended attribute entries (xentries), 291e51764aSArtem Bityutskiy * which are almost identical to directory entries, but have different key type. 301e51764aSArtem Bityutskiy * 311e51764aSArtem Bityutskiy * In other words, the situation with extended attributes is very similar to 321e51764aSArtem Bityutskiy * directories. Indeed, any inode (but of course not xattr inodes) may have a 331e51764aSArtem Bityutskiy * number of associated xentries, just like directory inodes have associated 341e51764aSArtem Bityutskiy * directory entries. Extended attribute entries store the name of the extended 351e51764aSArtem Bityutskiy * attribute, the host inode number, and the extended attribute inode number. 361e51764aSArtem Bityutskiy * Similarly, direntries store the name, the parent and the target inode 371e51764aSArtem Bityutskiy * numbers. Thus, most of the common UBIFS mechanisms may be re-used for 381e51764aSArtem Bityutskiy * extended attributes. 391e51764aSArtem Bityutskiy * 401e51764aSArtem Bityutskiy * The number of extended attributes is not limited, but there is Linux 411e51764aSArtem Bityutskiy * limitation on the maximum possible size of the list of all extended 421e51764aSArtem Bityutskiy * attributes associated with an inode (%XATTR_LIST_MAX), so UBIFS makes sure 431e51764aSArtem Bityutskiy * the sum of all extended attribute names of the inode does not exceed that 441e51764aSArtem Bityutskiy * limit. 451e51764aSArtem Bityutskiy * 461e51764aSArtem Bityutskiy * Extended attributes are synchronous, which means they are written to the 471e51764aSArtem Bityutskiy * flash media synchronously and there is no write-back for extended attribute 481e51764aSArtem Bityutskiy * inodes. The extended attribute values are not stored in compressed form on 491e51764aSArtem Bityutskiy * the media. 501e51764aSArtem Bityutskiy * 511e51764aSArtem Bityutskiy * Since extended attributes are represented by regular inodes, they are cached 521e51764aSArtem Bityutskiy * in the VFS inode cache. The xentries are cached in the LNC cache (see 531e51764aSArtem Bityutskiy * tnc.c). 541e51764aSArtem Bityutskiy * 551e51764aSArtem Bityutskiy * ACL support is not implemented. 561e51764aSArtem Bityutskiy */ 571e51764aSArtem Bityutskiy 58073aaa1bSAl Viro #include "ubifs.h" 597dcda1c9SJens Axboe #include <linux/fs.h> 605a0e3ad6STejun Heo #include <linux/slab.h> 611e51764aSArtem Bityutskiy #include <linux/xattr.h> 621e51764aSArtem Bityutskiy 631e51764aSArtem Bityutskiy /* 641e51764aSArtem Bityutskiy * Extended attribute type constants. 651e51764aSArtem Bityutskiy * 661e51764aSArtem Bityutskiy * USER_XATTR: user extended attribute ("user.*") 671e51764aSArtem Bityutskiy * TRUSTED_XATTR: trusted extended attribute ("trusted.*) 681e51764aSArtem Bityutskiy * SECURITY_XATTR: security extended attribute ("security.*") 691e51764aSArtem Bityutskiy */ 701e51764aSArtem Bityutskiy enum { 711e51764aSArtem Bityutskiy USER_XATTR, 721e51764aSArtem Bityutskiy TRUSTED_XATTR, 731e51764aSArtem Bityutskiy SECURITY_XATTR, 741e51764aSArtem Bityutskiy }; 751e51764aSArtem Bityutskiy 7614ffd5d0SSedat Dilek static const struct inode_operations empty_iops; 7714ffd5d0SSedat Dilek static const struct file_operations empty_fops; 781e51764aSArtem Bityutskiy 791e51764aSArtem Bityutskiy /** 801e51764aSArtem Bityutskiy * create_xattr - create an extended attribute. 811e51764aSArtem Bityutskiy * @c: UBIFS file-system description object 821e51764aSArtem Bityutskiy * @host: host inode 831e51764aSArtem Bityutskiy * @nm: extended attribute name 841e51764aSArtem Bityutskiy * @value: extended attribute value 851e51764aSArtem Bityutskiy * @size: size of extended attribute value 861e51764aSArtem Bityutskiy * 871e51764aSArtem Bityutskiy * This is a helper function which creates an extended attribute of name @nm 881e51764aSArtem Bityutskiy * and value @value for inode @host. The host inode is also updated on flash 891e51764aSArtem Bityutskiy * because the ctime and extended attribute accounting data changes. This 901e51764aSArtem Bityutskiy * function returns zero in case of success and a negative error code in case 911e51764aSArtem Bityutskiy * of failure. 921e51764aSArtem Bityutskiy */ 931e51764aSArtem Bityutskiy static int create_xattr(struct ubifs_info *c, struct inode *host, 94f4f61d2cSRichard Weinberger const struct fscrypt_name *nm, const void *value, int size) 951e51764aSArtem Bityutskiy { 96fee1756dSSubodh Nijsure int err, names_len; 971e51764aSArtem Bityutskiy struct inode *inode; 981e51764aSArtem Bityutskiy struct ubifs_inode *ui, *host_ui = ubifs_inode(host); 991e51764aSArtem Bityutskiy struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, 1005acd6ff8SZoltan Sogor .new_ino_d = ALIGN(size, 8), .dirtied_ino = 1, 101dab4b4d2SArtem Bityutskiy .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; 1021e51764aSArtem Bityutskiy 103*9ca2d732SRichard Weinberger if (host_ui->xattr_cnt >= ubifs_xattr_max_cnt(c)) { 104235c362bSSheng Yong ubifs_err(c, "inode %lu already has too many xattrs (%d), cannot create more", 105fee1756dSSubodh Nijsure host->i_ino, host_ui->xattr_cnt); 1061e51764aSArtem Bityutskiy return -ENOSPC; 107fee1756dSSubodh Nijsure } 1081e51764aSArtem Bityutskiy /* 1091e51764aSArtem Bityutskiy * Linux limits the maximum size of the extended attribute names list 110c78c7e35SArtem Bityutskiy * to %XATTR_LIST_MAX. This means we should not allow creating more 1111e51764aSArtem Bityutskiy * extended attributes if the name list becomes larger. This limitation 1121e51764aSArtem Bityutskiy * is artificial for UBIFS, though. 1131e51764aSArtem Bityutskiy */ 114f4f61d2cSRichard Weinberger names_len = host_ui->xattr_names + host_ui->xattr_cnt + fname_len(nm) + 1; 115fee1756dSSubodh Nijsure if (names_len > XATTR_LIST_MAX) { 116235c362bSSheng Yong ubifs_err(c, "cannot add one more xattr name to inode %lu, total names length would become %d, max. is %d", 117fee1756dSSubodh Nijsure host->i_ino, names_len, XATTR_LIST_MAX); 1181e51764aSArtem Bityutskiy return -ENOSPC; 119fee1756dSSubodh Nijsure } 1201e51764aSArtem Bityutskiy 1211e51764aSArtem Bityutskiy err = ubifs_budget_space(c, &req); 1221e51764aSArtem Bityutskiy if (err) 1231e51764aSArtem Bityutskiy return err; 1241e51764aSArtem Bityutskiy 1251e51764aSArtem Bityutskiy inode = ubifs_new_inode(c, host, S_IFREG | S_IRWXUGO); 1261e51764aSArtem Bityutskiy if (IS_ERR(inode)) { 1271e51764aSArtem Bityutskiy err = PTR_ERR(inode); 1281e51764aSArtem Bityutskiy goto out_budg; 1291e51764aSArtem Bityutskiy } 1301e51764aSArtem Bityutskiy 1311e51764aSArtem Bityutskiy /* Re-define all operations to be "nothing" */ 1327dcda1c9SJens Axboe inode->i_mapping->a_ops = &empty_aops; 13314ffd5d0SSedat Dilek inode->i_op = &empty_iops; 13414ffd5d0SSedat Dilek inode->i_fop = &empty_fops; 1351e51764aSArtem Bityutskiy 136422edaceSWang Shilong inode->i_flags |= S_SYNC | S_NOATIME | S_NOCMTIME; 1371e51764aSArtem Bityutskiy ui = ubifs_inode(inode); 1381e51764aSArtem Bityutskiy ui->xattr = 1; 1391e51764aSArtem Bityutskiy ui->flags |= UBIFS_XATTR_FL; 140eaecf43aSThomas Meyer ui->data = kmemdup(value, size, GFP_NOFS); 1411e51764aSArtem Bityutskiy if (!ui->data) { 1421e51764aSArtem Bityutskiy err = -ENOMEM; 143c78c7e35SArtem Bityutskiy goto out_free; 1441e51764aSArtem Bityutskiy } 145c78c7e35SArtem Bityutskiy inode->i_size = ui->ui_size = size; 146c78c7e35SArtem Bityutskiy ui->data_len = size; 147c78c7e35SArtem Bityutskiy 148c78c7e35SArtem Bityutskiy mutex_lock(&host_ui->ui_mutex); 149607a11adSDeepa Dinamani host->i_ctime = current_time(host); 1501e51764aSArtem Bityutskiy host_ui->xattr_cnt += 1; 151f4f61d2cSRichard Weinberger host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm)); 1521e51764aSArtem Bityutskiy host_ui->xattr_size += CALC_XATTR_BYTES(size); 153f4f61d2cSRichard Weinberger host_ui->xattr_names += fname_len(nm); 1541e51764aSArtem Bityutskiy 155d475a507SRichard Weinberger /* 156d475a507SRichard Weinberger * We handle UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT here because we 157d475a507SRichard Weinberger * have to set the UBIFS_CRYPT_FL flag on the host inode. 158d475a507SRichard Weinberger * To avoid multiple updates of the same inode in the same operation, 159d475a507SRichard Weinberger * let's do it here. 160d475a507SRichard Weinberger */ 161f4f61d2cSRichard Weinberger if (strcmp(fname_name(nm), UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) 162d475a507SRichard Weinberger host_ui->flags |= UBIFS_CRYPT_FL; 163d475a507SRichard Weinberger 1641e51764aSArtem Bityutskiy err = ubifs_jnl_update(c, host, nm, inode, 0, 1); 1651e51764aSArtem Bityutskiy if (err) 1661e51764aSArtem Bityutskiy goto out_cancel; 1672ee6a576SEric Biggers ubifs_set_inode_flags(host); 1681e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 1691e51764aSArtem Bityutskiy 1701e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 1711e51764aSArtem Bityutskiy insert_inode_hash(inode); 1721e51764aSArtem Bityutskiy iput(inode); 1731e51764aSArtem Bityutskiy return 0; 1741e51764aSArtem Bityutskiy 1751e51764aSArtem Bityutskiy out_cancel: 1761e51764aSArtem Bityutskiy host_ui->xattr_cnt -= 1; 177f4f61d2cSRichard Weinberger host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm)); 1781e51764aSArtem Bityutskiy host_ui->xattr_size -= CALC_XATTR_BYTES(size); 179f4f61d2cSRichard Weinberger host_ui->xattr_names -= fname_len(nm); 180d475a507SRichard Weinberger host_ui->flags &= ~UBIFS_CRYPT_FL; 1811e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 182c78c7e35SArtem Bityutskiy out_free: 1831e51764aSArtem Bityutskiy make_bad_inode(inode); 1841e51764aSArtem Bityutskiy iput(inode); 1851e51764aSArtem Bityutskiy out_budg: 1861e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 1871e51764aSArtem Bityutskiy return err; 1881e51764aSArtem Bityutskiy } 1891e51764aSArtem Bityutskiy 1901e51764aSArtem Bityutskiy /** 1911e51764aSArtem Bityutskiy * change_xattr - change an extended attribute. 1921e51764aSArtem Bityutskiy * @c: UBIFS file-system description object 1931e51764aSArtem Bityutskiy * @host: host inode 1941e51764aSArtem Bityutskiy * @inode: extended attribute inode 1951e51764aSArtem Bityutskiy * @value: extended attribute value 1961e51764aSArtem Bityutskiy * @size: size of extended attribute value 1971e51764aSArtem Bityutskiy * 1981e51764aSArtem Bityutskiy * This helper function changes the value of extended attribute @inode with new 1991e51764aSArtem Bityutskiy * data from @value. Returns zero in case of success and a negative error code 2001e51764aSArtem Bityutskiy * in case of failure. 2011e51764aSArtem Bityutskiy */ 2021e51764aSArtem Bityutskiy static int change_xattr(struct ubifs_info *c, struct inode *host, 2031e51764aSArtem Bityutskiy struct inode *inode, const void *value, int size) 2041e51764aSArtem Bityutskiy { 2051e51764aSArtem Bityutskiy int err; 2061e51764aSArtem Bityutskiy struct ubifs_inode *host_ui = ubifs_inode(host); 2071e51764aSArtem Bityutskiy struct ubifs_inode *ui = ubifs_inode(inode); 208ab92a20bSDongsheng Yang void *buf = NULL; 20974e9c700SPascal Eberhard int old_size; 2101e51764aSArtem Bityutskiy struct ubifs_budget_req req = { .dirtied_ino = 2, 2115acd6ff8SZoltan Sogor .dirtied_ino_d = ALIGN(size, 8) + ALIGN(host_ui->data_len, 8) }; 2121e51764aSArtem Bityutskiy 2136eb61d58SRichard Weinberger ubifs_assert(c, ui->data_len == inode->i_size); 2141e51764aSArtem Bityutskiy err = ubifs_budget_space(c, &req); 2151e51764aSArtem Bityutskiy if (err) 2161e51764aSArtem Bityutskiy return err; 2171e51764aSArtem Bityutskiy 218ab92a20bSDongsheng Yang buf = kmemdup(value, size, GFP_NOFS); 219ab92a20bSDongsheng Yang if (!buf) { 2201e51764aSArtem Bityutskiy err = -ENOMEM; 221c78c7e35SArtem Bityutskiy goto out_free; 2221e51764aSArtem Bityutskiy } 223ab92a20bSDongsheng Yang mutex_lock(&ui->ui_mutex); 224ab92a20bSDongsheng Yang kfree(ui->data); 225ab92a20bSDongsheng Yang ui->data = buf; 2261e51764aSArtem Bityutskiy inode->i_size = ui->ui_size = size; 22774e9c700SPascal Eberhard old_size = ui->data_len; 2281e51764aSArtem Bityutskiy ui->data_len = size; 229ab92a20bSDongsheng Yang mutex_unlock(&ui->ui_mutex); 2301e51764aSArtem Bityutskiy 231c78c7e35SArtem Bityutskiy mutex_lock(&host_ui->ui_mutex); 232607a11adSDeepa Dinamani host->i_ctime = current_time(host); 23374e9c700SPascal Eberhard host_ui->xattr_size -= CALC_XATTR_BYTES(old_size); 234c78c7e35SArtem Bityutskiy host_ui->xattr_size += CALC_XATTR_BYTES(size); 235c78c7e35SArtem Bityutskiy 2361e51764aSArtem Bityutskiy /* 2371e51764aSArtem Bityutskiy * It is important to write the host inode after the xattr inode 2381e51764aSArtem Bityutskiy * because if the host inode gets synchronized (via 'fsync()'), then 2391e51764aSArtem Bityutskiy * the extended attribute inode gets synchronized, because it goes 2401e51764aSArtem Bityutskiy * before the host inode in the write-buffer. 2411e51764aSArtem Bityutskiy */ 2421e51764aSArtem Bityutskiy err = ubifs_jnl_change_xattr(c, inode, host); 2431e51764aSArtem Bityutskiy if (err) 2441e51764aSArtem Bityutskiy goto out_cancel; 2451e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 2461e51764aSArtem Bityutskiy 2471e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 2481e51764aSArtem Bityutskiy return 0; 2491e51764aSArtem Bityutskiy 2501e51764aSArtem Bityutskiy out_cancel: 2511e51764aSArtem Bityutskiy host_ui->xattr_size -= CALC_XATTR_BYTES(size); 25274e9c700SPascal Eberhard host_ui->xattr_size += CALC_XATTR_BYTES(old_size); 2531e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 254c78c7e35SArtem Bityutskiy make_bad_inode(inode); 255c78c7e35SArtem Bityutskiy out_free: 2561e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 2571e51764aSArtem Bityutskiy return err; 2581e51764aSArtem Bityutskiy } 2591e51764aSArtem Bityutskiy 2601e51764aSArtem Bityutskiy static struct inode *iget_xattr(struct ubifs_info *c, ino_t inum) 2611e51764aSArtem Bityutskiy { 2621e51764aSArtem Bityutskiy struct inode *inode; 2631e51764aSArtem Bityutskiy 2641e51764aSArtem Bityutskiy inode = ubifs_iget(c->vfs_sb, inum); 2651e51764aSArtem Bityutskiy if (IS_ERR(inode)) { 266235c362bSSheng Yong ubifs_err(c, "dead extended attribute entry, error %d", 2671e51764aSArtem Bityutskiy (int)PTR_ERR(inode)); 2681e51764aSArtem Bityutskiy return inode; 2691e51764aSArtem Bityutskiy } 2701e51764aSArtem Bityutskiy if (ubifs_inode(inode)->xattr) 2711e51764aSArtem Bityutskiy return inode; 272235c362bSSheng Yong ubifs_err(c, "corrupt extended attribute entry"); 2731e51764aSArtem Bityutskiy iput(inode); 2741e51764aSArtem Bityutskiy return ERR_PTR(-EINVAL); 2751e51764aSArtem Bityutskiy } 2761e51764aSArtem Bityutskiy 277ade46c3aSRichard Weinberger int ubifs_xattr_set(struct inode *host, const char *name, const void *value, 278d8db5b1cSXiaolei Li size_t size, int flags, bool check_lock) 2791e51764aSArtem Bityutskiy { 280895d9db2SSubodh Nijsure struct inode *inode; 2811e51764aSArtem Bityutskiy struct ubifs_info *c = host->i_sb->s_fs_info; 282f4f61d2cSRichard Weinberger struct fscrypt_name nm = { .disk_name = FSTR_INIT((char *)name, strlen(name))}; 2831e51764aSArtem Bityutskiy struct ubifs_dent_node *xent; 2841e51764aSArtem Bityutskiy union ubifs_key key; 2852b88fc21SAndreas Gruenbacher int err; 2861e51764aSArtem Bityutskiy 287d8db5b1cSXiaolei Li if (check_lock) 2886eb61d58SRichard Weinberger ubifs_assert(c, inode_is_locked(host)); 2891e51764aSArtem Bityutskiy 2901e51764aSArtem Bityutskiy if (size > UBIFS_MAX_INO_DATA) 2911e51764aSArtem Bityutskiy return -ERANGE; 2921e51764aSArtem Bityutskiy 293f4f61d2cSRichard Weinberger if (fname_len(&nm) > UBIFS_MAX_NLEN) 2942b88fc21SAndreas Gruenbacher return -ENAMETOOLONG; 2951e51764aSArtem Bityutskiy 2961e51764aSArtem Bityutskiy xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); 2971e51764aSArtem Bityutskiy if (!xent) 2981e51764aSArtem Bityutskiy return -ENOMEM; 2991e51764aSArtem Bityutskiy 3001e51764aSArtem Bityutskiy /* 3011e51764aSArtem Bityutskiy * The extended attribute entries are stored in LNC, so multiple 3021e51764aSArtem Bityutskiy * look-ups do not involve reading the flash. 3031e51764aSArtem Bityutskiy */ 3041e51764aSArtem Bityutskiy xent_key_init(c, &key, host->i_ino, &nm); 3051e51764aSArtem Bityutskiy err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); 3061e51764aSArtem Bityutskiy if (err) { 3071e51764aSArtem Bityutskiy if (err != -ENOENT) 3081e51764aSArtem Bityutskiy goto out_free; 3091e51764aSArtem Bityutskiy 3101e51764aSArtem Bityutskiy if (flags & XATTR_REPLACE) 3111e51764aSArtem Bityutskiy /* We are asked not to create the xattr */ 3121e51764aSArtem Bityutskiy err = -ENODATA; 3131e51764aSArtem Bityutskiy else 3141e51764aSArtem Bityutskiy err = create_xattr(c, host, &nm, value, size); 3151e51764aSArtem Bityutskiy goto out_free; 3161e51764aSArtem Bityutskiy } 3171e51764aSArtem Bityutskiy 3181e51764aSArtem Bityutskiy if (flags & XATTR_CREATE) { 3191e51764aSArtem Bityutskiy /* We are asked not to replace the xattr */ 3201e51764aSArtem Bityutskiy err = -EEXIST; 3211e51764aSArtem Bityutskiy goto out_free; 3221e51764aSArtem Bityutskiy } 3231e51764aSArtem Bityutskiy 3241e51764aSArtem Bityutskiy inode = iget_xattr(c, le64_to_cpu(xent->inum)); 3251e51764aSArtem Bityutskiy if (IS_ERR(inode)) { 3261e51764aSArtem Bityutskiy err = PTR_ERR(inode); 3271e51764aSArtem Bityutskiy goto out_free; 3281e51764aSArtem Bityutskiy } 3291e51764aSArtem Bityutskiy 3301e51764aSArtem Bityutskiy err = change_xattr(c, host, inode, value, size); 3311e51764aSArtem Bityutskiy iput(inode); 3321e51764aSArtem Bityutskiy 3331e51764aSArtem Bityutskiy out_free: 3341e51764aSArtem Bityutskiy kfree(xent); 3351e51764aSArtem Bityutskiy return err; 3361e51764aSArtem Bityutskiy } 3371e51764aSArtem Bityutskiy 338ade46c3aSRichard Weinberger ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf, 339ade46c3aSRichard Weinberger size_t size) 3401e51764aSArtem Bityutskiy { 341ce23e640SAl Viro struct inode *inode; 3421e51764aSArtem Bityutskiy struct ubifs_info *c = host->i_sb->s_fs_info; 343f4f61d2cSRichard Weinberger struct fscrypt_name nm = { .disk_name = FSTR_INIT((char *)name, strlen(name))}; 3441e51764aSArtem Bityutskiy struct ubifs_inode *ui; 3451e51764aSArtem Bityutskiy struct ubifs_dent_node *xent; 3461e51764aSArtem Bityutskiy union ubifs_key key; 3471e51764aSArtem Bityutskiy int err; 3481e51764aSArtem Bityutskiy 349f4f61d2cSRichard Weinberger if (fname_len(&nm) > UBIFS_MAX_NLEN) 3502b88fc21SAndreas Gruenbacher return -ENAMETOOLONG; 3511e51764aSArtem Bityutskiy 3521e51764aSArtem Bityutskiy xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); 3531e51764aSArtem Bityutskiy if (!xent) 3541e51764aSArtem Bityutskiy return -ENOMEM; 3551e51764aSArtem Bityutskiy 3561e51764aSArtem Bityutskiy xent_key_init(c, &key, host->i_ino, &nm); 3571e51764aSArtem Bityutskiy err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); 3581e51764aSArtem Bityutskiy if (err) { 3591e51764aSArtem Bityutskiy if (err == -ENOENT) 3601e51764aSArtem Bityutskiy err = -ENODATA; 3611e51764aSArtem Bityutskiy goto out_unlock; 3621e51764aSArtem Bityutskiy } 3631e51764aSArtem Bityutskiy 3641e51764aSArtem Bityutskiy inode = iget_xattr(c, le64_to_cpu(xent->inum)); 3651e51764aSArtem Bityutskiy if (IS_ERR(inode)) { 3661e51764aSArtem Bityutskiy err = PTR_ERR(inode); 3671e51764aSArtem Bityutskiy goto out_unlock; 3681e51764aSArtem Bityutskiy } 3691e51764aSArtem Bityutskiy 3701e51764aSArtem Bityutskiy ui = ubifs_inode(inode); 3716eb61d58SRichard Weinberger ubifs_assert(c, inode->i_size == ui->data_len); 3726eb61d58SRichard Weinberger ubifs_assert(c, ubifs_inode(host)->xattr_size > ui->data_len); 3731e51764aSArtem Bityutskiy 374ab92a20bSDongsheng Yang mutex_lock(&ui->ui_mutex); 3751e51764aSArtem Bityutskiy if (buf) { 3761e51764aSArtem Bityutskiy /* If @buf is %NULL we are supposed to return the length */ 3771e51764aSArtem Bityutskiy if (ui->data_len > size) { 3781e51764aSArtem Bityutskiy err = -ERANGE; 3791e51764aSArtem Bityutskiy goto out_iput; 3801e51764aSArtem Bityutskiy } 3811e51764aSArtem Bityutskiy 3821e51764aSArtem Bityutskiy memcpy(buf, ui->data, ui->data_len); 3831e51764aSArtem Bityutskiy } 3841e51764aSArtem Bityutskiy err = ui->data_len; 3851e51764aSArtem Bityutskiy 3861e51764aSArtem Bityutskiy out_iput: 387ab92a20bSDongsheng Yang mutex_unlock(&ui->ui_mutex); 3881e51764aSArtem Bityutskiy iput(inode); 3891e51764aSArtem Bityutskiy out_unlock: 3901e51764aSArtem Bityutskiy kfree(xent); 3911e51764aSArtem Bityutskiy return err; 3921e51764aSArtem Bityutskiy } 3931e51764aSArtem Bityutskiy 39443b113feSRichard Weinberger static bool xattr_visible(const char *name) 39543b113feSRichard Weinberger { 39643b113feSRichard Weinberger /* File encryption related xattrs are for internal use only */ 39743b113feSRichard Weinberger if (strcmp(name, UBIFS_XATTR_NAME_ENCRYPTION_CONTEXT) == 0) 39843b113feSRichard Weinberger return false; 39943b113feSRichard Weinberger 40043b113feSRichard Weinberger /* Show trusted namespace only for "power" users */ 40143b113feSRichard Weinberger if (strncmp(name, XATTR_TRUSTED_PREFIX, 40243b113feSRichard Weinberger XATTR_TRUSTED_PREFIX_LEN) == 0 && !capable(CAP_SYS_ADMIN)) 40343b113feSRichard Weinberger return false; 40443b113feSRichard Weinberger 40543b113feSRichard Weinberger return true; 40643b113feSRichard Weinberger } 40743b113feSRichard Weinberger 4081e51764aSArtem Bityutskiy ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size) 4091e51764aSArtem Bityutskiy { 4101e51764aSArtem Bityutskiy union ubifs_key key; 4112b0143b5SDavid Howells struct inode *host = d_inode(dentry); 4121e51764aSArtem Bityutskiy struct ubifs_info *c = host->i_sb->s_fs_info; 4131e51764aSArtem Bityutskiy struct ubifs_inode *host_ui = ubifs_inode(host); 4141e51764aSArtem Bityutskiy struct ubifs_dent_node *xent, *pxent = NULL; 4151e51764aSArtem Bityutskiy int err, len, written = 0; 416f4f61d2cSRichard Weinberger struct fscrypt_name nm = {0}; 4171e51764aSArtem Bityutskiy 4184cb2a01dSAl Viro dbg_gen("ino %lu ('%pd'), buffer size %zd", host->i_ino, 4194cb2a01dSAl Viro dentry, size); 4201e51764aSArtem Bityutskiy 4211e51764aSArtem Bityutskiy len = host_ui->xattr_names + host_ui->xattr_cnt; 4221e51764aSArtem Bityutskiy if (!buffer) 4231e51764aSArtem Bityutskiy /* 4241e51764aSArtem Bityutskiy * We should return the minimum buffer size which will fit a 4251e51764aSArtem Bityutskiy * null-terminated list of all the extended attribute names. 4261e51764aSArtem Bityutskiy */ 4271e51764aSArtem Bityutskiy return len; 4281e51764aSArtem Bityutskiy 4291e51764aSArtem Bityutskiy if (len > size) 4301e51764aSArtem Bityutskiy return -ERANGE; 4311e51764aSArtem Bityutskiy 4321e51764aSArtem Bityutskiy lowest_xent_key(c, &key, host->i_ino); 4331e51764aSArtem Bityutskiy while (1) { 4341e51764aSArtem Bityutskiy xent = ubifs_tnc_next_ent(c, &key, &nm); 4358d47aef4SHirofumi Nakagawa if (IS_ERR(xent)) { 4361e51764aSArtem Bityutskiy err = PTR_ERR(xent); 4371e51764aSArtem Bityutskiy break; 4381e51764aSArtem Bityutskiy } 4391e51764aSArtem Bityutskiy 440f4f61d2cSRichard Weinberger fname_name(&nm) = xent->name; 441f4f61d2cSRichard Weinberger fname_len(&nm) = le16_to_cpu(xent->nlen); 4421e51764aSArtem Bityutskiy 44343b113feSRichard Weinberger if (xattr_visible(xent->name)) { 444f4f61d2cSRichard Weinberger memcpy(buffer + written, fname_name(&nm), fname_len(&nm) + 1); 445f4f61d2cSRichard Weinberger written += fname_len(&nm) + 1; 4461e51764aSArtem Bityutskiy } 4471e51764aSArtem Bityutskiy 4481e51764aSArtem Bityutskiy kfree(pxent); 4491e51764aSArtem Bityutskiy pxent = xent; 4501e51764aSArtem Bityutskiy key_read(c, &xent->key, &key); 4511e51764aSArtem Bityutskiy } 4521e51764aSArtem Bityutskiy 4531e51764aSArtem Bityutskiy kfree(pxent); 4541e51764aSArtem Bityutskiy if (err != -ENOENT) { 455235c362bSSheng Yong ubifs_err(c, "cannot find next direntry, error %d", err); 4561e51764aSArtem Bityutskiy return err; 4571e51764aSArtem Bityutskiy } 4581e51764aSArtem Bityutskiy 4596eb61d58SRichard Weinberger ubifs_assert(c, written <= size); 4601e51764aSArtem Bityutskiy return written; 4611e51764aSArtem Bityutskiy } 4621e51764aSArtem Bityutskiy 4631e51764aSArtem Bityutskiy static int remove_xattr(struct ubifs_info *c, struct inode *host, 464f4f61d2cSRichard Weinberger struct inode *inode, const struct fscrypt_name *nm) 4651e51764aSArtem Bityutskiy { 4661e51764aSArtem Bityutskiy int err; 4671e51764aSArtem Bityutskiy struct ubifs_inode *host_ui = ubifs_inode(host); 4681e51764aSArtem Bityutskiy struct ubifs_inode *ui = ubifs_inode(inode); 4695acd6ff8SZoltan Sogor struct ubifs_budget_req req = { .dirtied_ino = 2, .mod_dent = 1, 4705acd6ff8SZoltan Sogor .dirtied_ino_d = ALIGN(host_ui->data_len, 8) }; 4711e51764aSArtem Bityutskiy 4726eb61d58SRichard Weinberger ubifs_assert(c, ui->data_len == inode->i_size); 4731e51764aSArtem Bityutskiy 4741e51764aSArtem Bityutskiy err = ubifs_budget_space(c, &req); 4751e51764aSArtem Bityutskiy if (err) 4761e51764aSArtem Bityutskiy return err; 4771e51764aSArtem Bityutskiy 4781e51764aSArtem Bityutskiy mutex_lock(&host_ui->ui_mutex); 479607a11adSDeepa Dinamani host->i_ctime = current_time(host); 4801e51764aSArtem Bityutskiy host_ui->xattr_cnt -= 1; 481f4f61d2cSRichard Weinberger host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm)); 4821e51764aSArtem Bityutskiy host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len); 483f4f61d2cSRichard Weinberger host_ui->xattr_names -= fname_len(nm); 4841e51764aSArtem Bityutskiy 4851e51764aSArtem Bityutskiy err = ubifs_jnl_delete_xattr(c, host, inode, nm); 4861e51764aSArtem Bityutskiy if (err) 4871e51764aSArtem Bityutskiy goto out_cancel; 4881e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 4891e51764aSArtem Bityutskiy 4901e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 4911e51764aSArtem Bityutskiy return 0; 4921e51764aSArtem Bityutskiy 4931e51764aSArtem Bityutskiy out_cancel: 4941e51764aSArtem Bityutskiy host_ui->xattr_cnt += 1; 495f4f61d2cSRichard Weinberger host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm)); 4961e51764aSArtem Bityutskiy host_ui->xattr_size += CALC_XATTR_BYTES(ui->data_len); 497f4f61d2cSRichard Weinberger host_ui->xattr_names += fname_len(nm); 4981e51764aSArtem Bityutskiy mutex_unlock(&host_ui->ui_mutex); 4991e51764aSArtem Bityutskiy ubifs_release_budget(c, &req); 5001e51764aSArtem Bityutskiy make_bad_inode(inode); 5011e51764aSArtem Bityutskiy return err; 5021e51764aSArtem Bityutskiy } 5031e51764aSArtem Bityutskiy 504*9ca2d732SRichard Weinberger int ubifs_purge_xattrs(struct inode *host) 505*9ca2d732SRichard Weinberger { 506*9ca2d732SRichard Weinberger union ubifs_key key; 507*9ca2d732SRichard Weinberger struct ubifs_info *c = host->i_sb->s_fs_info; 508*9ca2d732SRichard Weinberger struct ubifs_dent_node *xent, *pxent = NULL; 509*9ca2d732SRichard Weinberger struct inode *xino; 510*9ca2d732SRichard Weinberger struct fscrypt_name nm = {0}; 511*9ca2d732SRichard Weinberger int err; 512*9ca2d732SRichard Weinberger 513*9ca2d732SRichard Weinberger if (ubifs_inode(host)->xattr_cnt < ubifs_xattr_max_cnt(c)) 514*9ca2d732SRichard Weinberger return 0; 515*9ca2d732SRichard Weinberger 516*9ca2d732SRichard Weinberger ubifs_warn(c, "inode %lu has too many xattrs, doing a non-atomic deletion", 517*9ca2d732SRichard Weinberger host->i_ino); 518*9ca2d732SRichard Weinberger 519*9ca2d732SRichard Weinberger lowest_xent_key(c, &key, host->i_ino); 520*9ca2d732SRichard Weinberger while (1) { 521*9ca2d732SRichard Weinberger xent = ubifs_tnc_next_ent(c, &key, &nm); 522*9ca2d732SRichard Weinberger if (IS_ERR(xent)) { 523*9ca2d732SRichard Weinberger err = PTR_ERR(xent); 524*9ca2d732SRichard Weinberger break; 525*9ca2d732SRichard Weinberger } 526*9ca2d732SRichard Weinberger 527*9ca2d732SRichard Weinberger fname_name(&nm) = xent->name; 528*9ca2d732SRichard Weinberger fname_len(&nm) = le16_to_cpu(xent->nlen); 529*9ca2d732SRichard Weinberger 530*9ca2d732SRichard Weinberger xino = ubifs_iget(c->vfs_sb, xent->inum); 531*9ca2d732SRichard Weinberger if (IS_ERR(xino)) { 532*9ca2d732SRichard Weinberger err = PTR_ERR(xino); 533*9ca2d732SRichard Weinberger ubifs_err(c, "dead directory entry '%s', error %d", 534*9ca2d732SRichard Weinberger xent->name, err); 535*9ca2d732SRichard Weinberger ubifs_ro_mode(c, err); 536*9ca2d732SRichard Weinberger kfree(pxent); 537*9ca2d732SRichard Weinberger return err; 538*9ca2d732SRichard Weinberger } 539*9ca2d732SRichard Weinberger 540*9ca2d732SRichard Weinberger ubifs_assert(c, ubifs_inode(xino)->xattr); 541*9ca2d732SRichard Weinberger 542*9ca2d732SRichard Weinberger clear_nlink(xino); 543*9ca2d732SRichard Weinberger err = remove_xattr(c, host, xino, &nm); 544*9ca2d732SRichard Weinberger if (err) { 545*9ca2d732SRichard Weinberger kfree(pxent); 546*9ca2d732SRichard Weinberger iput(xino); 547*9ca2d732SRichard Weinberger ubifs_err(c, "cannot remove xattr, error %d", err); 548*9ca2d732SRichard Weinberger return err; 549*9ca2d732SRichard Weinberger } 550*9ca2d732SRichard Weinberger 551*9ca2d732SRichard Weinberger iput(xino); 552*9ca2d732SRichard Weinberger 553*9ca2d732SRichard Weinberger kfree(pxent); 554*9ca2d732SRichard Weinberger pxent = xent; 555*9ca2d732SRichard Weinberger key_read(c, &xent->key, &key); 556*9ca2d732SRichard Weinberger } 557*9ca2d732SRichard Weinberger 558*9ca2d732SRichard Weinberger kfree(pxent); 559*9ca2d732SRichard Weinberger if (err != -ENOENT) { 560*9ca2d732SRichard Weinberger ubifs_err(c, "cannot find next direntry, error %d", err); 561*9ca2d732SRichard Weinberger return err; 562*9ca2d732SRichard Weinberger } 563*9ca2d732SRichard Weinberger 564*9ca2d732SRichard Weinberger return 0; 565*9ca2d732SRichard Weinberger } 566*9ca2d732SRichard Weinberger 567272eda82SRichard Weinberger /** 568272eda82SRichard Weinberger * ubifs_evict_xattr_inode - Evict an xattr inode. 569272eda82SRichard Weinberger * @c: UBIFS file-system description object 570272eda82SRichard Weinberger * @xattr_inum: xattr inode number 571272eda82SRichard Weinberger * 572272eda82SRichard Weinberger * When an inode that hosts xattrs is being removed we have to make sure 573272eda82SRichard Weinberger * that cached inodes of the xattrs also get removed from the inode cache 574272eda82SRichard Weinberger * otherwise we'd waste memory. This function looks up an inode from the 575272eda82SRichard Weinberger * inode cache and clears the link counter such that iput() will evict 576272eda82SRichard Weinberger * the inode. 577272eda82SRichard Weinberger */ 578272eda82SRichard Weinberger void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum) 579272eda82SRichard Weinberger { 580272eda82SRichard Weinberger struct inode *inode; 581272eda82SRichard Weinberger 582272eda82SRichard Weinberger inode = ilookup(c->vfs_sb, xattr_inum); 583272eda82SRichard Weinberger if (inode) { 584272eda82SRichard Weinberger clear_nlink(inode); 585272eda82SRichard Weinberger iput(inode); 586272eda82SRichard Weinberger } 587272eda82SRichard Weinberger } 588272eda82SRichard Weinberger 589ade46c3aSRichard Weinberger static int ubifs_xattr_remove(struct inode *host, const char *name) 5901e51764aSArtem Bityutskiy { 5912b88fc21SAndreas Gruenbacher struct inode *inode; 5921e51764aSArtem Bityutskiy struct ubifs_info *c = host->i_sb->s_fs_info; 593f4f61d2cSRichard Weinberger struct fscrypt_name nm = { .disk_name = FSTR_INIT((char *)name, strlen(name))}; 5941e51764aSArtem Bityutskiy struct ubifs_dent_node *xent; 5951e51764aSArtem Bityutskiy union ubifs_key key; 5961e51764aSArtem Bityutskiy int err; 5971e51764aSArtem Bityutskiy 5986eb61d58SRichard Weinberger ubifs_assert(c, inode_is_locked(host)); 5991e51764aSArtem Bityutskiy 600f4f61d2cSRichard Weinberger if (fname_len(&nm) > UBIFS_MAX_NLEN) 6012b88fc21SAndreas Gruenbacher return -ENAMETOOLONG; 6021e51764aSArtem Bityutskiy 6031e51764aSArtem Bityutskiy xent = kmalloc(UBIFS_MAX_XENT_NODE_SZ, GFP_NOFS); 6041e51764aSArtem Bityutskiy if (!xent) 6051e51764aSArtem Bityutskiy return -ENOMEM; 6061e51764aSArtem Bityutskiy 6071e51764aSArtem Bityutskiy xent_key_init(c, &key, host->i_ino, &nm); 6081e51764aSArtem Bityutskiy err = ubifs_tnc_lookup_nm(c, &key, xent, &nm); 6091e51764aSArtem Bityutskiy if (err) { 6101e51764aSArtem Bityutskiy if (err == -ENOENT) 6111e51764aSArtem Bityutskiy err = -ENODATA; 6121e51764aSArtem Bityutskiy goto out_free; 6131e51764aSArtem Bityutskiy } 6141e51764aSArtem Bityutskiy 6151e51764aSArtem Bityutskiy inode = iget_xattr(c, le64_to_cpu(xent->inum)); 6161e51764aSArtem Bityutskiy if (IS_ERR(inode)) { 6171e51764aSArtem Bityutskiy err = PTR_ERR(inode); 6181e51764aSArtem Bityutskiy goto out_free; 6191e51764aSArtem Bityutskiy } 6201e51764aSArtem Bityutskiy 6216eb61d58SRichard Weinberger ubifs_assert(c, inode->i_nlink == 1); 6226d6b77f1SMiklos Szeredi clear_nlink(inode); 6231e51764aSArtem Bityutskiy err = remove_xattr(c, host, inode, &nm); 6241e51764aSArtem Bityutskiy if (err) 625bfe86848SMiklos Szeredi set_nlink(inode, 1); 6261e51764aSArtem Bityutskiy 6271e51764aSArtem Bityutskiy /* If @i_nlink is 0, 'iput()' will delete the inode */ 6281e51764aSArtem Bityutskiy iput(inode); 6291e51764aSArtem Bityutskiy 6301e51764aSArtem Bityutskiy out_free: 6311e51764aSArtem Bityutskiy kfree(xent); 6321e51764aSArtem Bityutskiy return err; 6331e51764aSArtem Bityutskiy } 634d7f0b70dSSubodh Nijsure 6358326c1eeSHyunchul Lee #ifdef CONFIG_UBIFS_FS_SECURITY 636d7f0b70dSSubodh Nijsure static int init_xattrs(struct inode *inode, const struct xattr *xattr_array, 637d7f0b70dSSubodh Nijsure void *fs_info) 638d7f0b70dSSubodh Nijsure { 639d7f0b70dSSubodh Nijsure const struct xattr *xattr; 640d7f0b70dSSubodh Nijsure char *name; 641d7f0b70dSSubodh Nijsure int err = 0; 642d7f0b70dSSubodh Nijsure 643d7f0b70dSSubodh Nijsure for (xattr = xattr_array; xattr->name != NULL; xattr++) { 644d7f0b70dSSubodh Nijsure name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 645d7f0b70dSSubodh Nijsure strlen(xattr->name) + 1, GFP_NOFS); 646d7f0b70dSSubodh Nijsure if (!name) { 647d7f0b70dSSubodh Nijsure err = -ENOMEM; 648d7f0b70dSSubodh Nijsure break; 649d7f0b70dSSubodh Nijsure } 650d7f0b70dSSubodh Nijsure strcpy(name, XATTR_SECURITY_PREFIX); 651d7f0b70dSSubodh Nijsure strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name); 652d8db5b1cSXiaolei Li /* 653d8db5b1cSXiaolei Li * creating a new inode without holding the inode rwsem, 654d8db5b1cSXiaolei Li * no need to check whether inode is locked. 655d8db5b1cSXiaolei Li */ 656ade46c3aSRichard Weinberger err = ubifs_xattr_set(inode, name, xattr->value, 657d8db5b1cSXiaolei Li xattr->value_len, 0, false); 658d7f0b70dSSubodh Nijsure kfree(name); 659d7f0b70dSSubodh Nijsure if (err < 0) 660d7f0b70dSSubodh Nijsure break; 661d7f0b70dSSubodh Nijsure } 662d7f0b70dSSubodh Nijsure 663d7f0b70dSSubodh Nijsure return err; 664d7f0b70dSSubodh Nijsure } 665d7f0b70dSSubodh Nijsure 666d7f0b70dSSubodh Nijsure int ubifs_init_security(struct inode *dentry, struct inode *inode, 667d7f0b70dSSubodh Nijsure const struct qstr *qstr) 668d7f0b70dSSubodh Nijsure { 669d7f0b70dSSubodh Nijsure int err; 670d7f0b70dSSubodh Nijsure 671d7f0b70dSSubodh Nijsure err = security_inode_init_security(inode, dentry, qstr, 672d7f0b70dSSubodh Nijsure &init_xattrs, 0); 673235c362bSSheng Yong if (err) { 674235c362bSSheng Yong struct ubifs_info *c = dentry->i_sb->s_fs_info; 675235c362bSSheng Yong ubifs_err(c, "cannot initialize security for inode %lu, error %d", 676fee1756dSSubodh Nijsure inode->i_ino, err); 677235c362bSSheng Yong } 678d7f0b70dSSubodh Nijsure return err; 679d7f0b70dSSubodh Nijsure } 6808326c1eeSHyunchul Lee #endif 6812b88fc21SAndreas Gruenbacher 682ade46c3aSRichard Weinberger static int xattr_get(const struct xattr_handler *handler, 6832b88fc21SAndreas Gruenbacher struct dentry *dentry, struct inode *inode, 6842b88fc21SAndreas Gruenbacher const char *name, void *buffer, size_t size) 6852b88fc21SAndreas Gruenbacher { 6862b88fc21SAndreas Gruenbacher dbg_gen("xattr '%s', ino %lu ('%pd'), buf size %zd", name, 6872b88fc21SAndreas Gruenbacher inode->i_ino, dentry, size); 6882b88fc21SAndreas Gruenbacher 68917ce1eb0SRichard Weinberger name = xattr_full_name(handler, name); 690ade46c3aSRichard Weinberger return ubifs_xattr_get(inode, name, buffer, size); 6912b88fc21SAndreas Gruenbacher } 6922b88fc21SAndreas Gruenbacher 693ade46c3aSRichard Weinberger static int xattr_set(const struct xattr_handler *handler, 69459301226SAl Viro struct dentry *dentry, struct inode *inode, 69559301226SAl Viro const char *name, const void *value, 69659301226SAl Viro size_t size, int flags) 6972b88fc21SAndreas Gruenbacher { 6982b88fc21SAndreas Gruenbacher dbg_gen("xattr '%s', host ino %lu ('%pd'), size %zd", 6992b88fc21SAndreas Gruenbacher name, inode->i_ino, dentry, size); 7002b88fc21SAndreas Gruenbacher 70117ce1eb0SRichard Weinberger name = xattr_full_name(handler, name); 70217ce1eb0SRichard Weinberger 7032b88fc21SAndreas Gruenbacher if (value) 704d8db5b1cSXiaolei Li return ubifs_xattr_set(inode, name, value, size, flags, true); 7052b88fc21SAndreas Gruenbacher else 706ade46c3aSRichard Weinberger return ubifs_xattr_remove(inode, name); 7072b88fc21SAndreas Gruenbacher } 7082b88fc21SAndreas Gruenbacher 709dfaf8d2aSBen Dooks static const struct xattr_handler ubifs_user_xattr_handler = { 7102b88fc21SAndreas Gruenbacher .prefix = XATTR_USER_PREFIX, 711ade46c3aSRichard Weinberger .get = xattr_get, 712ade46c3aSRichard Weinberger .set = xattr_set, 7132b88fc21SAndreas Gruenbacher }; 7142b88fc21SAndreas Gruenbacher 715dfaf8d2aSBen Dooks static const struct xattr_handler ubifs_trusted_xattr_handler = { 7162b88fc21SAndreas Gruenbacher .prefix = XATTR_TRUSTED_PREFIX, 717ade46c3aSRichard Weinberger .get = xattr_get, 718ade46c3aSRichard Weinberger .set = xattr_set, 7192b88fc21SAndreas Gruenbacher }; 7202b88fc21SAndreas Gruenbacher 7218326c1eeSHyunchul Lee #ifdef CONFIG_UBIFS_FS_SECURITY 722dfaf8d2aSBen Dooks static const struct xattr_handler ubifs_security_xattr_handler = { 7232b88fc21SAndreas Gruenbacher .prefix = XATTR_SECURITY_PREFIX, 724ade46c3aSRichard Weinberger .get = xattr_get, 725ade46c3aSRichard Weinberger .set = xattr_set, 7262b88fc21SAndreas Gruenbacher }; 7278326c1eeSHyunchul Lee #endif 7282b88fc21SAndreas Gruenbacher 7292b88fc21SAndreas Gruenbacher const struct xattr_handler *ubifs_xattr_handlers[] = { 7302b88fc21SAndreas Gruenbacher &ubifs_user_xattr_handler, 7312b88fc21SAndreas Gruenbacher &ubifs_trusted_xattr_handler, 7328326c1eeSHyunchul Lee #ifdef CONFIG_UBIFS_FS_SECURITY 7332b88fc21SAndreas Gruenbacher &ubifs_security_xattr_handler, 7348326c1eeSHyunchul Lee #endif 7352b88fc21SAndreas Gruenbacher NULL 7362b88fc21SAndreas Gruenbacher }; 737