已合并
CVE修复: kernel_linux_6.6 master (20 个有效安全补丁) - 2026-05-21 #383
Provii创建于 5月21日
CVE修复: kernel_linux_6.6 master (20 个有效安全补丁) - 2026-05-21 #383
已合并
共 28 个文件变更+216-80
| @@ -190,6 +190,8 @@ static long media_request_ioctl_reinit(struct media_request *req) | |||
| 190 | struct media_device *mdev = req->mdev; | 190 | struct media_device *mdev = req->mdev; |
| 191 | unsigned long flags; | 191 | unsigned long flags; |
| 192 | 192 | ||
| 193 | + mutex_lock(&mdev->req_queue_mutex); | ||
| 194 | + | ||
| 193 | spin_lock_irqsave(&req->lock, flags); | 195 | spin_lock_irqsave(&req->lock, flags); |
| 194 | if (req->state != MEDIA_REQUEST_STATE_IDLE && | 196 | if (req->state != MEDIA_REQUEST_STATE_IDLE && |
| 195 | req->state != MEDIA_REQUEST_STATE_COMPLETE) { | 197 | req->state != MEDIA_REQUEST_STATE_COMPLETE) { |
| @@ -197,6 +199,7 @@ static long media_request_ioctl_reinit(struct media_request *req) | |||
| 197 | "request: %s not in idle or complete state, cannot reinit\n", | 199 | "request: %s not in idle or complete state, cannot reinit\n", |
| 198 | req->debug_str); | 200 | req->debug_str); |
| 199 | spin_unlock_irqrestore(&req->lock, flags); | 201 | spin_unlock_irqrestore(&req->lock, flags); |
| 202 | + mutex_unlock(&mdev->req_queue_mutex); | ||
| 200 | return -EBUSY; | 203 | return -EBUSY; |
| 201 | } | 204 | } |
| 202 | if (req->access_count) { | 205 | if (req->access_count) { |
| @@ -204,6 +207,7 @@ static long media_request_ioctl_reinit(struct media_request *req) | |||
| 204 | "request: %s is being accessed, cannot reinit\n", | 207 | "request: %s is being accessed, cannot reinit\n", |
| 205 | req->debug_str); | 208 | req->debug_str); |
| 206 | spin_unlock_irqrestore(&req->lock, flags); | 209 | spin_unlock_irqrestore(&req->lock, flags); |
| 210 | + mutex_unlock(&mdev->req_queue_mutex); | ||
| 207 | return -EBUSY; | 211 | return -EBUSY; |
| 208 | } | 212 | } |
| 209 | req->state = MEDIA_REQUEST_STATE_CLEANING; | 213 | req->state = MEDIA_REQUEST_STATE_CLEANING; |
| @@ -214,6 +218,7 @@ static long media_request_ioctl_reinit(struct media_request *req) | |||
| 214 | spin_lock_irqsave(&req->lock, flags); | 218 | spin_lock_irqsave(&req->lock, flags); |
| 215 | req->state = MEDIA_REQUEST_STATE_IDLE; | 219 | req->state = MEDIA_REQUEST_STATE_IDLE; |
| 216 | spin_unlock_irqrestore(&req->lock, flags); | 220 | spin_unlock_irqrestore(&req->lock, flags); |
| 221 | + mutex_unlock(&mdev->req_queue_mutex); | ||
| 217 | 222 | ||
| 218 | return 0; | 223 | return 0; |
| 219 | } | 224 | } |
| @@ -2998,13 +2998,14 @@ static long __video_do_ioctl(struct file *file, | |||
| 2998 | vfh = file->private_data; | 2998 | vfh = file->private_data; |
| 2999 | 2999 | ||
| 3000 | /* | 3000 | /* |
| 3001 | - * We need to serialize streamon/off with queueing new requests. | 3001 | + * We need to serialize streamon/off/reqbufs with queueing new requests. |
| 3002 | * These ioctls may trigger the cancellation of a streaming | 3002 | * These ioctls may trigger the cancellation of a streaming |
| 3003 | * operation, and that should not be mixed with queueing a new | 3003 | * operation, and that should not be mixed with queueing a new |
| 3004 | * request at the same time. | 3004 | * request at the same time. |
| 3005 | */ | 3005 | */ |
| 3006 | if (v4l2_device_supports_requests(vfd->v4l2_dev) && | 3006 | if (v4l2_device_supports_requests(vfd->v4l2_dev) && |
| 3007 | - (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF)) { | 3007 | + (cmd == VIDIOC_STREAMON || cmd == VIDIOC_STREAMOFF || |
| 3008 | + cmd == VIDIOC_REQBUFS)) { | ||
| 3008 | req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex; | 3009 | req_queue_lock = &vfd->v4l2_dev->mdev->req_queue_mutex; |
| 3009 | 3010 | ||
| 3010 | if (mutex_lock_interruptible(req_queue_lock)) | 3011 | if (mutex_lock_interruptible(req_queue_lock)) |
| @@ -1583,8 +1583,6 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, | |||
| 1583 | goto error; | 1583 | goto error; |
| 1584 | 1584 | ||
| 1585 | phy_resume(phydev); | 1585 | phy_resume(phydev); |
| 1586 | - if (!phydev->is_on_sfp_module) | ||
| 1587 | - phy_led_triggers_register(phydev); | ||
| 1588 | 1586 | ||
| 1589 | /** | 1587 | /** |
| 1590 | * If the external phy used by current mac interface is managed by | 1588 | * If the external phy used by current mac interface is managed by |
| @@ -1855,9 +1853,6 @@ void phy_detach(struct phy_device *phydev) | |||
| 1855 | } | 1853 | } |
| 1856 | phydev->phylink = NULL; | 1854 | phydev->phylink = NULL; |
| 1857 | 1855 | ||
| 1858 | - if (!phydev->is_on_sfp_module) | ||
| 1859 | - phy_led_triggers_unregister(phydev); | ||
| 1860 | - | ||
| 1861 | if (phydev->mdio.dev.driver) | 1856 | if (phydev->mdio.dev.driver) |
| 1862 | module_put(phydev->mdio.dev.driver->owner); | 1857 | module_put(phydev->mdio.dev.driver->owner); |
| 1863 | 1858 | ||
| @@ -3401,17 +3396,28 @@ static int phy_probe(struct device *dev) | |||
| 3401 | /* Set the state to READY by default */ | 3396 | /* Set the state to READY by default */ |
| 3402 | phydev->state = PHY_READY; | 3397 | phydev->state = PHY_READY; |
| 3403 | 3398 | ||
| 3399 | + /* Register the PHY LED triggers */ | ||
| 3400 | + if (!phydev->is_on_sfp_module) | ||
| 3401 | + phy_led_triggers_register(phydev); | ||
| 3402 | + | ||
| 3404 | /* Get the LEDs from the device tree, and instantiate standard | 3403 | /* Get the LEDs from the device tree, and instantiate standard |
| 3405 | * LEDs for them. | 3404 | * LEDs for them. |
| 3406 | */ | 3405 | */ |
| 3407 | if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && | 3406 | if (IS_ENABLED(CONFIG_PHYLIB_LEDS) && !phy_driver_is_genphy(phydev) && |
| 3408 | - !phy_driver_is_genphy_10g(phydev)) | 3407 | + !phy_driver_is_genphy_10g(phydev)) { |
| 3409 | err = of_phy_leds(phydev); | 3408 | err = of_phy_leds(phydev); |
| 3409 | + if (err) | ||
| 3410 | + goto out; | ||
| 3411 | + } | ||
| 3412 | + | ||
| 3413 | + return 0; | ||
| 3410 | 3414 | ||
| 3411 | out: | 3415 | out: |
| 3416 | + if (!phydev->is_on_sfp_module) | ||
| 3417 | + phy_led_triggers_unregister(phydev); | ||
| 3418 | + | ||
| 3412 | /* Re-assert the reset signal on error */ | 3419 | /* Re-assert the reset signal on error */ |
| 3413 | - if (err) | 3420 | + phy_device_reset(phydev, 1); |
| 3414 | - phy_device_reset(phydev, 1); | ||
| 3415 | 3421 | ||
| 3416 | return err; | 3422 | return err; |
| 3417 | } | 3423 | } |
| @@ -3426,6 +3432,9 @@ static int phy_remove(struct device *dev) | |||
| 3426 | !phy_driver_is_genphy_10g(phydev)) | 3432 | !phy_driver_is_genphy_10g(phydev)) |
| 3427 | phy_leds_unregister(phydev); | 3433 | phy_leds_unregister(phydev); |
| 3428 | 3434 | ||
| 3435 | + if (!phydev->is_on_sfp_module) | ||
| 3436 | + phy_led_triggers_unregister(phydev); | ||
| 3437 | + | ||
| 3429 | phydev->state = PHY_DOWN; | 3438 | phydev->state = PHY_DOWN; |
| 3430 | 3439 | ||
| 3431 | sfp_bus_del_upstream(phydev->sfp_bus); | 3440 | sfp_bus_del_upstream(phydev->sfp_bus); |
| @@ -1118,7 +1118,8 @@ static int nvme_poll(struct blk_mq_hw_ctx *hctx, struct io_comp_batch *iob) | |||
| 1118 | struct nvme_queue *nvmeq = hctx->driver_data; | 1118 | struct nvme_queue *nvmeq = hctx->driver_data; |
| 1119 | bool found; | 1119 | bool found; |
| 1120 | 1120 | ||
| 1121 | - if (!nvme_cqe_pending(nvmeq)) | 1121 | + if (!test_bit(NVMEQ_POLLED, &nvmeq->flags) || |
| 1122 | + !nvme_cqe_pending(nvmeq)) | ||
| 1122 | return 0; | 1123 | return 0; |
| 1123 | 1124 | ||
| 1124 | spin_lock(&nvmeq->cq_poll_lock); | 1125 | spin_lock(&nvmeq->cq_poll_lock); |
| @@ -1535,6 +1535,7 @@ struct ext4_sb_info { | |||
| 1535 | struct proc_dir_entry *s_proc; | 1535 | struct proc_dir_entry *s_proc; |
| 1536 | struct kobject s_kobj; | 1536 | struct kobject s_kobj; |
| 1537 | struct completion s_kobj_unregister; | 1537 | struct completion s_kobj_unregister; |
| 1538 | + struct mutex s_error_notify_mutex; /* protects sysfs_notify vs kobject_del */ | ||
| 1538 | struct super_block *s_sb; | 1539 | struct super_block *s_sb; |
| 1539 | struct buffer_head *s_mmp_bh; | 1540 | struct buffer_head *s_mmp_bh; |
| 1540 | 1541 | ||
| @@ -4358,9 +4358,13 @@ int ext4_ext_map_blocks(handle_t *handle, struct inode *inode, | |||
| 4358 | 4358 | ||
| 4359 | err = ext4_ext_insert_extent(handle, inode, &path, &newex, flags); | 4359 | err = ext4_ext_insert_extent(handle, inode, &path, &newex, flags); |
| 4360 | if (err) { | 4360 | if (err) { |
| 4361 | - if (allocated_clusters) { | 4361 | + /* |
| 4362 | + * Gracefully handle out of space conditions. If the filesystem | ||
| 4363 | + * is inconsistent, we'll just leak allocated blocks to avoid | ||
| 4364 | + * causing even more damage. | ||
| 4365 | + */ | ||
| 4366 | + if (allocated_clusters && (err == -EDQUOT || err == -ENOSPC)) { | ||
| 4362 | int fb_flags = 0; | 4367 | int fb_flags = 0; |
| 4363 | - | ||
| 4364 | /* | 4368 | /* |
| 4365 | * free data blocks we just allocated. | 4369 | * free data blocks we just allocated. |
| 4366 | * not a good idea to call discard here directly, | 4370 | * not a good idea to call discard here directly, |
| @@ -499,7 +499,15 @@ static int ext4_read_inline_folio(struct inode *inode, struct folio *folio) | |||
| 499 | goto out; | 499 | goto out; |
| 500 | 500 | ||
| 501 | len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); | 501 | len = min_t(size_t, ext4_get_inline_size(inode), i_size_read(inode)); |
| 502 | - BUG_ON(len > PAGE_SIZE); | 502 | + |
| 503 | + if (len > PAGE_SIZE) { | ||
| 504 | + ext4_error_inode(inode, __func__, __LINE__, 0, | ||
| 505 | + "inline size %zu exceeds PAGE_SIZE", len); | ||
| 506 | + ret = -EFSCORRUPTED; | ||
| 507 | + brelse(iloc.bh); | ||
| 508 | + goto out; | ||
| 509 | + } | ||
| 510 | + | ||
| 503 | kaddr = kmap_local_folio(folio, 0); | 511 | kaddr = kmap_local_folio(folio, 0); |
| 504 | ret = ext4_read_inline_data(inode, kaddr, len, &iloc); | 512 | ret = ext4_read_inline_data(inode, kaddr, len, &iloc); |
| 505 | flush_dcache_folio(folio); | 513 | flush_dcache_folio(folio); |
| @@ -5512,6 +5512,18 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry, | |||
| 5512 | if (attr->ia_size == inode->i_size) | 5512 | if (attr->ia_size == inode->i_size) |
| 5513 | inc_ivers = false; | 5513 | inc_ivers = false; |
| 5514 | 5514 | ||
| 5515 | + /* | ||
| 5516 | + * If file has inline data but new size exceeds inline capacity, | ||
| 5517 | + * convert to extent-based storage first to prevent inconsistent | ||
| 5518 | + * state (inline flag set but size exceeds inline capacity). | ||
| 5519 | + */ | ||
| 5520 | + if (ext4_has_inline_data(inode) && | ||
| 5521 | + attr->ia_size > EXT4_I(inode)->i_inline_size) { | ||
| 5522 | + error = ext4_convert_inline_data(inode); | ||
| 5523 | + if (error) | ||
| 5524 | + goto err_out; | ||
| 5525 | + } | ||
| 5526 | + | ||
| 5515 | if (shrink) { | 5527 | if (shrink) { |
| 5516 | if (ext4_should_order_data(inode)) { | 5528 | if (ext4_should_order_data(inode)) { |
| 5517 | error = ext4_begin_ordered_truncate(inode, | 5529 | error = ext4_begin_ordered_truncate(inode, |
| @@ -5335,6 +5335,7 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb) | |||
| 5335 | 5335 | ||
| 5336 | timer_setup(&sbi->s_err_report, print_daily_error_info, 0); | 5336 | timer_setup(&sbi->s_err_report, print_daily_error_info, 0); |
| 5337 | spin_lock_init(&sbi->s_error_lock); | 5337 | spin_lock_init(&sbi->s_error_lock); |
| 5338 | + mutex_init(&sbi->s_error_notify_mutex); | ||
| 5338 | INIT_WORK(&sbi->s_sb_upd_work, update_super_work); | 5339 | INIT_WORK(&sbi->s_sb_upd_work, update_super_work); |
| 5339 | 5340 | ||
| 5340 | err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed); | 5341 | err = ext4_group_desc_init(sb, es, logical_sb_block, &first_not_zeroed); |
| @@ -529,7 +529,10 @@ static const struct kobj_type ext4_feat_ktype = { | |||
| 529 | 529 | ||
| 530 | void ext4_notify_error_sysfs(struct ext4_sb_info *sbi) | 530 | void ext4_notify_error_sysfs(struct ext4_sb_info *sbi) |
| 531 | { | 531 | { |
| 532 | - sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); | 532 | + mutex_lock(&sbi->s_error_notify_mutex); |
| 533 | + if (sbi->s_kobj.state_in_sysfs) | ||
| 534 | + sysfs_notify(&sbi->s_kobj, NULL, "errors_count"); | ||
| 535 | + mutex_unlock(&sbi->s_error_notify_mutex); | ||
| 533 | } | 536 | } |
| 534 | 537 | ||
| 535 | static struct kobject *ext4_root; | 538 | static struct kobject *ext4_root; |
| @@ -542,8 +545,10 @@ int ext4_register_sysfs(struct super_block *sb) | |||
| 542 | int err; | 545 | int err; |
| 543 | 546 | ||
| 544 | init_completion(&sbi->s_kobj_unregister); | 547 | init_completion(&sbi->s_kobj_unregister); |
| 548 | + mutex_lock(&sbi->s_error_notify_mutex); | ||
| 545 | err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, ext4_root, | 549 | err = kobject_init_and_add(&sbi->s_kobj, &ext4_sb_ktype, ext4_root, |
| 546 | "%s", sb->s_id); | 550 | "%s", sb->s_id); |
| 551 | + mutex_unlock(&sbi->s_error_notify_mutex); | ||
| 547 | if (err) { | 552 | if (err) { |
| 548 | kobject_put(&sbi->s_kobj); | 553 | kobject_put(&sbi->s_kobj); |
| 549 | wait_for_completion(&sbi->s_kobj_unregister); | 554 | wait_for_completion(&sbi->s_kobj_unregister); |
| @@ -576,7 +581,10 @@ void ext4_unregister_sysfs(struct super_block *sb) | |||
| 576 | 581 | ||
| 577 | if (sbi->s_proc) | 582 | if (sbi->s_proc) |
| 578 | remove_proc_subtree(sb->s_id, ext4_proc_root); | 583 | remove_proc_subtree(sb->s_id, ext4_proc_root); |
| 584 | + | ||
| 585 | + mutex_lock(&sbi->s_error_notify_mutex); | ||
| 579 | kobject_del(&sbi->s_kobj); | 586 | kobject_del(&sbi->s_kobj); |
| 587 | + mutex_unlock(&sbi->s_error_notify_mutex); | ||
| 580 | } | 588 | } |
| 581 | 589 | ||
| 582 | int __init ext4_init_sysfs(void) | 590 | int __init ext4_init_sysfs(void) |
| @@ -340,6 +340,9 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer, | |||
| 340 | if (unlikely(length < 0)) | 340 | if (unlikely(length < 0)) |
| 341 | return -EIO; | 341 | return -EIO; |
| 342 | 342 | ||
| 343 | + if (unlikely(*offset < 0 || *offset >= SQUASHFS_METADATA_SIZE)) | ||
| 344 | + return -EIO; | ||
| 345 | + | ||
| 343 | while (length) { | 346 | while (length) { |
| 344 | entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); | 347 | entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); |
| 345 | if (entry->error) { | 348 | if (entry->error) { |
| @@ -22,6 +22,7 @@ | |||
| 22 | #include "xfs_trans.h" | 22 | #include "xfs_trans.h" |
| 23 | #include "xfs_log.h" | 23 | #include "xfs_log.h" |
| 24 | #include "xfs_log_priv.h" | 24 | #include "xfs_log_priv.h" |
| 25 | +#include "xfs_trans_priv.h" | ||
| 25 | #include "xfs_buf_item.h" | 26 | #include "xfs_buf_item.h" |
| 26 | #include "xfs_quota.h" | 27 | #include "xfs_quota.h" |
| 27 | #include "xfs_dquot_item.h" | 28 | #include "xfs_dquot_item.h" |
| @@ -50,6 +50,7 @@ | |||
| 50 | #include <linux/tracepoint.h> | 50 | #include <linux/tracepoint.h> |
| 51 | 51 | ||
| 52 | struct xfs_agf; | 52 | struct xfs_agf; |
| 53 | +struct xfs_ail; | ||
| 53 | struct xfs_alloc_arg; | 54 | struct xfs_alloc_arg; |
| 54 | struct xfs_attr_list_context; | 55 | struct xfs_attr_list_context; |
| 55 | struct xfs_buf_log_item; | 56 | struct xfs_buf_log_item; |
| @@ -1332,14 +1333,41 @@ TRACE_EVENT(xfs_log_force, | |||
| 1332 | DEFINE_EVENT(xfs_log_item_class, name, \ | 1333 | DEFINE_EVENT(xfs_log_item_class, name, \ |
| 1333 | TP_PROTO(struct xfs_log_item *lip), \ | 1334 | TP_PROTO(struct xfs_log_item *lip), \ |
| 1334 | TP_ARGS(lip)) | 1335 | TP_ARGS(lip)) |
| 1335 | -DEFINE_LOG_ITEM_EVENT(xfs_ail_push); | ||
| 1336 | -DEFINE_LOG_ITEM_EVENT(xfs_ail_pinned); | ||
| 1337 | -DEFINE_LOG_ITEM_EVENT(xfs_ail_locked); | ||
| 1338 | -DEFINE_LOG_ITEM_EVENT(xfs_ail_flushing); | ||
| 1339 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark); | 1336 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_mark); |
| 1340 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip); | 1337 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_skip); |
| 1341 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin); | 1338 | DEFINE_LOG_ITEM_EVENT(xfs_cil_whiteout_unpin); |
| 1342 | 1339 | ||
| 1340 | +DECLARE_EVENT_CLASS(xfs_ail_push_class, | ||
| 1341 | + TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), | ||
| 1342 | + TP_ARGS(ailp, type, flags, lsn), | ||
| 1343 | + TP_STRUCT__entry( | ||
| 1344 | + __field(dev_t, dev) | ||
| 1345 | + __field(uint, type) | ||
| 1346 | + __field(unsigned long, flags) | ||
| 1347 | + __field(xfs_lsn_t, lsn) | ||
| 1348 | + ), | ||
| 1349 | + TP_fast_assign( | ||
| 1350 | + __entry->dev = ailp->ail_log->l_mp->m_super->s_dev; | ||
| 1351 | + __entry->type = type; | ||
| 1352 | + __entry->flags = flags; | ||
| 1353 | + __entry->lsn = lsn; | ||
| 1354 | + ), | ||
| 1355 | + TP_printk("dev %d:%d lsn %d/%d type %s flags %s", | ||
| 1356 | + MAJOR(__entry->dev), MINOR(__entry->dev), | ||
| 1357 | + CYCLE_LSN(__entry->lsn), BLOCK_LSN(__entry->lsn), | ||
| 1358 | + __print_symbolic(__entry->type, XFS_LI_TYPE_DESC), | ||
| 1359 | + __print_flags(__entry->flags, "|", XFS_LI_FLAGS)) | ||
| 1360 | +) | ||
| 1361 | + | ||
| 1362 | +#define DEFINE_AIL_PUSH_EVENT(name) \ | ||
| 1363 | +DEFINE_EVENT(xfs_ail_push_class, name, \ | ||
| 1364 | + TP_PROTO(struct xfs_ail *ailp, uint type, unsigned long flags, xfs_lsn_t lsn), \ | ||
| 1365 | + TP_ARGS(ailp, type, flags, lsn)) | ||
| 1366 | +DEFINE_AIL_PUSH_EVENT(xfs_ail_push); | ||
| 1367 | +DEFINE_AIL_PUSH_EVENT(xfs_ail_pinned); | ||
| 1368 | +DEFINE_AIL_PUSH_EVENT(xfs_ail_locked); | ||
| 1369 | +DEFINE_AIL_PUSH_EVENT(xfs_ail_flushing); | ||
| 1370 | + | ||
| 1343 | DECLARE_EVENT_CLASS(xfs_ail_class, | 1371 | DECLARE_EVENT_CLASS(xfs_ail_class, |
| 1344 | TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), | 1372 | TP_PROTO(struct xfs_log_item *lip, xfs_lsn_t old_lsn, xfs_lsn_t new_lsn), |
| 1345 | TP_ARGS(lip, old_lsn, new_lsn), | 1373 | TP_ARGS(lip, old_lsn, new_lsn), |
| @@ -389,6 +389,12 @@ xfsaild_resubmit_item( | |||
| 389 | return XFS_ITEM_SUCCESS; | 389 | return XFS_ITEM_SUCCESS; |
| 390 | } | 390 | } |
| 391 | 391 | ||
| 392 | +/* | ||
| 393 | + * Push a single log item from the AIL. | ||
| 394 | + * | ||
| 395 | + * @lip may have been released and freed by the time this function returns, | ||
| 396 | + * so callers must not dereference the log item afterwards. | ||
| 397 | + */ | ||
| 392 | static inline uint | 398 | static inline uint |
| 393 | xfsaild_push_item( | 399 | xfsaild_push_item( |
| 394 | struct xfs_ail *ailp, | 400 | struct xfs_ail *ailp, |
| @@ -476,20 +482,26 @@ xfsaild_push( | |||
| 476 | 482 | ||
| 477 | lsn = lip->li_lsn; | 483 | lsn = lip->li_lsn; |
| 478 | while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { | 484 | while ((XFS_LSN_CMP(lip->li_lsn, target) <= 0)) { |
| 479 | - int lock_result; | 485 | + int lock_result; |
| 486 | + uint type = lip->li_type; | ||
| 487 | + unsigned long flags = lip->li_flags; | ||
| 488 | + xfs_lsn_t item_lsn = lip->li_lsn; | ||
| 480 | 489 | ||
| 481 | /* | 490 | /* |
| 482 | * Note that iop_push may unlock and reacquire the AIL lock. We | 491 | * Note that iop_push may unlock and reacquire the AIL lock. We |
| 483 | * rely on the AIL cursor implementation to be able to deal with | 492 | * rely on the AIL cursor implementation to be able to deal with |
| 484 | * the dropped lock. | 493 | * the dropped lock. |
| 494 | + * | ||
| 495 | + * The log item may have been freed by the push, so it must not | ||
| 496 | + * be accessed or dereferenced below this line. | ||
| 485 | */ | 497 | */ |
| 486 | lock_result = xfsaild_push_item(ailp, lip); | 498 | lock_result = xfsaild_push_item(ailp, lip); |
| 487 | switch (lock_result) { | 499 | switch (lock_result) { |
| 488 | case XFS_ITEM_SUCCESS: | 500 | case XFS_ITEM_SUCCESS: |
| 489 | XFS_STATS_INC(mp, xs_push_ail_success); | 501 | XFS_STATS_INC(mp, xs_push_ail_success); |
| 490 | - trace_xfs_ail_push(lip); | 502 | + trace_xfs_ail_push(ailp, type, flags, item_lsn); |
| 491 | 503 | ||
| 492 | - ailp->ail_last_pushed_lsn = lsn; | 504 | + ailp->ail_last_pushed_lsn = item_lsn; |
| 493 | break; | 505 | break; |
| 494 | 506 | ||
| 495 | case XFS_ITEM_FLUSHING: | 507 | case XFS_ITEM_FLUSHING: |
| @@ -505,22 +517,22 @@ xfsaild_push( | |||
| 505 | * AIL is being flushed. | 517 | * AIL is being flushed. |
| 506 | */ | 518 | */ |
| 507 | XFS_STATS_INC(mp, xs_push_ail_flushing); | 519 | XFS_STATS_INC(mp, xs_push_ail_flushing); |
| 508 | - trace_xfs_ail_flushing(lip); | 520 | + trace_xfs_ail_flushing(ailp, type, flags, item_lsn); |
| 509 | 521 | ||
| 510 | flushing++; | 522 | flushing++; |
| 511 | - ailp->ail_last_pushed_lsn = lsn; | 523 | + ailp->ail_last_pushed_lsn = item_lsn; |
| 512 | break; | 524 | break; |
| 513 | 525 | ||
| 514 | case XFS_ITEM_PINNED: | 526 | case XFS_ITEM_PINNED: |
| 515 | XFS_STATS_INC(mp, xs_push_ail_pinned); | 527 | XFS_STATS_INC(mp, xs_push_ail_pinned); |
| 516 | - trace_xfs_ail_pinned(lip); | 528 | + trace_xfs_ail_pinned(ailp, type, flags, item_lsn); |
| 517 | 529 | ||
| 518 | stuck++; | 530 | stuck++; |
| 519 | ailp->ail_log_flush++; | 531 | ailp->ail_log_flush++; |
| 520 | break; | 532 | break; |
| 521 | case XFS_ITEM_LOCKED: | 533 | case XFS_ITEM_LOCKED: |
| 522 | XFS_STATS_INC(mp, xs_push_ail_locked); | 534 | XFS_STATS_INC(mp, xs_push_ail_locked); |
| 523 | - trace_xfs_ail_locked(lip); | 535 | + trace_xfs_ail_locked(ailp, type, flags, item_lsn); |
| 524 | 536 | ||
| 525 | stuck++; | 537 | stuck++; |
| 526 | break; | 538 | break; |
| @@ -47,7 +47,7 @@ int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, | |||
| 47 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, | 47 | static inline int udp_sock_create6(struct net *net, struct udp_port_cfg *cfg, |
| 48 | struct socket **sockp) | 48 | struct socket **sockp) |
| 49 | { | 49 | { |
| 50 | - return 0; | 50 | + return -EPFNOSUPPORT; |
| 51 | } | 51 | } |
| 52 | #endif | 52 | #endif |
| 53 | 53 | ||
| @@ -4521,7 +4521,7 @@ static void __perf_event_read(void *info) | |||
| 4521 | struct perf_event *sub, *event = data->event; | 4521 | struct perf_event *sub, *event = data->event; |
| 4522 | struct perf_event_context *ctx = event->ctx; | 4522 | struct perf_event_context *ctx = event->ctx; |
| 4523 | struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context); | 4523 | struct perf_cpu_context *cpuctx = this_cpu_ptr(&perf_cpu_context); |
| 4524 | - struct pmu *pmu = event->pmu; | 4524 | + struct pmu *pmu; |
| 4525 | 4525 | ||
| 4526 | /* | 4526 | /* |
| 4527 | * If this is a task context, we need to check whether it is | 4527 | * If this is a task context, we need to check whether it is |
| @@ -4533,7 +4533,7 @@ static void __perf_event_read(void *info) | |||
| 4533 | if (ctx->task && cpuctx->task_ctx != ctx) | 4533 | if (ctx->task && cpuctx->task_ctx != ctx) |
| 4534 | return; | 4534 | return; |
| 4535 | 4535 | ||
| 4536 | - raw_spin_lock(&ctx->lock); | 4536 | + guard(raw_spinlock)(&ctx->lock); |
| 4537 | if (ctx->is_active & EVENT_TIME) { | 4537 | if (ctx->is_active & EVENT_TIME) { |
| 4538 | update_context_time(ctx); | 4538 | update_context_time(ctx); |
| 4539 | update_cgrp_time_from_event(event); | 4539 | update_cgrp_time_from_event(event); |
| @@ -4544,25 +4544,22 @@ static void __perf_event_read(void *info) | |||
| 4544 | perf_event_update_sibling_time(event); | 4544 | perf_event_update_sibling_time(event); |
| 4545 | 4545 | ||
| 4546 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 4546 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
| 4547 | - goto unlock; | 4547 | + return; |
| 4548 | 4548 | ||
| 4549 | if (!data->group) { | 4549 | if (!data->group) { |
| 4550 | - pmu->read(event); | 4550 | + perf_pmu_read(event); |
| 4551 | data->ret = 0; | 4551 | data->ret = 0; |
| 4552 | - goto unlock; | 4552 | + return; |
| 4553 | } | 4553 | } |
| 4554 | 4554 | ||
| 4555 | + pmu = event->pmu_ctx->pmu; | ||
| 4555 | pmu->start_txn(pmu, PERF_PMU_TXN_READ); | 4556 | pmu->start_txn(pmu, PERF_PMU_TXN_READ); |
| 4556 | 4557 | ||
| 4557 | - pmu->read(event); | 4558 | + perf_pmu_read(event); |
| 4558 | - | ||
| 4559 | for_each_sibling_event(sub, event) | 4559 | for_each_sibling_event(sub, event) |
| 4560 | perf_pmu_read(sub); | 4560 | perf_pmu_read(sub); |
| 4561 | - | ||
| 4562 | data->ret = pmu->commit_txn(pmu); | 4561 | data->ret = pmu->commit_txn(pmu); |
| 4563 | 4562 | ||
| 4564 | -unlock: | ||
| 4565 | - raw_spin_unlock(&ctx->lock); | ||
| 4566 | } | 4563 | } |
| 4567 | 4564 | ||
| 4568 | static inline u64 perf_event_count(struct perf_event *event) | 4565 | static inline u64 perf_event_count(struct perf_event *event) |
| @@ -13491,7 +13488,7 @@ inherit_event(struct perf_event *parent_event, | |||
| 13491 | get_ctx(child_ctx); | 13488 | get_ctx(child_ctx); |
| 13492 | child_event->ctx = child_ctx; | 13489 | child_event->ctx = child_ctx; |
| 13493 | 13490 | ||
| 13494 | - pmu_ctx = find_get_pmu_context(child_event->pmu, child_ctx, child_event); | 13491 | + pmu_ctx = find_get_pmu_context(parent_event->pmu_ctx->pmu, child_ctx, child_event); |
| 13495 | if (IS_ERR(pmu_ctx)) { | 13492 | if (IS_ERR(pmu_ctx)) { |
| 13496 | free_event(child_event); | 13493 | free_event(child_event); |
| 13497 | return ERR_CAST(pmu_ctx); | 13494 | return ERR_CAST(pmu_ctx); |
| @@ -930,9 +930,9 @@ int fixup_pi_owner(u32 __user *uaddr, struct futex_q *q, int locked) | |||
| 930 | int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock) | 930 | int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int trylock) |
| 931 | { | 931 | { |
| 932 | struct hrtimer_sleeper timeout, *to; | 932 | struct hrtimer_sleeper timeout, *to; |
| 933 | - struct task_struct *exiting = NULL; | ||
| 934 | struct rt_mutex_waiter rt_waiter; | 933 | struct rt_mutex_waiter rt_waiter; |
| 935 | struct futex_hash_bucket *hb; | 934 | struct futex_hash_bucket *hb; |
| 935 | + struct task_struct *exiting; | ||
| 936 | struct futex_q q = futex_q_init; | 936 | struct futex_q q = futex_q_init; |
| 937 | int res, ret; | 937 | int res, ret; |
| 938 | 938 | ||
| @@ -945,6 +945,7 @@ int futex_lock_pi(u32 __user *uaddr, unsigned int flags, ktime_t *time, int tryl | |||
| 945 | to = futex_setup_timer(time, &timeout, flags, 0); | 945 | to = futex_setup_timer(time, &timeout, flags, 0); |
| 946 | 946 | ||
| 947 | retry: | 947 | retry: |
| 948 | + exiting = NULL; | ||
| 948 | ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, FUTEX_WRITE); | 949 | ret = get_futex_key(uaddr, flags & FLAGS_SHARED, &q.key, FUTEX_WRITE); |
| 949 | if (unlikely(ret != 0)) | 950 | if (unlikely(ret != 0)) |
| 950 | goto out; | 951 | goto out; |
| @@ -4130,13 +4130,14 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset) | |||
| 4130 | struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); | 4130 | struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp); |
| 4131 | skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags - 1]; | 4131 | skb_frag_t *frag = &sinfo->frags[sinfo->nr_frags - 1]; |
| 4132 | struct xdp_rxq_info *rxq = xdp->rxq; | 4132 | struct xdp_rxq_info *rxq = xdp->rxq; |
| 4133 | - unsigned int tailroom; | 4133 | + int tailroom; |
| 4134 | 4134 | ||
| 4135 | if (!rxq->frag_size || rxq->frag_size > xdp->frame_sz) | 4135 | if (!rxq->frag_size || rxq->frag_size > xdp->frame_sz) |
| 4136 | return -EOPNOTSUPP; | 4136 | return -EOPNOTSUPP; |
| 4137 | 4137 | ||
| 4138 | tailroom = rxq->frag_size - skb_frag_size(frag) - skb_frag_off(frag); | 4138 | tailroom = rxq->frag_size - skb_frag_size(frag) - skb_frag_off(frag); |
| 4139 | if (unlikely(offset > tailroom)) | 4139 | if (unlikely(offset > tailroom)) |
| 4140 | + WARN_ON_ONCE(tailroom < 0); | ||
| 4140 | return -EINVAL; | 4141 | return -EINVAL; |
| 4141 | 4142 | ||
| 4142 | memset(skb_frag_address(frag) + skb_frag_size(frag), 0, offset); | 4143 | memset(skb_frag_address(frag) + skb_frag_size(frag), 0, offset); |
| @@ -763,6 +763,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, | |||
| 763 | { | 763 | { |
| 764 | struct in6_pktinfo *src_info; | 764 | struct in6_pktinfo *src_info; |
| 765 | struct cmsghdr *cmsg; | 765 | struct cmsghdr *cmsg; |
| 766 | + struct ipv6_rt_hdr *orthdr; | ||
| 766 | struct ipv6_rt_hdr *rthdr; | 767 | struct ipv6_rt_hdr *rthdr; |
| 767 | struct ipv6_opt_hdr *hdr; | 768 | struct ipv6_opt_hdr *hdr; |
| 768 | struct ipv6_txoptions *opt = ipc6->opt; | 769 | struct ipv6_txoptions *opt = ipc6->opt; |
| @@ -924,9 +925,13 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, | |||
| 924 | goto exit_f; | 925 | goto exit_f; |
| 925 | } | 926 | } |
| 926 | if (cmsg->cmsg_type == IPV6_DSTOPTS) { | 927 | if (cmsg->cmsg_type == IPV6_DSTOPTS) { |
| 928 | + if (opt->dst1opt) | ||
| 929 | + opt->opt_flen -= ipv6_optlen(opt->dst1opt); | ||
| 927 | opt->opt_flen += len; | 930 | opt->opt_flen += len; |
| 928 | opt->dst1opt = hdr; | 931 | opt->dst1opt = hdr; |
| 929 | } else { | 932 | } else { |
| 933 | + if (opt->dst0opt) | ||
| 934 | + opt->opt_nflen -= ipv6_optlen(opt->dst0opt); | ||
| 930 | opt->opt_nflen += len; | 935 | opt->opt_nflen += len; |
| 931 | opt->dst0opt = hdr; | 936 | opt->dst0opt = hdr; |
| 932 | } | 937 | } |
| @@ -969,12 +974,17 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk, | |||
| 969 | goto exit_f; | 974 | goto exit_f; |
| 970 | } | 975 | } |
| 971 | 976 | ||
| 977 | + orthdr = opt->srcrt; | ||
| 978 | + if (orthdr) | ||
| 979 | + opt->opt_nflen -= ((orthdr->hdrlen + 1) << 3); | ||
| 972 | opt->opt_nflen += len; | 980 | opt->opt_nflen += len; |
| 973 | opt->srcrt = rthdr; | 981 | opt->srcrt = rthdr; |
| 974 | 982 | ||
| 975 | if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) { | 983 | if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) { |
| 976 | int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); | 984 | int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); |
| 977 | 985 | ||
| 986 | + if (opt->dst0opt) | ||
| 987 | + opt->opt_nflen -= ipv6_optlen(opt->dst0opt); | ||
| 978 | opt->opt_nflen += dsthdrlen; | 988 | opt->opt_nflen += dsthdrlen; |
| 979 | opt->dst0opt = opt->dst1opt; | 989 | opt->dst0opt = opt->dst1opt; |
| 980 | opt->dst1opt = NULL; | 990 | opt->dst1opt = NULL; |
| @@ -654,7 +654,7 @@ static int exp_seq_show(struct seq_file *s, void *v) | |||
| 654 | if (expect->flags & NF_CT_EXPECT_USERSPACE) | 654 | if (expect->flags & NF_CT_EXPECT_USERSPACE) |
| 655 | seq_printf(s, "%sUSERSPACE", delim); | 655 | seq_printf(s, "%sUSERSPACE", delim); |
| 656 | 656 | ||
| 657 | - helper = rcu_dereference(nfct_help(expect->master)->helper); | 657 | + helper = rcu_dereference(expect->helper); |
| 658 | if (helper) { | 658 | if (helper) { |
| 659 | seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); | 659 | seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name); |
| 660 | if (helper->expect_policy[expect->class].name[0]) | 660 | if (helper->expect_policy[expect->class].name[0]) |
| @@ -400,14 +400,10 @@ EXPORT_SYMBOL_GPL(nf_conntrack_helper_register); | |||
| 400 | 400 | ||
| 401 | static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data) | 401 | static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data) |
| 402 | { | 402 | { |
| 403 | - struct nf_conn_help *help = nfct_help(exp->master); | ||
| 404 | const struct nf_conntrack_helper *me = data; | 403 | const struct nf_conntrack_helper *me = data; |
| 405 | const struct nf_conntrack_helper *this; | 404 | const struct nf_conntrack_helper *this; |
| 406 | 405 | ||
| 407 | - if (exp->helper == me) | 406 | + this = rcu_dereference_protected(exp->helper, |
| 408 | - return true; | ||
| 409 | - | ||
| 410 | - this = rcu_dereference_protected(help->helper, | ||
| 411 | lockdep_is_held(&nf_conntrack_expect_lock)); | 407 | lockdep_is_held(&nf_conntrack_expect_lock)); |
| 412 | return this == me; | 408 | return this == me; |
| 413 | } | 409 | } |
| @@ -2998,7 +2998,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
| 2998 | { | 2998 | { |
| 2999 | struct nf_conn *master = exp->master; | 2999 | struct nf_conn *master = exp->master; |
| 3000 | long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; | 3000 | long timeout = ((long)exp->timeout.expires - (long)jiffies) / HZ; |
| 3001 | - struct nf_conn_help *help; | 3001 | + struct nf_conntrack_helper *helper; |
| 3002 | #if IS_ENABLED(CONFIG_NF_NAT) | 3002 | #if IS_ENABLED(CONFIG_NF_NAT) |
| 3003 | struct nlattr *nest_parms; | 3003 | struct nlattr *nest_parms; |
| 3004 | struct nf_conntrack_tuple nat_tuple = {}; | 3004 | struct nf_conntrack_tuple nat_tuple = {}; |
| @@ -3043,15 +3043,12 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
| 3043 | nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || | 3043 | nla_put_be32(skb, CTA_EXPECT_FLAGS, htonl(exp->flags)) || |
| 3044 | nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) | 3044 | nla_put_be32(skb, CTA_EXPECT_CLASS, htonl(exp->class))) |
| 3045 | goto nla_put_failure; | 3045 | goto nla_put_failure; |
| 3046 | - help = nfct_help(master); | ||
| 3047 | - if (help) { | ||
| 3048 | - struct nf_conntrack_helper *helper; | ||
| 3049 | 3046 | ||
| 3050 | - helper = rcu_dereference(help->helper); | 3047 | + helper = rcu_dereference(exp->helper); |
| 3051 | - if (helper && | 3048 | + if (helper && |
| 3052 | - nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) | 3049 | + nla_put_string(skb, CTA_EXPECT_HELP_NAME, helper->name)) |
| 3053 | - goto nla_put_failure; | 3050 | + goto nla_put_failure; |
| 3054 | - } | 3051 | + |
| 3055 | expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn); | 3052 | expfn = nf_ct_helper_expectfn_find_by_symbol(exp->expectfn); |
| 3056 | if (expfn != NULL && | 3053 | if (expfn != NULL && |
| 3057 | nla_put_string(skb, CTA_EXPECT_FN, expfn->name)) | 3054 | nla_put_string(skb, CTA_EXPECT_FN, expfn->name)) |
| @@ -3363,12 +3360,9 @@ static int ctnetlink_get_expect(struct sk_buff *skb, | |||
| 3363 | static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data) | 3360 | static bool expect_iter_name(struct nf_conntrack_expect *exp, void *data) |
| 3364 | { | 3361 | { |
| 3365 | struct nf_conntrack_helper *helper; | 3362 | struct nf_conntrack_helper *helper; |
| 3366 | - const struct nf_conn_help *m_help; | ||
| 3367 | const char *name = data; | 3363 | const char *name = data; |
| 3368 | 3364 | ||
| 3369 | - m_help = nfct_help(exp->master); | 3365 | + helper = rcu_dereference(exp->helper); |
| 3370 | - | ||
| 3371 | - helper = rcu_dereference(m_help->helper); | ||
| 3372 | if (!helper) | 3366 | if (!helper) |
| 3373 | return false; | 3367 | return false; |
| 3374 | 3368 | ||
| @@ -3503,9 +3497,9 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct, | |||
| 3503 | struct nf_conntrack_tuple *tuple, | 3497 | struct nf_conntrack_tuple *tuple, |
| 3504 | struct nf_conntrack_tuple *mask) | 3498 | struct nf_conntrack_tuple *mask) |
| 3505 | { | 3499 | { |
| 3506 | - u_int32_t class = 0; | ||
| 3507 | struct nf_conntrack_expect *exp; | 3500 | struct nf_conntrack_expect *exp; |
| 3508 | struct nf_conn_help *help; | 3501 | struct nf_conn_help *help; |
| 3502 | + u32 class = 0; | ||
| 3509 | int err; | 3503 | int err; |
| 3510 | 3504 | ||
| 3511 | help = nfct_help(ct); | 3505 | help = nfct_help(ct); |
| @@ -3542,6 +3536,8 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct, | |||
| 3542 | 3536 | ||
| 3543 | exp->class = class; | 3537 | exp->class = class; |
| 3544 | exp->master = ct; | 3538 | exp->master = ct; |
| 3539 | + if (!helper) | ||
| 3540 | + helper = rcu_dereference(help->helper); | ||
| 3545 | exp->helper = helper; | 3541 | exp->helper = helper; |
| 3546 | exp->tuple = *tuple; | 3542 | exp->tuple = *tuple; |
| 3547 | exp->mask.src.u3 = mask->src.u3; | 3543 | exp->mask.src.u3 = mask->src.u3; |
| @@ -924,7 +924,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, | |||
| 924 | exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); | 924 | exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); |
| 925 | 925 | ||
| 926 | if (!exp || exp->master == ct || | 926 | if (!exp || exp->master == ct || |
| 927 | - nfct_help(exp->master)->helper != nfct_help(ct)->helper || | 927 | + exp->helper != nfct_help(ct)->helper || |
| 928 | exp->class != class) | 928 | exp->class != class) |
| 929 | break; | 929 | break; |
| 930 | #if IS_ENABLED(CONFIG_NF_NAT) | 930 | #if IS_ENABLED(CONFIG_NF_NAT) |
| @@ -16,6 +16,7 @@ | |||
| 16 | #include <net/netfilter/nf_conntrack_ecache.h> | 16 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 17 | #include <net/netfilter/nf_conntrack_timeout.h> | 17 | #include <net/netfilter/nf_conntrack_timeout.h> |
| 18 | #include <net/netfilter/nf_conntrack_zones.h> | 18 | #include <net/netfilter/nf_conntrack_zones.h> |
| 19 | +#include "nf_internals.h" | ||
| 19 | 20 | ||
| 20 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) | 21 | static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct) |
| 21 | { | 22 | { |
| @@ -283,6 +284,9 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par, | |||
| 283 | struct nf_conn_help *help; | 284 | struct nf_conn_help *help; |
| 284 | 285 | ||
| 285 | if (ct) { | 286 | if (ct) { |
| 287 | + if (info->helper[0] || info->timeout[0]) | ||
| 288 | + nf_queue_nf_hook_drop(par->net); | ||
| 289 | + | ||
| 286 | help = nfct_help(ct); | 290 | help = nfct_help(ct); |
| 287 | xt_ct_put_helper(help); | 291 | xt_ct_put_helper(help); |
| 288 | 292 | ||
| @@ -105,6 +105,28 @@ multiport_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 105 | return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); | 105 | return ports_match_v1(multiinfo, ntohs(pptr[0]), ntohs(pptr[1])); |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | +static bool | ||
| 109 | +multiport_valid_ranges(const struct xt_multiport_v1 *multiinfo) | ||
| 110 | +{ | ||
| 111 | + unsigned int i; | ||
| 112 | + | ||
| 113 | + for (i = 0; i < multiinfo->count; i++) { | ||
| 114 | + if (!multiinfo->pflags[i]) | ||
| 115 | + continue; | ||
| 116 | + | ||
| 117 | + if (++i >= multiinfo->count) | ||
| 118 | + return false; | ||
| 119 | + | ||
| 120 | + if (multiinfo->pflags[i]) | ||
| 121 | + return false; | ||
| 122 | + | ||
| 123 | + if (multiinfo->ports[i - 1] > multiinfo->ports[i]) | ||
| 124 | + return false; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + return true; | ||
| 128 | +} | ||
| 129 | + | ||
| 108 | static inline bool | 130 | static inline bool |
| 109 | check(u_int16_t proto, | 131 | check(u_int16_t proto, |
| 110 | u_int8_t ip_invflags, | 132 | u_int8_t ip_invflags, |
| @@ -127,8 +149,10 @@ static int multiport_mt_check(const struct xt_mtchk_param *par) | |||
| 127 | const struct ipt_ip *ip = par->entryinfo; | 149 | const struct ipt_ip *ip = par->entryinfo; |
| 128 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; | 150 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; |
| 129 | 151 | ||
| 130 | - return check(ip->proto, ip->invflags, multiinfo->flags, | 152 | + if (!check(ip->proto, ip->invflags, multiinfo->flags, multiinfo->count)) |
| 131 | - multiinfo->count) ? 0 : -EINVAL; | 153 | + return -EINVAL; |
| 154 | + | ||
| 155 | + return multiport_valid_ranges(multiinfo) ? 0 : -EINVAL; | ||
| 132 | } | 156 | } |
| 133 | 157 | ||
| 134 | static int multiport_mt6_check(const struct xt_mtchk_param *par) | 158 | static int multiport_mt6_check(const struct xt_mtchk_param *par) |
| @@ -136,8 +160,10 @@ static int multiport_mt6_check(const struct xt_mtchk_param *par) | |||
| 136 | const struct ip6t_ip6 *ip = par->entryinfo; | 160 | const struct ip6t_ip6 *ip = par->entryinfo; |
| 137 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; | 161 | const struct xt_multiport_v1 *multiinfo = par->matchinfo; |
| 138 | 162 | ||
| 139 | - return check(ip->proto, ip->invflags, multiinfo->flags, | 163 | + if (!check(ip->proto, ip->invflags, multiinfo->flags, multiinfo->count)) |
| 140 | - multiinfo->count) ? 0 : -EINVAL; | 164 | + return -EINVAL; |
| 165 | + | ||
| 166 | + return multiport_valid_ranges(multiinfo) ? 0 : -EINVAL; | ||
| 141 | } | 167 | } |
| 142 | 168 | ||
| 143 | static struct xt_match multiport_mt_reg[] __read_mostly = { | 169 | static struct xt_match multiport_mt_reg[] __read_mostly = { |
| @@ -3196,6 +3196,7 @@ static int packet_release(struct socket *sock) | |||
| 3196 | 3196 | ||
| 3197 | spin_lock(&po->bind_lock); | 3197 | spin_lock(&po->bind_lock); |
| 3198 | unregister_prot_hook(sk, false); | 3198 | unregister_prot_hook(sk, false); |
| 3199 | + WRITE_ONCE(po->num, 0); | ||
| 3199 | packet_cached_dev_reset(po); | 3200 | packet_cached_dev_reset(po); |
| 3200 | 3201 | ||
| 3201 | if (po->prot_hook.dev) { | 3202 | if (po->prot_hook.dev) { |
| @@ -494,18 +494,24 @@ bool rds_tcp_tune(struct socket *sock) | |||
| 494 | struct rds_tcp_net *rtn; | 494 | struct rds_tcp_net *rtn; |
| 495 | 495 | ||
| 496 | tcp_sock_set_nodelay(sock->sk); | 496 | tcp_sock_set_nodelay(sock->sk); |
| 497 | - lock_sock(sk); | ||
| 498 | /* TCP timer functions might access net namespace even after | 497 | /* TCP timer functions might access net namespace even after |
| 499 | * a process which created this net namespace terminated. | 498 | * a process which created this net namespace terminated. |
| 500 | */ | 499 | */ |
| 501 | if (!sk->sk_net_refcnt) { | 500 | if (!sk->sk_net_refcnt) { |
| 502 | - if (!maybe_get_net(net)) { | 501 | + if (!maybe_get_net(net)) |
| 503 | - release_sock(sk); | ||
| 504 | return false; | 502 | return false; |
| 505 | - } | 503 | + /* |
| 504 | + * sk_net_refcnt_upgrade() must be called before lock_sock() | ||
| 505 | + * because it does a GFP_KERNEL allocation, which can trigger | ||
| 506 | + * fs_reclaim and create a circular lock dependency with the | ||
| 507 | + * socket lock. The fields it modifies (sk_net_refcnt, | ||
| 508 | + * ns_tracker) are not accessed by any concurrent code path | ||
| 509 | + * at this point. | ||
| 510 | + */ | ||
| 506 | /* Update ns_tracker to current stack trace and refcounted tracker */ | 511 | /* Update ns_tracker to current stack trace and refcounted tracker */ |
| 507 | __netns_tracker_free(net, &sk->ns_tracker, false); | 512 | __netns_tracker_free(net, &sk->ns_tracker, false); |
| 508 | 513 | ||
| 514 | + lock_sock(sk); | ||
| 509 | sk->sk_net_refcnt = 1; | 515 | sk->sk_net_refcnt = 1; |
| 510 | netns_tracker_alloc(net, &sk->ns_tracker, GFP_KERNEL); | 516 | netns_tracker_alloc(net, &sk->ns_tracker, GFP_KERNEL); |
| 511 | sock_inuse_add(net, 1); | 517 | sock_inuse_add(net, 1); |
| @@ -10,6 +10,10 @@ | |||
| 10 | #include <net/af_rxrpc.h> | 10 | #include <net/af_rxrpc.h> |
| 11 | #include "ar-internal.h" | 11 | #include "ar-internal.h" |
| 12 | 12 | ||
| 13 | +#define RXRPC_PROC_ADDRBUF_SIZE \ | ||
| 14 | + (sizeof("[xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255]") + \ | ||
| 15 | + sizeof(":12345")) | ||
| 16 | + | ||
| 13 | static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { | 17 | static const char *const rxrpc_conn_states[RXRPC_CONN__NR_STATES] = { |
| 14 | [RXRPC_CONN_UNUSED] = "Unused ", | 18 | [RXRPC_CONN_UNUSED] = "Unused ", |
| 15 | [RXRPC_CONN_CLIENT_UNSECURED] = "ClUnsec ", | 19 | [RXRPC_CONN_CLIENT_UNSECURED] = "ClUnsec ", |
| @@ -54,7 +58,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) | |||
| 54 | enum rxrpc_call_state state; | 58 | enum rxrpc_call_state state; |
| 55 | unsigned long timeout = 0; | 59 | unsigned long timeout = 0; |
| 56 | rxrpc_seq_t acks_hard_ack; | 60 | rxrpc_seq_t acks_hard_ack; |
| 57 | - char lbuff[50], rbuff[50]; | 61 | + char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; |
| 58 | 62 | ||
| 59 | if (v == &rxnet->calls) { | 63 | if (v == &rxnet->calls) { |
| 60 | seq_puts(seq, | 64 | seq_puts(seq, |
| @@ -69,11 +73,11 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v) | |||
| 69 | 73 | ||
| 70 | local = call->local; | 74 | local = call->local; |
| 71 | if (local) | 75 | if (local) |
| 72 | - sprintf(lbuff, "%pISpc", &local->srx.transport); | 76 | + scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); |
| 73 | else | 77 | else |
| 74 | strcpy(lbuff, "no_local"); | 78 | strcpy(lbuff, "no_local"); |
| 75 | 79 | ||
| 76 | - sprintf(rbuff, "%pISpc", &call->dest_srx.transport); | 80 | + scnprintf(rbuff, sizeof(rbuff), "%pISpc", &call->dest_srx.transport); |
| 77 | 81 | ||
| 78 | state = rxrpc_call_state(call); | 82 | state = rxrpc_call_state(call); |
| 79 | if (state != RXRPC_CALL_SERVER_PREALLOC) { | 83 | if (state != RXRPC_CALL_SERVER_PREALLOC) { |
| @@ -144,7 +148,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
| 144 | struct rxrpc_connection *conn; | 148 | struct rxrpc_connection *conn; |
| 145 | struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); | 149 | struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq)); |
| 146 | const char *state; | 150 | const char *state; |
| 147 | - char lbuff[50], rbuff[50]; | 151 | + char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; |
| 148 | 152 | ||
| 149 | if (v == &rxnet->conn_proc_list) { | 153 | if (v == &rxnet->conn_proc_list) { |
| 150 | seq_puts(seq, | 154 | seq_puts(seq, |
| @@ -163,8 +167,8 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v) | |||
| 163 | goto print; | 167 | goto print; |
| 164 | } | 168 | } |
| 165 | 169 | ||
| 166 | - sprintf(lbuff, "%pISpc", &conn->local->srx.transport); | 170 | + scnprintf(lbuff, sizeof(lbuff), "%pISpc", &conn->local->srx.transport); |
| 167 | - sprintf(rbuff, "%pISpc", &conn->peer->srx.transport); | 171 | + scnprintf(rbuff, sizeof(rbuff), "%pISpc", &conn->peer->srx.transport); |
| 168 | print: | 172 | print: |
| 169 | state = rxrpc_is_conn_aborted(conn) ? | 173 | state = rxrpc_is_conn_aborted(conn) ? |
| 170 | rxrpc_call_completions[conn->completion] : | 174 | rxrpc_call_completions[conn->completion] : |
| @@ -205,7 +209,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) | |||
| 205 | { | 209 | { |
| 206 | struct rxrpc_peer *peer; | 210 | struct rxrpc_peer *peer; |
| 207 | time64_t now; | 211 | time64_t now; |
| 208 | - char lbuff[50], rbuff[50]; | 212 | + char lbuff[RXRPC_PROC_ADDRBUF_SIZE], rbuff[RXRPC_PROC_ADDRBUF_SIZE]; |
| 209 | 213 | ||
| 210 | if (v == SEQ_START_TOKEN) { | 214 | if (v == SEQ_START_TOKEN) { |
| 211 | seq_puts(seq, | 215 | seq_puts(seq, |
| @@ -218,9 +222,9 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v) | |||
| 218 | 222 | ||
| 219 | peer = list_entry(v, struct rxrpc_peer, hash_link); | 223 | peer = list_entry(v, struct rxrpc_peer, hash_link); |
| 220 | 224 | ||
| 221 | - sprintf(lbuff, "%pISpc", &peer->local->srx.transport); | 225 | + scnprintf(lbuff, sizeof(lbuff), "%pISpc", &peer->local->srx.transport); |
| 222 | 226 | ||
| 223 | - sprintf(rbuff, "%pISpc", &peer->srx.transport); | 227 | + scnprintf(rbuff, sizeof(rbuff), "%pISpc", &peer->srx.transport); |
| 224 | 228 | ||
| 225 | now = ktime_get_seconds(); | 229 | now = ktime_get_seconds(); |
| 226 | seq_printf(seq, | 230 | seq_printf(seq, |
| @@ -330,7 +334,7 @@ const struct seq_operations rxrpc_peer_seq_ops = { | |||
| 330 | static int rxrpc_local_seq_show(struct seq_file *seq, void *v) | 334 | static int rxrpc_local_seq_show(struct seq_file *seq, void *v) |
| 331 | { | 335 | { |
| 332 | struct rxrpc_local *local; | 336 | struct rxrpc_local *local; |
| 333 | - char lbuff[50]; | 337 | + char lbuff[RXRPC_PROC_ADDRBUF_SIZE]; |
| 334 | 338 | ||
| 335 | if (v == SEQ_START_TOKEN) { | 339 | if (v == SEQ_START_TOKEN) { |
| 336 | seq_puts(seq, | 340 | seq_puts(seq, |
| @@ -341,7 +345,7 @@ static int rxrpc_local_seq_show(struct seq_file *seq, void *v) | |||
| 341 | 345 | ||
| 342 | local = hlist_entry(v, struct rxrpc_local, link); | 346 | local = hlist_entry(v, struct rxrpc_local, link); |
| 343 | 347 | ||
| 344 | - sprintf(lbuff, "%pISpc", &local->srx.transport); | 348 | + scnprintf(lbuff, sizeof(lbuff), "%pISpc", &local->srx.transport); |
| 345 | 349 | ||
| 346 | seq_printf(seq, | 350 | seq_printf(seq, |
| 347 | "UDP %-47.47s %3u %3u %3u\n", | 351 | "UDP %-47.47s %3u %3u %3u\n", |