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. - Eric

