On Tue, 2 Jun 2026 at 04:44, Eric Biggers <[email protected]> wrote: > On Wed, May 13, 2026 at 10:53:10AM +0200, Daniel Vacek wrote: > > From: Josef Bacik <[email protected]> > > > > Send needs to send the decrypted value of the symlinks, handle the case > > where the inode is encrypted and decrypt the symlink name into a buffer > > and copy this buffer into our fs_path struct. > > > > Signed-off-by: Josef Bacik <[email protected]> > > Signed-off-by: Daniel Vacek <[email protected]> > > --- > > > > No changes in v7. > > v6 changes: > > * read_symlink_encrypted() reworked from using pages to using folios. > > v5: > > https://lore.kernel.org/linux-btrfs/4d97f35d6f85ff041b09bed33b63446a92b7a20c.1706116485.git.jo...@toxicpanda.com/ > > --- > > fs/btrfs/send.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- > > 1 file changed, 42 insertions(+), 3 deletions(-) > > > > diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c > > index 89d72d8cb85f..d5256c22fe7a 100644 > > --- a/fs/btrfs/send.c > > +++ b/fs/btrfs/send.c > > @@ -1701,9 +1701,7 @@ static int find_extent_clone(struct send_ctx *sctx, > > return ret; > > } > > > > -static int read_symlink(struct btrfs_root *root, > > - u64 ino, > > - struct fs_path *dest) > > +static int read_symlink_unencrypted(struct btrfs_root *root, u64 ino, > > struct fs_path *dest) > > { > > int ret; > > BTRFS_PATH_AUTO_FREE(path); > > @@ -1764,6 +1762,47 @@ static int read_symlink(struct btrfs_root *root, > > return fs_path_add_from_extent_buffer(dest, path->nodes[0], off, len); > > } > > > > +static int read_symlink_encrypted(struct btrfs_root *root, u64 ino, struct > > fs_path *dest) > > +{ > > + DEFINE_DELAYED_CALL(done); > > + const char *buf; > > + struct folio *folio; > > + struct btrfs_inode *inode; > > + int ret = 0; > > + > > + inode = btrfs_iget(ino, root); > > + if (IS_ERR(inode)) > > + return PTR_ERR(inode); > > + > > + folio = read_mapping_folio(inode->vfs_inode.i_mapping, 0, NULL); > > + if (IS_ERR(folio)) { > > + iput(&inode->vfs_inode); > > + return PTR_ERR(folio); > > + } > > + > > + buf = fscrypt_get_symlink(&inode->vfs_inode, folio_address(folio), > > + BTRFS_MAX_INLINE_DATA_SIZE(root->fs_info), > > + &done); > > + folio_put(folio); > > + iput(&inode->vfs_inode); > > + > > + if (IS_ERR(buf)) > > + return PTR_ERR(buf); > > + > > + ret = fs_path_add(dest, buf, strlen(buf)); > > + do_delayed_call(&done); > > + return ret; > > +} > > + > > + > > +static int read_symlink(struct btrfs_root *root, u64 ino, > > + struct fs_path *dest) > > +{ > > + if (btrfs_fs_incompat(root->fs_info, ENCRYPT)) > > + return read_symlink_encrypted(root, ino, dest); > > + return read_symlink_unencrypted(root, ino, dest); > > +} > > This just assumes that all the symlinks on the filesystem are encrypted, > without checking the actual encrypt flag in the inode. > > Of course, looking at the Sashiko review for this patch, it already > found this, as well as a use-after-free. > > I don't know why I'm even reviewing this.
This is unrelated to fscrypt; it is internal to btrfs. Btrfs encryption is experimental and under development. Not all features are ready. For now, btrfs send is not implemented or supported and it returns EINVAL with an error message in the log before the code even reaches this point. So far read_symlink() is never called on encrypted FS. Yes, it can be improved, but it was not a priority right now. I am really grateful for your insight as I am not familiar with all the fscrypt internals. And don't get me wrong, for the next version I'm also addressing the points Sashiko raised. I am sure we can all work together to get btrfs encryption into a usable state. --nX > - Eric

