commit: bea0a2cdc30808ed55ebdaf1c1f96a3a14622cc9 Author: Arisu Tachibana <alicef <AT> gentoo <DOT> org> AuthorDate: Thu Aug 21 05:16:30 2025 +0000 Commit: Arisu Tachibana <alicef <AT> gentoo <DOT> org> CommitDate: Thu Aug 21 05:16:30 2025 +0000 URL: https://gitweb.gentoo.org/proj/linux-patches.git/commit/?id=bea0a2cd
Linux patch 5.4.277 Signed-off-by: Arisu Tachibana <alicef <AT> gentoo.org> 0000_README | 4 + 1276_linux-5.4.277.patch | 672 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 676 insertions(+) diff --git a/0000_README b/0000_README index 45e0bd46..7d241cb7 100644 --- a/0000_README +++ b/0000_README @@ -1147,6 +1147,10 @@ Patch: 1275_linux-5.4.276.patch From: https://www.kernel.org Desc: Linux 5.4.276 +Patch: 1276_linux-5.4.277.patch +From: https://www.kernel.org +Desc: Linux 5.4.277 + Patch: 1500_XATTR_USER_PREFIX.patch From: https://bugs.gentoo.org/show_bug.cgi?id=470644 Desc: Support for namespace user.pax.* on tmpfs. diff --git a/1276_linux-5.4.277.patch b/1276_linux-5.4.277.patch new file mode 100644 index 00000000..d06c01ba --- /dev/null +++ b/1276_linux-5.4.277.patch @@ -0,0 +1,672 @@ +diff --git a/Documentation/sphinx/kernel_include.py b/Documentation/sphinx/kernel_include.py +index f523aa68a36b3..cf601bd058abe 100755 +--- a/Documentation/sphinx/kernel_include.py ++++ b/Documentation/sphinx/kernel_include.py +@@ -94,7 +94,6 @@ class KernelInclude(Include): + # HINT: this is the only line I had to change / commented out: + #path = utils.relative_path(None, path) + +- path = nodes.reprunicode(path) + encoding = self.options.get( + 'encoding', self.state.document.settings.input_encoding) + e_handler=self.state.document.settings.input_encoding_error_handler +diff --git a/Makefile b/Makefile +index b45c9b7543e51..99ea904294654 100644 +--- a/Makefile ++++ b/Makefile +@@ -1,7 +1,7 @@ + # SPDX-License-Identifier: GPL-2.0 + VERSION = 5 + PATCHLEVEL = 4 +-SUBLEVEL = 276 ++SUBLEVEL = 277 + EXTRAVERSION = + NAME = Kleptomaniac Octopus + +diff --git a/arch/arm64/boot/dts/qcom/msm8998.dtsi b/arch/arm64/boot/dts/qcom/msm8998.dtsi +index 9cb7163c5714c..5c653ab907463 100644 +--- a/arch/arm64/boot/dts/qcom/msm8998.dtsi ++++ b/arch/arm64/boot/dts/qcom/msm8998.dtsi +@@ -872,10 +872,10 @@ pcie0: pci@1c00000 { + interrupts = <GIC_SPI 405 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "msi"; + interrupt-map-mask = <0 0 0 0x7>; +- interrupt-map = <0 0 0 1 &intc 0 135 IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 2 &intc 0 136 IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 3 &intc 0 138 IRQ_TYPE_LEVEL_HIGH>, +- <0 0 0 4 &intc 0 139 IRQ_TYPE_LEVEL_HIGH>; ++ interrupt-map = <0 0 0 1 &intc 0 0 135 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 2 &intc 0 0 136 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 3 &intc 0 0 138 IRQ_TYPE_LEVEL_HIGH>, ++ <0 0 0 4 &intc 0 0 139 IRQ_TYPE_LEVEL_HIGH>; + + clocks = <&gcc GCC_PCIE_0_PIPE_CLK>, + <&gcc GCC_PCIE_0_MSTR_AXI_CLK>, +diff --git a/drivers/firmware/arm_scmi/reset.c b/drivers/firmware/arm_scmi/reset.c +index 6d223f345b6c9..b45d3e9cee129 100644 +--- a/drivers/firmware/arm_scmi/reset.c ++++ b/drivers/firmware/arm_scmi/reset.c +@@ -135,8 +135,12 @@ static int scmi_domain_reset(const struct scmi_handle *handle, u32 domain, + struct scmi_xfer *t; + struct scmi_msg_reset_domain_reset *dom; + struct scmi_reset_info *pi = handle->reset_priv; +- struct reset_dom_info *rdom = pi->dom_info + domain; ++ struct reset_dom_info *rdom; + ++ if (domain >= pi->num_domains) ++ return -EINVAL; ++ ++ rdom = pi->dom_info + domain; + if (rdom->async_reset) + flags |= ASYNCHRONOUS_RESET; + +diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +index 9c5cbc47edf1a..b6fc191c353a7 100644 +--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c ++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +@@ -594,6 +594,9 @@ int amdgpu_ras_error_query(struct amdgpu_device *adev, + if (!obj) + return -EINVAL; + ++ if (!info || info->head.block == AMDGPU_RAS_BLOCK_COUNT) ++ return -EINVAL; ++ + switch (info->head.block) { + case AMDGPU_RAS_BLOCK__UMC: + if (adev->umc.funcs->query_ras_error_count) +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +index 469cfc74617a6..fd5f9a3a8352d 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c +@@ -1990,12 +1990,18 @@ static void umac_enable_set(struct bcmgenet_priv *priv, u32 mask, bool enable) + { + u32 reg; + ++ spin_lock_bh(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); ++ if (reg & CMD_SW_RESET) { ++ spin_unlock_bh(&priv->reg_lock); ++ return; ++ } + if (enable) + reg |= mask; + else + reg &= ~mask; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock_bh(&priv->reg_lock); + + /* UniMAC stops on a packet boundary, wait for a full-size packet + * to be processed +@@ -2010,11 +2016,11 @@ static void reset_umac(struct bcmgenet_priv *priv) + bcmgenet_rbuf_ctrl_set(priv, 0); + udelay(10); + +- /* disable MAC while updating its registers */ +- bcmgenet_umac_writel(priv, 0, UMAC_CMD); +- +- /* issue soft reset with (rg)mii loopback to ensure a stable rxclk */ +- bcmgenet_umac_writel(priv, CMD_SW_RESET | CMD_LCL_LOOP_EN, UMAC_CMD); ++ /* issue soft reset and disable MAC while updating its registers */ ++ spin_lock_bh(&priv->reg_lock); ++ bcmgenet_umac_writel(priv, CMD_SW_RESET, UMAC_CMD); ++ udelay(2); ++ spin_unlock_bh(&priv->reg_lock); + } + + static void bcmgenet_intr_disable(struct bcmgenet_priv *priv) +@@ -2882,7 +2888,9 @@ static void bcmgenet_netif_start(struct net_device *dev) + struct bcmgenet_priv *priv = netdev_priv(dev); + + /* Start the network engine */ ++ netif_addr_lock_bh(dev); + bcmgenet_set_rx_mode(dev); ++ netif_addr_unlock_bh(dev); + bcmgenet_enable_rx_napi(priv); + + umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); +@@ -3146,16 +3154,19 @@ static void bcmgenet_set_rx_mode(struct net_device *dev) + * 3. The number of filters needed exceeds the number filters + * supported by the hardware. + */ ++ spin_lock(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); + if ((dev->flags & (IFF_PROMISC | IFF_ALLMULTI)) || + (nfilter > MAX_MDF_FILTER)) { + reg |= CMD_PROMISC; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock(&priv->reg_lock); + bcmgenet_umac_writel(priv, 0, UMAC_MDF_CTRL); + return; + } else { + reg &= ~CMD_PROMISC; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock(&priv->reg_lock); + } + + /* update MDF filter */ +@@ -3513,6 +3524,7 @@ static int bcmgenet_probe(struct platform_device *pdev) + goto err; + } + ++ spin_lock_init(&priv->reg_lock); + spin_lock_init(&priv->lock); + + SET_NETDEV_DEV(dev, &pdev->dev); +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h +index 29bf256d13f67..9efc503a9c8b2 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h +@@ -608,6 +608,8 @@ struct bcmgenet_rx_ring { + /* device context */ + struct bcmgenet_priv { + void __iomem *base; ++ /* reg_lock: lock to serialize access to shared registers */ ++ spinlock_t reg_lock; + enum bcmgenet_version version; + struct net_device *dev; + +diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +index a2da09da4907b..973275d116b61 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +@@ -132,10 +132,16 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, + return -EINVAL; + } + +- /* disable RX */ ++ /* Can't suspend with WoL if MAC is still in reset */ ++ spin_lock_bh(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); ++ if (reg & CMD_SW_RESET) ++ reg &= ~CMD_SW_RESET; ++ ++ /* disable RX */ + reg &= ~CMD_RX_EN; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock_bh(&priv->reg_lock); + mdelay(10); + + reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL); +@@ -159,6 +165,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, + retries); + + /* Enable CRC forward */ ++ spin_lock_bh(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); + priv->crc_fwd_en = 1; + reg |= CMD_CRC_FWD; +@@ -166,6 +173,7 @@ int bcmgenet_wol_power_down_cfg(struct bcmgenet_priv *priv, + /* Receiver must be enabled for WOL MP detection */ + reg |= CMD_RX_EN; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock_bh(&priv->reg_lock); + + return 0; + } +@@ -187,8 +195,10 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, + bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL); + + /* Disable CRC Forward */ ++ spin_lock_bh(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); + reg &= ~CMD_CRC_FWD; + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock_bh(&priv->reg_lock); + priv->crc_fwd_en = 0; + } +diff --git a/drivers/net/ethernet/broadcom/genet/bcmmii.c b/drivers/net/ethernet/broadcom/genet/bcmmii.c +index 026f00ccaa0cd..bd532e5b9f73b 100644 +--- a/drivers/net/ethernet/broadcom/genet/bcmmii.c ++++ b/drivers/net/ethernet/broadcom/genet/bcmmii.c +@@ -91,12 +91,20 @@ void bcmgenet_mii_setup(struct net_device *dev) + reg |= RGMII_LINK; + bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); + ++ spin_lock_bh(&priv->reg_lock); + reg = bcmgenet_umac_readl(priv, UMAC_CMD); + reg &= ~((CMD_SPEED_MASK << CMD_SPEED_SHIFT) | + CMD_HD_EN | + CMD_RX_PAUSE_IGNORE | CMD_TX_PAUSE_IGNORE); + reg |= cmd_bits; ++ if (reg & CMD_SW_RESET) { ++ reg &= ~CMD_SW_RESET; ++ bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ udelay(2); ++ reg |= CMD_TX_EN | CMD_RX_EN; ++ } + bcmgenet_umac_writel(priv, reg, UMAC_CMD); ++ spin_unlock_bh(&priv->reg_lock); + + priv->eee.eee_active = phy_init_eee(phydev, 0) >= 0; + bcmgenet_eee_enable_set(dev, +@@ -187,38 +195,8 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) + const char *phy_name = NULL; + u32 id_mode_dis = 0; + u32 port_ctrl; +- int bmcr = -1; +- int ret; + u32 reg; + +- /* MAC clocking workaround during reset of umac state machines */ +- reg = bcmgenet_umac_readl(priv, UMAC_CMD); +- if (reg & CMD_SW_RESET) { +- /* An MII PHY must be isolated to prevent TXC contention */ +- if (priv->phy_interface == PHY_INTERFACE_MODE_MII) { +- ret = phy_read(phydev, MII_BMCR); +- if (ret >= 0) { +- bmcr = ret; +- ret = phy_write(phydev, MII_BMCR, +- bmcr | BMCR_ISOLATE); +- } +- if (ret) { +- netdev_err(dev, "failed to isolate PHY\n"); +- return ret; +- } +- } +- /* Switch MAC clocking to RGMII generated clock */ +- bcmgenet_sys_writel(priv, PORT_MODE_EXT_GPHY, SYS_PORT_CTRL); +- /* Ensure 5 clks with Rx disabled +- * followed by 5 clks with Reset asserted +- */ +- udelay(4); +- reg &= ~(CMD_SW_RESET | CMD_LCL_LOOP_EN); +- bcmgenet_umac_writel(priv, reg, UMAC_CMD); +- /* Ensure 5 more clocks before Rx is enabled */ +- udelay(2); +- } +- + priv->ext_phy = !priv->internal_phy && + (priv->phy_interface != PHY_INTERFACE_MODE_MOCA); + +@@ -250,9 +228,6 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) + phy_set_max_speed(phydev, SPEED_100); + bcmgenet_sys_writel(priv, + PORT_MODE_EXT_EPHY, SYS_PORT_CTRL); +- /* Restore the MII PHY after isolation */ +- if (bmcr >= 0) +- phy_write(phydev, MII_BMCR, bmcr); + break; + + case PHY_INTERFACE_MODE_REVMII: +@@ -296,6 +271,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) + * block for the interface to work + */ + if (priv->ext_phy) { ++ mutex_lock(&phydev->lock); + reg = bcmgenet_ext_readl(priv, EXT_RGMII_OOB_CTRL); + reg |= id_mode_dis; + if (GENET_IS_V1(priv) || GENET_IS_V2(priv) || GENET_IS_V3(priv)) +@@ -303,6 +279,7 @@ int bcmgenet_mii_config(struct net_device *dev, bool init) + else + reg |= RGMII_MODE_EN; + bcmgenet_ext_writel(priv, reg, EXT_RGMII_OOB_CTRL); ++ mutex_unlock(&phydev->lock); + } + + if (init) +diff --git a/drivers/pinctrl/core.c b/drivers/pinctrl/core.c +index 3947b7064bead..44802e5017945 100644 +--- a/drivers/pinctrl/core.c ++++ b/drivers/pinctrl/core.c +@@ -203,6 +203,7 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, + const struct pinctrl_pin_desc *pin) + { + struct pin_desc *pindesc; ++ int error; + + pindesc = pin_desc_get(pctldev, pin->number); + if (pindesc) { +@@ -224,18 +225,25 @@ static int pinctrl_register_one_pin(struct pinctrl_dev *pctldev, + } else { + pindesc->name = kasprintf(GFP_KERNEL, "PIN%u", pin->number); + if (!pindesc->name) { +- kfree(pindesc); +- return -ENOMEM; ++ error = -ENOMEM; ++ goto failed; + } + pindesc->dynamic_name = true; + } + + pindesc->drv_data = pin->drv_data; + +- radix_tree_insert(&pctldev->pin_desc_tree, pin->number, pindesc); ++ error = radix_tree_insert(&pctldev->pin_desc_tree, pin->number, pindesc); ++ if (error) ++ goto failed; ++ + pr_debug("registered pin %d (%s) on %s\n", + pin->number, pindesc->name, pctldev->desc->name); + return 0; ++ ++failed: ++ kfree(pindesc); ++ return error; + } + + static int pinctrl_register_pins(struct pinctrl_dev *pctldev, +diff --git a/drivers/tty/serial/kgdboc.c b/drivers/tty/serial/kgdboc.c +index 6d4792ec9e5fa..2df77f894746d 100644 +--- a/drivers/tty/serial/kgdboc.c ++++ b/drivers/tty/serial/kgdboc.c +@@ -19,6 +19,7 @@ + #include <linux/console.h> + #include <linux/vt_kern.h> + #include <linux/input.h> ++#include <linux/irq_work.h> + #include <linux/module.h> + #include <linux/platform_device.h> + +@@ -42,6 +43,25 @@ static int kgdb_tty_line; + + static struct platform_device *kgdboc_pdev; + ++/* ++ * When we leave the debug trap handler we need to reset the keyboard status ++ * (since the original keyboard state gets partially clobbered by kdb use of ++ * the keyboard). ++ * ++ * The path to deliver the reset is somewhat circuitous. ++ * ++ * To deliver the reset we register an input handler, reset the keyboard and ++ * then deregister the input handler. However, to get this done right, we do ++ * have to carefully manage the calling context because we can only register ++ * input handlers from task context. ++ * ++ * In particular we need to trigger the action from the debug trap handler with ++ * all its NMI and/or NMI-like oddities. To solve this the kgdboc trap exit code ++ * (the "post_exception" callback) uses irq_work_queue(), which is NMI-safe, to ++ * schedule a callback from a hardirq context. From there we have to defer the ++ * work again, this time using schedule_work(), to get a callback using the ++ * system workqueue, which runs in task context. ++ */ + #ifdef CONFIG_KDB_KEYBOARD + static int kgdboc_reset_connect(struct input_handler *handler, + struct input_dev *dev, +@@ -93,10 +113,17 @@ static void kgdboc_restore_input_helper(struct work_struct *dummy) + + static DECLARE_WORK(kgdboc_restore_input_work, kgdboc_restore_input_helper); + ++static void kgdboc_queue_restore_input_helper(struct irq_work *unused) ++{ ++ schedule_work(&kgdboc_restore_input_work); ++} ++ ++static DEFINE_IRQ_WORK(kgdboc_restore_input_irq_work, kgdboc_queue_restore_input_helper); ++ + static void kgdboc_restore_input(void) + { + if (likely(system_state == SYSTEM_RUNNING)) +- schedule_work(&kgdboc_restore_input_work); ++ irq_work_queue(&kgdboc_restore_input_irq_work); + } + + static int kgdboc_register_kbd(char **cptr) +@@ -127,6 +154,7 @@ static void kgdboc_unregister_kbd(void) + i--; + } + } ++ irq_work_sync(&kgdboc_restore_input_irq_work); + flush_work(&kgdboc_restore_input_work); + } + #else /* ! CONFIG_KDB_KEYBOARD */ +diff --git a/drivers/usb/typec/ucsi/displayport.c b/drivers/usb/typec/ucsi/displayport.c +index 166c2aabb512b..f67c5a3041559 100644 +--- a/drivers/usb/typec/ucsi/displayport.c ++++ b/drivers/usb/typec/ucsi/displayport.c +@@ -251,8 +251,6 @@ static void ucsi_displayport_work(struct work_struct *work) + struct ucsi_dp *dp = container_of(work, struct ucsi_dp, work); + int ret; + +- mutex_lock(&dp->con->lock); +- + ret = typec_altmode_vdm(dp->alt, dp->header, + dp->vdo_data, dp->vdo_size); + if (ret) +@@ -261,8 +259,6 @@ static void ucsi_displayport_work(struct work_struct *work) + dp->vdo_data = NULL; + dp->vdo_size = 0; + dp->header = 0; +- +- mutex_unlock(&dp->con->lock); + } + + void ucsi_displayport_remove_partner(struct typec_altmode *alt) +diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c +index d7014b2b28d6a..10cc12ad2a2bd 100644 +--- a/fs/btrfs/volumes.c ++++ b/fs/btrfs/volumes.c +@@ -3277,6 +3277,7 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info) + * alignment and size). + */ + ret = -EUCLEAN; ++ mutex_unlock(&fs_info->delete_unused_bgs_mutex); + goto error; + } + +diff --git a/fs/cifs/smb2ops.c b/fs/cifs/smb2ops.c +index 5fea15a5f3419..b2e45e168548b 100644 +--- a/fs/cifs/smb2ops.c ++++ b/fs/cifs/smb2ops.c +@@ -787,9 +787,11 @@ int open_shroot(unsigned int xid, struct cifs_tcon *tcon, + /* BB TBD check to see if oplock level check can be removed below */ + if (o_rsp->OplockLevel == SMB2_OPLOCK_LEVEL_LEASE) { + kref_get(&tcon->crfid.refcount); +- smb2_parse_contexts(server, o_rsp, ++ rc = smb2_parse_contexts(server, rsp_iov, + &oparms.fid->epoch, + oparms.fid->lease_key, &oplock, NULL); ++ if (rc) ++ goto oshr_exit; + } else + goto oshr_exit; + +diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c +index da1a1b531ca5e..667528132b692 100644 +--- a/fs/cifs/smb2pdu.c ++++ b/fs/cifs/smb2pdu.c +@@ -1929,48 +1929,73 @@ parse_query_id_ctxt(struct create_context *cc, struct smb2_file_all_info *buf) + buf->IndexNumber = pdisk_id->DiskFileId; + } + +-void +-smb2_parse_contexts(struct TCP_Server_Info *server, +- struct smb2_create_rsp *rsp, +- unsigned int *epoch, char *lease_key, __u8 *oplock, +- struct smb2_file_all_info *buf) ++int smb2_parse_contexts(struct TCP_Server_Info *server, ++ struct kvec *rsp_iov, ++ unsigned int *epoch, ++ char *lease_key, __u8 *oplock, ++ struct smb2_file_all_info *buf) + { +- char *data_offset; ++ struct smb2_create_rsp *rsp = rsp_iov->iov_base; + struct create_context *cc; +- unsigned int next; +- unsigned int remaining; ++ size_t rem, off, len; ++ size_t doff, dlen; ++ size_t noff, nlen; + char *name; + + *oplock = 0; +- data_offset = (char *)rsp + le32_to_cpu(rsp->CreateContextsOffset); +- remaining = le32_to_cpu(rsp->CreateContextsLength); +- cc = (struct create_context *)data_offset; ++ ++ off = le32_to_cpu(rsp->CreateContextsOffset); ++ rem = le32_to_cpu(rsp->CreateContextsLength); ++ if (check_add_overflow(off, rem, &len) || len > rsp_iov->iov_len) ++ return -EINVAL; ++ cc = (struct create_context *)((u8 *)rsp + off); + + /* Initialize inode number to 0 in case no valid data in qfid context */ + if (buf) + buf->IndexNumber = 0; + +- while (remaining >= sizeof(struct create_context)) { +- name = le16_to_cpu(cc->NameOffset) + (char *)cc; +- if (le16_to_cpu(cc->NameLength) == 4 && +- strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4) == 0) +- *oplock = server->ops->parse_lease_buf(cc, epoch, +- lease_key); +- else if (buf && (le16_to_cpu(cc->NameLength) == 4) && +- strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4) == 0) +- parse_query_id_ctxt(cc, buf); +- +- next = le32_to_cpu(cc->Next); +- if (!next) ++ while (rem >= sizeof(*cc)) { ++ doff = le16_to_cpu(cc->DataOffset); ++ dlen = le32_to_cpu(cc->DataLength); ++ if (check_add_overflow(doff, dlen, &len) || len > rem) ++ return -EINVAL; ++ ++ noff = le16_to_cpu(cc->NameOffset); ++ nlen = le16_to_cpu(cc->NameLength); ++ if (noff + nlen >= doff) ++ return -EINVAL; ++ ++ name = (char *)cc + noff; ++ switch (nlen) { ++ case 4: ++ if (!strncmp(name, SMB2_CREATE_REQUEST_LEASE, 4)) { ++ *oplock = server->ops->parse_lease_buf(cc, epoch, ++ lease_key); ++ } else if (buf && ++ !strncmp(name, SMB2_CREATE_QUERY_ON_DISK_ID, 4)) { ++ parse_query_id_ctxt(cc, buf); ++ } ++ break; ++ default: ++ cifs_dbg(FYI, "%s: unhandled context (nlen=%zu dlen=%zu)\n", ++ __func__, nlen, dlen); ++ if (IS_ENABLED(CONFIG_CIFS_DEBUG2)) ++ cifs_dump_mem("context data: ", cc, dlen); ++ break; ++ } ++ ++ off = le32_to_cpu(cc->Next); ++ if (!off) + break; +- remaining -= next; +- cc = (struct create_context *)((char *)cc + next); ++ if (check_sub_overflow(rem, off, &rem)) ++ return -EINVAL; ++ cc = (struct create_context *)((u8 *)cc + off); + } + + if (rsp->OplockLevel != SMB2_OPLOCK_LEVEL_LEASE) + *oplock = rsp->OplockLevel; + +- return; ++ return 0; + } + + static int +@@ -2680,8 +2705,8 @@ SMB2_open(const unsigned int xid, struct cifs_open_parms *oparms, __le16 *path, + } + + +- smb2_parse_contexts(server, rsp, &oparms->fid->epoch, +- oparms->fid->lease_key, oplock, buf); ++ rc = smb2_parse_contexts(server, &rsp_iov, &oparms->fid->epoch, ++ oparms->fid->lease_key, oplock, buf); + creat_exit: + SMB2_open_free(&rqst); + free_rsp_buf(resp_buftype, rsp); +diff --git a/fs/cifs/smb2proto.h b/fs/cifs/smb2proto.h +index 4d4c0faa3d8a3..2f08f7f13ced7 100644 +--- a/fs/cifs/smb2proto.h ++++ b/fs/cifs/smb2proto.h +@@ -238,10 +238,12 @@ extern int smb3_validate_negotiate(const unsigned int, struct cifs_tcon *); + + extern enum securityEnum smb2_select_sectype(struct TCP_Server_Info *, + enum securityEnum); +-extern void smb2_parse_contexts(struct TCP_Server_Info *server, +- struct smb2_create_rsp *rsp, +- unsigned int *epoch, char *lease_key, +- __u8 *oplock, struct smb2_file_all_info *buf); ++int smb2_parse_contexts(struct TCP_Server_Info *server, ++ struct kvec *rsp_iov, ++ unsigned int *epoch, ++ char *lease_key, __u8 *oplock, ++ struct smb2_file_all_info *buf); ++ + extern int smb3_encryption_required(const struct cifs_tcon *tcon); + extern int smb2_validate_iov(unsigned int offset, unsigned int buffer_length, + struct kvec *iov, unsigned int min_buf_size); +diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c +index 98e1b1ddb4ec7..90b12c7c0f20a 100644 +--- a/fs/ext4/extents.c ++++ b/fs/ext4/extents.c +@@ -409,7 +409,7 @@ static int ext4_valid_extent_entries(struct inode *inode, + { + unsigned short entries; + ext4_lblk_t lblock = 0; +- ext4_lblk_t prev = 0; ++ ext4_lblk_t cur = 0; + + if (eh->eh_entries == 0) + return 1; +@@ -435,12 +435,12 @@ static int ext4_valid_extent_entries(struct inode *inode, + + /* Check for overlapping extents */ + lblock = le32_to_cpu(ext->ee_block); +- if ((lblock <= prev) && prev) { ++ if (lblock < cur) { + pblock = ext4_ext_pblock(ext); + es->s_last_error_block = cpu_to_le64(pblock); + return 0; + } +- prev = lblock + ext4_ext_get_actual_len(ext) - 1; ++ cur = lblock + ext4_ext_get_actual_len(ext); + ext++; + entries--; + } +@@ -460,13 +460,13 @@ static int ext4_valid_extent_entries(struct inode *inode, + + /* Check for overlapping index extents */ + lblock = le32_to_cpu(ext_idx->ei_block); +- if ((lblock <= prev) && prev) { ++ if (lblock < cur) { + *pblk = ext4_idx_pblock(ext_idx); + return 0; + } + ext_idx++; + entries--; +- prev = lblock; ++ cur = lblock + 1; + } + } + return 1; +diff --git a/tools/testing/selftests/vm/map_hugetlb.c b/tools/testing/selftests/vm/map_hugetlb.c +index c65c55b7a789f..312889edb84ab 100644 +--- a/tools/testing/selftests/vm/map_hugetlb.c ++++ b/tools/testing/selftests/vm/map_hugetlb.c +@@ -15,7 +15,6 @@ + #include <unistd.h> + #include <sys/mman.h> + #include <fcntl.h> +-#include "vm_util.h" + + #define LENGTH (256UL*1024*1024) + #define PROTECTION (PROT_READ | PROT_WRITE) +@@ -71,16 +70,10 @@ int main(int argc, char **argv) + { + void *addr; + int ret; +- size_t hugepage_size; + size_t length = LENGTH; + int flags = FLAGS; + int shift = 0; + +- hugepage_size = default_huge_page_size(); +- /* munmap with fail if the length is not page aligned */ +- if (hugepage_size > length) +- length = hugepage_size; +- + if (argc > 1) + length = atol(argv[1]) << 20; + if (argc > 2) {
