已合并
CVE修复: kernel_linux_6.6 master (3 个安全补丁) - 2026-05-19 #381
wanghao794创建于 5月19日
CVE修复: kernel_linux_6.6 master (3 个安全补丁) - 2026-05-19 #381
已合并
共 6 个文件变更+74-7
| @@ -1022,7 +1022,8 @@ static void fbcon_init(struct vc_data *vc, bool init) | |||
| 1022 | return; | 1022 | return; |
| 1023 | 1023 | ||
| 1024 | if (!info->fbcon_par) | 1024 | if (!info->fbcon_par) |
| 1025 | - con2fb_acquire_newinfo(vc, info, vc->vc_num); | 1025 | + if (con2fb_acquire_newinfo(vc, info, vc->vc_num)) |
| 1026 | + return; | ||
| 1026 | 1027 | ||
| 1027 | /* If we are not the first console on this | 1028 | /* If we are not the first console on this |
| 1028 | fb, copy the font from that console */ | 1029 | fb, copy the font from that console */ |
| @@ -4001,6 +4001,25 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file, | |||
| 4001 | goto out; | 4001 | goto out; |
| 4002 | } | 4002 | } |
| 4003 | 4003 | ||
| 4004 | + received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, | ||
| 4005 | + BTRFS_UUID_SIZE); | ||
| 4006 | + | ||
| 4007 | + /* | ||
| 4008 | + * Before we attempt to add the new received uuid, check if we have room | ||
| 4009 | + * for it in case there's already an item. If the size of the existing | ||
| 4010 | + * item plus this root's ID (u64) exceeds the maximum item size, we can | ||
| 4011 | + * return here without the need to abort a transaction. If we don't do | ||
| 4012 | + * this check, the btrfs_uuid_tree_add() call below would fail with | ||
| 4013 | + * -EOVERFLOW and result in a transaction abort. Malicious users could | ||
| 4014 | + * exploit this to turn the fs into RO mode. | ||
| 4015 | + */ | ||
| 4016 | + if (received_uuid_changed && !btrfs_is_empty_uuid(sa->uuid)) { | ||
| 4017 | + ret = btrfs_uuid_tree_check_overflow(fs_info, sa->uuid, | ||
| 4018 | + BTRFS_UUID_KEY_RECEIVED_SUBVOL); | ||
| 4019 | + if (ret < 0) | ||
| 4020 | + goto out; | ||
| 4021 | + } | ||
| 4022 | + | ||
| 4004 | /* | 4023 | /* |
| 4005 | * 1 - root item | 4024 | * 1 - root item |
| 4006 | * 2 - uuid items (received uuid + subvol uuid) | 4025 | * 2 - uuid items (received uuid + subvol uuid) |
| @@ -4016,8 +4035,6 @@ static long _btrfs_ioctl_set_received_subvol(struct file *file, | |||
| 4016 | sa->rtime.sec = ct.tv_sec; | 4035 | sa->rtime.sec = ct.tv_sec; |
| 4017 | sa->rtime.nsec = ct.tv_nsec; | 4036 | sa->rtime.nsec = ct.tv_nsec; |
| 4018 | 4037 | ||
| 4019 | - received_uuid_changed = memcmp(root_item->received_uuid, sa->uuid, | ||
| 4020 | - BTRFS_UUID_SIZE); | ||
| 4021 | if (received_uuid_changed && | 4038 | if (received_uuid_changed && |
| 4022 | !btrfs_is_empty_uuid(root_item->received_uuid)) { | 4039 | !btrfs_is_empty_uuid(root_item->received_uuid)) { |
| 4023 | ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid, | 4040 | ret = btrfs_uuid_tree_remove(trans, root_item->received_uuid, |
| @@ -228,6 +228,49 @@ int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, | |||
| 228 | return ret; | 228 | return ret; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | +/* | ||
| 232 | + * Check if we can add one root ID to a UUID key. | ||
| 233 | + * If the key does not yet exists, we can, otherwise only if extended item does | ||
| 234 | + * not exceeds the maximum item size permitted by the leaf size. | ||
| 235 | + * | ||
| 236 | + * Returns 0 on success, negative value on error. | ||
| 237 | + */ | ||
| 238 | +int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, | ||
| 239 | + u8 *uuid, u8 type) | ||
| 240 | +{ | ||
| 241 | + struct btrfs_path *path; | ||
| 242 | + int ret; | ||
| 243 | + u32 item_size; | ||
| 244 | + struct btrfs_key key; | ||
| 245 | + | ||
| 246 | + if (WARN_ON_ONCE(!fs_info->uuid_root)) | ||
| 247 | + return -EINVAL; | ||
| 248 | + | ||
| 249 | + path = btrfs_alloc_path(); | ||
| 250 | + if (!path) | ||
| 251 | + return -ENOMEM; | ||
| 252 | + | ||
| 253 | + btrfs_uuid_to_key(uuid, type, &key); | ||
| 254 | + ret = btrfs_search_slot(NULL, fs_info->uuid_root, &key, path, 0, 0); | ||
| 255 | + if (ret < 0) { | ||
| 256 | + btrfs_free_path(path); | ||
| 257 | + return ret; | ||
| 258 | + } | ||
| 259 | + if (ret > 0) { | ||
| 260 | + btrfs_free_path(path); | ||
| 261 | + return 0; | ||
| 262 | + } | ||
| 263 | + | ||
| 264 | + item_size = btrfs_item_size(path->nodes[0], path->slots[0]); | ||
| 265 | + btrfs_free_path(path); | ||
| 266 | + | ||
| 267 | + if (sizeof(struct btrfs_item) + item_size + sizeof(u64) > | ||
| 268 | + BTRFS_LEAF_DATA_SIZE(fs_info)) | ||
| 269 | + return -EOVERFLOW; | ||
| 270 | + | ||
| 271 | + return 0; | ||
| 272 | +} | ||
| 273 | + | ||
| 231 | static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type, | 274 | static int btrfs_uuid_iter_rem(struct btrfs_root *uuid_root, u8 *uuid, u8 type, |
| 232 | u64 subid) | 275 | u64 subid) |
| 233 | { | 276 | { |
| @@ -7,6 +7,8 @@ int btrfs_uuid_tree_add(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, | |||
| 7 | u64 subid); | 7 | u64 subid); |
| 8 | int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, | 8 | int btrfs_uuid_tree_remove(struct btrfs_trans_handle *trans, u8 *uuid, u8 type, |
| 9 | u64 subid); | 9 | u64 subid); |
| 10 | +int btrfs_uuid_tree_check_overflow(struct btrfs_fs_info *fs_info, | ||
| 11 | + u8 *uuid, u8 type); | ||
| 10 | int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info); | 12 | int btrfs_uuid_tree_iterate(struct btrfs_fs_info *fs_info); |
| 11 | 13 | ||
| 12 | 14 | ||
| @@ -789,12 +789,15 @@ TRACE_EVENT(btrfs_sync_file, | |||
| 789 | ), | 789 | ), |
| 790 | 790 | ||
| 791 | TP_fast_assign( | 791 | TP_fast_assign( |
| 792 | - const struct dentry *dentry = file->f_path.dentry; | 792 | + struct dentry *dentry = file_dentry(file); |
| 793 | - const struct inode *inode = d_inode(dentry); | 793 | + struct inode *inode = file_inode(file); |
| 794 | + struct dentry *parent = dget_parent(dentry); | ||
| 795 | + struct inode *parent_inode = d_inode(parent); | ||
| 794 | 796 | ||
| 795 | - TP_fast_assign_fsid(btrfs_sb(file->f_path.dentry->d_sb)); | 797 | + dput(parent); |
| 798 | + TP_fast_assign_fsid(btrfs_sb(inode->i_sb)); | ||
| 796 | __entry->ino = btrfs_ino(BTRFS_I(inode)); | 799 | __entry->ino = btrfs_ino(BTRFS_I(inode)); |
| 797 | - __entry->parent = btrfs_ino(BTRFS_I(d_inode(dentry->d_parent))); | 800 | + __entry->parent = btrfs_ino(BTRFS_I(parent_inode)); |
| 798 | __entry->datasync = datasync; | 801 | __entry->datasync = datasync; |
| 799 | __entry->root_objectid = | 802 | __entry->root_objectid = |
| 800 | BTRFS_I(inode)->root->root_key.objectid; | 803 | BTRFS_I(inode)->root->root_key.objectid; |
| @@ -1185,6 +1185,7 @@ static __always_inline bool free_pages_prepare(struct page *page, | |||
| 1185 | 1185 | ||
| 1186 | page_cpupid_reset_last(page); | 1186 | page_cpupid_reset_last(page); |
| 1187 | page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; | 1187 | page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP; |
| 1188 | + page->private = 0; | ||
| 1188 | reset_page_owner(page, order); | 1189 | reset_page_owner(page, order); |
| 1189 | page_table_check_free(page, order); | 1190 | page_table_check_free(page, order); |
| 1190 | 1191 | ||
已提供测试报告