From 5dc90d3e15db315dddb3fead5eab817027c4312c Mon Sep 17 00:00:00 2001 From: Reagan Bohan Date: Sat, 30 Mar 2024 09:54:05 +0000 Subject: [PATCH] bcachefs: Initial support for security labels. --- fs/bcachefs/fs.c | 41 ++++++++++++++++++++++++++++++++ fs/bcachefs/xattr.c | 57 ++++++++++++++++++++++++++------------------- fs/bcachefs/xattr.h | 5 ++++ 3 files changed, 79 insertions(+), 24 deletions(-) diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index b5ea9fa1259d1..f60324b241e2e 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -261,6 +262,34 @@ struct inode *bch2_vfs_inode_get(struct bch_fs *c, subvol_inum inum) return ret ? ERR_PTR(ret) : &inode->v; } +struct initxattr_params { + struct bch_fs *c; + struct btree_trans *trans; + struct bch_inode_info *inode; + subvol_inum inum; +}; + +static int bch2_initxattrs(struct inode *vinode, + const struct xattr *xattr_array, void *fs_info) +{ + const struct xattr *xattr; + struct initxattr_params *params = fs_info; + struct bch_hash_info hash = + bch2_hash_info_init(params->c, ¶ms->inode->ei_inode); + int ret; + + for (xattr = xattr_array; xattr->name != NULL; xattr++) { + ret = __bch2_xattr_set_inner( + params->trans, inode_inum(params->inode), &hash, + xattr->name, xattr->value, xattr->value_len, + KEY_TYPE_XATTR_INDEX_SECURITY, XATTR_CREATE); + + if (ret < 0) + break; + } + return ret; +} + struct bch_inode_info * __bch2_create(struct mnt_idmap *idmap, struct bch_inode_info *dir, struct dentry *dentry, @@ -273,6 +302,7 @@ __bch2_create(struct mnt_idmap *idmap, struct bch_inode_info *inode; struct bch_inode_unpacked inode_u; struct posix_acl *default_acl = NULL, *acl = NULL; + struct initxattr_params sec_params; subvol_inum inum; struct bch_subvolume subvol; u64 journal_seq = 0; @@ -342,6 +372,17 @@ __bch2_create(struct mnt_idmap *idmap, set_cached_acl(&inode->v, ACL_TYPE_ACCESS, acl); set_cached_acl(&inode->v, ACL_TYPE_DEFAULT, default_acl); + sec_params.c = c; + sec_params.trans = trans; + sec_params.inode = inode; + sec_params.inum = inum; + + ret = security_inode_init_security(&inode->v, &dir->v, &dentry->d_name, + &bch2_initxattrs, &sec_params); + + if (unlikely(ret)) + goto err_trans; + /* * we must insert the new inode into the inode cache before calling * bch2_trans_exit() and dropping locks, else we could race with another diff --git a/fs/bcachefs/xattr.c b/fs/bcachefs/xattr.c index 754f17bba68ed..259884adc4f70 100644 --- a/fs/bcachefs/xattr.c +++ b/fs/bcachefs/xattr.c @@ -166,6 +166,37 @@ static int bch2_xattr_get_trans(struct btree_trans *trans, struct bch_inode_info return ret < 0 && bch2_err_matches(ret, ENOENT) ? -ENODATA : ret; } +int __bch2_xattr_set_inner(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, 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 ? BCH_HASH_SET_MUST_CREATE : 0) | + (flags & XATTR_REPLACE ? BCH_HASH_SET_MUST_REPLACE : + 0)); +} + int bch2_xattr_set(struct btree_trans *trans, subvol_inum inum, struct bch_inode_unpacked *inode_u, const struct bch_hash_info *hash_info, @@ -190,30 +221,8 @@ int bch2_xattr_set(struct btree_trans *trans, subvol_inum inum, return 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, 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 ? BCH_HASH_SET_MUST_CREATE : 0)| - (flags & XATTR_REPLACE ? BCH_HASH_SET_MUST_REPLACE : 0)); + return __bch2_xattr_set_inner(trans, inum, hash_info, name, + value, size, type, flags); } else { struct xattr_search_key search = X_SEARCH(type, name, strlen(name)); diff --git a/fs/bcachefs/xattr.h b/fs/bcachefs/xattr.h index 1337f31a5c492..c4932c4dcaae9 100644 --- a/fs/bcachefs/xattr.h +++ b/fs/bcachefs/xattr.h @@ -38,6 +38,11 @@ struct xattr_handler; struct bch_hash_info; struct bch_inode_info; +int __bch2_xattr_set_inner(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); + /* Exported for cmd_migrate.c in tools: */ int bch2_xattr_set(struct btree_trans *, subvol_inum, struct bch_inode_unpacked *, const struct bch_hash_info *,