mirror of
https://github.com/torvalds/linux.git
synced 2024-11-01 04:53:36 +01:00
for-6.12-tag
-----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEE8rQSAMVO+zA4DBdWxWXV+ddtWDsFAmbxUdkACgkQxWXV+ddt WDtAVQ//SCg5XtExxtol1emzZ+AGQjwRnRfUPo/x32h9SmaynaHa/sLsG2EwePKs 1lrkW8gEx3NF1bfeCubhoVX2eAo/1rwGqtPEbweE7XaYtmSnxT8jXeH2fQcMwQMc PkYfnCMIOdJzwoVS8wS3kLmuDep+9DJrbeI9oN5tUgugkTTbW7g576uv/SXjp46D Dl4b1uvVOCowBbY2Bz1pg0fQpBzJcLzvynGElSi85uoQ520JuA8PP/3Pszg8BTxm 6MO99kF0MhVSBnKSvmlIgxmlnGhlW/AlZakxywRYYKsiSM/eCWHpyUV0p4mMcpWW QM8yeJcAhugTDIV3VdRpGx4NcJSo1PPaXxRrMr/vnnuOPF4VQ2gSw+S4p44YCsML VpyNJIjeXNO86A6feQybxwczMzdpkc5UzdfJ+l3CDSxcGiQGRU3WWPIHjte90e38 ZNjXknc96EwOmxsx8ojGlfi7Lh9yHklMGslxI64488PTa+2RRGITUSziAla29nrd E4U6bh+bLeh2a11u+OjvSqIjdDfoJZD40Abnqe6DVA9pboPaLvf8vAVZa1FOJxsI oVJgkdhEBGbn26KqlghlnbkYBdjuGxtBoyuCvUAI8ybOTVnp423d+JYXkZOnSq9A EdL3UGII4LWQ71p+QxF3tm5nuKfbulyibfoBNj57zk0hM2OVNdg= =wGXc -----END PGP SIGNATURE----- Merge tag 'for-6.12-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux Pull btrfs fixes from David Sterba: - fix dangling pointer to rb-tree of defragmented inodes after cleanup - a followup fix to handle concurrent lseek on the same fd that could leak memory under some conditions - fix wrong root id reported in tree checker when verifying dref * tag 'for-6.12-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux: btrfs: fix use-after-free on rbtree that tracks inodes for auto defrag btrfs: tree-checker: fix the wrong output of data backref objectid btrfs: fix race setting file private on concurrent lseek using same fd
This commit is contained in:
commit
a1fb2fcbb6
5 changed files with 37 additions and 4 deletions
|
@ -152,6 +152,7 @@ struct btrfs_inode {
|
|||
* logged_trans), to access/update delalloc_bytes, new_delalloc_bytes,
|
||||
* defrag_bytes, disk_i_size, outstanding_extents, csum_bytes and to
|
||||
* update the VFS' inode number of bytes used.
|
||||
* Also protects setting struct file::private_data.
|
||||
*/
|
||||
spinlock_t lock;
|
||||
|
||||
|
|
|
@ -463,6 +463,8 @@ struct btrfs_file_private {
|
|||
void *filldir_buf;
|
||||
u64 last_index;
|
||||
struct extent_state *llseek_cached_state;
|
||||
/* Task that allocated this structure. */
|
||||
struct task_struct *owner_task;
|
||||
};
|
||||
|
||||
static inline u32 BTRFS_LEAF_DATA_SIZE(const struct btrfs_fs_info *info)
|
||||
|
|
|
@ -213,6 +213,8 @@ void btrfs_cleanup_defrag_inodes(struct btrfs_fs_info *fs_info)
|
|||
&fs_info->defrag_inodes, rb_node)
|
||||
kmem_cache_free(btrfs_inode_defrag_cachep, defrag);
|
||||
|
||||
fs_info->defrag_inodes = RB_ROOT;
|
||||
|
||||
spin_unlock(&fs_info->defrag_inodes_lock);
|
||||
}
|
||||
|
||||
|
|
|
@ -3485,7 +3485,7 @@ static bool find_desired_extent_in_hole(struct btrfs_inode *inode, int whence,
|
|||
static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
|
||||
{
|
||||
struct btrfs_inode *inode = BTRFS_I(file->f_mapping->host);
|
||||
struct btrfs_file_private *private = file->private_data;
|
||||
struct btrfs_file_private *private;
|
||||
struct btrfs_fs_info *fs_info = inode->root->fs_info;
|
||||
struct extent_state *cached_state = NULL;
|
||||
struct extent_state **delalloc_cached_state;
|
||||
|
@ -3513,7 +3513,19 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
|
|||
inode_get_bytes(&inode->vfs_inode) == i_size)
|
||||
return i_size;
|
||||
|
||||
if (!private) {
|
||||
spin_lock(&inode->lock);
|
||||
private = file->private_data;
|
||||
spin_unlock(&inode->lock);
|
||||
|
||||
if (private && private->owner_task != current) {
|
||||
/*
|
||||
* Not allocated by us, don't use it as its cached state is used
|
||||
* by the task that allocated it and we don't want neither to
|
||||
* mess with it nor get incorrect results because it reflects an
|
||||
* invalid state for the current task.
|
||||
*/
|
||||
private = NULL;
|
||||
} else if (!private) {
|
||||
private = kzalloc(sizeof(*private), GFP_KERNEL);
|
||||
/*
|
||||
* No worries if memory allocation failed.
|
||||
|
@ -3521,7 +3533,23 @@ static loff_t find_desired_extent(struct file *file, loff_t offset, int whence)
|
|||
* lseek SEEK_HOLE/DATA calls to a file when there's delalloc,
|
||||
* so everything will still be correct.
|
||||
*/
|
||||
file->private_data = private;
|
||||
if (private) {
|
||||
bool free = false;
|
||||
|
||||
private->owner_task = current;
|
||||
|
||||
spin_lock(&inode->lock);
|
||||
if (file->private_data)
|
||||
free = true;
|
||||
else
|
||||
file->private_data = private;
|
||||
spin_unlock(&inode->lock);
|
||||
|
||||
if (free) {
|
||||
kfree(private);
|
||||
private = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (private)
|
||||
|
|
|
@ -1517,7 +1517,7 @@ static int check_extent_item(struct extent_buffer *leaf,
|
|||
dref_objectid > BTRFS_LAST_FREE_OBJECTID)) {
|
||||
extent_err(leaf, slot,
|
||||
"invalid data ref objectid value %llu",
|
||||
dref_root);
|
||||
dref_objectid);
|
||||
return -EUCLEAN;
|
||||
}
|
||||
if (unlikely(!IS_ALIGNED(dref_offset,
|
||||
|
|
Loading…
Reference in a new issue