Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 32 additions & 24 deletions fs/fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,36 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info
return ret;
}

int __bch2_xattr_set(struct btree_trans *trans, subvol_inum inum,
const struct bch_hash_info *hash_info,
const char *name, const void *value, size_t size,
int type, int flags)
{
struct bkey_i_xattr *xattr;
unsigned namelen = strlen(name);
unsigned u64s = BKEY_U64s + xattr_val_u64s(namelen, size);

if (u64s > U8_MAX)
return -ERANGE;

xattr = bch2_trans_kmalloc(trans, u64s * sizeof(u64));
if (IS_ERR(xattr))
return PTR_ERR(xattr);

bkey_xattr_init(&xattr->k_i);
xattr->k.u64s = u64s;
xattr->v.x_type = type;
xattr->v.x_name_len = namelen;
xattr->v.x_val_len = cpu_to_le16(size);
memcpy(xattr->v.x_name_and_value, name, namelen);
memcpy(xattr_val(&xattr->v), value, size);

return bch2_hash_set(trans, bch2_xattr_hash_desc, hash_info,
inum, &xattr->k_i,
(flags & XATTR_CREATE ? STR_HASH_must_create : 0)|
(flags & XATTR_REPLACE ? STR_HASH_must_replace : 0));
}

int bch2_xattr_set(struct btree_trans *trans, subvol_inum inum,
struct bch_inode_unpacked *inode_u,
const char *name, const void *value, size_t size,
Expand Down Expand Up @@ -190,30 +220,8 @@ int bch2_xattr_set(struct btree_trans *trans, subvol_inum inum,

int ret;
if (value) {
struct bkey_i_xattr *xattr;
unsigned namelen = strlen(name);
unsigned u64s = BKEY_U64s +
xattr_val_u64s(namelen, size);

if (u64s > U8_MAX)
return -ERANGE;

xattr = bch2_trans_kmalloc(trans, u64s * sizeof(u64));
if (IS_ERR(xattr))
return PTR_ERR(xattr);

bkey_xattr_init(&xattr->k_i);
xattr->k.u64s = u64s;
xattr->v.x_type = type;
xattr->v.x_name_len = namelen;
xattr->v.x_val_len = cpu_to_le16(size);
memcpy(xattr->v.x_name_and_value, name, namelen);
memcpy(xattr_val(&xattr->v), value, size);

ret = bch2_hash_set(trans, bch2_xattr_hash_desc, &hash_info,
inum, &xattr->k_i,
(flags & XATTR_CREATE ? STR_HASH_must_create : 0)|
(flags & XATTR_REPLACE ? STR_HASH_must_replace : 0));
ret = __bch2_xattr_set(trans, inum, &hash_info,
name, value, size, type, flags);
} else {
struct xattr_search_key search =
X_SEARCH(type, name, strlen(name));
Expand Down
4 changes: 4 additions & 0 deletions fs/fs/xattr.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ struct xattr_handler;
struct bch_hash_info;
struct bch_inode_info;

int __bch2_xattr_set(struct btree_trans *, subvol_inum,
const struct bch_hash_info *,
const char *, const void *, size_t, int, int);

/* Exported for cmd_migrate.c in tools: */
int bch2_xattr_set(struct btree_trans *, subvol_inum,
struct bch_inode_unpacked *,
Expand Down
55 changes: 55 additions & 0 deletions fs/vfs/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <linux/pagemap.h>
#include <linux/posix_acl.h>
#include <linux/random.h>
#include <linux/security.h>
#include <linux/seq_file.h>
#include <linux/siphash.h>
#include <linux/statfs.h>
Expand Down Expand Up @@ -573,6 +574,55 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum,
return ret ? ERR_PTR(ret) : &inode->v;
}

struct bch2_initxattrs_ctx {
struct btree_trans *trans;
subvol_inum inum;
struct bch_hash_info hash;
};

static int bch2_initxattrs(struct inode *vinode,
const struct xattr *xattr_array,
void *fs_data)
{
struct bch2_initxattrs_ctx *ctx = fs_data;
const struct xattr *xattr;

for (xattr = xattr_array; xattr->name; xattr++) {
int ret = __bch2_xattr_set(ctx->trans, ctx->inum, &ctx->hash,
xattr->name, xattr->value,
xattr->value_len,
KEY_TYPE_XATTR_INDEX_SECURITY,
XATTR_CREATE);
if (ret)
return ret;
}

return 0;
}

static int bch2_inode_init_security(struct btree_trans *trans,
struct bch_inode_info *dir,
struct bch_inode_info *inode,
struct dentry *dentry,
subvol_inum inum,
struct bch_inode_unpacked *inode_u)
{
struct bch2_initxattrs_ctx ctx = {
.trans = trans,
.inum = inum,
};

inode->v.i_ino = inum.inum;
inode->ei_inum = inum;
inode->ei_inode.bi_inum = inum.inum;
bch2_inode_update_after_write(trans, inode, inode_u, ~0);

try(bch2_hash_info_init(trans->c, inode_u, &ctx.hash));

return security_inode_init_security(&inode->v, &dir->v, &dentry->d_name,
bch2_initxattrs, &ctx);
}

struct bch_inode_info *
__bch2_create(struct mnt_idmap *idmap,
struct bch_inode_info *dir, struct dentry *dentry,
Expand Down Expand Up @@ -636,8 +686,13 @@ __bch2_create(struct mnt_idmap *idmap,
inum.subvol = inode_u.bi_subvol ?: dir->ei_inum.subvol;
inum.inum = inode_u.bi_inum;

ret = bch2_inode_init_security(trans, dir, inode, dentry, inum, &inode_u);
if (unlikely(ret))
goto err_after_quota;

ret = bch2_trans_commit(trans, NULL, NULL, 0);
if (unlikely(ret)) {
err_after_quota:
bch2_quota_acct(c, bch_qid(&inode_u), Q_INO, -1,
KEY_TYPE_QUOTA_WARN);
err_before_quota:
Expand Down
Loading