Commit ab3c5c18 authored by Sweet Tea Dorminy's avatar Sweet Tea Dorminy Committed by David Sterba

btrfs: setup qstr from dentrys using fscrypt helper

Most places where we get a struct qstr, we are doing so from a dentry.
With fscrypt, the dentry's name may be encrypted on-disk, so fscrypt
provides a helper to convert a dentry name to the appropriate disk name
if necessary. Convert each of the dentry name accesses to use
fscrypt_setup_filename(), then convert the resulting fscrypt_name back
to an unencrypted qstr. This does not work for nokey names, but the
specific locations that could spawn nokey names are noted.

At present, since there are no encrypted directories, nothing goes down
the filename encryption paths.
Signed-off-by: default avatarSweet Tea Dorminy <sweettea-kernel@dorminy.me>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent e43eec81
......@@ -28,6 +28,7 @@
#include <linux/refcount.h>
#include <linux/crc32c.h>
#include <linux/iomap.h>
#include <linux/fscrypt.h>
#include "extent-io-tree.h"
#include "extent_io.h"
#include "extent_map.h"
......@@ -1674,6 +1675,8 @@ struct btrfs_new_inode_args {
*/
struct posix_acl *default_acl;
struct posix_acl *acl;
struct fscrypt_name fname;
struct qstr name;
};
int btrfs_new_inode_prepare(struct btrfs_new_inode_args *args,
unsigned int *trans_num_items);
......
This diff is collapsed.
......@@ -6,6 +6,7 @@
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/sched/mm.h>
#include <linux/writeback.h>
#include <linux/pagemap.h>
#include <linux/blkdev.h>
......@@ -1611,10 +1612,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
struct btrfs_root *root = pending->root;
struct btrfs_root *parent_root;
struct btrfs_block_rsv *rsv;
struct inode *parent_inode;
struct inode *parent_inode = pending->dir;
struct btrfs_path *path;
struct btrfs_dir_item *dir_item;
struct dentry *dentry;
struct extent_buffer *tmp;
struct extent_buffer *old;
struct timespec64 cur_time;
......@@ -1623,6 +1623,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
u64 index = 0;
u64 objectid;
u64 root_flags;
unsigned int nofs_flags;
struct fscrypt_name fname;
struct qstr name;
ASSERT(pending->path);
path = pending->path;
......@@ -1630,9 +1633,23 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
ASSERT(pending->root_item);
new_root_item = pending->root_item;
/*
* We're inside a transaction and must make sure that any potential
* allocations with GFP_KERNEL in fscrypt won't recurse back to
* filesystem.
*/
nofs_flags = memalloc_nofs_save();
pending->error = fscrypt_setup_filename(parent_inode,
&pending->dentry->d_name, 0,
&fname);
memalloc_nofs_restore(nofs_flags);
if (pending->error)
goto free_pending;
name = (struct qstr)FSTR_TO_QSTR(&fname.disk_name);
pending->error = btrfs_get_free_objectid(tree_root, &objectid);
if (pending->error)
goto no_free_objectid;
goto free_fname;
/*
* Make qgroup to skip current new snapshot's qgroupid, as it is
......@@ -1661,8 +1678,6 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
trace_btrfs_space_reservation(fs_info, "transaction",
trans->transid,
trans->bytes_reserved, 1);
dentry = pending->dentry;
parent_inode = pending->dir;
parent_root = BTRFS_I(parent_inode)->root;
ret = record_root_in_trans(trans, parent_root, 0);
if (ret)
......@@ -1678,7 +1693,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
/* check if there is a file/dir which has the same name. */
dir_item = btrfs_lookup_dir_item(NULL, parent_root, path,
btrfs_ino(BTRFS_I(parent_inode)),
&dentry->d_name, 0);
&name, 0);
if (dir_item != NULL && !IS_ERR(dir_item)) {
pending->error = -EEXIST;
goto dir_item_existed;
......@@ -1773,7 +1788,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
ret = btrfs_add_root_ref(trans, objectid,
parent_root->root_key.objectid,
btrfs_ino(BTRFS_I(parent_inode)), index,
&dentry->d_name);
&name);
if (ret) {
btrfs_abort_transaction(trans, ret);
goto fail;
......@@ -1805,9 +1820,8 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
if (ret < 0)
goto fail;
ret = btrfs_insert_dir_item(trans, &dentry->d_name,
BTRFS_I(parent_inode), &key, BTRFS_FT_DIR,
index);
ret = btrfs_insert_dir_item(trans, &name, BTRFS_I(parent_inode), &key,
BTRFS_FT_DIR, index);
/* We have check then name at the beginning, so it is impossible. */
BUG_ON(ret == -EEXIST || ret == -EOVERFLOW);
if (ret) {
......@@ -1816,7 +1830,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
}
btrfs_i_size_write(BTRFS_I(parent_inode), parent_inode->i_size +
dentry->d_name.len * 2);
name.len * 2);
parent_inode->i_mtime = current_time(parent_inode);
parent_inode->i_ctime = parent_inode->i_mtime;
ret = btrfs_update_inode_fallback(trans, parent_root, BTRFS_I(parent_inode));
......@@ -1848,7 +1862,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
trans->bytes_reserved = 0;
clear_skip_qgroup:
btrfs_clear_skip_qgroup(trans);
no_free_objectid:
free_fname:
fscrypt_free_filename(&fname);
free_pending:
kfree(new_root_item);
pending->root_item = NULL;
btrfs_free_path(path);
......
......@@ -7446,9 +7446,16 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
if (old_dir && old_dir->logged_trans == trans->transid) {
struct btrfs_root *log = old_dir->root->log_root;
struct btrfs_path *path;
struct fscrypt_name fname;
struct qstr name;
ASSERT(old_dir_index >= BTRFS_DIR_START_INDEX);
ret = fscrypt_setup_filename(&old_dir->vfs_inode,
&old_dentry->d_name, 0, &fname);
if (ret)
goto out;
name = (struct qstr)FSTR_TO_QSTR(&fname.disk_name);
/*
* We have two inodes to update in the log, the old directory and
* the inode that got renamed, so we must pin the log to prevent
......@@ -7468,6 +7475,7 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
path = btrfs_alloc_path();
if (!path) {
ret = -ENOMEM;
fscrypt_free_filename(&fname);
goto out;
}
......@@ -7483,7 +7491,7 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
*/
mutex_lock(&old_dir->log_mutex);
ret = del_logged_dentry(trans, log, path, btrfs_ino(old_dir),
&old_dentry->d_name, old_dir_index);
&name, old_dir_index);
if (ret > 0) {
/*
* The dentry does not exist in the log, so record its
......@@ -7497,6 +7505,7 @@ void btrfs_log_new_name(struct btrfs_trans_handle *trans,
mutex_unlock(&old_dir->log_mutex);
btrfs_free_path(path);
fscrypt_free_filename(&fname);
if (ret < 0)
goto out;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment