From fc6f5aa39be716d30625ede00988b558870a7293 Mon Sep 17 00:00:00 2001 From: almalinux-bot-kernel Date: Sun, 2 Aug 2026 05:10:28 +0000 Subject: [PATCH] Import of kernel-5.14.0-687.31.1.el9_8 --- ...87.30.1.el9 => COPYING-5.14.0-687.31.1.el9 | 0 Makefile.rhelver | 2 +- block/blk-mq.c | 34 +++----- configs/kernel-5.14.0-x86_64-debug.config | 9 ++- configs/kernel-5.14.0-x86_64-rt-debug.config | 9 ++- configs/kernel-5.14.0-x86_64-rt.config | 9 ++- configs/kernel-5.14.0-x86_64.config | 9 ++- drivers/iommu/intel/iommu.c | 13 ++-- drivers/watchdog/iTCO_wdt.c | 60 ++++++++------- drivers/watchdog/softdog.c | 8 +- drivers/watchdog/watchdog_dev.c | 9 ++- .../watchdog/watchdog_hrtimer_pretimeout.c | 4 +- drivers/watchdog/wdat_wdt.c | 66 ++++++++++------ fs/nfsd/nfs4state.c | 7 +- fs/nfsd/nfsctl.c | 9 ++- fs/nfsd/state.h | 4 +- kernel.sbat | 4 +- kernel/fork.c | 12 ++- kernel/watchdog.c | 3 +- lib/buildid.c | 32 +++++--- net/xfrm/xfrm_state.c | 77 +++++++++++-------- .../x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV | 1 + .../x86/CONFIG_SOFT_WATCHDOG_PRETIMEOUT | 1 + .../x86/CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT | 1 + ...ONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP | 1 + ...NFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC | 1 + .../x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV | 1 + .../x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP | 1 + .../x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC | 1 + redhat/kernel.changelog-9.8 | 25 ++++++ 30 files changed, 253 insertions(+), 160 deletions(-) rename COPYING-5.14.0-687.30.1.el9 => COPYING-5.14.0-687.31.1.el9 (100%) create mode 100644 redhat/configs/rhel/automotive/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_SOFT_WATCHDOG_PRETIMEOUT create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP create mode 100644 redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC diff --git a/COPYING-5.14.0-687.30.1.el9 b/COPYING-5.14.0-687.31.1.el9 similarity index 100% rename from COPYING-5.14.0-687.30.1.el9 rename to COPYING-5.14.0-687.31.1.el9 diff --git a/Makefile.rhelver b/Makefile.rhelver index 3a700f7944..0251b016a0 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 8 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 687.30.1 +RHEL_RELEASE = 687.31.1 # # ZSTREAM diff --git a/block/blk-mq.c b/block/blk-mq.c index a08953158c..0e994fdec4 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -3046,7 +3046,7 @@ static struct request *blk_mq_get_new_requests(struct request_queue *q, /* * Check if there is a suitable cached request and return it. */ -static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, +static struct request *blk_mq_get_cached_request(struct blk_plug *plug, struct request_queue *q, blk_opf_t opf) { enum hctx_type type = blk_mq_get_hctx_type(opf); @@ -3062,27 +3062,10 @@ static struct request *blk_mq_peek_cached_request(struct blk_plug *plug, return NULL; if (op_is_flush(rq->cmd_flags) != op_is_flush(opf)) return NULL; + rq_list_pop(&plug->cached_rqs); return rq; } -static void blk_mq_use_cached_rq(struct request *rq, struct blk_plug *plug, - struct bio *bio) -{ - if (rq_list_pop(&plug->cached_rqs) != rq) - WARN_ON_ONCE(1); - - /* - * If any qos ->throttle() end up blocking, we will have flushed the - * plug and hence killed the cached_rq list as well. Pop this entry - * before we throttle. - */ - rq_qos_throttle(rq->q, bio); - - blk_mq_rq_time_init(rq, blk_time_get_ns()); - rq->cmd_flags = bio->bi_opf; - INIT_LIST_HEAD(&rq->queuelist); -} - static bool bio_unaligned(const struct bio *bio, struct request_queue *q) { unsigned int bs_mask = queue_logical_block_size(q) - 1; @@ -3120,7 +3103,7 @@ void blk_mq_submit_bio(struct bio *bio) /* * If the plug has a cached request for this queue, try to use it. */ - rq = blk_mq_peek_cached_request(plug, q, bio->bi_opf); + rq = blk_mq_get_cached_request(plug, q, bio->bi_opf); /* * A BIO that was released from a zone write plug has already been @@ -3179,7 +3162,10 @@ void blk_mq_submit_bio(struct bio *bio) new_request: if (rq) { - blk_mq_use_cached_rq(rq, plug, bio); + rq_qos_throttle(rq->q, bio); + blk_mq_rq_time_init(rq, blk_time_get_ns()); + rq->cmd_flags = bio->bi_opf; + INIT_LIST_HEAD(&rq->queuelist); } else { rq = blk_mq_get_new_requests(q, plug, bio); if (unlikely(!rq)) { @@ -3225,12 +3211,10 @@ new_request: return; queue_exit: - /* - * Don't drop the queue reference if we were trying to use a cached - * request and thus didn't acquire one. - */ if (!rq) blk_queue_exit(q); + else + rq_list_add_head(&plug->cached_rqs, rq); } #ifdef CONFIG_BLK_MQ_STACKING diff --git a/configs/kernel-5.14.0-x86_64-debug.config b/configs/kernel-5.14.0-x86_64-debug.config index 416659d34b..64e22b0d9a 100644 --- a/configs/kernel-5.14.0-x86_64-debug.config +++ b/configs/kernel-5.14.0-x86_64-debug.config @@ -4550,17 +4550,22 @@ CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y CONFIG_WATCHDOG_OPEN_TIMEOUT=0 CONFIG_WATCHDOG_SYSFS=y -# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set +CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y # # Watchdog Pretimeout Governors # -# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y # # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m +# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set CONFIG_WDAT_WDT=m # CONFIG_XILINX_WATCHDOG is not set # CONFIG_ZIIRAVE_WATCHDOG is not set diff --git a/configs/kernel-5.14.0-x86_64-rt-debug.config b/configs/kernel-5.14.0-x86_64-rt-debug.config index a4251639dc..3c013977f7 100644 --- a/configs/kernel-5.14.0-x86_64-rt-debug.config +++ b/configs/kernel-5.14.0-x86_64-rt-debug.config @@ -4557,17 +4557,22 @@ CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y CONFIG_WATCHDOG_OPEN_TIMEOUT=0 CONFIG_WATCHDOG_SYSFS=y -# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set +CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y # # Watchdog Pretimeout Governors # -# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y # # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m +# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set CONFIG_WDAT_WDT=m # CONFIG_XILINX_WATCHDOG is not set # CONFIG_ZIIRAVE_WATCHDOG is not set diff --git a/configs/kernel-5.14.0-x86_64-rt.config b/configs/kernel-5.14.0-x86_64-rt.config index 1ece4021c4..b4f40e8aa4 100644 --- a/configs/kernel-5.14.0-x86_64-rt.config +++ b/configs/kernel-5.14.0-x86_64-rt.config @@ -4541,17 +4541,22 @@ CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y CONFIG_WATCHDOG_OPEN_TIMEOUT=0 CONFIG_WATCHDOG_SYSFS=y -# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set +CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y # # Watchdog Pretimeout Governors # -# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y # # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m +# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set CONFIG_WDAT_WDT=m # CONFIG_XILINX_WATCHDOG is not set # CONFIG_ZIIRAVE_WATCHDOG is not set diff --git a/configs/kernel-5.14.0-x86_64.config b/configs/kernel-5.14.0-x86_64.config index ce39dea203..bc61b7cee6 100644 --- a/configs/kernel-5.14.0-x86_64.config +++ b/configs/kernel-5.14.0-x86_64.config @@ -4533,17 +4533,22 @@ CONFIG_WATCHDOG_CORE=y CONFIG_WATCHDOG_HANDLE_BOOT_ENABLED=y CONFIG_WATCHDOG_OPEN_TIMEOUT=0 CONFIG_WATCHDOG_SYSFS=y -# CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT is not set +CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y # # Watchdog Pretimeout Governors # -# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y +CONFIG_WATCHDOG_PRETIMEOUT_GOV_SEL=m +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y # # Watchdog Device Drivers # CONFIG_SOFT_WATCHDOG=m +# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set CONFIG_WDAT_WDT=m # CONFIG_XILINX_WATCHDOG is not set # CONFIG_ZIIRAVE_WATCHDOG is not set diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index dff2d895b8..3d4148d349 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -4066,8 +4066,8 @@ void domain_remove_dev_pasid(struct iommu_domain *domain, if (!domain) return; - /* Identity domain has no meta data for pasid. */ - if (domain->type == IOMMU_DOMAIN_IDENTITY) + /* Identity domain and blocked domain have no meta data for pasid. */ + if (domain->type == IOMMU_DOMAIN_IDENTITY || domain->type == IOMMU_DOMAIN_BLOCKED) return; dmar_domain = to_dmar_domain(domain); @@ -4081,12 +4081,13 @@ void domain_remove_dev_pasid(struct iommu_domain *domain, } spin_unlock_irqrestore(&dmar_domain->lock, flags); + if (WARN_ON_ONCE(!dev_pasid)) + return; + cache_tag_unassign_domain(dmar_domain, dev, pasid); domain_detach_iommu(dmar_domain, iommu); - if (!WARN_ON_ONCE(!dev_pasid)) { - intel_iommu_debugfs_remove_dev_pasid(dev_pasid); - kfree(dev_pasid); - } + intel_iommu_debugfs_remove_dev_pasid(dev_pasid); + kfree(dev_pasid); } static int blocking_domain_set_dev_pasid(struct iommu_domain *domain, diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index ced2fc0deb..35b358bcf9 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c @@ -94,7 +94,6 @@ struct iTCO_wdt_private { * NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2), * or memory-mapped PMC register bit 4 (TCO version 3). */ - struct resource *gcs_pmc_res; unsigned long __iomem *gcs_pmc; /* the lock for io operations */ spinlock_t io_lock; @@ -424,15 +423,28 @@ static unsigned int iTCO_wdt_get_timeleft(struct watchdog_device *wd_dev) return time_left; } +/* Returns true if the watchdog was running */ +static bool iTCO_wdt_set_running(struct iTCO_wdt_private *p) +{ + u16 val; + + /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled */ + val = inw(TCO1_CNT(p)); + if (!(val & BIT(11))) { + set_bit(WDOG_HW_RUNNING, &p->wddev.status); + return true; + } + return false; +} + /* * Kernel Interfaces */ -static const struct watchdog_info ident = { +static struct watchdog_info ident = { .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, - .firmware_version = 0, .identity = DRV_NAME, }; @@ -497,10 +509,7 @@ static int iTCO_wdt_probe(struct platform_device *pdev) */ if (p->iTCO_version >= 2 && p->iTCO_version < 6 && !pdata->no_reboot_use_pmc) { - p->gcs_pmc_res = platform_get_resource(pdev, - IORESOURCE_MEM, - ICH_RES_MEM_GCS_PMC); - p->gcs_pmc = devm_ioremap_resource(dev, p->gcs_pmc_res); + p->gcs_pmc = devm_platform_ioremap_resource(pdev, ICH_RES_MEM_GCS_PMC); if (IS_ERR(p->gcs_pmc)) return PTR_ERR(p->gcs_pmc); } @@ -512,9 +521,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev) return -ENODEV; /* Cannot reset NO_REBOOT bit */ } - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - p->update_no_reboot_bit(p->no_reboot_priv, true); - if (turn_SMI_watchdog_clear_off >= p->iTCO_version) { /* * Bit 13: TCO_EN -> 0 @@ -556,8 +562,9 @@ static int iTCO_wdt_probe(struct platform_device *pdev) break; } - p->wddev.info = &ident, - p->wddev.ops = &iTCO_wdt_ops, + ident.firmware_version = p->iTCO_version; + p->wddev.info = &ident; + p->wddev.ops = &iTCO_wdt_ops; p->wddev.bootstatus = 0; p->wddev.timeout = WATCHDOG_TIMEOUT; watchdog_set_nowayout(&p->wddev, nowayout); @@ -566,8 +573,13 @@ static int iTCO_wdt_probe(struct platform_device *pdev) watchdog_set_drvdata(&p->wddev, p); platform_set_drvdata(pdev, p); - /* Make sure the watchdog is not running */ - iTCO_wdt_stop(&p->wddev); + if (!iTCO_wdt_set_running(p)) { + /* + * If the watchdog was not running set NO_REBOOT now to + * prevent later reboots. + */ + p->update_no_reboot_bit(p->no_reboot_priv, true); + } /* Check that the heartbeat value is within it's range; if not reset to the default */ @@ -591,7 +603,6 @@ static int iTCO_wdt_probe(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP /* * Suspend-to-idle requires this, because it stops the ticks and timekeeping, so * the watchdog cannot be pinged while in that state. In ACPI sleep states the @@ -599,15 +610,15 @@ static int iTCO_wdt_probe(struct platform_device *pdev) */ #ifdef CONFIG_ACPI -static inline bool need_suspend(void) +static inline bool __maybe_unused need_suspend(void) { return acpi_target_system_state() == ACPI_STATE_S0; } #else -static inline bool need_suspend(void) { return true; } +static inline bool __maybe_unused need_suspend(void) { return true; } #endif -static int iTCO_wdt_suspend_noirq(struct device *dev) +static int __maybe_unused iTCO_wdt_suspend_noirq(struct device *dev) { struct iTCO_wdt_private *p = dev_get_drvdata(dev); int ret = 0; @@ -621,7 +632,7 @@ static int iTCO_wdt_suspend_noirq(struct device *dev) return ret; } -static int iTCO_wdt_resume_noirq(struct device *dev) +static int __maybe_unused iTCO_wdt_resume_noirq(struct device *dev) { struct iTCO_wdt_private *p = dev_get_drvdata(dev); @@ -632,20 +643,15 @@ static int iTCO_wdt_resume_noirq(struct device *dev) } static const struct dev_pm_ops iTCO_wdt_pm = { - .suspend_noirq = iTCO_wdt_suspend_noirq, - .resume_noirq = iTCO_wdt_resume_noirq, + SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(iTCO_wdt_suspend_noirq, + iTCO_wdt_resume_noirq) }; -#define ITCO_WDT_PM_OPS (&iTCO_wdt_pm) -#else -#define ITCO_WDT_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - static struct platform_driver iTCO_wdt_driver = { .probe = iTCO_wdt_probe, .driver = { .name = DRV_NAME, - .pm = ITCO_WDT_PM_OPS, + .pm = &iTCO_wdt_pm, }, }; diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 7a1096265f..0820e35ad2 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c @@ -187,14 +187,12 @@ static int __init softdog_init(void) watchdog_set_nowayout(&softdog_dev, nowayout); watchdog_stop_on_reboot(&softdog_dev); - hrtimer_init(&softdog_ticktock, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - softdog_ticktock.function = softdog_fire; + hrtimer_setup(&softdog_ticktock, softdog_fire, CLOCK_MONOTONIC, HRTIMER_MODE_REL); if (IS_ENABLED(CONFIG_SOFT_WATCHDOG_PRETIMEOUT)) { softdog_info.options |= WDIOF_PRETIMEOUT; - hrtimer_init(&softdog_preticktock, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - softdog_preticktock.function = softdog_pretimeout; + hrtimer_setup(&softdog_preticktock, softdog_pretimeout, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); } if (soft_active_on_boot) diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c index 837a9f676f..81a9f2c7cb 100644 --- a/drivers/watchdog/watchdog_dev.c +++ b/drivers/watchdog/watchdog_dev.c @@ -401,7 +401,7 @@ static int watchdog_set_pretimeout(struct watchdog_device *wdd, if (watchdog_pretimeout_invalid(wdd, timeout)) return -EINVAL; - if (wdd->ops->set_pretimeout) + if (wdd->ops->set_pretimeout && (wdd->info->options & WDIOF_PRETIMEOUT)) err = wdd->ops->set_pretimeout(wdd, timeout); else wdd->pretimeout = timeout; @@ -1012,8 +1012,8 @@ static int watchdog_cdev_register(struct watchdog_device *wdd) dev_set_name(&wd_data->dev, "watchdog%d", wdd->id); kthread_init_work(&wd_data->work, watchdog_ping_work); - hrtimer_init(&wd_data->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); - wd_data->timer.function = watchdog_timer_expired; + hrtimer_setup(&wd_data->timer, watchdog_timer_expired, CLOCK_MONOTONIC, + HRTIMER_MODE_REL_HARD); watchdog_hrtimer_pretimeout_init(wdd); if (wdd->id == 0) { @@ -1095,6 +1095,8 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) watchdog_stop(wdd); } + watchdog_hrtimer_pretimeout_stop(wdd); + mutex_lock(&wd_data->lock); wd_data->wdd = NULL; wdd->wd_data = NULL; @@ -1102,7 +1104,6 @@ static void watchdog_cdev_unregister(struct watchdog_device *wdd) hrtimer_cancel(&wd_data->timer); kthread_cancel_work_sync(&wd_data->work); - watchdog_hrtimer_pretimeout_stop(wdd); put_device(&wd_data->dev); } diff --git a/drivers/watchdog/watchdog_hrtimer_pretimeout.c b/drivers/watchdog/watchdog_hrtimer_pretimeout.c index 940b53718a..fbc7eecd8b 100644 --- a/drivers/watchdog/watchdog_hrtimer_pretimeout.c +++ b/drivers/watchdog/watchdog_hrtimer_pretimeout.c @@ -23,8 +23,8 @@ void watchdog_hrtimer_pretimeout_init(struct watchdog_device *wdd) { struct watchdog_core_data *wd_data = wdd->wd_data; - hrtimer_init(&wd_data->pretimeout_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - wd_data->pretimeout_timer.function = watchdog_hrtimer_pretimeout; + hrtimer_setup(&wd_data->pretimeout_timer, watchdog_hrtimer_pretimeout, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); } void watchdog_hrtimer_pretimeout_start(struct watchdog_device *wdd) diff --git a/drivers/watchdog/wdat_wdt.c b/drivers/watchdog/wdat_wdt.c index 0ba99bed59..dd3c2d69c9 100644 --- a/drivers/watchdog/wdat_wdt.c +++ b/drivers/watchdog/wdat_wdt.c @@ -269,7 +269,7 @@ static int wdat_wdt_stop(struct watchdog_device *wdd) static int wdat_wdt_ping(struct watchdog_device *wdd) { - return wdat_wdt_run_action(to_wdat_wdt(wdd), ACPI_WDAT_RESET, 0, NULL); + return wdat_wdt_run_action(to_wdat_wdt(wdd), ACPI_WDAT_RESET, wdd->timeout, NULL); } static int wdat_wdt_set_timeout(struct watchdog_device *wdd, @@ -326,19 +326,27 @@ static int wdat_wdt_probe(struct platform_device *pdev) return -ENODEV; wdat = devm_kzalloc(dev, sizeof(*wdat), GFP_KERNEL); - if (!wdat) - return -ENOMEM; + if (!wdat) { + ret = -ENOMEM; + goto out_put_table; + } regs = devm_kcalloc(dev, pdev->num_resources, sizeof(*regs), GFP_KERNEL); - if (!regs) - return -ENOMEM; + if (!regs) { + ret = -ENOMEM; + goto out_put_table; + } /* WDAT specification wants to have >= 1ms period */ - if (tbl->timer_period < 1) - return -EINVAL; - if (tbl->min_count > tbl->max_count) - return -EINVAL; + if (tbl->timer_period < 1) { + ret = -EINVAL; + goto out_put_table; + } + if (tbl->min_count > tbl->max_count) { + ret = -EINVAL; + goto out_put_table; + } wdat->period = tbl->timer_period; wdat->wdd.min_timeout = DIV_ROUND_UP(wdat->period * tbl->min_count, 1000); @@ -355,15 +363,20 @@ static int wdat_wdt_probe(struct platform_device *pdev) res = &pdev->resource[i]; if (resource_type(res) == IORESOURCE_MEM) { reg = devm_ioremap_resource(dev, res); - if (IS_ERR(reg)) - return PTR_ERR(reg); + if (IS_ERR(reg)) { + ret = PTR_ERR(reg); + goto out_put_table; + } } else if (resource_type(res) == IORESOURCE_IO) { reg = devm_ioport_map(dev, res->start, 1); - if (!reg) - return -ENOMEM; + if (!reg) { + ret = -ENOMEM; + goto out_put_table; + } } else { dev_err(dev, "Unsupported resource\n"); - return -EINVAL; + ret = -EINVAL; + goto out_put_table; } regs[i] = reg; @@ -385,8 +398,10 @@ static int wdat_wdt_probe(struct platform_device *pdev) } instr = devm_kzalloc(dev, sizeof(*instr), GFP_KERNEL); - if (!instr) - return -ENOMEM; + if (!instr) { + ret = -ENOMEM; + goto out_put_table; + } INIT_LIST_HEAD(&instr->node); instr->entry = entries[i]; @@ -417,7 +432,8 @@ static int wdat_wdt_probe(struct platform_device *pdev) if (!instr->reg) { dev_err(dev, "I/O resource not found\n"); - return -EINVAL; + ret = -EINVAL; + goto out_put_table; } instructions = wdat->instructions[action]; @@ -425,8 +441,10 @@ static int wdat_wdt_probe(struct platform_device *pdev) instructions = devm_kzalloc(dev, sizeof(*instructions), GFP_KERNEL); - if (!instructions) - return -ENOMEM; + if (!instructions) { + ret = -ENOMEM; + goto out_put_table; + } INIT_LIST_HEAD(instructions); wdat->instructions[action] = instructions; @@ -443,7 +461,7 @@ static int wdat_wdt_probe(struct platform_device *pdev) ret = wdat_wdt_enable_reboot(wdat); if (ret) - return ret; + goto out_put_table; platform_set_drvdata(pdev, wdat); @@ -460,12 +478,16 @@ static int wdat_wdt_probe(struct platform_device *pdev) ret = wdat_wdt_set_timeout(&wdat->wdd, timeout); if (ret) - return ret; + goto out_put_table; watchdog_set_nowayout(&wdat->wdd, nowayout); watchdog_stop_on_reboot(&wdat->wdd); watchdog_stop_on_unregister(&wdat->wdd); - return devm_watchdog_register_device(dev, &wdat->wdd); + ret = devm_watchdog_register_device(dev, &wdat->wdd); + +out_put_table: + acpi_put_table((struct acpi_table_header *)tbl); + return ret; } static int wdat_wdt_suspend_noirq(struct device *dev) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 83e2ec7a84..c6908394e6 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1739,7 +1739,7 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp, /** * nfsd4_revoke_states - revoke all nfsv4 states associated with given filesystem - * @net: used to identify instance of nfsd (there is one per net namespace) + * @nn: used to identify instance of nfsd (there is one per net namespace) * @sb: super_block used to identify target filesystem * * All nfs4 states (open, lock, delegation, layout) held by the server instance @@ -1751,16 +1751,15 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp, * The clients which own the states will subsequently being notified that the * states have been "admin-revoked". */ -void nfsd4_revoke_states(struct net *net, struct super_block *sb) +void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb) { - struct nfsd_net *nn = net_generic(net, nfsd_net_id); unsigned int idhashval; unsigned int sc_types; sc_types = SC_TYPE_OPEN | SC_TYPE_LOCK | SC_TYPE_DELEG | SC_TYPE_LAYOUT; spin_lock(&nn->client_lock); - for (idhashval = 0; idhashval < CLIENT_HASH_MASK; idhashval++) { + for (idhashval = 0; idhashval < CLIENT_HASH_SIZE; idhashval++) { struct list_head *head = &nn->conf_id_hashtbl[idhashval]; struct nfs4_client *clp; retry: diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2116dbde38..727e69eb3d 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -254,6 +254,7 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) struct path path; char *fo_path; int error; + struct nfsd_net *nn; /* sanity check */ if (size == 0) @@ -280,7 +281,13 @@ static ssize_t write_unlock_fs(struct file *file, char *buf, size_t size) * 3. Is that directory the root of an exported file system? */ error = nlmsvc_unlock_all_by_sb(path.dentry->d_sb); - nfsd4_revoke_states(netns(file), path.dentry->d_sb); + mutex_lock(&nfsd_mutex); + nn = net_generic(netns(file), nfsd_net_id); + if (nn->nfsd_serv) + nfsd4_revoke_states(nn, path.dentry->d_sb); + else + error = -EINVAL; + mutex_unlock(&nfsd_mutex); path_put(&path); return error; diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 66fa4b5a38..37f8177f3a 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -765,9 +765,9 @@ static inline void get_nfs4_file(struct nfs4_file *fi) struct nfsd_file *find_any_file(struct nfs4_file *f); #ifdef CONFIG_NFSD_V4 -void nfsd4_revoke_states(struct net *net, struct super_block *sb); +void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb); #else -static inline void nfsd4_revoke_states(struct net *net, struct super_block *sb) +static inline void nfsd4_revoke_states(struct nfsd_net *nn, struct super_block *sb) { } #endif diff --git a/kernel.sbat b/kernel.sbat index 3714da50bb..b54e7dd0c8 100644 --- a/kernel.sbat +++ b/kernel.sbat @@ -1,3 +1,3 @@ sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.30.1.el9.x86_64,mailto:secalert@redhat.com -kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.30.1.el9.x86_64,mailto:security@almalinux.org +kernel.rhel,1,Red Hat,kernel-core,5.14.0-687.31.1.el9.x86_64,mailto:secalert@redhat.com +kernel.almalinux,1,AlmaLinux,kernel-core,5.14.0-687.31.1.el9.x86_64,mailto:security@almalinux.org diff --git a/kernel/fork.c b/kernel/fork.c index 36fa7c3634..cfcd664692 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -2151,9 +2151,11 @@ static void rv_task_fork(struct task_struct *p) static bool need_futex_hash_allocate_default(u64 clone_flags) { - if ((clone_flags & (CLONE_THREAD | CLONE_VM)) != (CLONE_THREAD | CLONE_VM)) - return false; - return true; + /* + * Allocate a default futex hash for any sibling that will + * share the parent's mm, except vfork. + */ + return (clone_flags & (CLONE_VM | CLONE_VFORK)) == CLONE_VM; } /* @@ -2530,10 +2532,6 @@ static __latent_entropy struct task_struct *copy_process( */ sched_cgroup_fork(p, args); - /* - * Allocate a default futex hash for the user process once the first - * thread spawns. - */ if (need_futex_hash_allocate_default(clone_flags)) { retval = futex_hash_allocate_default(); if (retval) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 65b3808a83..8e848a5ebb 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -461,8 +461,7 @@ static void watchdog_enable(unsigned int cpu) * Start the timer first to prevent the NMI watchdog triggering * before the timer has a chance to fire. */ - hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); - hrtimer->function = watchdog_timer_fn; + hrtimer_setup(hrtimer, watchdog_timer_fn, CLOCK_MONOTONIC, HRTIMER_MODE_REL_HARD); hrtimer_start(hrtimer, ns_to_ktime(sample_period), HRTIMER_MODE_REL_PINNED_HARD); diff --git a/lib/buildid.c b/lib/buildid.c index 7ef09b8ae6..235ea02b0f 100644 --- a/lib/buildid.c +++ b/lib/buildid.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #define BUILD_ID 3 @@ -65,20 +66,9 @@ static int freader_get_folio(struct freader *r, loff_t file_off) freader_put_folio(r); - /* reject secretmem folios created with memfd_secret() */ - if (secretmem_mapping(r->file->f_mapping)) - return -EFAULT; - + /* only use page cache lookup - fail if not already cached */ r->folio = filemap_get_folio(r->file->f_mapping, file_off >> PAGE_SHIFT); - /* if sleeping is allowed, wait for the page, if necessary */ - if (r->may_fault && (IS_ERR(r->folio) || !folio_test_uptodate(r->folio))) { - filemap_invalidate_lock_shared(r->file->f_mapping); - r->folio = read_cache_folio(r->file->f_mapping, file_off >> PAGE_SHIFT, - NULL, r->file); - filemap_invalidate_unlock_shared(r->file->f_mapping); - } - if (IS_ERR(r->folio) || !folio_test_uptodate(r->folio)) { if (!IS_ERR(r->folio)) folio_put(r->folio); @@ -116,6 +106,24 @@ static const void *freader_fetch(struct freader *r, loff_t file_off, size_t sz) return r->data + file_off; } + /* reject secretmem folios created with memfd_secret() */ + if (secretmem_mapping(r->file->f_mapping)) { + r->err = -EFAULT; + return NULL; + } + + /* use __kernel_read() for sleepable context */ + if (r->may_fault) { + ssize_t ret; + + ret = __kernel_read(r->file, r->buf, sz, &file_off); + if (ret != sz) { + r->err = (ret < 0) ? ret : -EIO; + return NULL; + } + return r->buf; + } + /* fetch or reuse folio for given file offset */ r->err = freader_get_folio(r, file_off); if (r->err) diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 93a8144d43..65da6cb66f 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1505,6 +1505,26 @@ struct xfrm_state *xfrm_state_lookup_byspi(struct net *net, __be32 spi, } EXPORT_SYMBOL(xfrm_state_lookup_byspi); +static struct xfrm_state *xfrm_state_lookup_spi_proto(struct net *net, __be32 spi, u8 proto) +{ + struct xfrm_state *x; + unsigned int i; + + rcu_read_lock(); + for (i = 0; i <= net->xfrm.state_hmask; i++) { + hlist_for_each_entry_rcu(x, &net->xfrm.state_byspi[i], byspi) { + if (x->id.spi == spi && x->id.proto == proto) { + if (!xfrm_state_hold_rcu(x)) + continue; + rcu_read_unlock(); + return x; + } + } + } + rcu_read_unlock(); + return NULL; +} + static void __xfrm_state_insert(struct xfrm_state *x) { struct net *net = xs_net(x); @@ -2314,10 +2334,8 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high, unsigned int h; struct xfrm_state *x0; int err = -ENOENT; - __be32 minspi = htonl(low); - __be32 maxspi = htonl(high); + u32 range = high - low + 1; __be32 newspi = 0; - u32 mark = x->mark.v & x->mark.m; spin_lock_bh(&x->lock); if (x->km.state == XFRM_STATE_DEAD) { @@ -2331,39 +2349,38 @@ int xfrm_alloc_spi(struct xfrm_state *x, u32 low, u32 high, err = -ENOENT; - if (minspi == maxspi) { - x0 = xfrm_state_lookup(net, mark, &x->id.daddr, minspi, x->id.proto, x->props.family); - if (x0) { - NL_SET_ERR_MSG(extack, "Requested SPI is already in use"); - xfrm_state_put(x0); + for (h = 0; h < range; h++) { + u32 spi = (low == high) ? low : get_random_u32_inclusive(low, high); + if (spi == 0) + goto next; + newspi = htonl(spi); + + spin_lock_bh(&net->xfrm.xfrm_state_lock); + x0 = xfrm_state_lookup_spi_proto(net, newspi, x->id.proto); + if (!x0) { + x->id.spi = newspi; + h = xfrm_spi_hash(net, &x->id.daddr, newspi, x->id.proto, x->props.family); + XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, x->xso.type); + spin_unlock_bh(&net->xfrm.xfrm_state_lock); + err = 0; goto unlock; } - newspi = minspi; - } else { - u32 spi = 0; - for (h = 0; h < high-low+1; h++) { - spi = low + prandom_u32()%(high-low+1); - x0 = xfrm_state_lookup(net, mark, &x->id.daddr, htonl(spi), x->id.proto, x->props.family); - if (x0 == NULL) { - newspi = htonl(spi); - break; - } - xfrm_state_put(x0); - } - } - if (newspi) { - spin_lock_bh(&net->xfrm.xfrm_state_lock); - x->id.spi = newspi; - h = xfrm_spi_hash(net, &x->id.daddr, x->id.spi, x->id.proto, x->props.family); - XFRM_STATE_INSERT(byspi, &x->byspi, net->xfrm.state_byspi + h, - x->xso.type); + xfrm_state_put(x0); spin_unlock_bh(&net->xfrm.xfrm_state_lock); - err = 0; - } else { - NL_SET_ERR_MSG(extack, "No SPI available in the requested range"); +next: + if (signal_pending(current)) { + err = -ERESTARTSYS; + goto unlock; + } + + if (low == high) + break; } + if (err) + NL_SET_ERR_MSG(extack, "No SPI available in the requested range"); + unlock: spin_unlock_bh(&x->lock); diff --git a/redhat/configs/rhel/automotive/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV b/redhat/configs/rhel/automotive/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV new file mode 100644 index 0000000000..9002114dfe --- /dev/null +++ b/redhat/configs/rhel/automotive/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV @@ -0,0 +1 @@ +# CONFIG_WATCHDOG_PRETIMEOUT_GOV is not set diff --git a/redhat/configs/rhel/generic/x86/CONFIG_SOFT_WATCHDOG_PRETIMEOUT b/redhat/configs/rhel/generic/x86/CONFIG_SOFT_WATCHDOG_PRETIMEOUT new file mode 100644 index 0000000000..d70ffa0103 --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_SOFT_WATCHDOG_PRETIMEOUT @@ -0,0 +1 @@ +# CONFIG_SOFT_WATCHDOG_PRETIMEOUT is not set diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT new file mode 100644 index 0000000000..2872790374 --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT @@ -0,0 +1 @@ +CONFIG_WATCHDOG_HRTIMER_PRETIMEOUT=y diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP new file mode 100644 index 0000000000..e017e8fdbc --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP @@ -0,0 +1 @@ +# CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_NOOP is not set diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC new file mode 100644 index 0000000000..7ca335b94e --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC @@ -0,0 +1 @@ +CONFIG_WATCHDOG_PRETIMEOUT_DEFAULT_GOV_PANIC=y diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV new file mode 100644 index 0000000000..d7d095b471 --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV @@ -0,0 +1 @@ +CONFIG_WATCHDOG_PRETIMEOUT_GOV=y diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP new file mode 100644 index 0000000000..855f90b7be --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP @@ -0,0 +1 @@ +# CONFIG_WATCHDOG_PRETIMEOUT_GOV_NOOP is not set diff --git a/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC new file mode 100644 index 0000000000..42dc93a56d --- /dev/null +++ b/redhat/configs/rhel/generic/x86/CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC @@ -0,0 +1 @@ +CONFIG_WATCHDOG_PRETIMEOUT_GOV_PANIC=y diff --git a/redhat/kernel.changelog-9.8 b/redhat/kernel.changelog-9.8 index df43702a70..cfba9185a3 100644 --- a/redhat/kernel.changelog-9.8 +++ b/redhat/kernel.changelog-9.8 @@ -1,3 +1,28 @@ +* Mon Jul 27 2026 CKI KWF Bot [5.14.0-687.31.1.el9_8] +- blk-mq: reinsert cached request to the list (CKI Backport Bot) [RHEL-213163] {CVE-2026-64017} +- blk-mq: pop cached request if it is usable (CKI Backport Bot) [RHEL-213163] {CVE-2026-64017} +- futex: Drop CLONE_THREAD requirement for private default hash alloc (Audra Mitchell) [RHEL-193517] {CVE-2026-52973} +- watchdog: Fix NULL pointer dereference when releasing cdev (Krzysztof Pawlinski) [RHEL-193729] +- redhat/configs: enable watchdog pretimout panic functionality for x86 (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: wdat_wdt: Fix ACPI table leak in probe function (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: Switch to use hrtimer_setup() (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: Convert comma to semicolon (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: wdat_wdt: Add timeout value as a param in ping method (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: Report firmware_version (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: Set NO_REBOOT if the watchdog is not already running (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: Using existing macro define covers more scenarios (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: No need to stop the timer in probe (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: only run driver set_pretimeout op if device supports it (Krzysztof Pawlinski) [RHEL-193729] +- watchdog: iTCO_wdt: Make use of the helper function devm_platform_ioremap_resource() (Krzysztof Pawlinski) [RHEL-193729] +- xfrm: xfrm_alloc_spi shouldn't use 0 as SPI (Sabrina Dubroca) [RHEL-180033] {CVE-2025-39797} +- xfrm: Duplicate SPI Handling (Sabrina Dubroca) [RHEL-180033] {CVE-2025-39797} +- iommu/vt-d: Avoid NULL pointer dereference or refcount corruption (Eder Zulian) [RHEL-190342] {CVE-2026-53281} +- iommu/vt-d: Fix oops due to out of scope access (Eder Zulian) [RHEL-190342] +- lib/buildid: use __kernel_read() for sleepable context (CKI Backport Bot) [RHEL-189962] {CVE-2026-23002} +- nfsd: use correct loop termination in nfsd4_revoke_states() (CKI Backport Bot) [RHEL-188257] +- nfsd: check that server is running in unlock_filesystem (CKI Backport Bot) [RHEL-188257] +Resolves: RHEL-180033, RHEL-188257, RHEL-189962, RHEL-190342, RHEL-193517, RHEL-193729, RHEL-213163 + * Wed Jul 22 2026 CKI KWF Bot [5.14.0-687.30.1.el9_8] - KVM: x86/mmu: Ensure hugepage is in by slot before checking max mapping level (Aidan Wallace) [RHEL-213468] {CVE-2026-63807} - KVM: nVMX: Hide shadow VMCS right after VMCLEAR (Aidan Wallace) [RHEL-213468]