From: "Luís Henriques" <lhenriques@suse.de>
To: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Cc: "Theodore Y. Ts'o" <tytso@mit.edu>,
Jaegeuk Kim <jaegeuk@kernel.org>,
Eric Biggers <ebiggers@kernel.org>, Chris Mason <clm@fb.com>,
Josef Bacik <josef@toxicpanda.com>,
David Sterba <dsterba@suse.com>,
linux-fscrypt@vger.kernel.org, linux-btrfs@vger.kernel.org,
kernel-team@meta.com, Omar Sandoval <osandov@osandov.com>
Subject: Re: [PATCH v2 07/17] btrfs: adapt readdir for encrypted and nokey names
Date: Mon, 17 Jul 2023 16:34:32 +0100 [thread overview]
Message-ID: <87351mwns7.fsf@suse.de> (raw)
In-Reply-To: ba4d9065b8109ea74fc1c5bed788e45c95a07e75.1689564024.git.sweettea-kernel@dorminy.me
Sweet Tea Dorminy <sweettea-kernel@dorminy.me> writes:
> From: Omar Sandoval <osandov@osandov.com>
> @@ -5793,13 +5787,18 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
> struct btrfs_root *root = BTRFS_I(dir)->root;
> struct btrfs_root *sub_root = root;
> struct btrfs_key location;
> + struct fscrypt_name fname;
> u8 di_type = 0;
> int ret = 0;
>
> if (dentry->d_name.len > BTRFS_NAME_LEN)
> return ERR_PTR(-ENAMETOOLONG);
>
> - ret = btrfs_inode_by_name(BTRFS_I(dir), dentry, &location, &di_type);
> + ret = fscrypt_prepare_lookup(dir, dentry, &fname);
> + if (ret)
> + return ERR_PTR(ret);
> +
I _think_ these error paths below need to be changed in order to invoke
fscrypt_free_lookup().
Cheers,
--
Luís
>
> + ret = btrfs_inode_by_name(BTRFS_I(dir), &fname, &location, &di_type);
> if (ret < 0)
> return ERR_PTR(ret);
>
> @@ -5940,18 +5939,32 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> struct list_head del_list;
> int ret;
> char *name_ptr;
> - int name_len;
> + u32 name_len;
> int entries = 0;
> int total_len = 0;
> bool put = false;
> struct btrfs_key location;
> + struct fscrypt_str fstr = FSTR_INIT(NULL, 0);
> + u32 fstr_len = 0;
>
> if (!dir_emit_dots(file, ctx))
> return 0;
>
> + if (BTRFS_I(inode)->flags & BTRFS_INODE_ENCRYPT) {
> + ret = fscrypt_prepare_readdir(inode);
> + if (ret)
> + return ret;
> + ret = fscrypt_fname_alloc_buffer(BTRFS_NAME_LEN, &fstr);
> + if (ret)
> + return ret;
> + fstr_len = fstr.len;
> + }
> +
> path = btrfs_alloc_path();
> - if (!path)
> - return -ENOMEM;
> + if (!path) {
> + ret = -ENOMEM;
> + goto err_fstr;
> + }
>
> addr = private->filldir_buf;
> path->reada = READA_FORWARD;
> @@ -5969,6 +5982,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> struct dir_entry *entry;
> struct extent_buffer *leaf = path->nodes[0];
> u8 ftype;
> + u32 nokey_len;
>
> if (found_key.objectid != key.objectid)
> break;
> @@ -5980,8 +5994,13 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> continue;
> di = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_dir_item);
> name_len = btrfs_dir_name_len(leaf, di);
> - if ((total_len + sizeof(struct dir_entry) + name_len) >=
> - PAGE_SIZE) {
> + nokey_len = DIV_ROUND_UP(name_len * 4, 3);
> + /*
> + * If name is encrypted, and we don't have the key, we could
> + * need up to 4/3rds the bytes to print it.
> + */
> + if ((total_len + sizeof(struct dir_entry) + nokey_len)
> + >= PAGE_SIZE) {
> btrfs_release_path(path);
> ret = btrfs_filldir(private->filldir_buf, entries, ctx);
> if (ret)
> @@ -5995,8 +6014,36 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> ftype = btrfs_dir_flags_to_ftype(btrfs_dir_flags(leaf, di));
> entry = addr;
> name_ptr = (char *)(entry + 1);
> - read_extent_buffer(leaf, name_ptr,
> - (unsigned long)(di + 1), name_len);
> + if (btrfs_dir_flags(leaf, di) & BTRFS_FT_ENCRYPTED) {
> + struct fscrypt_str oname = FSTR_INIT(name_ptr,
> + nokey_len);
> + u32 hash = 0, minor_hash = 0;
> +
> + read_extent_buffer(leaf, fstr.name,
> + (unsigned long)(di + 1), name_len);
> + fstr.len = name_len;
> + /*
> + * We're iterating through DIR_INDEX items, so we don't
> + * have the DIR_ITEM hash handy. Only compute it if
> + * we'll need it -- the nokey name stores it, so that
> + * we can look up the appropriate item by nokey name
> + * later on.
> + */
> + if (!fscrypt_has_encryption_key(inode)) {
> + u64 name_hash = btrfs_name_hash(fstr.name,
> + fstr.len);
> + hash = name_hash;
> + minor_hash = name_hash >> 32;
> + }
> + ret = fscrypt_fname_disk_to_usr(inode, hash, minor_hash,
> + &fstr, &oname);
> + if (ret)
> + goto err;
> + name_len = oname.len;
> + } else {
> + read_extent_buffer(leaf, name_ptr,
> + (unsigned long)(di + 1), name_len);
> + }
> put_unaligned(name_len, &entry->name_len);
> put_unaligned(fs_ftype_to_dtype(ftype), &entry->type);
> btrfs_dir_item_key_to_cpu(leaf, di, &location);
> @@ -6016,7 +6063,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> if (ret)
> goto nopos;
>
> - ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
> + fstr.len = fstr_len;
> + ret = btrfs_readdir_delayed_dir_index(inode, &fstr, ctx, &ins_list);
> if (ret)
> goto nopos;
>
> @@ -6047,6 +6095,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
> if (put)
> btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list);
> btrfs_free_path(path);
> +err_fstr:
> + fscrypt_fname_free_buffer(&fstr);
> return ret;
> }
>
> @@ -6555,6 +6605,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
> struct btrfs_root *root = parent_inode->root;
> u64 ino = btrfs_ino(inode);
> u64 parent_ino = btrfs_ino(parent_inode);
> + struct fscrypt_name fname = { .disk_name = *name };
>
> if (unlikely(ino == BTRFS_FIRST_FREE_OBJECTID)) {
> memcpy(&key, &inode->root->root_key, sizeof(key));
> @@ -6612,7 +6663,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
> int err;
> err = btrfs_del_root_ref(trans, key.objectid,
> root->root_key.objectid, parent_ino,
> - &local_index, name);
> + &local_index, &fname);
> if (err)
> btrfs_abort_transaction(trans, err);
> } else if (add_backref) {
> @@ -8982,7 +9033,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
> } else { /* src is an inode */
> ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir),
> BTRFS_I(old_dentry->d_inode),
> - old_name, &old_rename_ctx);
> + &old_fname, &old_rename_ctx);
> if (!ret)
> ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
> }
> @@ -8997,7 +9048,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
> } else { /* dest is an inode */
> ret = __btrfs_unlink_inode(trans, BTRFS_I(new_dir),
> BTRFS_I(new_dentry->d_inode),
> - new_name, &new_rename_ctx);
> + &new_fname, &new_rename_ctx);
> if (!ret)
> ret = btrfs_update_inode(trans, dest, BTRFS_I(new_inode));
> }
> @@ -9246,7 +9297,7 @@ static int btrfs_rename(struct mnt_idmap *idmap,
> } else {
> ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir),
> BTRFS_I(d_inode(old_dentry)),
> - &old_fname.disk_name, &rename_ctx);
> + &old_fname, &rename_ctx);
> if (!ret)
> ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
> }
> @@ -9265,7 +9316,7 @@ static int btrfs_rename(struct mnt_idmap *idmap,
> } else {
> ret = btrfs_unlink_inode(trans, BTRFS_I(new_dir),
> BTRFS_I(d_inode(new_dentry)),
> - &new_fname.disk_name);
> + &new_fname);
> }
> if (!ret && new_inode->i_nlink == 0)
> ret = btrfs_orphan_add(trans,
> diff --git a/fs/btrfs/root-tree.c b/fs/btrfs/root-tree.c
> index 859874579456..5fa416ef54ad 100644
> --- a/fs/btrfs/root-tree.c
> +++ b/fs/btrfs/root-tree.c
> @@ -10,6 +10,7 @@
> #include "messages.h"
> #include "transaction.h"
> #include "disk-io.h"
> +#include "fscrypt.h"
> #include "print-tree.h"
> #include "qgroup.h"
> #include "space-info.h"
> @@ -333,7 +334,7 @@ int btrfs_del_root(struct btrfs_trans_handle *trans,
>
> int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
> u64 ref_id, u64 dirid, u64 *sequence,
> - const struct fscrypt_str *name)
> + struct fscrypt_name *name)
> {
> struct btrfs_root *tree_root = trans->fs_info->tree_root;
> struct btrfs_path *path;
> @@ -355,13 +356,14 @@ int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
> if (ret < 0) {
> goto out;
> } else if (ret == 0) {
> + u32 name_len;
> leaf = path->nodes[0];
> ref = btrfs_item_ptr(leaf, path->slots[0],
> struct btrfs_root_ref);
> ptr = (unsigned long)(ref + 1);
> + name_len = btrfs_root_ref_name_len(leaf, ref);
> if ((btrfs_root_ref_dirid(leaf, ref) != dirid) ||
> - (btrfs_root_ref_name_len(leaf, ref) != name->len) ||
> - memcmp_extent_buffer(leaf, name->name, ptr, name->len)) {
> + !btrfs_fscrypt_match_name(name, leaf, ptr, name_len)) {
> ret = -ENOENT;
> goto out;
> }
> diff --git a/fs/btrfs/root-tree.h b/fs/btrfs/root-tree.h
> index cbbaca32126e..a57bbf7b0180 100644
> --- a/fs/btrfs/root-tree.h
> +++ b/fs/btrfs/root-tree.h
> @@ -13,7 +13,7 @@ int btrfs_add_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
> const struct fscrypt_str *name);
> int btrfs_del_root_ref(struct btrfs_trans_handle *trans, u64 root_id,
> u64 ref_id, u64 dirid, u64 *sequence,
> - const struct fscrypt_str *name);
> + struct fscrypt_name *name);
> int btrfs_del_root(struct btrfs_trans_handle *trans, const struct btrfs_key *key);
> int btrfs_insert_root(struct btrfs_trans_handle *trans, struct btrfs_root *root,
> const struct btrfs_key *key,
> diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
> index 8ad7e7e38d18..3bf746668e07 100644
> --- a/fs/btrfs/tree-log.c
> +++ b/fs/btrfs/tree-log.c
> @@ -901,9 +901,10 @@ static int unlink_inode_for_log_replay(struct btrfs_trans_handle *trans,
> struct btrfs_inode *inode,
> const struct fscrypt_str *name)
> {
> + struct fscrypt_name fname = { .disk_name = *name, };
> int ret;
>
> - ret = btrfs_unlink_inode(trans, dir, inode, name);
> + ret = btrfs_unlink_inode(trans, dir, inode, &fname);
> if (ret)
> return ret;
> /*
> --
>
> 2.40.1
>
next prev parent reply other threads:[~2023-07-17 15:39 UTC|newest]
Thread overview: 33+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-07-17 3:52 [PATCH v2 00/17] btrfs: add encryption feature Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 01/17] btrfs: disable various operations on encrypted inodes Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 02/17] btrfs: disable verity " Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 03/17] fscrypt: expose fscrypt_nokey_name Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 04/17] btrfs: start using fscrypt hooks Sweet Tea Dorminy
2023-07-17 15:34 ` Luís Henriques
2023-07-17 17:28 ` David Sterba
2023-07-18 8:36 ` Luís Henriques
2023-07-17 3:52 ` [PATCH v2 05/17] btrfs: add inode encryption contexts Sweet Tea Dorminy
2023-07-17 15:41 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 06/17] btrfs: add new FEATURE_INCOMPAT_ENCRYPT flag Sweet Tea Dorminy
2023-07-17 15:42 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 07/17] btrfs: adapt readdir for encrypted and nokey names Sweet Tea Dorminy
2023-07-17 15:34 ` Luís Henriques [this message]
2023-07-17 17:46 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 08/17] btrfs: use correct name hash for " Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 09/17] btrfs: implement fscrypt ioctls Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 10/17] btrfs: add encryption to CONFIG_BTRFS_DEBUG Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 11/17] btrfs: add get_devices hook for fscrypt Sweet Tea Dorminy
2023-07-17 17:51 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 12/17] btrfs: turn on inlinecrypt mount option for encrypt Sweet Tea Dorminy
2023-07-17 15:34 ` Luís Henriques
2023-07-17 17:55 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 13/17] btrfs: turn on the encryption ioctls Sweet Tea Dorminy
2023-07-17 3:52 ` [PATCH v2 14/17] btrfs: create and free extent fscrypt_infos Sweet Tea Dorminy
2023-07-17 17:58 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 15/17] btrfs: start tracking extent encryption context info Sweet Tea Dorminy
2023-07-17 18:11 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 16/17] btrfs: explicitly track file extent length and encryption Sweet Tea Dorminy
2023-07-17 15:30 ` Josef Bacik
2023-07-17 18:12 ` Josef Bacik
2023-07-17 3:52 ` [PATCH v2 17/17] btrfs: save and load fscrypt extent contexts Sweet Tea Dorminy
2023-07-17 18:15 ` Josef Bacik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87351mwns7.fsf@suse.de \
--to=lhenriques@suse.de \
--cc=clm@fb.com \
--cc=dsterba@suse.com \
--cc=ebiggers@kernel.org \
--cc=jaegeuk@kernel.org \
--cc=josef@toxicpanda.com \
--cc=kernel-team@meta.com \
--cc=linux-btrfs@vger.kernel.org \
--cc=linux-fscrypt@vger.kernel.org \
--cc=osandov@osandov.com \
--cc=sweettea-kernel@dorminy.me \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox