6.6.145-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 386/1266 vxlan: Fix potential null-ptr-deref in vxlan_gro_prepare_receive().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 30a45c0bffdd62350261e2f2689fdba426a33578 ]
udp_tunnel_sock_release() could set sk->sk_user_data to NULL while vxlan_gro_prepare_receive() is running.
Let's check if rcu_dereference_sk_user_data() is NULL after skb_gro_remcsum_init().
--- drivers/net/vxlan/vxlan_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +6 -2
@@ -680,14 +680,18 @@ static struct vxlanhdr *vxlan_gro_prepare_receive(struct sock *sk,struct sk_buff *skb, struct gro_remcsum *grc) { - struct sk_buff *p; struct vxlanhdr *vh, *vh2;unsigned int hlen, off_vx; -struct vxlan_sock *vs =rcu_dereference_sk_user_data (sk); +struct vxlan_sock *vs; +struct sk_buff *p;__be32 flags;skb_gro_remcsum_init (grc); + vs =rcu_dereference_sk_user_data (sk); +if (!vs) +return NULL ; + off_vx =skb_gro_offset (skb); hlen = off_vx +sizeof (*vh); vh =skb_gro_header (skb, hlen, off_vx);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 387/1266 crypto: atmel-sha204a - fix blocking and non-blocking rng logic
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lothar Rubusch <[email protected]>
[ Upstream commit 319400fc5ee15db5793aa45f854968141326effc ]
The blocking and non-blocking paths were failing to provide valid entropy due to improper buffer management. Reading the buffer starting from byte 1, only fetch the 32 bytes of random data from the return message.
Tested on an Atmel SHA204A device.
Before (here for blocking), tests showed repeatedly reading reduced bytes.
$ head -c 32 /dev/hwrng | hexdump -C 00000000 02 28 85 b3 47 40 f2 ee 00 00 00 00 00 00 00 00 |.(..G@..........| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000020
After, the result will be similar to the following:
$ head -c 32 /dev/hwrng | hexdump -C 00000000 5a fc 3f 13 14 68 fe 06 68 0a bd 04 83 6e 09 69 |Z.?..h..h....n.i| 00000010 75 ff cf 87 10 84 3b c9 c1 df ae eb 45 53 4c c3 |u.....;.....ESL.| 00000020
--- drivers/crypto/atmel-sha204a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/crypto/atmel-sha204a.c +4 -4
@@ -47,8 +47,8 @@ static int atmel_sha204a_rng_read_nonblocking(struct hwrng *rng, void *data,if (rng->priv) { work_data = (struct atmel_i2c_work_data *)rng->priv; - max =min (sizeof (work_data->cmd.data), max); -memcpy (data, &work_data->cmd.data, max); + max =min (RANDOM_RSP_SIZE -CMD_OVERHEAD_SIZE , max); +memcpy (data, &work_data->cmd.data[RSP_DATA_IDX ], max); rng->priv =0 ; }else { work_data =kmalloc (sizeof (*work_data),GFP_ATOMIC );
@@ -86,8 +86,8 @@ static int atmel_sha204a_rng_read(struct hwrng *rng, void *data, size_t max,if (ret)return ret; - max =min (sizeof (cmd.data), max); -memcpy (data, cmd.data, max); + max =min (RANDOM_RSP_SIZE -CMD_OVERHEAD_SIZE , max); +memcpy (data, &cmd.data[RSP_DATA_IDX ], max);return max; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 388/1266 crypto: ecrdsa - fix unknown OID check in ecrdsa_param_curve
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 2d7b2cfc59998baf5e8622a24dc28f69a5212e06 ]
The ->curve_oid check in ecrdsa_param_curve() rejects the valid enum value 0 (OID_id_dsa_with_sha1), but look_up_OID() returns OID__NR on lookup failure. Compare ->curve_oid with OID__NR instead to ensure that only unknown OIDs return -EINVAL.
--- crypto/ecrdsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
crypto/ecrdsa.c +1 -1
@@ -153,7 +153,7 @@ int ecrdsa_param_curve(void *context, size_t hdrlen, unsigned char tag,struct ecrdsa_ctx *ctx = context; ctx->curve_oid =look_up_OID (value, vlen); -if (!ctx->curve_oid) +if (ctx->curve_oid ==OID__NR )return -EINVAL ; ctx->curve =get_curve_by_oid (ctx->curve_oid);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 389/1266 crypto: asymmetric_keys - fix OOB read in pefile_digest_pe_contents
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit f7dd32c5179d7755de18e21d5674b08f9e5cb180 ]
pefile_digest_pe_contents() computes the trailing-data hash length as pelen - (hashed_bytes + certs_size). A crafted PE can make the addition exceed pelen, causing the unsigned subtraction to underflow to ~4 GiB. This is passed to crypto_shash_update() which reads out of bounds and panics on unmapped vmalloc guard pages.
BUG: unable to handle page fault for address: ffffc900038d8000 Oops: Oops: 0000 [#1] SMP KASAN NOPTI RIP: 0010:sha256_blocks_generic (lib/crypto/sha256.c:152) Call Trace: <TASK> __sha256_update (lib/crypto/sha256.c:208) crypto_sha256_update (crypto/sha256.c:142) verify_pefile_signature (crypto/asymmetric_keys/verify_pefile.c:436) kexec_kernel_verify_pe_sig (kernel/kexec_file.c:151) __do_sys_kexec_file_load (kernel/kexec_file.c:406) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) </TASK> Kernel panic - not syncing: Fatal exception
Validate that the addition does not overflow and the result does not exceed pelen before the subtraction. Return -ELIBBAD on failure.
--- crypto/asymmetric_keys/verify_pefile.c | 2 ++ 1 file changed, 2 insertions(+)
crypto/asymmetric_keys/verify_pefile.c +2 -0
@@ -305,6 +305,8 @@ static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,if (pelen > hashed_bytes) { tmp = hashed_bytes + ctx->certs_size; +if (tmp <= hashed_bytes || pelen < tmp) +return -ELIBBAD ; ret =crypto_shash_update (desc, pebuf + hashed_bytes, pelen - tmp);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 390/1266 dlm: fix add msg handle in send_queue ordered
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Aring <[email protected]>
[ Upstream commit d2248cb70c070f8f04762872772e155b59016f17 ]
In a benchmark scenario triggering a lot of requests that triggers a lot of DLM messages on the network it can be that the mh->seq is not ordered according the oldest seq number. This ordering is required by dlm_receive_ack as "before(mh->seq, seq)" will stop to check for older sequence numbers that are ordered in the tail of "node->send_queue".
The side effects of not having it correct ordered regarding "before(mh->seq, seq)" are refcounting issues and use-after free.
I only was able to reproduce this issue in a experimental DLM branch and a user space DLM benchmark that uses io_uring. After changing this I don't experienced any refcounting with the sending buffer issues anymore.
--- fs/dlm/midcomms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/dlm/midcomms.c +2 -2
@@ -970,10 +970,10 @@ static void midcomms_new_msg_cb(void *data)atomic_inc (&mh->node->send_queue_cnt);spin_lock_bh (&mh->node->send_queue_lock); +/* need to be locked with list_add_tail_rcu() because list is ordered */ + mh->seq =atomic_fetch_inc (&mh->node->seq_send);list_add_tail_rcu (&mh->list, &mh->node->send_queue);spin_unlock_bh (&mh->node->send_queue_lock); - - mh->seq =atomic_fetch_inc (&mh->node->seq_send); } static struct dlm_msg *dlm_midcomms_get_msg_3_2(struct dlm_mhandle *mh, int nodeid,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 391/1266 nilfs2: fix backing_dev_info reference leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <[email protected]>
[ Upstream commit 665f192a2a11384cb7dc1be5f87d16438522a4ed ]
setup_bdev_super() already initializes sb->s_bdev and takes a reference on the block device backing_dev_info when assigning sb->s_bdi.
nilfs_fill_super() takes another reference to the same backing_dev_info and stores it in sb->s_bdi again. The extra reference is not paired with a matching bdi_put(), since generic_shutdown_super() releases sb->s_bdi only once.
Drop the redundant bdi_get() in nilfs_fill_super(). The single reference taken by setup_bdev_super() is enough and is released during superblock shutdown.
--- fs/nilfs2/super.c | 2 -- 1 file changed, 2 deletions(-)
fs/nilfs2/super.c +0 -2
@@ -1086,8 +1086,6 @@ nilfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_time_gran =1 ; sb->s_max_links =NILFS_LINK_MAX ; - sb->s_bdi =bdi_get (sb->s_bdev->bd_disk->bdi); - err =load_nilfs (nilfs, sb);if (err) goto failed_nilfs;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 392/1266 iommu/amd: Fix a stale comment about which legacy mode is user visible
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit 4bf53c2d0c08bbdaa32f2114281f1ddab61902bf ]
Update a stale comment about which of the legacy modes is visible to the user, i.e. can be forced via amd_iommu_intr=legacy.
--- drivers/iommu/amd/amd_iommu_types.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/iommu/amd/amd_iommu_types.h +6 -5
@@ -926,12 +926,13 @@ static inline int get_hpet_devid(int id) }enum amd_iommu_intr_mode_type { -AMD_IOMMU_GUEST_IR_LEGACY , - -/* This mode is not visible to users. It is used when -* we cannot fully enable vAPIC and fallback to only support -* legacy interrupt remapping via 128-bit IRTE. +/* +* The legacy format mode is not visible to users to prevent the user +* from crashing x2APIC systems, which for all intents and purposes +* require 128-bit IRTEs. The legacy format will be forced as needed +* when hardware doesn't support 128-bit IRTEs. */ +AMD_IOMMU_GUEST_IR_LEGACY ,AMD_IOMMU_GUEST_IR_LEGACY_GA ,AMD_IOMMU_GUEST_IR_VAPIC , };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 393/1266 arm64: dts: mediatek: mt8192-asurada: Move PCIe DMA bounce buffer to host
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit 533275a4b5240a2bf2c592bd4536560388306d26 ]
The DMA bounce buffer is attached to the PCIe host controller, i.e. all PCIe DMA transfers should use it.
Move it from the PCIe (WiFi) device node down to the PCIe host controller node.
--- arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/mediatek/mt8192-asurada.dtsi +1 -1
@@ -494,6 +494,7 @@ flash@0 { &pcie { pinctrl-names = "default"; pinctrl-0 = <&pcie_pins>; + memory-region = <&wifi_restricted_dma_region>; pcie0: pcie@0,0 { device_type = "pci";
@@ -508,7 +509,6 @@ pcie0: pcie@0,0 { wifi: wifi@0,0 { reg = <0x10000 0 0 0 0x100000>, <0x10000 0 0x100000 0 0x100000>; - memory-region = <&wifi_restricted_dma_region>; }; }; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 394/1266 clk: scmi: Fix clock rate rounding
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Marussi <[email protected]>
[ Upstream commit d0c81a38d06d446d341532700b3a4a43d3b00eb1 ]
While the do_div() helper used for rounding expects its divisor argument to be a 32bits quantity, the currently provided divisor parameter is a 64bit value that, as a consequence, is silently truncated and a possible source of bugs.
Fix by using the proper div64_ul helper.
--- drivers/clk/clk-scmi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/clk/clk-scmi.c +2 -2
@@ -9,9 +9,9 @@#include <linux/device.h> #include <linux/err.h> #include <linux/of.h> +#include <linux/math64.h> #include <linux/module.h> #include <linux/scmi_protocol.h> -#include <asm/div64.h> static const struct scmi_clk_proto_ops *scmi_proto_clk_ops;
@@ -61,7 +61,7 @@ static long scmi_clk_round_rate(struct clk_hw *hw, unsigned long rate, ftmp = rate - fmin; ftmp += clk->info->range.step_size -1 ;/* to round up */ -do_div (ftmp, clk->info->range.step_size); + ftmp =div64_ul (ftmp, clk->info->range.step_size);return ftmp * clk->info->range.step_size + fmin; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 395/1266 arm64: dts: qcom: sm8450: Fix ICE reg size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuldeep Singh <[email protected]>
[ Upstream commit 7fb3d0512dacc0d09217eb45057357f00298203d ]
The ICE register region size was originally described incorrectly when the ICE hardware was first introduced. The same value was later carried over unchanged when the ICE node was split out from the UFS node into its own DT entry.
Correct the register size to match the hardware specification.
--- arch/arm64/boot/dts/qcom/sm8450.dtsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sm8450.dtsi +1 -1
@@ -4223,7 +4223,7 @@ ufs_mem_phy_lanes: phy@1d87400 { ice: crypto@1d88000 { compatible = "qcom,sm8450-inline-crypto-engine", "qcom,inline-crypto-engine"; - reg = <0 0x01d88000 0 0x8000>; + reg = <0 0x01d88000 0 0x18000>; clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 396/1266 drm/hisilicon/hibmc: move display contrl config to hibmc_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lin He <[email protected]>
[ Upstream commit de2a56c71f9b223922ea8fe0192d3c1fa2954608 ]
If there's no VGA output, this encoder modeset won't be called, which will cause displaying data from GPU being cut off. It's actually a common display config for DP and VGA, so move the vdac encoder modeset to driver load stage.
Removed invalid bit configurations from hibmc_display_ctrl
--- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 11 ++++++++++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 22 ------------------- 2 files changed, 11 insertions(+), 22 deletions(-)
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +11 -0
@@ -174,6 +174,15 @@ void hibmc_set_current_gate(struct hibmc_drm_private *priv, unsigned int gate)writel (gate, mmio + gate_reg); } +static void hibmc_display_ctrl (struct hibmc_drm_private *priv) +{ +u32 reg; + + reg =readl (priv->mmio +HIBMC_DISPLAY_CONTROL_HISILE ); + reg |=HIBMC_DISPLAY_CONTROL_PANELDATE (1 ); +writel (reg, priv->mmio +HIBMC_DISPLAY_CONTROL_HISILE ); +} +static void hibmc_hw_config (struct hibmc_drm_private *priv) {u32 reg;
@@ -205,6 +214,8 @@ static void hibmc_hw_config(struct hibmc_drm_private *priv) reg |=HIBMC_MSCCTL_LOCALMEM_RESET (1 );writel (reg, priv->mmio +HIBMC_MISC_CTRL ); + +hibmc_display_ctrl (priv); }static int hibmc_hw_map (struct hibmc_drm_private *priv)
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +0 -22
@@ -66,26 +66,6 @@ static const struct drm_connector_funcs hibmc_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static void hibmc_encoder_mode_set (struct drm_encoder *encoder, -struct drm_display_mode *mode, -struct drm_display_mode *adj_mode) -{ -u32 reg; -struct drm_device *dev = encoder->dev; -struct hibmc_drm_private *priv =to_hibmc_drm_private (dev); - - reg =readl (priv->mmio +HIBMC_DISPLAY_CONTROL_HISILE ); - reg |=HIBMC_DISPLAY_CONTROL_FPVDDEN (1 ); - reg |=HIBMC_DISPLAY_CONTROL_PANELDATE (1 ); - reg |=HIBMC_DISPLAY_CONTROL_FPEN (1 ); - reg |=HIBMC_DISPLAY_CONTROL_VBIASEN (1 ); -writel (reg, priv->mmio +HIBMC_DISPLAY_CONTROL_HISILE ); -} - -static const struct drm_encoder_helper_funcs hibmc_encoder_helper_funcs = { - .mode_set = hibmc_encoder_mode_set, -}; -int hibmc_vdac_init (struct hibmc_drm_private *priv) {struct drm_device *dev = &priv->dev;
@@ -108,8 +88,6 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)return ret; } -drm_encoder_helper_add (encoder, &hibmc_encoder_helper_funcs); - ret = drm_connector_init_with_ddc(dev, connector, &hibmc_connector_funcs, DRM_MODE_CONNECTOR_VGA,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 397/1266 drm/hisilicon/hibmc: use clock to look up the PLL value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lin He <[email protected]>
[ Upstream commit 99ef3a4f1c1813cabd50bb3e8522e85e00838bb2 ]
In the past, we use width and height to look up our PLL value. But actually the actual clock check is also necessnary. There are some resolutions that width and height same, but its clock different. Add the clock check when using pll_table to determine the PLL value.
--- .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 80 +++++++++++-------- 1 file changed, 45 insertions(+), 35 deletions(-)
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +45 -35
@@ -32,26 +32,43 @@ struct hibmc_display_panel_pll {struct hibmc_dislay_pll_config {u64 hdisplay;u64 vdisplay; +int clock;u32 pll1_config_value;u32 pll2_config_value; };static const struct hibmc_dislay_pll_config hibmc_pll_table[] = { - {640 ,480 ,CRT_PLL1_HS_25MHZ ,CRT_PLL2_HS_25MHZ }, - {800 ,600 ,CRT_PLL1_HS_40MHZ ,CRT_PLL2_HS_40MHZ }, - {1024 ,768 ,CRT_PLL1_HS_65MHZ ,CRT_PLL2_HS_65MHZ }, - {1152 ,864 ,CRT_PLL1_HS_80MHZ_1152 ,CRT_PLL2_HS_80MHZ }, - {1280 ,768 ,CRT_PLL1_HS_80MHZ ,CRT_PLL2_HS_80MHZ }, - {1280 ,720 ,CRT_PLL1_HS_74MHZ ,CRT_PLL2_HS_74MHZ }, - {1280 ,960 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, - {1280 ,1024 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, - {1440 ,900 ,CRT_PLL1_HS_106MHZ ,CRT_PLL2_HS_106MHZ }, - {1600 ,900 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, - {1600 ,1200 ,CRT_PLL1_HS_162MHZ ,CRT_PLL2_HS_162MHZ }, - {1920 ,1080 ,CRT_PLL1_HS_148MHZ ,CRT_PLL2_HS_148MHZ }, - {1920 ,1200 ,CRT_PLL1_HS_193MHZ ,CRT_PLL2_HS_193MHZ }, + {640 ,480 ,25000 ,CRT_PLL1_HS_25MHZ ,CRT_PLL2_HS_25MHZ }, + {800 ,600 ,40000 ,CRT_PLL1_HS_40MHZ ,CRT_PLL2_HS_40MHZ }, + {1024 ,768 ,65000 ,CRT_PLL1_HS_65MHZ ,CRT_PLL2_HS_65MHZ }, + {1152 ,864 ,78750 ,CRT_PLL1_HS_80MHZ_1152 ,CRT_PLL2_HS_80MHZ }, + {1280 ,768 ,80000 ,CRT_PLL1_HS_80MHZ ,CRT_PLL2_HS_80MHZ }, + {1280 ,720 ,74375 ,CRT_PLL1_HS_74MHZ ,CRT_PLL2_HS_74MHZ }, + {1280 ,960 ,108000 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, + {1280 ,1024 ,108000 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, + {1440 ,900 ,105952 ,CRT_PLL1_HS_106MHZ ,CRT_PLL2_HS_106MHZ }, + {1600 ,900 ,108000 ,CRT_PLL1_HS_108MHZ ,CRT_PLL2_HS_108MHZ }, + {1600 ,1200 ,162500 ,CRT_PLL1_HS_162MHZ ,CRT_PLL2_HS_162MHZ }, + {1920 ,1080 ,148750 ,CRT_PLL1_HS_148MHZ ,CRT_PLL2_HS_148MHZ }, + {1920 ,1200 ,193750 ,CRT_PLL1_HS_193MHZ ,CRT_PLL2_HS_193MHZ }, }; +static int hibmc_get_best_clock_idx (const struct drm_display_mode *mode) +{ +int i, diff; + +for (i =0 ; i <ARRAY_SIZE (hibmc_pll_table); i++) { +if (hibmc_pll_table[i].hdisplay == mode->hdisplay && + hibmc_pll_table[i].vdisplay == mode->vdisplay) { + diff =abs (mode->clock - hibmc_pll_table[i].clock); +if (diff < mode->clock /100 )/* tolerance 1/100 */ +return i; + } + } + +return -MODE_CLOCK_RANGE ; +} +static int hibmc_plane_atomic_check (struct drm_plane *plane,struct drm_atomic_state *state) {
@@ -214,19 +231,15 @@ static enum drm_mode_status hibmc_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode) { - size_t i = 0; int vrefresh = drm_mode_vrefresh(mode);if (vrefresh <59 || vrefresh >61 )return MODE_NOCLOCK ; -for (i =0 ; i <ARRAY_SIZE (hibmc_pll_table); i++) { -if (hibmc_pll_table[i].hdisplay == mode->hdisplay && - hibmc_pll_table[i].vdisplay == mode->vdisplay) -return MODE_OK ; - } +if (hibmc_get_best_clock_idx (mode) >=0 ) +return MODE_OK ; -return MODE_BAD ; +return MODE_CLOCK_RANGE ; }static u32 format_pll_reg (void )
@@ -281,23 +294,20 @@ static void set_vclock_hisilicon(struct drm_device *dev, u64 pll)writel (val, priv->mmio +CRT_PLL1_HS ); } -static void get_pll_config (u64 x,u64 y,u32 *pll1,u32 *pll2) +static void get_pll_config (struct drm_display_mode *mode,u32 *pll1,u32 *pll2) { -size_t i; -size_t count =ARRAY_SIZE (hibmc_pll_table); - -for (i =0 ; i < count; i++) { -if (hibmc_pll_table[i].hdisplay == x && - hibmc_pll_table[i].vdisplay == y) { - *pll1 = hibmc_pll_table[i].pll1_config_value; - *pll2 = hibmc_pll_table[i].pll2_config_value; -return ; - } +int idx; + + idx =hibmc_get_best_clock_idx (mode); +if (idx <0 ) { +/* if found none, we use default value */ + *pll1 =CRT_PLL1_HS_25MHZ ; + *pll2 =CRT_PLL2_HS_25MHZ ; +return ; } -/* if found none, we use default value */ - *pll1 =CRT_PLL1_HS_25MHZ ; - *pll2 =CRT_PLL2_HS_25MHZ ; + *pll1 = hibmc_pll_table[idx].pll1_config_value; + *pll2 = hibmc_pll_table[idx].pll2_config_value; }/*
@@ -319,7 +329,7 @@ static u32 display_ctrl_adjust(struct drm_device *dev, x = mode->hdisplay; y = mode->vdisplay; -get_pll_config (x, y, &pll1, &pll2); +get_pll_config (mode, &pll1, &pll2);writel (pll2, priv->mmio +CRT_PLL2_HS );set_vclock_hisilicon (dev, pll1);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 398/1266 evm: terminate and bound the evm_xattrs read buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 11143a19f5b8dc8f414deab87571134f9f447313 ]
evm_read_xattrs() allocates size + 1 bytes, fills them from the list of enabled xattrs, and then passes strlen(temp) to simple_read_from_buffer(). When no configured xattrs are enabled, the fill loop stores nothing and temp[0] remains uninitialized, so strlen() reads beyond initialized memory.
Explicitly terminate the buffer after allocation, use snprintf() for each formatted line, and pass the accumulated length, without risk of truncation, to simple_read_from_buffer().
--- security/integrity/evm/evm_secfs.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
security/integrity/evm/evm_secfs.c +11 -5
@@ -128,8 +128,8 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf, size_t count, loff_t *ppos) { char *temp; -int offset =0 ; -ssize_t rc, size =0 ; +size_t offset =0 , size =0 ; +ssize_t rc;struct xattr_list *xattr;if (*ppos !=0 )
@@ -152,16 +152,22 @@ static ssize_t evm_read_xattrs(struct file *filp, char __user *buf,return -ENOMEM ; } + temp[size] ='\0' ; + +/* +* No truncation possible: size is computed over the same enabled +* xattrs under xattr_list_mutex, so offset never exceeds size. +*/ list_for_each_entry (xattr, &evm_config_xattrnames, list) {if (!xattr->enabled)continue ; -sprintf (temp + offset,"%s\n" , xattr->name); - offset +=strlen (xattr->name) +1 ; + offset +=snprintf (temp + offset, size +1 - offset,"%s\n" , + xattr->name); }mutex_unlock (&xattr_list_mutex); - rc =simple_read_from_buffer (buf, count, ppos, temp,strlen (temp)); + rc =simple_read_from_buffer (buf, count, ppos, temp, offset);kfree (temp);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 399/1266 thermal: hwmon: Fix critical temperature attribute removal
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit c2114dbda05354dbcf4dfbb30a2c623e8611c43a ]
Since the return value of thermal_zone_crit_temp_valid() depends on the behavior of the thermal zone .get_crit_temp() callback which may change over time in theory, thermal_remove_hwmon_sysfs() may attempt to remove a critical temperature attribute that has not been created, passing a pointer to an uninitialized attribute structure to device_remove_file().
To avoid that, set a flag in struct thermal_hwmon_temp after creating a critical temperature attribute and use the value of that flag to decide whether or not the attribute needs to be removed.
--- drivers/thermal/thermal_hwmon.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/thermal/thermal_hwmon.c +4 -1
@@ -40,6 +40,7 @@ struct thermal_hwmon_temp {struct thermal_zone_device *tz;struct thermal_hwmon_attr temp_input;/* hwmon sys attr */ struct thermal_hwmon_attr temp_crit;/* hwmon sys attr */ +bool temp_crit_present; };static LIST_HEAD (thermal_hwmon_list);
@@ -197,6 +198,8 @@ int thermal_add_hwmon_sysfs(struct thermal_zone_device *tz) &temp->temp_crit.attr);if (result) goto unregister_input; + + temp->temp_crit_present = true; }mutex_lock (&thermal_hwmon_list_lock);
@@ -241,7 +244,7 @@ void thermal_remove_hwmon_sysfs(struct thermal_zone_device *tz) }device_remove_file (hwmon->device, &temp->temp_input.attr); -if (thermal_zone_crit_temp_valid (tz)) +if (temp->temp_crit_present)device_remove_file (hwmon->device, &temp->temp_crit.attr);mutex_lock (&thermal_hwmon_list_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 400/1266 clk: scpi: Unregister child clock providers on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stepan Ionichev <[email protected]>
[ Upstream commit b79d9b5747d961516c35ef4d5e91efa579fd3e9a ]
SCPI clock providers are registered for each child node in scpi_clk_add(), but scpi_clocks_remove() unregisters the parent node on each iteration.
of_clk_del_provider() matches providers by the node used at registration time, so passing the parent node leaves the child providers registered. This leaks the provider allocations and the node references held by the clock provider core.
Pass the child node to of_clk_del_provider() so the remove path matches the probe path.
(sudeep.holla: Updated commit title and message a bit)
--- drivers/clk/clk-scpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/clk/clk-scpi.c +1 -1
@@ -256,7 +256,7 @@ static void scpi_clocks_remove(struct platform_device *pdev) }for_each_available_child_of_node (np, child) -of_clk_del_provider (np); +of_clk_del_provider (child); }static int scpi_clocks_probe (struct platform_device *pdev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 401/1266 net/sched: sch_hfsc: annotate data-races in hfsc_dump_class_stats()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit e300c7d470ad2726d6abf7d11b31b5d9912d9cf0 ]
hfsc_dump_class_stats() runs without qdisc spinlock being held.
Add READ_ONCE()/WRITE_ONCE() annotations around:
- cl->level
- cl->cl_vtperiod
- cl->cl_total
- cl->cl_cumul
--- net/sched/sch_hfsc.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
net/sched/sch_hfsc.c +11 -11
@@ -715,7 +715,7 @@ init_vf(struct hfsc_class *cl, unsigned int len)rtsc_min (&cl->cl_virtual, &cl->cl_fsc, cl->cl_vt, cl->cl_total); cl->cl_vtadj =0 ; - cl->cl_vtperiod++;/* increment vt period */ +WRITE_ONCE (cl->cl_vtperiod, cl->cl_vtperiod +1 );/* increment vt period */ cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;if (cl->cl_parent->cl_nactive ==0 ) cl->cl_parentperiod++;
@@ -757,7 +757,7 @@ update_vf(struct hfsc_class *cl, unsigned int len, u64 cur_time) go_passive =1 ;for (; cl->cl_parent !=NULL ; cl = cl->cl_parent) { - cl->cl_total += len; +WRITE_ONCE (cl->cl_total, cl->cl_total + len);if (!(cl->cl_flags &HFSC_FSC ) || cl->cl_nactive ==0 )continue ;
@@ -847,7 +847,7 @@ hfsc_adjust_levels(struct hfsc_class *cl)if (p->level >= level) level = p->level +1 ; } - cl->level = level; +WRITE_ONCE (cl->level, level); }while ((cl = cl->cl_parent) !=NULL ); }
@@ -1337,10 +1337,10 @@ hfsc_dump_class_stats(struct Qdisc *sch, unsigned long arg,__u32 qlen;qdisc_qstats_qlen_backlog (cl->qdisc, &qlen, &cl->qstats.backlog); - xstats.level = cl->level; - xstats.period = cl->cl_vtperiod; - xstats.work = cl->cl_total; - xstats.rtwork = cl->cl_cumul; + xstats.level =READ_ONCE (cl->level); + xstats.period =READ_ONCE (cl->cl_vtperiod); + xstats.work =READ_ONCE (cl->cl_total); + xstats.rtwork =READ_ONCE (cl->cl_cumul); if (gnet_stats_copy_basic(d, NULL, &cl->bstats, true) < 0 || gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
@@ -1453,15 +1453,15 @@ hfsc_change_qdisc(struct Qdisc *sch, struct nlattr *opt,static void hfsc_reset_class (struct hfsc_class *cl) { - cl->cl_total =0 ; - cl->cl_cumul =0 ; +WRITE_ONCE (cl->cl_total,0 ); +WRITE_ONCE (cl->cl_cumul,0 ); cl->cl_d =0 ; cl->cl_e =0 ; cl->cl_vt =0 ; cl->cl_vtadj =0 ; cl->cl_cvtmin =0 ; cl->cl_cvtoff =0 ; - cl->cl_vtperiod =0 ; +WRITE_ONCE (cl->cl_vtperiod,0 ); cl->cl_parentperiod =0 ; cl->cl_f =0 ; cl->cl_myf =0 ;
@@ -1627,7 +1627,7 @@ hfsc_dequeue(struct Qdisc *sch)bstats_update (&cl->bstats, skb);update_vf (cl,qdisc_pkt_len (skb), cur_time);if (realtime) - cl->cl_cumul +=qdisc_pkt_len (skb); +WRITE_ONCE (cl->cl_cumul, cl->cl_cumul +qdisc_pkt_len (skb));if (cl->cl_flags &HFSC_RSC ) {if (cl->qdisc->q.qlen !=0 ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 402/1266 crypto: ccp - Treat zero-length cert chain as query for blob lengths
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
[ Upstream commit ef8c9dacda2871accd64e3eda951fef6b788b1ea ]
When handling a PDH export, treat a zero-length userspace cert chain buffer as a request to query the length of the relevant blobs. Failure to account for the zero-length buffer trips a BUG_ON() when running with CONFIG_DEBUG_VIRTUAL=y due to trying to get the physical address of the ZERO_SIZE_PTR (returned by kzalloc() on the bogus allocation).
kernel BUG at arch/x86/mm/physaddr.c:28 !
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
CPU: 30 UID: 0 PID: 28580 Comm: syz.2.18 Kdump: loaded
Tainted: G W 6.18.16-smp-DEV #1 NONE
Tainted: [W]=WARN
Hardware name: Google, Inc. Arcadia_IT_80/Arcadia_IT_80, BIOS 12.62.0-0 11/19/2025
RIP: 0010:__phys_addr+0x16a/0x180 arch/x86/mm/physaddr.c:28
RSP: 0018:ffffc9008329fc80 EFLAGS: 00010293
RAX: ffffffff8179110a RBX: 0000778000000010 RCX: ffff8884e6992600
RDX: 0000000000000000 RSI: 0000000080000010 RDI: 0000778000000010
RBP: ffffc9008329fdf0 R08: 0000000000000dc0 R09: 00000000ffffffff
R10: dffffc0000000000 R11: fffffbfff126d297 R12: dffffc0000000000
R13: 1ffff92010653fc8 R14: 0000000080000010 R15: dffffc0000000000
FS: 0000555556bec9c0(0000) GS:ffff88aa4ce1c000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fd3159e7000 CR3: 00000004fbc44000 CR4: 0000000000350ef0
Call Trace:
<TASK>
[<ffffffff853d3869>] sev_ioctl_do_pdh_export+0x559/0x7a0 drivers/crypto/ccp/sev-dev.c:2308
[<ffffffff853d1fdd>] sev_ioctl+0x2cd/0x480 drivers/crypto/ccp/sev-dev.c:2556
[<ffffffff82549ebc>] vfs_ioctl fs/ioctl.c:52 [inline]
[<ffffffff82549ebc>] __do_sys_ioctl fs/ioctl.c:598 [inline]
[<ffffffff82549ebc>] __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:584
[<ffffffff8630115f>] do_syscall_x64 arch/x86/entry/syscall_64.c:64 [inline]
[<ffffffff8630115f>] do_syscall_64+0x9f/0xf40 arch/x86/entry/syscall_64.c:98
[<ffffffff81000136>] entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7fd3158eac39
</TASK>Thankfully, the bug is benign outside of CONFIG_DEBUG_VIRTUAL=y as getting the physical address is just arithmetic, and the PSP errors out before trying to write to the garbage address (which it must, otherwise querying the blob lengths would clobber memory at pfn=0).
--- drivers/crypto/ccp/sev-dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/crypto/ccp/sev-dev.c +2 -1
@@ -1016,7 +1016,8 @@ static int sev_ioctl_do_pdh_export(struct sev_issue_cmd *argp, bool writable)/* Userspace wants to query the certificate length. */ if (!input.pdh_cert_address || !input.pdh_cert_len || - !input.cert_chain_address) + !input.cert_chain_address || + !input.cert_chain_len) goto cmd; input_pdh_cert_address = (void __user *)input.pdh_cert_address;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 403/1266 spi: hisi-kunpeng: Use dev_err_probe() for host registration failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qiang Ma <[email protected]>
[ Upstream commit 59b991990a04b1d1ce95373983b7c8b65bdf7acc ]
When the SPI core registers the Kunpeng controller it may need to acquire chip-select GPIO descriptors. If the GPIO provider has not probed yet, spi_register_controller() returns -EPROBE_DEFER.
On a Kunpeng system this currently prints an alarming error even though the next deferred-probe retry succeeds:
hisi-kunpeng-spi HISI03E1:00: failed to register spi host, ret=-517 hisi-kunpeng-spi HISI03E1:00: hw version:0x30 max-freq:12500 kHz
Use dev_err_probe() so that -EPROBE_DEFER is reported through the deferred probe mechanism instead of as a hard error, while preserving normal error reporting for real registration failures.
--- drivers/spi/spi-hisi-kunpeng.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/spi/spi-hisi-kunpeng.c +2 -4
@@ -518,10 +518,8 @@ static int hisi_spi_probe(struct platform_device *pdev) } ret =spi_register_controller (host); -if (ret) { -dev_err (dev,"failed to register spi host, ret=%d\n" , ret); -return ret; - } +if (ret) +return dev_err_probe (dev, ret,"failed to register spi host\n" );if (hisi_spi_debugfs_init (hs))dev_info (dev,"failed to create debugfs dir\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 404/1266 net/sched: sch_htb: do not change sch->flags in htb_dump()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 9b949fa69129e4b694ed11ee3be6d6edd4a9b8f4 ]
htb_dump() runs without holding qdisc spinlock.
It is illegal to touch sch->flags with non locked RMW, as concurrent readers might see intermediate wrong values.
Set TCQ_F_OFFLOADED in control path (htb_init()) instead.
--- net/sched/sch_htb.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
net/sched/sch_htb.c +1 -5
@@ -1148,6 +1148,7 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt,* parts (especially calling ndo_setup_tc) on errors. */ q->offload = true; + sch->flags |=TCQ_F_OFFLOADED ;return 0 ; }
@@ -1208,11 +1209,6 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)struct nlattr *nest;struct tc_htb_glob gopt; -if (q->offload) - sch->flags |=TCQ_F_OFFLOADED ; -else - sch->flags &= ~TCQ_F_OFFLOADED ; - sch->qstats.overlimits = q->overlimits;/* Its safe to not acquire qdisc lock. As we hold RTNL, * no change can happen on the qdisc parameters.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 405/1266 net/sched: sch_htb: annotate data-races (I)
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit e54c33503bf7cebb1c1790251ce90f1252678081 ]
htb_dump() runs without holding qdisc spinlock.
Add missing READ_ONCE()/WRITE_ONCE() annotations around q->overlimits and q->direct_pkts.
--- net/sched/sch_htb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/sched/sch_htb.c +4 -4
@@ -568,7 +568,7 @@ htb_change_class_mode(struct htb_sched *q, struct htb_class *cl, s64 *diff)if (new_mode ==HTB_CANT_SEND ) { cl->overlimits++; - q->overlimits++; +WRITE_ONCE (q->overlimits, q->overlimits +1 ); }if (cl->prio_activity) {/* not necessary: speed optimization */
@@ -628,7 +628,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,/* enqueue to helper queue */ if (q->direct_queue.qlen < q->direct_qlen) {__qdisc_enqueue_tail (skb, &q->direct_queue); - q->direct_pkts++; +WRITE_ONCE (q->direct_pkts, q->direct_pkts +1 ); }else {return qdisc_drop (skb, sch, to_free); }
@@ -1209,12 +1209,12 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb)struct nlattr *nest;struct tc_htb_glob gopt; - sch->qstats.overlimits = q->overlimits; + sch->qstats.overlimits =READ_ONCE (q->overlimits);/* Its safe to not acquire qdisc lock. As we hold RTNL, * no change can happen on the qdisc parameters. */ - gopt.direct_pkts = q->direct_pkts; + gopt.direct_pkts =READ_ONCE (q->direct_pkts); gopt.version =HTB_VER ; gopt.rate2quantum = q->rate2quantum; gopt.defcls = q->defcls;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 406/1266 ipv6: addrconf: bail out of dad_failure when state is no longer POSTDAD
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linmao Li <[email protected]>
[ Upstream commit 627ac78f2741e2ebd2225e2e953b6964a8a9182f ]
addrconf_dad_failure() transitions ifp->state from DAD to POSTDAD via addrconf_dad_end(), which drops ifp->lock on return. The lock is re-acquired after net_info_ratelimited(). A concurrent ipv6_del_addr() can take the lock in that window, set ifp->state to DEAD and run list_del_rcu(&ifp->if_list).
addrconf_dad_failure() then overwrites DEAD with ERRDAD at errdad:
and schedules a new dad_work. The work calls ipv6_del_addr() again, hitting the already-poisoned list entry:
general protection fault: 0000 [#1] SMP NOPTI CPU: 4 PID: 217 Comm: kworker/4:1 Workqueue: ipv6_addrconf addrconf_dad_work RIP: 0010:ipv6_del_addr+0xe9/0x280 RAX: dead000000000122 Call Trace: addrconf_dad_stop+0x113/0x140 addrconf_dad_work+0x28c/0x430 process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 ret_from_fork+0x35/0x40
Fold the addrconf_dad_end() logic into addrconf_dad_failure() under a single ifp->lock critical section. The STABLE_PRIVACY branch temporarily drops ifp->lock around address regeneration, so atlock_errdad: verify the state is still POSTDAD before transitioning to ERRDAD; bail out otherwise to avoid overwriting a state set by another path while the lock was released.
--- net/ipv6/addrconf.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv6/addrconf.c +10 -3
@@ -2138,16 +2138,18 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)struct inet6_dev *idev = ifp->idev;struct net *net =dev_net (idev->dev); -if (addrconf_dad_end (ifp)) { +spin_lock_bh (&ifp->lock); + +if (ifp->state !=INET6_IFADDR_STATE_DAD ) { +spin_unlock_bh (&ifp->lock);in6_ifa_put (ifp);return ; } + ifp->state =INET6_IFADDR_STATE_POSTDAD ;net_info_ratelimited ("%s: IPv6 duplicate address %pI6c used by %pM detected!\n" , ifp->idev->dev->name, &ifp->addr,eth_hdr (skb)->h_source); -spin_lock_bh (&ifp->lock); -if (ifp->flags &IFA_F_STABLE_PRIVACY ) {struct in6_addr new_addr;struct inet6_ifaddr *ifp2;
@@ -2195,6 +2197,11 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)in6_ifa_put (ifp2); lock_errdad:spin_lock_bh (&ifp->lock); +if (ifp->state !=INET6_IFADDR_STATE_POSTDAD ) { +spin_unlock_bh (&ifp->lock); +in6_ifa_put (ifp); +return ; + } } errdad:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 407/1266 IB/mlx5: Fix transport-domain rollback and initialize lb mutex earlier
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prathamesh Deshpande <[email protected]>
[ Upstream commit e79389115b9d27287ff6230a9750675106ed7668 ]
mlx5_ib_alloc_transport_domain() allocates a transport domain and then may fail in mlx5_ib_enable_lb(). In that case, the allocated TD is leaked.
Fix this by deallocating the TD when mlx5_ib_enable_lb() returns an error. Also return 0 explicitly in the no-loopback-capability success branch, and move dev->lb.mutex initialization to mlx5_ib_stage_init_init().
--- drivers/infiniband/hw/mlx5/main.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
drivers/infiniband/hw/mlx5/main.c +8 -7
@@ -1785,9 +1785,13 @@ static int mlx5_ib_alloc_transport_domain(struct mlx5_ib_dev *dev, u32 *tdn,if ((MLX5_CAP_GEN (dev->mdev, port_type) !=MLX5_CAP_PORT_TYPE_ETH ) || (!MLX5_CAP_GEN (dev->mdev, disable_local_lb_uc) && !MLX5_CAP_GEN (dev->mdev, disable_local_lb_mc))) -return err; +return 0 ; + + err =mlx5_ib_enable_lb (dev, true, false); +if (err) +mlx5_cmd_dealloc_transport_domain (dev->mdev, *tdn, uid); -return mlx5_ib_enable_lb (dev, true, false); +return err; } static void mlx5_ib_dealloc_transport_domain(struct mlx5_ib_dev *dev, u32 tdn,
@@ -3791,6 +3795,8 @@ static int mlx5_ib_stage_init_init(struct mlx5_ib_dev *dev) dev->port[i].roce.last_port_state =IB_PORT_DOWN ; } +mutex_init (&dev->lb.mutex); + err =mlx5r_cmd_query_special_mkeys (dev);if (err)return err;
@@ -4006,11 +4012,6 @@ static int mlx5_ib_stage_caps_init(struct mlx5_ib_dev *dev)if (err)return err; -if ((MLX5_CAP_GEN (dev->mdev, port_type) ==MLX5_CAP_PORT_TYPE_ETH ) && - (MLX5_CAP_GEN (dev->mdev, disable_local_lb_uc) || -MLX5_CAP_GEN (dev->mdev, disable_local_lb_mc))) -mutex_init (&dev->lb.mutex); -if (MLX5_CAP_GEN_64 (dev->mdev, general_obj_types) &MLX5_GENERAL_OBJ_TYPES_CAP_VIRTIO_NET_Q ) { err =mlx5_ib_init_var_table (dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 408/1266 RDMA/hns: Fix arithmetic overflow in calc_hem_config()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Chesnokov <[email protected]>
[ Upstream commit a38e4410af9ad8b7ad2217254da06cd4dc21f0ed ]
If bt_num is 3 or 2, then the expressions like l0_idx * chunk_ba_num + l1_idx are computed in 32-bit arithmetic before being assigned to a u64 index field, which can lead to overflow.
Cast the first operand to u64 to ensure the arithmetic is performed in 64-bit.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/infiniband/hw/hns/hns_roce_hem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/infiniband/hw/hns/hns_roce_hem.c +4 -4
@@ -355,14 +355,14 @@ static int calc_hem_config(struct hns_roce_dev *hr_dev, bt_num =hns_roce_get_bt_num (table->type, mhop->hop_num);switch (bt_num) {case 3 : - index->l1 = l0_idx * chunk_ba_num + l1_idx; + index->l1 = (u64 )l0_idx * chunk_ba_num + l1_idx; index->l0 = l0_idx; - index->buf = l0_idx * chunk_ba_num * chunk_ba_num + - l1_idx * chunk_ba_num + l2_idx; + index->buf = (u64 )l0_idx * chunk_ba_num * chunk_ba_num + + (u64 )l1_idx * chunk_ba_num + l2_idx;break ;case 2 : index->l0 = l0_idx; - index->buf = l0_idx * chunk_ba_num + l1_idx; + index->buf = (u64 )l0_idx * chunk_ba_num + l1_idx;break ;case 1 : index->buf = l0_idx;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 409/1266 RDMA/mlx5: Fix devx subscribe-event unwind NULL dereference
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prathamesh Deshpande <[email protected]>
[ Upstream commit 43f8f7946814c8e5f464518246fdbc69b6e32326 ]
MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT() links event_sub into sub_list before initializing the fields used by the shared error path.
If eventfd_ctx_fdget() then fails, the unwind path dereferences event_sub->ev_file in uverbs_uobject_put() and calls subscribe_event_xa_dealloc() with an unset xa_key_level1.
subscribe_event_xa_alloc() creates the XA entry exactly once for a given key_level1, on the first occurrence of that key. The unwind path must therefore call subscribe_event_xa_dealloc() exactly once for it as well.
Enforce that by adding devx_key_in_sub_list() and calling subscribe_event_xa_dealloc() only when the last matching pending entry is being cleaned up.
--- drivers/infiniband/hw/mlx5/devx.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-)
drivers/infiniband/hw/mlx5/devx.c +23 -7
@@ -1851,6 +1851,17 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_ASYNC_QUERY)(return err; } +static bool devx_key_in_sub_list (struct list_head *list,u32 key_level1) +{ +struct devx_event_subscription *s; + +list_for_each_entry (s, list, event_list) +if (s->xa_key_level1 == key_level1) +return true; + +return false; +} + static void subscribe_event_xa_dealloc(struct mlx5_devx_event_table *devx_event_table, u32 key_level1,
@@ -2098,10 +2109,17 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)( event_sub =kzalloc (sizeof (*event_sub),GFP_KERNEL );if (!event_sub) { +if (!devx_key_in_sub_list (&sub_list, key_level1)) +subscribe_event_xa_dealloc (devx_event_table, + key_level1, + obj, + obj_id); err = -ENOMEM ; goto err; } + event_sub->ev_file = ev_file; + event_sub->xa_key_level1 = key_level1;list_add_tail (&event_sub->event_list, &sub_list);uverbs_uobject_get (&ev_file->uobj);if (use_eventfd) {
@@ -2116,9 +2134,6 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)( } event_sub->cookie = cookie; - event_sub->ev_file = ev_file; -/* May be needed upon cleanup the devx object/subscription */ - event_sub->xa_key_level1 = key_level1; event_sub->xa_key_level2 = obj_id;INIT_LIST_HEAD (&event_sub->obj_list); }
@@ -2163,10 +2178,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_SUBSCRIBE_EVENT)(list_for_each_entry_safe (event_sub, tmp_sub, &sub_list, event_list) {list_del (&event_sub->event_list); -subscribe_event_xa_dealloc (devx_event_table, - event_sub->xa_key_level1, - obj, - obj_id); +if (!devx_key_in_sub_list (&sub_list, event_sub->xa_key_level1)) +subscribe_event_xa_dealloc (devx_event_table, + event_sub->xa_key_level1, + obj, + obj_id);if (event_sub->eventfd)eventfd_ctx_put (event_sub->eventfd);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 410/1266 RDMA/srpt: fix integer overflow in immediate data length check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sara Venkatesh <[email protected]>
[ Upstream commit eb4ecdf631fe00e8020bf461503cb9b7017ed796 ]
imm_buf->len is a user-controlled uint32_t received from the network. Adding it to imm_data_offset without overflow checking allows a malicious initiator to send len=0xFFFFFFFF, causing req_size to wrap around to a small value, bypassing the bounds check, and subsequently passing a ~4GB length to sg_init_one().
Use check_add_overflow() to detect wrapping before the comparison.
--- drivers/infiniband/ulp/srpt/ib_srpt.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/infiniband/ulp/srpt/ib_srpt.c +3 -2
@@ -1129,9 +1129,10 @@ static int srpt_get_desc_tbl(struct srpt_recv_ioctx *recv_ioctx,struct srp_imm_buf *imm_buf =srpt_get_desc_buf (srp_cmd);void *data = (void *)srp_cmd + imm_data_offset;uint32_t len =be32_to_cpu (imm_buf->len); -uint32_t req_size = imm_data_offset + len; +uint32_t req_size; -if (req_size > srp_max_req_size) { +if (check_add_overflow ((uint32_t )imm_data_offset, len, &req_size) || + req_size > srp_max_req_size) {pr_err ("Immediate data (length %d + %d) exceeds request size %d\n" , imm_data_offset, len, srp_max_req_size);return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 411/1266 media: atomisp: Fix memory leak in atomisp_fixed_pattern_table()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit 4e8156bd9517fa18c3613ea39c222c7035f0221e ]
atomisp_v4l2_framebuffer_to_css_frame() allocates memory for temporary variable raw_black_frame, which must be released via ia_css_frame_free() before the function returns. However, if sh_css_set_black_frame() fails, the function returns immediately without performing this cleanup, leading to a memory leak.
Fix this by assigning the return value of sh_css_set_black_frame() to ret. This ensures that the error code is propagated while allowing the execution to fall through to the ia_css_frame_free() cleanup call.
The bug was originally detected on v6.13-rc1 using an experimental static analysis tool we are developing, and we have verified that the issue persists in the latest mainline kernel. The tool is based on the LLVM framework and is specifically designed to detect memory management issues. It is currently under active development and not yet publicly available.
We performed build testing on x86_64 with allyesconfig. Since triggering this error path in atomisp requires specific Intel Atom ISP hardware and firmware, we were unable to perform runtime testing and instead verified the fix according to the code logic.
--- drivers/staging/media/atomisp/pci/atomisp_cmd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/staging/media/atomisp/pci/atomisp_cmd.c +2 -4
@@ -3486,10 +3486,8 @@ int atomisp_fixed_pattern_table(struct atomisp_sub_device *asd,if (ret)return ret; -if (sh_css_set_black_frame (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL ].stream, - raw_black_frame) !=0 ) -return -ENOMEM ; - + ret =sh_css_set_black_frame (asd->stream_env[ATOMISP_INPUT_STREAM_GENERAL ].stream, + raw_black_frame);ia_css_frame_free (raw_black_frame);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 412/1266 firmware: arm_scmi: Read sensor config as 32-bit value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit f6fe7c3c007df18afd289ff2d98c692fae9ab085 ]
The SENSOR_CONFIG_GET response contains a 32-bit sensor_config field, and the xfer is initialized with a 4-byte RX buffer. Reading it with get_unaligned_le64() can consume bytes past the returned payload.
Use get_unaligned_le32() to match the protocol layout and the allocated response size.
--- drivers/firmware/arm_scmi/sensors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/arm_scmi/sensors.c +1 -1
@@ -777,7 +777,7 @@ static int scmi_sensor_config_get(const struct scmi_protocol_handle *ph,if (!ret) {struct scmi_sensor_info *s = si->sensors + sensor_id; - *sensor_config =get_unaligned_le64 (t->rx.buf); + *sensor_config =get_unaligned_le32 (t->rx.buf); s->sensor_config = *sensor_config; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 413/1266 sysfs: clamp show() return value in sysfs_kf_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
[ Upstream commit 454257f6d124a92342dcbb7710c03dd6ef96c731 ]
sysfs_kf_seq_show() defends against buggy show() callbacks that return larger than PAGE_SIZE by clamping the value and printing a warning. sysfs_kf_read(), the prealloc variant, has no such defense.
The only current in-tree user of __ATTR_PREALLOC is drivers/md/md.c, whose show() callbacks are well-behaved, so this is hardening against future drivers doing foolish things and out-of-tree code doing even more foolish things.
--- fs/sysfs/file.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/sysfs/file.c +4 -0
@@ -114,6 +114,10 @@ static ssize_t sysfs_kf_read(struct kernfs_open_file *of, char *buf, len = ops->show (kobj, of->kn->priv, buf);if (len <0 )return len; +if (len >= (ssize_t )PAGE_SIZE ) { +printk ("fill_read_buffer: %pS returned bad count\n" , ops->show); + len =PAGE_SIZE -1 ; + }if (pos) {if (len <= pos)return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 414/1266 bitops: use common function parameter names
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Randy Dunlap <[email protected]>
[ Upstream commit 8a51b2e874f47a6094353b59ecae421f0968fe3a ]
Fix the function prototypes to use the common parameter name 'addr' instead of 'p' (common to arch-specific implementations of these functions).
This avoids the kernel-doc warnings:
Warning: include/asm-generic/bitops/lock.h:19 function parameter 'p'
not described in 'arch_test_and_set_bit_lock'
Warning: include/asm-generic/bitops/lock.h:41 function parameter 'p'
not described in 'arch_clear_bit_unlock'
Warning: include/asm-generic/bitops/lock.h:59 function parameter 'p'
not described in 'arch___clear_bit_unlock'
--- include/asm-generic/bitops/lock.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-)
include/asm-generic/bitops/lock.h +11 -11
@@ -16,16 +16,16 @@* It can be used to implement bit locks. */ static __always_inline int -arch_test_and_set_bit_lock (unsigned int nr,volatile unsigned long *p) +arch_test_and_set_bit_lock (unsigned int nr,volatile unsigned long *addr) {long old;unsigned long mask =BIT_MASK (nr); - p +=BIT_WORD (nr); -if (READ_ONCE (*p) & mask) + addr +=BIT_WORD (nr); +if (READ_ONCE (*addr) & mask)return 1 ; - old =raw_atomic_long_fetch_or_acquire (mask, (atomic_long_t *)p); + old =raw_atomic_long_fetch_or_acquire (mask, (atomic_long_t *)addr);return !!(old & mask); }
@@ -38,10 +38,10 @@ arch_test_and_set_bit_lock(unsigned int nr, volatile unsigned long *p)* This operation is atomic and provides release barrier semantics. */ static __always_inline void -arch_clear_bit_unlock (unsigned int nr,volatile unsigned long *p) +arch_clear_bit_unlock (unsigned int nr,volatile unsigned long *addr) { - p +=BIT_WORD (nr); -raw_atomic_long_fetch_andnot_release (BIT_MASK (nr), (atomic_long_t *)p); + addr +=BIT_WORD (nr); +raw_atomic_long_fetch_andnot_release (BIT_MASK (nr), (atomic_long_t *)addr); }/**
@@ -56,14 +56,14 @@ arch_clear_bit_unlock(unsigned int nr, volatile unsigned long *p)* See for example x86's implementation. */ static inline void -arch___clear_bit_unlock (unsigned int nr,volatile unsigned long *p) +arch___clear_bit_unlock (unsigned int nr,volatile unsigned long *addr) {unsigned long old; - p +=BIT_WORD (nr); - old =READ_ONCE (*p); + addr +=BIT_WORD (nr); + old =READ_ONCE (*addr); old &= ~BIT_MASK (nr); -raw_atomic_long_set_release ((atomic_long_t *)p, old); +raw_atomic_long_set_release ((atomic_long_t *)addr, old); }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 415/1266 regulator: dt-bindings: mt6359: Drop regulator-name pattern restrictions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit cdc517688ffa2c30a64a20b558a9ecbf046c70f1 ]
The name of the regulator should match what the board design specifies for the power rail. There should be no limitations on what the name can be, and they definitely don't always follow the PMIC's own names.
Drop the restrictions on regulator-name.
--- .../bindings/regulator/mt6359-regulator.yaml | 43 ------------------- 1 file changed, 43 deletions(-)
Documentation/devicetree/bindings/regulator/mt6359-regulator.yaml +0 -43
@@ -18,84 +18,41 @@ patternProperties: "^buck_v(s1|gpu11|modem|pu|core|s2|pa|proc2|proc1|core_sshub)$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^v(s1|gpu11|modem|pu|core|s2|pa|proc2|proc1|core_sshub)$" - unevaluatedProperties: false "^ldo_v(ibr|rf12|usb|camio|efuse|xo22)$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^v(ibr|rf12|usb|camio|efuse|xo22)$" - unevaluatedProperties: false "^ldo_v(rfck|emc|a12|a09|ufs|bbck)$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^v(rfck|emc|a12|a09|ufs|bbck)$" - unevaluatedProperties: false "^ldo_vcn(18|13|33_1_bt|13_1_wifi|33_2_bt|33_2_wifi)$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^vcn(18|13|33_1_bt|13_1_wifi|33_2_bt|33_2_wifi)$" - unevaluatedProperties: false "^ldo_vsram_(proc2|others|md|proc1|others_sshub)$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^vsram_(proc2|others|md|proc1|others_sshub)$" - unevaluatedProperties: false "^ldo_v(fe|bif|io)28$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^v(fe|bif|io)28$" - unevaluatedProperties: false "^ldo_v(aud|io|aux|rf|m)18$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^v(aud|io|aux|rf|m)18$" - unevaluatedProperties: false "^ldo_vsim[12]$": type: object $ref: regulator.yaml# - - properties: - regulator-name: - pattern: "^vsim[12]$" - - required: - - regulator-name - unevaluatedProperties: false additionalProperties: false
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 416/1266 net/sched: sch_drr: annotate data-races around cl->deficit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit c67b104fd7982162885c5e43057ca761006748e2 ]
drr_dump_class_stats() runs without qdisc spinlock held.
Add missing READ_ONCE()/WRITE_ONCE() annotations around cl->deficit.
--- net/sched/sch_drr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/sched/sch_drr.c +4 -4
@@ -270,7 +270,7 @@ static int drr_dump_class_stats(struct Qdisc *sch, unsigned long arg,memset (&xstats,0 ,sizeof (xstats));if (qlen) - xstats.deficit = cl->deficit; + xstats.deficit =READ_ONCE (cl->deficit); if (gnet_stats_copy_basic(d, NULL, &cl->bstats, true) < 0 || gnet_stats_copy_rate_est(d, &cl->rate_est) < 0 ||
@@ -362,7 +362,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,if (!cl_is_active (cl)) {list_add_tail (&cl->alist, &q->active); - cl->deficit = cl->quantum; +WRITE_ONCE (cl->deficit, cl->quantum); } sch->qstats.backlog += len;
@@ -389,7 +389,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch) len =qdisc_pkt_len (skb);if (len <= cl->deficit) { - cl->deficit -= len; +WRITE_ONCE (cl->deficit, cl->deficit - len); skb =qdisc_dequeue_peeked (cl->qdisc);if (unlikely (skb ==NULL )) goto out;
@@ -403,7 +403,7 @@ static struct sk_buff *drr_dequeue(struct Qdisc *sch)return skb; } - cl->deficit += cl->quantum; +WRITE_ONCE (cl->deficit, cl->deficit + cl->quantum);list_move_tail (&cl->alist, &q->active); } out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 417/1266 media: rockchip: rga: fix too small buffer size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Püschel <[email protected]>
[ Upstream commit 65017e26c065d1240b0512c15867ef1128034fd8 ]
Fix the command buffer size being only a quarter of the actual size. The RGA_CMDBUF_SIZE macro was potentially intended to specify the length of the cmdbuf u32 array pointer. But as it's used to specify the size of the allocation, which is counted in bytes. Therefore adjust the macro size to bytes as it better matches the variable name and adjust it's users accordingly.
As the command buffer is relatively small, it probably didn't caused an issue due to being smaller than a single page.
--- drivers/media/platform/rockchip/rga/rga-hw.c | 2 +- drivers/media/platform/rockchip/rga/rga-hw.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/rockchip/rga/rga-hw.c +1 -1
@@ -379,7 +379,7 @@ static void rga_cmd_set(struct rga_ctx *ctx) {struct rockchip_rga *rga = ctx->rga; -memset (rga->cmdbuf_virt,0 ,RGA_CMDBUF_SIZE *4 ); +memset (rga->cmdbuf_virt,0 ,RGA_CMDBUF_SIZE );rga_cmd_set_src_addr (ctx, rga->src_mmu_pages);/*
drivers/media/platform/rockchip/rga/rga-hw.h +1 -1
@@ -6,7 +6,7 @@#ifndef __RGA_HW_H__#define __RGA_HW_H__ -#define RGA_CMDBUF_SIZE 0x20 +#define RGA_CMDBUF_SIZE 0x80/* Hardware limits */ #define MAX_WIDTH 8192
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 418/1266 firmware: arm_scmi: Fix OOB in scmi_power_name_get()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Geert Uytterhoeven <[email protected]>
[ Upstream commit f9ef3f66f4b18078e464b7606f9497e4dbeb9905 ]
scmi_power_name_get() does not validate the domain number passed by the external caller, which may lead to an out-of-bounds access.
Fix this by returning "unknown" for invalid domains, like scmi_reset_name_get() does.
--- drivers/firmware/arm_scmi/power.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/firmware/arm_scmi/power.c +5 -1
@@ -194,8 +194,12 @@ scmi_power_name_get(const struct scmi_protocol_handle *ph, u32 domain) {struct scmi_power_info *pi = ph->get_priv (ph); -struct power_dom_info *dom = pi->dom_info + domain; +struct power_dom_info *dom; +if (domain >= pi->num_domains) +return "unknown" ; + + dom = pi->dom_info + domain;return dom->name; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 419/1266 arm64: dts: qcom: sm8450: Add power-domain and iface clk for ice node
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshal Dev <[email protected]>
[ Upstream commit 3a5cb1ccbfb3141862b28f24cd5050083233aae7 ]
Qualcomm in-line crypto engine (ICE) platform driver specifies and votes for its own resources. Before accessing ICE hardware during probe, to avoid potential unclocked register access issues (when clk_ignore_unused is not passed on the kernel command line), in addition to the 'core' clock the 'iface' clock should also be turned on by the driver. This can only be done if the UFS_PHY_GDSC power domain is enabled. Specify both the UFS_PHY_GDSC power domain and the 'iface' clock in the ICE node for sm8450.
--- arch/arm64/boot/dts/qcom/sm8450.dtsi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/arm64/boot/dts/qcom/sm8450.dtsi +5 -1
@@ -4224,7 +4224,11 @@ ice: crypto@1d88000 { compatible = "qcom,sm8450-inline-crypto-engine", "qcom,inline-crypto-engine"; reg = <0 0x01d88000 0 0x18000>; - clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>; + clocks = <&gcc GCC_UFS_PHY_ICE_CORE_CLK>, + <&gcc GCC_UFS_PHY_AHB_CLK>; + clock-names = "core", + "iface"; + power-domains = <&gcc UFS_PHY_GDSC>; }; cryptobam: dma-controller@1dc4000 {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 420/1266 tracing: Bound synthetic-field strings with seq_buf
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit f07883450eb14d1cf020b55d9f3a7ec5683bcd26 ]
The synthetic field helpers build a prefixed synthetic variable name and a generated hist command in fixed MAX_FILTER_STR_VAL buffers. The current code appends those strings with raw strcat(), so long key lists, field names, or saved filters can run past the end of the staging buffers.
Build both strings with seq_buf and propagate -E2BIG if either the synthetic variable name or the generated command exceeds MAX_FILTER_STR_VAL. This keeps the existing tracing-side limit while using the helper intended for bounded command construction.
--- kernel/trace/trace_events_hist.c | 41 ++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 12 deletions(-)
kernel/trace/trace_events_hist.c +29 -12
@@ -8,6 +8,7 @@#include <linux/module.h> #include <linux/kallsyms.h> #include <linux/security.h> +#include <linux/seq_buf.h> #include <linux/mutex.h> #include <linux/slab.h> #include <linux/stacktrace.h>
@@ -2943,13 +2944,22 @@ find_synthetic_field_var(struct hist_trigger_data *target_hist_data, {struct hist_field *event_var;char *synthetic_name; +struct seq_buf s; synthetic_name =kzalloc (MAX_FILTER_STR_VAL ,GFP_KERNEL );if (!synthetic_name)return ERR_PTR (-ENOMEM ); -strcpy (synthetic_name,"synthetic_" ); -strcat (synthetic_name, field_name); +seq_buf_init (&s, synthetic_name,MAX_FILTER_STR_VAL ); +seq_buf_printf (&s,"synthetic_%s" , field_name); + +/* Terminate synthetic_name with a NUL. */ +seq_buf_str (&s); + +if (seq_buf_has_overflowed (&s)) { +kfree (synthetic_name); +return ERR_PTR (-E2BIG ); + } event_var =find_event_var (target_hist_data, system, event_name, synthetic_name);
@@ -2995,6 +3005,7 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,struct hist_field *key_field;struct hist_field *event_var;char *saved_filter; +struct seq_buf s;char *cmd;int ret;
@@ -3039,28 +3050,34 @@ create_field_var_hist(struct hist_trigger_data *target_hist_data,return ERR_PTR (-ENOMEM ); } +seq_buf_init (&s, cmd,MAX_FILTER_STR_VAL ); +/* Use the same keys as the compatible histogram */ -strcat (cmd,"keys=" ); +seq_buf_puts (&s,"keys=" );for_each_hist_key_field (i, hist_data) { key_field = hist_data->fields[i];if (!first) -strcat (cmd,"," ); -strcat (cmd, key_field->field->name); +seq_buf_putc (&s,',' ); +seq_buf_puts (&s, key_field->field->name); first = false; }/* Create the synthetic field variable specification */ -strcat (cmd,":synthetic_" ); -strcat (cmd, field_name); -strcat (cmd,"=" ); -strcat (cmd, field_name); +seq_buf_printf (&s,":synthetic_%s=%s" , field_name, field_name);/* Use the same filter as the compatible histogram */ saved_filter =find_trigger_filter (hist_data, file); -if (saved_filter) { -strcat (cmd," if " ); -strcat (cmd, saved_filter); +if (saved_filter) +seq_buf_printf (&s," if %s" , saved_filter); + +/* Terminate cmd with a NUL. */ +seq_buf_str (&s); + +if (seq_buf_has_overflowed (&s)) { +kfree (cmd); +kfree (var_hist); +return ERR_PTR (-E2BIG ); } var_hist->cmd =kstrdup (cmd,GFP_KERNEL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 421/1266 device property: fix fwnode reference leak in fwnode_graph_get_endpoint_by_id()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stepan Ionichev <[email protected]>
[ Upstream commit 9582485a65eacfd7245ec7f0a9d7e2c34749d669 ]
When called with FWNODE_GRAPH_ENDPOINT_NEXT, the function walks every endpoint under the requested port and, for any endpoint whose ID is greater than or equal to the requested one, may store a fwnode reference in best_ep via fwnode_handle_get(). If a later iteration finds an exact-ID match, the function returns that endpoint directly without dropping the reference held by best_ep, leaking it.
Drop the saved candidate before returning the exact-match endpoint.
This affects callers that use FWNODE_GRAPH_ENDPOINT_NEXT to ask for the next endpoint with ID >= the requested one (used by a number of media drivers, e.g. imx7/8, sun6i CSI, omap3isp, xilinx-csi2, stm32-csi). Each leak retains a fwnode reference until reboot/unbind.
--- drivers/base/property.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/base/property.c +3 -1
@@ -1207,8 +1207,10 @@ fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,if (fwnode_ep.port != port)continue ; -if (fwnode_ep.id == endpoint) +if (fwnode_ep.id == endpoint) { +fwnode_handle_put (best_ep);return ep; + }if (!endpoint_next)continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 422/1266 driver core: Use mod_delayed_work to prevent lost deferred probe work
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yuwei <[email protected]>
[ Upstream commit 1137838865bfc9a7cd5869c1dc5c22aa45ec12c8 ]
The deferred_probe_timeout_work may be permanently and unexpectedly canceled when deferred_probe_extend_timeout() executes concurrently. Starting with deferred_probe_timeout_work pending, the problem can occur after the following sequence:
CPU0 CPU1deferred_probe_extend_timeout
-> cancel_delayed_work() => true
deferred_probe_extend_timeout
-> cancel_delayed_work()
-> __cancel_work()
-> try_grab_pending()
-> schedule_delayed_work()
-> queue_delayed_work_on()(Since the pending bit is grabbed,
it just returns without queuing)
-> set_work_pool_and_clear_pending()
(This __cancel_work() returns false and
the work will never be queued again)
The root cause is that the WORK_STRUCT_PENDING_BIT of the work_struct is set temporarily in __cancel_work() (via try_grab_pending()). This transient state prevents the work_struct from being successfully queued by another CPU.
To fix this, replace the original non-atomic cancel and schedule mechanism with mod_delayed_work(). This ensures the modification is handled atomically and guarantees that the work is not lost.
--- drivers/base/dd.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/base/dd.c +2 -4
@@ -326,12 +326,10 @@ void deferred_probe_extend_timeout(void)* If the work hasn't been queued yet or if the work expired, don't * start a new one. */ -if (cancel_delayed_work (&deferred_probe_timeout_work)) { -schedule_delayed_work (&deferred_probe_timeout_work, - driver_deferred_probe_timeout *HZ ); +if (mod_delayed_work (system_wq, &deferred_probe_timeout_work, + driver_deferred_probe_timeout))pr_debug ("Extended deferred probe timeout by %d secs\n" , driver_deferred_probe_timeout); - } }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 423/1266 Revert "treewide: Fix probing of devices in DT overlays"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Saravana Kannan <[email protected]>
[ Upstream commit aaf08c52df9a19148731d4a3cfd85d98455db901 ]
This reverts commit 1a50d9403fb90cbe4dea0ec9fd0351d2ecbd8924.
While the commit fixed fw_devlink overlay handling for one case, it broke it for another case. So revert it and redo the fix in a separate patch.
[Herve: Fix conflicts due to f72e77c33e4b ("device property: Make modifications of fwnode "flags" thread safe")]
--- drivers/bus/imx-weim.c | 6 ------ drivers/i2c/i2c-core-of.c | 5 ----- drivers/of/dynamic.c | 1 - drivers/of/platform.c | 5 ----- drivers/spi/spi.c | 5 ----- 5 files changed, 22 deletions(-)
drivers/bus/imx-weim.c +0 -6
@@ -330,12 +330,6 @@ static int of_weim_notify(struct notifier_block *nb, unsigned long action, "Failed to setup timing for '%pOF'\n", rd->dn);if (!of_node_check_flag (rd->dn,OF_POPULATED )) { -/* -* Clear the flag before adding the device so that -* fw_devlink doesn't skip adding consumers to this -* device. -*/ -fwnode_clear_flag (&rd->dn->fwnode,FWNODE_FLAG_NOT_DEVICE );if (!of_platform_device_create (rd->dn,NULL , &pdev->dev)) { dev_err(&pdev->dev, "Failed to create child device '%pOF'\n",
drivers/i2c/i2c-core-of.c +0 -5
@@ -178,11 +178,6 @@ static int of_i2c_notify(struct notifier_block *nb, unsigned long action,return NOTIFY_OK ; } -/* -* Clear the flag before adding the device so that fw_devlink -* doesn't skip adding consumers to this device. -*/ -fwnode_clear_flag (&rd->dn->fwnode,FWNODE_FLAG_NOT_DEVICE ); client =of_i2c_register_device (adap, rd->dn);if (IS_ERR (client)) { dev_err(&adap->dev, "failed to create client for '%pOF'\n",
drivers/of/dynamic.c +0 -1
@@ -224,7 +224,6 @@ static void __of_attach_node(struct device_node *np) np->sibling = np->parent->child; np->parent->child = np;of_node_clear_flag (np,OF_DETACHED ); -fwnode_set_flag (&np->fwnode,FWNODE_FLAG_NOT_DEVICE );raw_spin_unlock_irqrestore (&devtree_lock, flags);
drivers/of/platform.c +0 -5
@@ -770,11 +770,6 @@ static int of_platform_notify(struct notifier_block *nb,if (of_node_check_flag (rd->dn,OF_POPULATED ))return NOTIFY_OK ; -/* -* Clear the flag before adding the device so that fw_devlink -* doesn't skip adding consumers to this device. -*/ -fwnode_clear_flag (&rd->dn->fwnode,FWNODE_FLAG_NOT_DEVICE );/* pdev_parent may be NULL when no bus platform device */ pdev_parent =of_find_device_by_node (rd->dn->parent); pdev = of_platform_device_create(rd->dn, NULL,
drivers/spi/spi.c +0 -5
@@ -4541,11 +4541,6 @@ static int of_spi_notify(struct notifier_block *nb, unsigned long action,return NOTIFY_OK ; } -/* -* Clear the flag before adding the device so that fw_devlink -* doesn't skip adding consumers to this device. -*/ -fwnode_clear_flag (&rd->dn->fwnode,FWNODE_FLAG_NOT_DEVICE ); spi =of_register_spi_device (ctlr, rd->dn);put_device (&ctlr->dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 424/1266 cpufreq: Documentation: fix sampling_down_factor range
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengjie Zhang <[email protected]>
[ Upstream commit 85524e651d20944399322d46fb97960337831d43 ]
The ondemand governor implementation accepts sampling_down_factor values from 1 to 100000 via MAX_SAMPLING_DOWN_FACTOR, but the documentation in admin-guide/pm/cpufreq.rst still says the valid range is 1 to 100.
Update the documentation to match the actual code.
--- Documentation/admin-guide/pm/cpufreq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
Documentation/admin-guide/pm/cpufreq.rst +1 -1
@@ -499,7 +499,7 @@ This governor exposes the following tunables: of those tasks above 0 and set this attribute to 1. ``sampling_down_factor`` - Temporary multiplier, between 1 (default) and 100 inclusive, to apply to + Temporary multiplier, between 1 (default) and 100000 inclusive, to apply to the ``sampling_rate`` value if the CPU load goes above ``up_threshold``. This causes the next execution of the governor's worker routine (after
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 425/1266 cpufreq: conservative: Simplify frequency limit handling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lifeng Zheng <[email protected]>
[ Upstream commit 3494dff89779b73a6c70481c982e0e96d336454a ]
cs_dbs_update() performs explicit checks against policy->min/max before updating the target frequency. These checks are redundant as __cpufreq_driver_target() already clamps the requested frequency to the valid policy limits.
Remove the unnecessary boundary checks and simplify the update logic.
This also fixes an issue introduced by commit 00bfe05889e9 ("cpufreq:
conservative: Decrease frequency faster for deferred updates"), where stale target comparisons could cause frequency updates to be skipped entirely after deferred adjustments.
--- drivers/cpufreq/cpufreq_conservative.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
drivers/cpufreq/cpufreq_conservative.c +1 -11
@@ -103,10 +103,6 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)if (load > dbs_data->up_threshold) { dbs_info->down_skip =0 ; -/* if we are already at full speed then break out early */ -if (requested_freq == policy->max) - goto out; - requested_freq += freq_step;if (requested_freq > policy->max) requested_freq = policy->max;
@@ -124,13 +120,7 @@ static unsigned int cs_dbs_update(struct cpufreq_policy *policy)/* Check for frequency decrease */ if (load < cs_tuners->down_threshold) { -/* -* if we cannot reduce the frequency anymore, break out early -*/ -if (requested_freq == policy->min) - goto out; - -if (requested_freq > freq_step) +if (requested_freq > policy->min + freq_step) requested_freq -= freq_step;else requested_freq = policy->min;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 426/1266 pwm: imx27: Fix variable truncation in .apply()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ronaldo Nunez <[email protected]>
[ Upstream commit dc9e08fdbcc3eb08a1d2b868b535081c44425e27 ]
Fix a variable truncation when calculating period in microseconds as part of the solution for the ERR051198 in .apply() callback.
Example scenario:
- Period of 3us (PWMPR = 196 and prescaler = 1)
- Expected value in tmp: 198000000000 (NSEC_PER_SEC * (196 + 2) * 1)
- Actual value is 431504384 (truncation to u32)
--- drivers/pwm/pwm-imx27.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/pwm/pwm-imx27.c +7 -1
@@ -218,7 +218,7 @@ static void pwm_imx27_wait_fifo_slot(struct pwm_chip *chip,static int pwm_imx27_apply (struct pwm_chip *chip,struct pwm_device *pwm,const struct pwm_state *state) { -unsigned long period_cycles, duty_cycles, prescale, period_us, tmp; +unsigned long period_cycles, duty_cycles, prescale, period_us;struct pwm_imx27_chip *imx =to_pwm_imx27_chip (chip);struct pwm_state cstate;unsigned long long c;
@@ -227,6 +227,7 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm,int val;int ret;u32 cr; +u64 tmp;pwm_get_state (pwm, &cstate);
@@ -270,6 +271,11 @@ static int pwm_imx27_apply(struct pwm_chip *chip, struct pwm_device *pwm, val =readl (imx->mmio_base +MX3_PWMPR ); val = val >=MX3_PWMPR_MAX ?MX3_PWMPR_MAX : val; cr =readl (imx->mmio_base +MX3_PWMCR ); + +/* +* tmp stores period in nanoseconds. Result fits in u64 since +* val <= 0xfffe and prescaler in [1, 0x1000]. +*/ tmp =NSEC_PER_SEC * (u64)(val +2 ) *MX3_PWMCR_PRESCALER_GET (cr); tmp =DIV_ROUND_UP_ULL (tmp, clkrate); period_us =DIV_ROUND_UP_ULL (tmp,1000 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 427/1266 bus: sunxi-rsb: Always check register address validity
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <[email protected]>
[ Upstream commit 61192938a5870ac36edae81e4775b680dcf02c61 ]
The register address was already validated for read operations in regmap_sunxi_rsb_reg_read before being truncated to a u8. Write operations have the same set of possible addresses, and the address is being truncated from u32 to u8 here as well, so the same check is needed.
--- drivers/bus/sunxi-rsb.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/bus/sunxi-rsb.c +3 -0
@@ -447,6 +447,9 @@ static int regmap_sunxi_rsb_reg_write(void *context, unsigned int reg,struct sunxi_rsb_ctx *ctx = context;struct sunxi_rsb_device *rdev = ctx->rdev; +if (reg >0xff ) +return -EINVAL ; +return sunxi_rsb_write (rdev->rsb, rdev->rtaddr, reg, &val, ctx->size); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 428/1266 RDMA/irdma: Fix out-of-bounds write in irdma_copy_user_pgaddrs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 5ebb3ed757be3e04cf803026004aa0beaeb13e9b ]
The irdma_copy_user_pgaddrs function loops through all of the umem DMA blocks to populate the PBLEs and will stop when either the last DMA block is reached or palloc->total_cnt is reached. The issue is that the logic for checking palloc->total_cnt would only work for non-zero values.
When irdma_setup_pbles is called with lvl==0, it
calls irdma_copy_user_pgaddrs with palloc->total_cnt==0, which means the only way to break out of the loop is to reach the last umem DMA block, which means it could end up going beyond the fixed size of 4 iwmr->pgaddrmem array that is used in the lvl==0 case.
In the case of QP/CQ/SRQ rings, the value of lvl is determined by a separate input (for example, req.cq_pages in the case of a CQ). So, we must perform explicit checking to ensure we don't overflow the pgaddrmem array if the user provides a umem that consists of more blocks than their provided req.cq_pages.
--- drivers/infiniband/hw/irdma/verbs.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/infiniband/hw/irdma/verbs.c +10 -4
@@ -2326,10 +2326,11 @@ static inline u64 *irdma_next_pbl_addr(u64 *pbl, struct irdma_pble_info **pinfo,* irdma_copy_user_pgaddrs - copy user page address to pble's os locally * @iwmr: iwmr for IB's user page addresses * @pbl: ple pointer to save 1 level or 0 level pble +* @pbl_len: Max number of PBL entries to populate * @level: indicated level 0, 1 or 2 */ static void irdma_copy_user_pgaddrs (struct irdma_mr *iwmr,u64 *pbl, -enum irdma_pble_level level) +u32 pbl_len,enum irdma_pble_level level) {struct ib_umem *region = iwmr->region;struct irdma_pbl *iwpbl = &iwmr->iwpbl;
@@ -2337,7 +2338,9 @@ static void irdma_copy_user_pgaddrs(struct irdma_mr *iwmr, u64 *pbl,struct irdma_pble_info *pinfo;struct ib_block_iter biter;u32 idx =0 ; -u32 pbl_cnt =0 ; + +if (!pbl_len) +return ; pinfo = (level ==PBLE_LEVEL_1 ) ?NULL : palloc->level2.leaf;
@@ -2346,7 +2349,7 @@ static void irdma_copy_user_pgaddrs(struct irdma_mr *iwmr, u64 *pbl,rdma_umem_for_each_dma_block (region, &biter, iwmr->page_size) { *pbl =rdma_block_iter_dma_address (&biter); -if (++pbl_cnt == palloc->total_cnt) +if (!--pbl_len)break ; pbl =irdma_next_pbl_addr (pbl, &pinfo, &idx); }
@@ -2422,6 +2425,7 @@ static int irdma_setup_pbles(struct irdma_pci_f *rf, struct irdma_mr *iwmr,u64 *pbl;int status;enum irdma_pble_level level =PBLE_LEVEL_1 ; +u32 pbl_len;if (lvl) { status = irdma_get_pble(rf->pble_rsrc, palloc, iwmr->page_cnt,
@@ -2429,16 +2433,18 @@ static int irdma_setup_pbles(struct irdma_pci_f *rf, struct irdma_mr *iwmr,if (status)return status; + pbl_len = palloc->total_cnt; iwpbl->pbl_allocated = true; level = palloc->level; pinfo = (level ==PBLE_LEVEL_1 ) ? &palloc->level1 : palloc->level2.leaf; pbl = pinfo->addr; }else { + pbl_len =IRDMA_MAX_SAVED_PHY_PGADDR ; pbl = iwmr->pgaddrmem; } -irdma_copy_user_pgaddrs (iwmr, pbl, level); +irdma_copy_user_pgaddrs (iwmr, pbl, pbl_len, level);if (lvl) iwmr->pgaddrmem[0 ] = *pbl;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 429/1266 RDMA/rxe: Fix a use-after-free problem in rxe_mmap
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhu Yanjun <[email protected]>
[ Upstream commit 35744ab3d03c5fca8c1752f53fc8fc674e14c561 ]
rxe_mmap() removes a rxe_mmap_info struct from the pending_mmaps list and releases pending_lock while the struct's kref is still at 1:
list_del_init(&ip->pending_mmaps);
spin_unlock_bh(&rxe->pending_lock); /* ref == 1, no lock held */
ret = remap_vmalloc_range(vma, ip->obj, 0); /* walks PTEs */ [...]
rxe_vma_open(vma); /* kref_get, ref → 2 */
remap_vmalloc_range_partial() walks PTEs without any lock.
A concurrent DESTROY_CQ ioctl on another CPU calls:
kref_put(&q->ip->ref, rxe_mmap_release) /* ref 1→0 */
vfree(ip->obj) /* clears vmalloc PTEs mid-walk */
kfree(ip) /* frees rxe_mmap_info */This yields:
1. Kernel crash, vmalloc_to_page() returns NULL when vfree wins the per-PTE race -> vm_insert_page(NULL) → GPF in validate_page_before_insert
2. Page UAF, vmalloc_to_page() reads a stale PTE before vfree clears it. User VMA holds a PTE to a free'd page which might eventually get reallocated later by vmalloc which allows the attacker to get a clean page-level UAF.
It is worth noting that even though a page-level UAF is possible given the strong primitive, it is statistically very difficult to achieve given the very short time window (after the last insert_page and before the kref_get).
The call trace are as below:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 UID: 1000 PID: 413 Comm: poc Not tainted 7.0.0-rc5-dirty #28 PREEMPT(lazy) Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 RIP: 0010:validate_page_before_insert+0x32/0x300 Code: e5 41 57 41 56 49 89 fe 41 55 41 54 53 48 89 f3 e8 93 b5 a3 ff 48 8d 7b 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 7b 02 00 00 4c 8b 63 08 31 ff 4d 89 e5 41 83 e5 RSP: 0018:ffff88811b15f2f0 EFLAGS: 00000202 RAX: dffffc0000000000 RBX: 0000000000000000 RCX: 0000000000000000 RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000008 RBP: ffff88811b15f318 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8881181eee00 R13: 0000000000000000 R14: ffff8881181eee00 R15: ffff8881181eee20 FS: 00007b1e000f76c0(0000) GS:ffff8884268e0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007b1e00a24ac0 CR3: 0000000116eb3000 CR4: 00000000000006f0 Call Trace: <TASK> insert_page+0x8f/0x190 ? __pfx_insert_page+0x10/0x10 ? kasan_save_alloc_info+0x38/0x60 vm_insert_page+0x2e7/0x400 remap_vmalloc_range_partial+0x212/0x3e0 remap_vmalloc_range+0x6e/0xb0 ? __kasan_check_write+0x14/0x30 rxe_mmap+0x2e9/0x5d0 ib_uverbs_mmap+0x1ad/0x2c0 __mmap_region+0x12c2/0x2ad0 ? __pfx___mmap_region+0x10/0x10 ? __sanitizer_cov_trace_switch+0x58/0xb0 ? mas_prev_slot+0x360/0x39c0 ? __sanitizer_cov_trace_switch+0x58/0xb0 ? mas_next_slot+0x1e5b/0x2f40 ? __sanitizer_cov_trace_cmp8+0x18/0x30 ? unmapped_area_topdown+0x4dd/0x610 ? kfree+0x1b1/0x440 ? free_cpumask_var+0x16/0x30 ? __kasan_slab_free+0x7d/0xa0 ? __sanitizer_cov_trace_cmp8+0x18/0x30 mmap_region+0x2e6/0x3c0 do_mmap+0xa3e/0x12a0 ? __pfx_do_mmap+0x10/0x10 ? __kasan_check_write+0x14/0x30 ? down_write_killable+0xba/0x160 ? __pfx_down_write_killable+0x10/0x10 ? __sanitizer_cov_trace_cmp4+0x16/0x30 vm_mmap_pgoff+0x2d4/0x4a0 ? __pfx_vm_mmap_pgoff+0x10/0x10 ? fget+0x1bf/0x270 ksys_mmap_pgoff+0x40c/0x690 ? __sanitizer_cov_trace_const_cmp4+0x16/0x30 ? __pfx_ksys_mmap_pgoff+0x10/0x10 ? __kasan_check_write+0x14/0x30 ? _raw_spin_trylock+0xbb/0x130 ? __pfx__raw_spin_trylock+0x10/0x10 __x64_sys_mmap+0x135/0x1e0 x64_sys_call+0x1c14/0x2790 do_syscall_64+0xd2/0x1050 ? rcu_core+0x352/0x7d0 ? rcu_core_si+0xe/0x20 ? handle_softirqs+0x1aa/0x650 ? __sanitizer_cov_trace_cmp4+0x16/0x30 ? fpregs_assert_state_consistent+0xe1/0x160 ? irqentry_exit+0xb1/0x670 entry_SYSCALL_64_after_hwframe+0x76/0x7e
--- drivers/infiniband/sw/rxe/rxe_mmap.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
drivers/infiniband/sw/rxe/rxe_mmap.c +16 -3
@@ -93,18 +93,31 @@ int rxe_mmap(struct ib_ucontext *context, struct vm_area_struct *vma) goto done; found_it: +/* +* Increment refcount and check whether it is being freed atm while +* holding lock to prevent UAF +*/ +if (!kref_get_unless_zero (&ip->ref)) { +spin_unlock_bh (&rxe->pending_lock); + ret = -ENXIO ; + goto done; + } +list_del_init (&ip->pending_mmaps);spin_unlock_bh (&rxe->pending_lock); + vma->vm_ops = &rxe_vm_ops; + vma->vm_private_data = ip; + ret =remap_vmalloc_range (vma, ip->obj,0 );if (ret) { + vma->vm_private_data =NULL ; + vma->vm_ops =NULL ; +kref_put (&ip->ref, rxe_mmap_release);rxe_dbg_dev (rxe,"err %d from remap_vmalloc_range\n" , ret); goto done; } - vma->vm_ops = &rxe_vm_ops; - vma->vm_private_data = ip; -rxe_vma_open (vma); done:return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 430/1266 IB/mlx4: Fix refcount leak in add_port() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 9a8826fdfbcd7ed2ccf745f5d54208358d939def ]
After kobject_init_and_add(), the lifetime of the embedded struct kobject is expected to be managed through the kobject core reference counting.
In add_port(), failure paths after kobject_init_and_add() must not free struct mlx4_port directly, because the embedded kobject is then managed by the kobject core. Freeing it directly leaves the kobject reference counting unbalanced and can lead to incorrect lifetime handling.
Allocate the pkey and gid attribute arrays before kobject_init_and_add(), so failures before kobject initialization can be handled by directly freeing the allocated memory. Once kobject_init_and_add() has been called, unwind later failures by removing any successfully created sysfs groups, calling kobject_del(), and then releasing the embedded kobject with kobject_put().
--- drivers/infiniband/hw/mlx4/sysfs.c | 45 ++++++++++++++++++------------ 1 file changed, 27 insertions(+), 18 deletions(-)
drivers/infiniband/hw/mlx4/sysfs.c +27 -18
@@ -638,12 +638,6 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) p->port_num = port_num; p->slave = slave; - ret =kobject_init_and_add (&p->kobj, &port_type, -kobject_get (dev->dev_ports_parent[slave]), -"%d" , port_num); -if (ret) - goto err_alloc; - p->pkey_group.name ="pkey_idx" ; p->pkey_group.attrs = alloc_group_attrs(show_port_pkey,
@@ -651,13 +645,9 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) dev->dev->caps.pkey_table_len[port_num]);if (!p->pkey_group.attrs) { ret = -ENOMEM ; - goto err_alloc; + goto err_free_port; } - ret =sysfs_create_group (&p->kobj, &p->pkey_group); -if (ret) - goto err_free_pkey; - p->gid_group.name ="gid_idx" ; p->gid_group.attrs =alloc_group_attrs (show_port_gid_idx,NULL ,1 );if (!p->gid_group.attrs) {
@@ -665,28 +655,47 @@ static int add_port(struct mlx4_ib_dev *dev, int port_num, int slave) goto err_free_pkey; } + ret =kobject_init_and_add (&p->kobj, &port_type, +kobject_get (dev->dev_ports_parent[slave]), +"%d" , port_num); +if (ret) + goto err_put; + + ret =sysfs_create_group (&p->kobj, &p->pkey_group); +if (ret) + goto err_del; + ret =sysfs_create_group (&p->kobj, &p->gid_group);if (ret) - goto err_free_gid; + goto err_remove_pkey; ret =add_vf_smi_entries (p);if (ret) - goto err_free_gid; + goto err_remove_gid;list_add_tail (&p->kobj.entry, &dev->pkeys.pkey_port_list[slave]);return 0 ; -err_free_gid: -kfree (p->gid_group.attrs[0 ]); -kfree (p->gid_group.attrs); +err_remove_gid: +sysfs_remove_group (&p->kobj, &p->gid_group); + +err_remove_pkey: +sysfs_remove_group (&p->kobj, &p->pkey_group); + +err_del: +kobject_del (&p->kobj); + +err_put: +kobject_put (dev->dev_ports_parent[slave]); +kobject_put (&p->kobj); +return ret; err_free_pkey:for (i =0 ; i < dev->dev->caps.pkey_table_len[port_num]; ++i)kfree (p->pkey_group.attrs[i]);kfree (p->pkey_group.attrs); -err_alloc: -kobject_put (dev->dev_ports_parent[slave]); +err_free_port:kfree (p);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 431/1266 RDMA/hns: Fix warning in poll cq direct mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lianfa Weng <[email protected]>
[ Upstream commit 3f19c2a3852e6ba75f3e92dd5edc4e07f3d07f4a ]
CQs allocated by ib_alloc_cq() always have a comp_handler. Though in direct mode this handler is never expected to be called, it is still called when the driver is reset, triggering the following WARN_ONCE():
Call trace: ib_cq_completion_direct+0x38/0x60 hns_roce_cq_completion+0x54/0x90 (hns_roce_hw_v2] hns_roce_handle_device_err+Ox1c8/0x340 [hns_roce_hw_v2] hns_roce_hw_v2_uninit_instance.constprop.0+0x34/0x70 [hns_roce_hw_v2] hns_roce_hw_v2_reset_notify+0xc4/0xe0 [hns_roce_hw_v2] hclge_notify_roce_client+0x60/0xbc [hclge] hclge_reset_rebuild+0x48/0x34c [hclge] hclge_reset_subtask+0xcc/0xec [hclge] hclge_reset_service_task+0x80/0x160 [hclge] hclge_service_task+0x50/0x80 (hclge] process_one_work+0x1cc/0x4d0 worker_thread+0x154/0x414 kthread+0x104/0x144 ret_from_fork+0x10/0x18
--- drivers/infiniband/hw/hns/hns_roce_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/hns/hns_roce_main.c +1 -1
@@ -969,7 +969,7 @@ static void check_and_get_armed_cq(struct list_head *cq_list, struct ib_cq *cq)unsigned long flags;spin_lock_irqsave (&hr_cq->lock, flags); -if (cq->comp_handler) { +if (cq->comp_handler && hr_cq->ib_cq.poll_ctx !=IB_POLL_DIRECT ) {if (!hr_cq->is_armed) { hr_cq->is_armed =1 ;list_add_tail (&hr_cq->node, cq_list);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 432/1266 RDMA/counter: Fix incorrect port index in rdma_counter_init() error cleanup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tao Cui <[email protected]>
[ Upstream commit b86fd95805a7bd4c5b9465c9e7f75e45bbe7eb6f ]
The error cleanup loop in rdma_counter_init() iterates with variable 'i' but accesses dev->port_data[port] instead of dev->port_data[i]. This causes the failed port's hstats to be freed multiple times while leaking hstats of previously initialized ports.
--- drivers/infiniband/core/counters.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/core/counters.c +1 -1
@@ -649,7 +649,7 @@ void rdma_counter_init(struct ib_device *dev) fail:for (i = port; i >=rdma_start_port (dev); i--) { - port_counter = &dev->port_data[port].port_counter; + port_counter = &dev->port_data[i].port_counter;rdma_free_hw_stats_struct (port_counter->hstats); port_counter->hstats =NULL ;mutex_destroy (&port_counter->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 433/1266 PM: sleep: Use complete() in device_pm_sleep_init()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiakai Xu <[email protected]>
[ Upstream commit 3855941f1e4069182c895d5093c5fa589f5b38bd ]
Replace complete_all() with complete() in device_pm_sleep_init() to allow it to be called in atomic contexts without triggering a false-positive WARNING from lockdep_assert_RT_in_threaded_ctx() when CONFIG_PROVE_RAW_LOCK_NESTING is enabled.
device_pm_sleep_init() may be called during device initialization while holding a raw_spinlock (e.g., from within device_initialize()), and complete_all() is unsafe in atomic contexts on PREEMPT_RT kernels. complete(), which is safe to call from any context, is sufficient here.
complete_all() sets the completion count to UINT_MAX/2 (permanently signaled), while complete() increments it by 1. Since no threads can be waiting during device initialization, both are functionally equivalent. The completion is always reinitialized via reinit_completion() in dpm_clear_async_state() before each suspend/resume cycle.
However, changing to complete() introduces a potential deadlock for devices with no PM support (dev->power.no_pm = true). Such devices are never added to the dpm_list and never go through dpm_clear_async_state(), so their completion is never reinitialized. A parent device waiting on a no_pm child across multiple suspend phases would consume the single-use token in the first phase and block forever in the second.
Fix this by adding an early return in dpm_wait() when dev->power.no_pm is set, since no_pm devices do not participate in system suspend/resume.
--- drivers/base/power/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/base/power/main.c +5 -1
@@ -101,7 +101,7 @@ void device_pm_sleep_init(struct device *dev) dev->power.is_noirq_suspended = false; dev->power.is_late_suspended = false;init_completion (&dev->power.completion); -complete_all (&dev->power.completion); +complete (&dev->power.completion); dev->power.wakeup =NULL ;INIT_LIST_HEAD (&dev->power.entry); }
@@ -238,6 +238,10 @@ static void dpm_wait(struct device *dev, bool async)if (!dev)return ; +/* Devices with no PM support don't use the completion. */ +if (dev->power.no_pm) +return ; +if (async || (pm_async_enabled && dev->power.async_suspend))wait_for_completion (&dev->power.completion); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 434/1266 MIPS: Fix big-endian stack argument fetching in o32 wrapper
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
[ Upstream commit 8e0780d30b1b51248e42895b7acc7a20f147b40b ]
Fix an issue in call_o32() where the upper 32-bit half of incoming n64 stack arguments is fetched and used for outgoing o32 stack arguments on big-endian platforms.
This code was adapted from arch/mips/dec/prom/call_o32.S which was meant for a little-endian platform only and therefore using 32-bit loads from 64-bit stack slot locations holding incoming stack arguments resulted in correct values being retrieved for data that is expected to be 32-bit.
This works on little-endian platforms where the lower 32-bit half of the 64-bit value is located at every 64-bit stack slot location. However on big-endian platforms the lower 32-bit half is instead located at offset 4 from every 64-bit stack slot location.
So to fix the issue the offset of 4 would have to be used on big-endian platforms only, or alternatively a 64-bit load from the 64-bit stack slot location can be used across the board, as the subsequent 32-bit store to the corresponding outgoing stack argument slot will correctly truncate the value and cause no unpredictable result. We already take advantage of this architectural feature for the incoming arguments held in $a6 and $a7 registers, since the o32 wrapper does not know how many incoming arguments there are and consequently propagates incoming data which may not be 32-bit.
Since this code is generally supposed to be used with the stack located in cached memory there is no extra overhead expected for 64-bit loads as opposed to 32-bit ones, so pick this variant for code simplicity.
--- arch/mips/fw/lib/call_o32.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/fw/lib/call_o32.S +1 -1
@@ -74,7 +74,7 @@ NESTED(call_o32, O32_FRAMESZ, ra) PTR_LA t1,6*O32_SZREG(fp) li t2,O32_ARGC-6 1: - lw t3,(t0) + ld t3,(t0) REG_ADDU t0,SZREG sw t3,(t1) REG_SUBU t2,1
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 435/1266 MIPS: DEC: Remove do_IRQ() call indirection
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
[ Upstream commit 35554eadc1b127bb5294504a4ac8f3a5dd9e299d ]
As from commit 8f99a1626535 ("MIPS: Tracing: Add IRQENTRY_EXIT section for MIPS") do_IRQ() is not a macro anymore and can be invoked directly from assembly code, as a tail call. Remove the dec_irq_dispatch() stub then and the indirection previously introduced with commit 187933f23679 ("[MIPS] do_IRQ cleanup"), improving performance by reducing the number of control flow changes and the overall instruction count, while fixing a compiler's complaint about a missing prototype for said stub:
arch/mips/dec/setup.c:780:25: warning: no previous prototype for 'dec_irq_dispatch' [-Wmissing-prototypes]
780 | asmlinkage unsigned int dec_irq_dispatch(unsigned int irq)
| ^~~~~~~~~~~~~~~~
(which gets promoted to a compilation error with CONFIG_WERROR).
--- arch/mips/dec/int-handler.S | 2 +- arch/mips/dec/setup.c | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-)
arch/mips/dec/int-handler.S +1 -1
@@ -277,7 +277,7 @@ srlv t3,t1,t2 handle_it: - j dec_irq_dispatch + j do_IRQ nop #if defined(CONFIG_32BIT) && defined(CONFIG_MIPS_FP_SUPPORT)
arch/mips/dec/setup.c +0 -6
@@ -776,9 +776,3 @@ void __init arch_init_irq(void)pr_err ("Failed to register halt interrupt\n" ); } } - -asmlinkage unsigned int dec_irq_dispatch(unsigned int irq) -{ -do_IRQ (irq); -return 0 ; -}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 436/1266 mips: ralink: mt7621: add missing __iomem
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit 4ddaf88aadd3bd09c2eb3734c53d2864af6b144e ]
raw_readl and writel calls expect pointers annotated with __iomem.
--- arch/mips/ralink/mt7621.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/ralink/mt7621.c +1 -1
@@ -63,7 +63,7 @@ phys_addr_t mips_cpc_default_phys_base(void)static bool __init mt7621_addr_wraparound_test (phys_addr_t size) { -void *dm = (void *)KSEG1ADDR (&detect_magic); +void __iomem *dm = (void __iomem *)KSEG1ADDR (&detect_magic);if (CPHYSADDR (dm + size) >=MT7621_LOWMEM_MAX_SIZE )return true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 437/1266 mips: n64: add __iomem for writel call
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit 579f5329d5df2dbcf4bb5ef398701c2501d24892 ]
sparse: incorrect type in argument 2 (different address spaces) @@ expected void volatile [noderef] __iomem *mem @@
got unsigned int [usertype] *
--- arch/mips/n64/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/mips/n64/init.c +1 -1
@@ -50,7 +50,7 @@ void __init prom_init(void)#define W 320#define H 240 -#define REG_BASE ((u32 *) CKSEG1ADDR(0x4400000)) +#define REG_BASE ((u32 __iomem *) CKSEG1ADDR(0x4400000))static void __init n64rdp_write_reg (const u8 reg,const u32 value) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 438/1266 mtd: spi-nor: Drop duplicate Kconfig dependency
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miquel Raynal <[email protected]>
[ Upstream commit a6470e2162e9c3779a4bd6ff3bed1b81d796e46e ]
I do not think the MTD dependency is needed twice. This is likely a duplicate coming from a former rebase when the spi-nor core got cleaned up a while ago. Remove the extra line.
--- drivers/mtd/spi-nor/Kconfig | 1 - 1 file changed, 1 deletion(-)
drivers/mtd/spi-nor/Kconfig +0 -1
@@ -1,7 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menuconfig MTD_SPI_NOR tristate "SPI NOR device support" - depends on MTD depends on MTD && SPI_MASTER select SPI_MEM help
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 439/1266 ALSA: seq: midi: Serialize output teardown with event_input
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit ef7607ab1c8adc6258fb1b27d08e26aecdc18a58 ]
event_process_midi() borrows msynth->output_rfile.output and then passes the substream to dump_midi() and snd_rawmidi_kernel_write() without synchronizing with the output open/close transition. midisynth_use() also publishes output_rfile before snd_rawmidi_output_params() has finished.
The last midisynth_unuse() can therefore release the same rawmidi file and free substream->runtime before snd_rawmidi_kernel_write1() takes its runtime buffer reference. That leaves the event_input path using a stale substream or runtime and can end in a NULL-deref or use-after-free.
Fix this with two pieces of synchronization. Keep a short IRQ-safe spinlock only for publishing or clearing output_rfile and for pairing the output snapshot with an snd_use_lock_t reference. Once event_process_midi() has taken that in-flight reference, it drops the spinlock before calling snd_seq_dump_var_event(), dump_midi(), or snd_rawmidi_kernel_write(). midisynth_unuse() now detaches the visible rawmidi file under the same spinlock, waits for the in-flight writers to drain, and only then drains and releases the saved file. midisynth_use() likewise opens into a local snd_rawmidi_file and publishes it only after snd_rawmidi_output_params() succeeds.
The buggy scenario involves two paths, with each column showing the order within that path:
event_input path: last unuse path:
1. event_process_midi() snapshots 1. midisynth_unuse() starts
output_rfile.output. tearing down output_rfile.
2. dump_midi() reaches 2. snd_rawmidi_kernel_release()
snd_rawmidi_kernel_write() closes the output file.
before runtime is pinned. 3. close_substream() frees
3. The callback keeps using substream->runtime.
the borrowed substream.
Validation reproduced this kernel report:
KASAN null-ptr-deref in snd_rawmidi_kernel_write1+0x56/0x360
RIP: 0033:0x7fde7dd0837f RIP: 0010:snd_rawmidi_kernel_write1+0x56/0x360
--- sound/core/seq/seq_midi.c | 55 +++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 14 deletions(-)
sound/core/seq/seq_midi.c +41 -14
@@ -24,6 +24,7 @@ Possible options for midisynth module:#include <sound/seq_device.h> #include <sound/seq_midi_event.h> #include <sound/initval.h> +#include "seq_lock.h" MODULE_AUTHOR ("Frank van de Pol <[email protected]>, Jaroslav Kysela <[email protected]>" );MODULE_DESCRIPTION ("Advanced Linux Sound Architecture sequencer MIDI synth." );
@@ -42,6 +43,8 @@ struct seq_midisynth {int device;int subdevice;struct snd_rawmidi_file input_rfile; +spinlock_t output_lock;/* protects output_rfile publication */ +snd_use_lock_t output_use_lock;/* in-flight event_input users */ struct snd_rawmidi_file output_rfile;int seq_client;int seq_port;
@@ -125,31 +128,42 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,struct seq_midisynth *msynth = private_data;unsigned char msg[10 ];/* buffer for constructing midi messages */ struct snd_rawmidi_substream *substream; +int err =0 ;int len;if (snd_BUG_ON (!msynth))return -EINVAL ; - substream = msynth->output_rfile.output; -if (substream ==NULL ) -return -ENODEV ; + + scoped_guard(spinlock_irqsave, &msynth->output_lock) { + substream = msynth->output_rfile.output; +if (!substream) +return -ENODEV ; +snd_use_lock_use (&msynth->output_use_lock); + } +if (ev->type ==SNDRV_SEQ_EVENT_SYSEX ) {/* special case, to save space */ if ((ev->flags &SNDRV_SEQ_EVENT_LENGTH_MASK ) !=SNDRV_SEQ_EVENT_LENGTH_VARIABLE ) {/* invalid event */ pr_debug ("ALSA: seq_midi: invalid sysex event flags = 0x%x\n" , ev->flags); -return 0 ; + goto out; }snd_seq_dump_var_event (ev, __dump_midi, substream);snd_midi_event_reset_decode (msynth->parser); }else { -if (msynth->parser ==NULL ) -return -EIO ; +if (!msynth->parser) { + err = -EIO ; + goto out; + } len =snd_midi_event_decode (msynth->parser, msg,sizeof (msg), ev);if (len <0 ) -return 0 ; + goto out;if (dump_midi (substream, msg, len) <0 )snd_midi_event_reset_decode (msynth->parser); } -return 0 ; + +out: +snd_use_lock_free (&msynth->output_use_lock); +return err; }
@@ -163,6 +177,8 @@ static int snd_seq_midisynth_new(struct seq_midisynth *msynth, msynth->card = card; msynth->device = device; msynth->subdevice = subdevice; +spin_lock_init (&msynth->output_lock); +snd_use_lock_init (&msynth->output_use_lock);return 0 ; }
@@ -215,12 +231,13 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info {int err;struct seq_midisynth *msynth = private_data; +struct snd_rawmidi_file rfile = {};struct snd_rawmidi_params params;/* open midi port */ err =snd_rawmidi_kernel_open (msynth->rmidi, msynth->subdevice,SNDRV_RAWMIDI_LFLG_OUTPUT , - &msynth->output_rfile); + &rfile);if (err <0 ) {pr_debug ("ALSA: seq_midi: midi output open failed!!!\n" );return err;
@@ -229,12 +246,14 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info params.avail_min =1 ; params.buffer_size = output_buffer_size; params.no_active_sensing =1 ; - err =snd_rawmidi_output_params (msynth->output_rfile.output, ¶ms); + err =snd_rawmidi_output_params (rfile.output, ¶ms);if (err <0 ) { -snd_rawmidi_kernel_release (&msynth->output_rfile); +snd_rawmidi_kernel_release (&rfile);return err; }snd_midi_event_reset_decode (msynth->parser); +scoped_guard (spinlock_irqsave, &msynth->output_lock) + msynth->output_rfile = rfile;return 0 ; }
@@ -242,11 +261,19 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *infostatic int midisynth_unuse (void *private_data,struct snd_seq_port_subscribe *info) {struct seq_midisynth *msynth = private_data; +struct snd_rawmidi_file rfile = {}; -if (snd_BUG_ON (!msynth->output_rfile.output)) + scoped_guard(spinlock_irqsave, &msynth->output_lock) { + rfile = msynth->output_rfile; + msynth->output_rfile = (struct snd_rawmidi_file ){}; + } + +if (snd_BUG_ON (!rfile.output))return -EINVAL ; -snd_rawmidi_drain_output (msynth->output_rfile.output); -return snd_rawmidi_kernel_release (&msynth->output_rfile); + +snd_use_lock_sync (&msynth->output_use_lock); +snd_rawmidi_drain_output (rfile.output); +return snd_rawmidi_kernel_release (&rfile); }/* delete given midi synth port */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 440/1266 pinctrl: cs42l43: Fix polarity on debounce
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Keepax <[email protected]>
[ Upstream commit 9da52ee80aee3ab3c69208bd1cfbb4be01371214 ]
The debounce bit sets a bypass on the debounce rather than enabling it, as such the current polarity of the debounce is set incorrectly. Invert the polarity to correct this.
--- drivers/pinctrl/cirrus/pinctrl-cs42l43.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/cirrus/pinctrl-cs42l43.c +1 -1
@@ -343,7 +343,7 @@ static inline int cs42l43_pin_set_db(struct cs42l43_pin *priv, unsigned int pin,return regmap_update_bits (priv->regmap,CS42L43_GPIO_CTRL2 ,CS42L43_GPIO1_DEGLITCH_BYP_MASK << pin, - !!us << pin); + !us << pin); } static int cs42l43_pin_config_get(struct pinctrl_dev *pctldev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 441/1266 nvme-multipath: fix flex array size in struct nvme_ns_head
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nilay Shroff <[email protected]>
[ Upstream commit 001e57554de81aa79c25c18fd53911d8a415c304 ]
struct nvme_ns_head contains a flexible array member, current_path[], which is indexed using the NUMA node ID:
head->current_path[numa_node_id()]
The structure is currently allocated as:
size = sizeof(struct nvme_ns_head) +
(num_possible_nodes() * sizeof(struct nvme_ns *));
head = kzalloc(size, GFP_KERNEL);
This allocation assumes that NUMA node IDs are sequential and densely packed from 0 .. num_possible_nodes() - 1. While this assumption holds on many systems, it is not always true on some architectures such as powerpc.
On some powerpc systems, NUMA node IDs can be sparse. For example:
NUMA:
NUMA node(s): 6 NUMA node0 CPU(s): 80-159 NUMA node8 CPU(s): 0-79
NUMA node252 CPU(s):
NUMA node253 CPU(s):
NUMA node254 CPU(s):
NUMA node255 CPU(s):
That is, the possible/online NUMA node IDs are: 0, 8, 252, 253, 254, 255 In this case: num_possible_nodes() = 6
So memory is allocated for only 6 entries in current_path[]. However, the array is later indexed using the actual NUMA node ID. As a result, accesses such as:
head->current_path[8] or
head->current_path[252]
goes out of bounds, leading to the following KASAN splat:
==================================================================
BUG: KASAN: slab-out-of-bounds in nvme_mpath_revalidate_paths+0x22c/0x290 [nvme_core] Write of size 8 at addr c00020003bda35b8 by task kworker/u641:2/1997 CPU: 1 UID: 0 PID: 1997 Comm: kworker/u641:2 Not tainted 7.1.0-rc5-dirty #14 PREEMPT(lazy) Hardware name: 8335-GTH POWER9 0x4e1202 opal:skiboot-v6.5.3-35-g1851b2a06 PowerNV Workqueue: async async_run_entry_fn Call Trace: [c000200037fa7510] [c0000000021c23d4] dump_stack_lvl+0x88/0xdc (unreliable) [c000200037fa7540] [c0000000009fda90] print_report+0x22c/0x67c [c000200037fa7630] [c0000000009fd508] kasan_report+0x108/0x220 [c000200037fa7740] [c0000000009fff48] __asan_store8+0xe8/0x120 [c000200037fa7760] [c008000018e76474] nvme_mpath_revalidate_paths+0x22c/0x290 [nvme_core] [c000200037fa7800] [c008000018e6556c] nvme_update_ns_info+0x4a4/0x5e0 [nvme_core] [c000200037fa7a50] [c008000018e66270] nvme_alloc_ns+0x6d8/0x1a70 [nvme_core] [c000200037fa7c20] [c008000018e679fc] nvme_scan_ns+0x3f4/0x630 [nvme_core] [c000200037fa7d10] [c00000000031f22c] async_run_entry_fn+0x9c/0x3a0 [c000200037fa7db0] [c0000000002fa544] process_one_work+0x414/0xa10 [c000200037fa7ec0] [c0000000002fbf00] worker_thread+0x320/0x640 [c000200037fa7f80] [c00000000030d0f8] kthread+0x278/0x290 [c000200037fa7fe0] [c00000000000ded8] start_kernel_thread+0x14/0x18 Allocated by task 1997 on cpu 1 at 35.928317s: The buggy address belongs to the object at c00020003bda3000 which belongs to the cache kmalloc-rnd-15-2k of size 2048
The buggy address is located 16 bytes to the right of
allocated 1448-byte region [c00020003bda3000, c00020003bda35a8)
The buggy address belongs to the physical page:
Memory state around the buggy address:
c00020003bda3480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
c00020003bda3500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>c00020003bda3580: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
^
c00020003bda3600: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
c00020003bda3680: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
==================================================================Fix this by allocating the flexible array using nr_node_ids instead of num_possible_nodes(). Since nr_node_ids represents the maximum possible NUMA node IDs, indexing current_path[] using numa_node_id() becomes safe even on systems with sparse node IDs.
--- drivers/nvme/host/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/core.c +1 -1
@@ -3396,7 +3396,7 @@ static struct nvme_ns_head *nvme_alloc_ns_head(struct nvme_ctrl *ctrl,int ret = -ENOMEM ;#ifdef CONFIG_NVME_MULTIPATH - size +=num_possible_nodes () *sizeof (struct nvme_ns *); + size += nr_node_ids *sizeof (struct nvme_ns *);#endif head =kzalloc (size,GFP_KERNEL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 442/1266 workqueue: drop spurious * from print_worker_info() fn declaration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 611583a76ea97991b0f65ec1ff099eac7fe0bae4 ]
print_worker_info() declares its local 'fn' as work_func_t * but worker->current_func has type work_func_t (a function pointer). The extra level of indirection is wrong and only happens to be harmless today because every supported Linux architecture has sizeof(work_func_t) == sizeof(work_func_t *):copy_from_kernel_nofault() reads the correct number of bytes by accident, and %ps still resolves the printed address because the stored value is the function address regardless of declared type.
On any future ABI where sizeof(void (*)()) differs from sizeof(void *), the nofault copy would transfer the wrong number of bytes and the subsequent %ps would print an incorrect address.
Match the field type so the intent is explicit and the code does not silently rely on equal pointer sizes.
--- kernel/workqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/workqueue.c +1 -1
@@ -5119,7 +5119,7 @@ EXPORT_SYMBOL_GPL(set_worker_desc);*/ void print_worker_info (const char *log_lvl,struct task_struct *task) { -work_func_t *fn =NULL ; +work_func_t fn =NULL ;char name[WQ_NAME_LEN ] = { };char desc[WORKER_DESC_LEN ] = { };struct pool_workqueue *pwq =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 443/1266 ipv6: guard against possible NULL deref in __in6_dev_stats_get()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 507541c2a8eeb76c02bd2511958f73a8cfa3e1bc ]
dev_get_by_index_rcu() could return NULL if the original physical device is unregistered.
Found by Sashiko.
--- include/net/addrconf.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
include/net/addrconf.h +4 -1
@@ -334,8 +334,11 @@ static inline struct inet6_dev *__in6_dev_get(const struct net_device *dev)static inline struct inet6_dev *__in6_dev_stats_get (const struct net_device *dev,const struct sk_buff *skb) { -if (netif_is_l3_master (dev)) +if (netif_is_l3_master (dev)) { dev =dev_get_by_index_rcu (dev_net (dev),inet6_iif (skb)); +if (!dev) +return NULL ; + }return __in6_dev_get (dev); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 444/1266 net/sched: cls_bpf: prevent unbounded recursion in offload rollback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit 27db54b90bcc7c37867fe664107fa25ea6a116e4 ]
Quan Sun reported [1] a stack overflow in cls_bpf_offload_cmd().
Reproducer on netdevsim: add a skip_sw cls_bpf filter, set the bpf_tc_accept debugfs knob to 0, then tc filter replace. The replace calls tc_setup_cb_replace() which fails. cls_bpf_offload_cmd() then swaps prog/oldprog and recursively calls itself to roll back. But bpf_tc_accept=0 makes the rollback fail too, which triggers yet another rollback frame with the same arguments, and so on until the stack is exhausted.
bpf_tc_accept is just a convenient knob for the reproducer. Any driver whose tc_setup_cb_replace() fails twice in a row can hit the same loop, so this is not a netdevsim-only issue.
Two ways to fix it:
1) Have the rollback call tc_setup_cb_add() on oldprog instead of re-entering cls_bpf_offload_cmd().
2) Mark the rollback frame with a flag and skip a second-level rollback from inside it.
Go with (2). It is the smaller change and keeps the original behaviour:
the rollback still goes through tc_setup_cb_replace(), so the driver gets one real chance to restore its state. If that attempt also fails, we just return the original error instead of recursing.
[1]: https://lore.kernel.org/bpf/[email protected]/T/#u
--- net/sched/cls_bpf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
net/sched/cls_bpf.c +6 -4
@@ -142,7 +142,8 @@ static bool cls_bpf_is_ebpf(const struct cls_bpf_prog *prog)static int cls_bpf_offload_cmd (struct tcf_proto *tp,struct cls_bpf_prog *prog,struct cls_bpf_prog *oldprog, -struct netlink_ext_ack *extack) +struct netlink_ext_ack *extack, +bool is_rollback) {struct tcf_block *block = tp->chain->block;struct tc_cls_bpf_offload cls_bpf = {};
@@ -177,7 +178,8 @@ static int cls_bpf_offload_cmd(struct tcf_proto *tp, struct cls_bpf_prog *prog, &oldprog->in_hw_count, true);if (prog && err) { -cls_bpf_offload_cmd (tp, oldprog, prog, extack); +if (!is_rollback) +cls_bpf_offload_cmd (tp, oldprog, prog, extack, true);return err; }
@@ -208,7 +210,7 @@ static int cls_bpf_offload(struct tcf_proto *tp, struct cls_bpf_prog *prog,if (!prog && !oldprog)return 0 ; -return cls_bpf_offload_cmd (tp, prog, oldprog, extack); +return cls_bpf_offload_cmd (tp, prog, oldprog, extack, false); } static void cls_bpf_stop_offload(struct tcf_proto *tp,
@@ -217,7 +219,7 @@ static void cls_bpf_stop_offload(struct tcf_proto *tp, {int err; - err =cls_bpf_offload_cmd (tp,NULL , prog, extack); + err =cls_bpf_offload_cmd (tp,NULL , prog, extack, false);if (err)pr_err ("Stopping hardware offload failed: %d\n" , err); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 445/1266 drm/tegra: gr2d/gr3d: Initialize address register map before HOST1X client is registered
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Svyatoslav Ryhel <[email protected]>
[ Upstream commit c4ef5ba1131346159e31f4ef858525cf377380a6 ]
The host1x_client_register() function is called just prior to register map initialization loop, making the device available to userspace. This may result in userspace attempting to submits a job before the register map is initialized. Address this by moving register initialization before host1x client registration.
Stable-dep-of: ace01e2af387 ("drm/tegra: gr2d/gr3d: Contain PM in the gr*d_probe/gr*d_remove")
--- drivers/gpu/drm/tegra/gr2d.c | 8 ++++---- drivers/gpu/drm/tegra/gr3d.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-)
drivers/gpu/drm/tegra/gr2d.c +4 -4
@@ -276,16 +276,16 @@ static int gr2d_probe(struct platform_device *pdev)if (err)return err; +/* initialize address register map */ +for (i =0 ; i <ARRAY_SIZE (gr2d_addr_regs); i++) +set_bit (gr2d_addr_regs[i], gr2d->addr_regs); + err =host1x_client_register (&gr2d->client.base);if (err <0 ) {dev_err (dev,"failed to register host1x client: %d\n" , err);return err; } -/* initialize address register map */ -for (i =0 ; i <ARRAY_SIZE (gr2d_addr_regs); i++) -set_bit (gr2d_addr_regs[i], gr2d->addr_regs); -return 0 ; }
drivers/gpu/drm/tegra/gr3d.c +4 -4
@@ -529,6 +529,10 @@ static int gr3d_probe(struct platform_device *pdev)if (err)return err; +/* initialize address register map */ +for (i =0 ; i <ARRAY_SIZE (gr3d_addr_regs); i++) +set_bit (gr3d_addr_regs[i], gr3d->addr_regs); + err =host1x_client_register (&gr3d->client.base);if (err <0 ) { dev_err(&pdev->dev, "failed to register host1x client: %d\n",
@@ -536,10 +540,6 @@ static int gr3d_probe(struct platform_device *pdev)return err; } -/* initialize address register map */ -for (i =0 ; i <ARRAY_SIZE (gr3d_addr_regs); i++) -set_bit (gr3d_addr_regs[i], gr3d->addr_regs); -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 446/1266 drm/tegra: gr2d/gr3d: Contain PM in the gr*d_probe/gr*d_remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ion Agorria <[email protected]>
[ Upstream commit ace01e2af3871343d700fb60c6f64d8f8e3180e1 ]
The current power management configuration causes GR2G/GR3D to malfunction after resume. Reconfigure all PM actions to be handled within the GR*D probe and remove operations to address this.
--- drivers/gpu/drm/tegra/gr2d.c | 13 ++++++------- drivers/gpu/drm/tegra/gr3d.c | 13 ++++++------- 2 files changed, 12 insertions(+), 14 deletions(-)
drivers/gpu/drm/tegra/gr2d.c +6 -7
@@ -100,9 +100,6 @@ static int gr2d_exit(struct host1x_client *client)if (err <0 )return err; -pm_runtime_dont_use_autosuspend (client->dev); -pm_runtime_force_suspend (client->dev); -host1x_client_iommu_detach (client);host1x_syncpt_put (client->syncpts[0 ]);host1x_channel_put (gr2d->channel);
@@ -280,12 +277,18 @@ static int gr2d_probe(struct platform_device *pdev)for (i =0 ; i <ARRAY_SIZE (gr2d_addr_regs); i++)set_bit (gr2d_addr_regs[i], gr2d->addr_regs); +pm_runtime_enable (dev); + err =host1x_client_register (&gr2d->client.base);if (err <0 ) { +pm_runtime_disable (dev);dev_err (dev,"failed to register host1x client: %d\n" , err);return err; } +pm_runtime_use_autosuspend (dev); +pm_runtime_set_autosuspend_delay (dev,500 ); +return 0 ; }
@@ -367,10 +370,6 @@ static int __maybe_unused gr2d_runtime_resume(struct device *dev) goto disable_clk; } -pm_runtime_enable (dev); -pm_runtime_use_autosuspend (dev); -pm_runtime_set_autosuspend_delay (dev,500 ); -return 0 ; disable_clk:
drivers/gpu/drm/tegra/gr3d.c +6 -7
@@ -108,9 +108,6 @@ static int gr3d_exit(struct host1x_client *client)if (err <0 )return err; -pm_runtime_dont_use_autosuspend (client->dev); -pm_runtime_force_suspend (client->dev); -host1x_client_iommu_detach (client);host1x_syncpt_put (client->syncpts[0 ]);host1x_channel_put (gr3d->channel);
@@ -533,13 +530,19 @@ static int gr3d_probe(struct platform_device *pdev)for (i =0 ; i <ARRAY_SIZE (gr3d_addr_regs); i++)set_bit (gr3d_addr_regs[i], gr3d->addr_regs); +pm_runtime_enable (&pdev->dev); + err =host1x_client_register (&gr3d->client.base);if (err <0 ) { +pm_runtime_disable (&pdev->dev);dev_err (&pdev->dev,"failed to register host1x client: %d\n" , err);return err; } +pm_runtime_use_autosuspend (&pdev->dev); +pm_runtime_set_autosuspend_delay (&pdev->dev,500 ); +return 0 ; }
@@ -601,10 +604,6 @@ static int __maybe_unused gr3d_runtime_resume(struct device *dev) goto disable_clk; } -pm_runtime_enable (dev); -pm_runtime_use_autosuspend (dev); -pm_runtime_set_autosuspend_delay (dev,500 ); -return 0 ; disable_clk:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 447/1266 gpu: host1x: Allow entries in BO caches to be freed
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit 3cbf5e3c46e66d9b3b6b91099bb720c6cb1be3bc ]
When a buffer object is pinned via host1x_bo_pin() with a cache, the resulting mapping is kept in the cache so it can be reused on subsequent pins. Each mapping held a reference to the underlying host1x_bo (taken in tegra_bo_pin / gather_bo_pin), so as long as a mapping was cached, the bo itself could not be freed.
However, the only way to remove the cached mapping was through the free path of the buffer object. This meant that if a bo got cached, it could never get freed again.
Resolve the circularity by holding a weak reference to the bo from the cache side. This is done by having the .pin callbacks not bump the bo's refcount -- instead the common Host1x bo code does so, except for the cache reference.
Also move the remove-cache-mapping-on-free code into a common function inside Host1x code. This is only called from the TegraDRM GEM buffers since those are the only ones that can be cached at the moment.
--- drivers/gpu/drm/tegra/gem.c | 13 ++------ drivers/gpu/drm/tegra/submit.c | 3 +- drivers/gpu/host1x/bus.c | 60 +++++++++++++++++++++++++++++++++- include/linux/host1x.h | 7 ++++ 4 files changed, 69 insertions(+), 14 deletions(-)
drivers/gpu/drm/tegra/gem.c +2 -11
@@ -69,7 +69,7 @@ static struct host1x_bo_mapping *tegra_bo_pin(struct device *dev, struct host1x_return ERR_PTR (-ENOMEM );kref_init (&map->ref); - map->bo =host1x_bo_get (bo); + map->bo = bo; map->direction = direction; map->dev = dev;
@@ -170,7 +170,6 @@ static void tegra_bo_unpin(struct host1x_bo_mapping *map)kfree (map->sgt); } -host1x_bo_put (map->bo);kfree (map); }
@@ -494,17 +493,9 @@ static struct tegra_bo *tegra_bo_import(struct drm_device *drm,void tegra_bo_free_object (struct drm_gem_object *gem) {struct tegra_drm *tegra = gem->dev->dev_private; -struct host1x_bo_mapping *mapping, *tmp;struct tegra_bo *bo =to_tegra_bo (gem); -/* remove all mappings of this buffer object from any caches */ -list_for_each_entry_safe (mapping, tmp, &bo->base.mappings, list) { -if (mapping->cache) -host1x_bo_unpin (mapping); -else -dev_err (gem->dev->dev,"mapping %p stale for device %s\n" , mapping, -dev_name (mapping->dev)); - } +host1x_bo_clear_cached_mappings (&bo->base);if (tegra->domain)tegra_bo_iommu_unmap (tegra, bo);
drivers/gpu/drm/tegra/submit.c +1 -2
@@ -76,7 +76,7 @@ gather_bo_pin(struct device *dev, struct host1x_bo *bo, enum dma_data_directionreturn ERR_PTR (-ENOMEM );kref_init (&map->ref); - map->bo =host1x_bo_get (bo); + map->bo = bo; map->direction = direction; map->dev = dev;
@@ -117,7 +117,6 @@ static void gather_bo_unpin(struct host1x_bo_mapping *map)dma_unmap_sgtable (map->dev, map->sgt, map->direction,0 );sg_free_table (map->sgt);kfree (map->sgt); -host1x_bo_put (map->bo);kfree (map); }
drivers/gpu/host1x/bus.c +59 -1
98 lines not on this page · raw message
include/linux/host1x.h +7 -0
@@ -138,6 +138,12 @@ static inline struct host1x_bo_mapping *to_host1x_bo_mapping(struct kref *ref) return container_of(ref, struct host1x_bo_mapping, ref); } +/** +* struct host1x_bo_ops - operations implemented by a host1x_bo provider +* +* @pin: create a DMA mapping. Implementation must not touch the bo's refcount. +* @unpin: destroy a DMA mapping. Implementation must not touch the bo's refcount. +*/ struct host1x_bo_ops {struct host1x_bo *(*get)(struct host1x_bo *bo);void (*put)(struct host1x_bo *bo);
@@ -176,6 +182,7 @@ struct host1x_bo_mapping *host1x_bo_pin(struct device *dev, struct host1x_bo *boenum dma_data_direction dir, struct host1x_bo_cache *cache);void host1x_bo_unpin (struct host1x_bo_mapping *map); +void host1x_bo_clear_cached_mappings (struct host1x_bo *bo);static inline void *host1x_bo_mmap (struct host1x_bo *bo) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 448/1266 drm/tegra: dc: Fix device node reference leak in tegra_dc_has_output()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 63a3998d792ab5c45304bf879e385a31fa923b61 ]
The of_for_each_phandle() macro increments the reference count of the device node it iterates over. If the loop exits early, the reference must be released manually.
In tegra_dc_has_output(), the function returns true immediately when a match is found, failing to release the current node's reference.
Fix this by adding a call to of_node_put() before returning from the loop.
--- drivers/gpu/drm/tegra/dc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/tegra/dc.c +3 -1
@@ -100,8 +100,10 @@ bool tegra_dc_has_output(struct tegra_dc *dc, struct device *dev)int err;of_for_each_phandle (&it, err, np,"nvidia,outputs" ,NULL ,0 ) -if (it.node == dev->of_node) +if (it.node == dev->of_node) { +of_node_put (it.node);return true; + }return false; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 449/1266 gpu: host1x: Fix iommu_map_sgtable() return value check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit 18f74762013a4b6aa6f905c4459e0f506f9c5c7b ]
Commit "iommu: return full error code from iommu_map_sg[_atomic]()" changed iommu_map_sgtable() to return an ssize_t and negative values in error cases, rather than a size_t and a zero.
pin_job() also was incorrectly assigning to 'int', which could cause overflows into negative values.
Update pin_job() to correctly check for errors from iommu_map_sgtable.
--- drivers/gpu/host1x/job.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/gpu/host1x/job.c +6 -4
@@ -235,6 +235,8 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) }if (host->domain) { +ssize_t map_err; +for_each_sgtable_sg (map->sgt, sg, j) gather_size += sg->length;
@@ -248,11 +250,11 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) goto put; } - err =iommu_map_sgtable (host->domain,iova_dma_addr (&host->iova, alloc), - map->sgt,IOMMU_READ ); -if (err ==0 ) { + map_err =iommu_map_sgtable (host->domain,iova_dma_addr (&host->iova, alloc), + map->sgt,IOMMU_READ ); +if (map_err <0 ) {__free_iova (&host->iova, alloc); - err = -EINVAL ; + err = map_err; goto put; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 450/1266 drm/tegra: Fix iommu_map_sgtable() return value check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikko Perttunen <[email protected]>
[ Upstream commit b3f349517de8f4469c385ebb7bfdfcc148790c0f ]
Commit "iommu: return full error code from iommu_map_sg[_atomic]()" changed iommu_map_sgtable() to return an ssize_t and negative values in error cases, rather than a size_t and a zero.
Update tegra_bo_iommu_map() to correctly check for errors from iommu_map_sgtable.
--- drivers/gpu/drm/tegra/gem.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/gpu/drm/tegra/gem.c +6 -3
@@ -224,6 +224,7 @@ static const struct host1x_bo_ops tegra_bo_ops = {static int tegra_bo_iommu_map (struct tegra_drm *tegra,struct tegra_bo *bo) {int prot =IOMMU_READ |IOMMU_WRITE ; +ssize_t size;int err;if (bo->mm)
@@ -245,13 +246,15 @@ static int tegra_bo_iommu_map(struct tegra_drm *tegra, struct tegra_bo *bo) bo->iova = bo->mm->start; - bo->size =iommu_map_sgtable (tegra->domain, bo->iova, bo->sgt, prot); -if (!bo->size) { + size =iommu_map_sgtable (tegra->domain, bo->iova, bo->sgt, prot); +if (size <0 ) {dev_err (tegra->drm->dev,"failed to map buffer\n" ); - err = -ENOMEM ; + err = size; goto remove; } + bo->size = size; +mutex_unlock (&tegra->mm_lock);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 451/1266 drm/nouveau/bios: specify correct display fuse register for Ampere and Ada
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Tabi <[email protected]>
[ Upstream commit c1cf2d5db80ce91a85855bbaf4da85ff603e089a ]
The NV_FUSE_STATUS_OPT_DISPLAY register is used to determine whether the GPU has display hardware. The current code that normally reads this register is instead hard-coded to check for GA100 vs later GPUs. Since this function is called only on pre-Hopper GPUs, and this if-statement applies only to GA100 and later, the check works because GA100 is the only non-display Ampere and Ada GPU.
However, there actually is a register that can be read, so we should use it.
--- drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowramin.c +2 -1
@@ -65,13 +65,14 @@ pramin_init(struct nvkm_bios *bios, const char *name)/* we can't get the bios image pointer without PDISP */ if (device->card_type >=GA100 ) - addr = device->chipset ==0x170 ;/*XXX: find the fuse reg for this */ + addr =nvkm_rd32 (device,0x820c04 );else if (device->card_type >=GM100 ) addr =nvkm_rd32 (device,0x021c04 );else if (device->card_type >=NV_C0 ) addr =nvkm_rd32 (device,0x022500 ); +if (addr &0x00000001 ) {nvkm_debug (subdev,"... display disabled\n" );return ERR_PTR (-ENODEV );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 452/1266 libbpf: Harden parse_vma_segs() path parsing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit fee9a38174f4c6454fb1fbaf2b9b5a1cca9070d0 ]
parse_vma_segs() in tools/lib/bpf/usdt.c parses /proc/<pid>/maps with two widthless scansets, "%s" into mode[16] and "%[^\n]" into line[4096]. A VMA name in maps is not limited to that local buffer; a deeply nested backing path can produce a maps record long enough to overflow the stack buffer.
Bound both scansets to the declared buffer sizes ("%15s" for mode[16] and "%4095[^\n]" for line[4096]) and drain any residue past line[4094] with "%*[^\n]" before the trailing "\n". Without the drain, the residue of an over-long record would stay in the stream and break the next "%zx-%zx" parse, so the loop would exit early and silently skip later maps records.
Also stop using sscanf(..., "%s") to peel the /proc/<pid>/root prefix from lib_path. Parse the pid and prefix length with "%n", check for the following slash, and copy the remainder with libbpf_strlcpy(). That removes a second unbounded stack write and preserves paths containing spaces.
--- tools/lib/bpf/usdt.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
tools/lib/bpf/usdt.c +12 -4
@@ -449,10 +449,10 @@ static int parse_elf_segs(Elf *elf, const char *path, struct elf_seg **segs, sizstatic int parse_vma_segs (int pid,const char *lib_path,struct elf_seg **segs,size_t *seg_cnt) { -char path[PATH_MAX ], line[PATH_MAX ], mode[16 ]; +char path[PATH_MAX ], line[4096 ], mode[16 ];size_t seg_start, seg_end, seg_off;struct elf_seg *seg; -int tmp_pid, i, err; +int tmp_pid, n, i, err;FILE *f; *seg_cnt =0 ;
@@ -461,8 +461,13 @@ static int parse_vma_segs(int pid, const char *lib_path, struct elf_seg **segs,* /proc/<pid>/root/<path>. They will be reported as just /<path> in * /proc/<pid>/maps. */ -if (sscanf (lib_path,"/proc/%d/root%s" , &tmp_pid, path) ==2 && pid == tmp_pid) +/* %n is not counted in sscanf() return value, so initialize it. */ + n =0 ; +if (sscanf (lib_path,"/proc/%d/root%n" , &tmp_pid, &n) ==1 && + n >0 && pid == tmp_pid && lib_path[n] =='/' ) { +libbpf_strlcpy (path, lib_path + n,sizeof (path)); goto proceed; + }if (!realpath (lib_path, path)) { pr_warn("usdt: failed to get absolute path of '%s' (err %d), using path as is...\n",
@@ -485,8 +490,11 @@ static int parse_vma_segs(int pid, const char *lib_path, struct elf_seg **segs,* 7f5c6f5d1000-7f5c6f5d3000 rw-p 001c7000 08:04 21238613 /usr/lib64/libc-2.17.so * 7f5c6f5d3000-7f5c6f5d8000 rw-p 00000000 00:00 0 * 7f5c6f5d8000-7f5c6f5d9000 r-xp 00000000 103:01 362990598 /data/users/andriin/linux/tools/bpf/usdt/libhello_usdt.so +* +* Some VMA names can be longer than the local buffer. Bound the +* writes, but still consume the rest of the line. */ -while (fscanf (f,"%zx-%zx %s %zx %*s %*d%[^\n]\n" , +while (fscanf (f,"%zx-%zx %15s %zx %*s %*d%4095[^\n]%*[^\n]\n" , &seg_start, &seg_end, mode, &seg_off, line) ==5 ) {void *tmp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 453/1266 libbpf: Fix UAF in strset__add_str()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Llamas <[email protected]>
[ Upstream commit b23705e6afb6ac4ae6d220dcb35975698667dd76 ]
strset_add_str_mem() might reallocate the strset data buffer in order to accommodate the provided string 's'. However, if 's' points to a string already present in the buffer, it becomes dangling after the realloc. This leads to a use-after-free when attempting to memcpy() the string into the new buffer.
One scenario that triggers this problematic path is when resolve_btfids attempts to patch kfunc prototypes using existing BTF parameter names:
| resolve_btfids: function bpf_list_push_back_impl already exists in BTF | Segmentation fault (core dumped)
Compiling resolve_btfids with fsanitize=address generates a detailed report of the UAF:
| ================================================================= | ERROR: AddressSanitizer: heap-use-after-free on address 0x7f4c4a500bd4 | ==1507892==ERROR: AddressSanitizer: heap-use-after-free on address 0x7f4c4a500bd4 at pc 0x55d25155a2a8 bp 0x7ffcef879060 sp 0x7ffcef878818 | READ of size 5 at 0x7f4c4a500bd4 thread T0 | #0 0x55d25155a2a7 in memcpy (tools/bpf/resolve_btfids/resolve_btfids+0xcf2a7) | #1 0x55d2515d708e in strset__add_str tools/lib/bpf/strset.c:162:2 | #2 0x55d2515c730b in btf__add_str tools/lib/bpf/btf.c:2109:8 | #3 0x55d2515c9020 in btf__add_func_param tools/lib/bpf/btf.c:3108:14 | #4 0x55d25159f0b5 in process_kfunc_with_implicit_args tools/bpf/resolve_btfids/main.c:1196:9 | #5 0x55d25159e004 in btf2btf tools/bpf/resolve_btfids/main.c:1229:9 | #6 0x55d25159cee7 in main tools/bpf/resolve_btfids/main.c:1535:6 | #7 0x7f4c78e29f76 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16 | #8 0x7f4c78e2a026 in __libc_start_main csu/../csu/libc-start.c:360:3 | #9 0x55d2514bb860 in _start (tools/bpf/resolve_btfids/resolve_btfids+0x30860) | | 0x7f4c4a500bd4 is located 13268 bytes inside of 2829000-byte region [0x7f4c4a4fd800,0x7f4c4a7b02c8) | freed by thread T0 here: | #0 0x55d25155b700 in realloc (tools/bpf/resolve_btfids/resolve_btfids+0xd0700) | #1 0x55d2515c426c in libbpf_reallocarray tools/lib/bpf/./libbpf_internal.h:220:9 | #2 0x55d2515c426c in libbpf_add_mem tools/lib/bpf/btf.c:224:13 | | previously allocated by thread T0 here: | #0 0x55d25155b2e3 in malloc (tools/bpf/resolve_btfids/resolve_btfids+0xd02e3) | #1 0x55d2515d6e7d in strset__new tools/lib/bpf/strset.c:58:20
While resolve_btfids could be refactored to avoid this call path, let's instead fix this issue at the source in strset__add_str() and avoid similar scenarios.
Let's check if set->strs_data was reallocated and whether 's' points to an internal string within the old strset buffer. In such case, 's' is reconstructed to point to the new buffer.
While already here, also fix strset__find_str() which suffers from the same problem by factoring out the common operations into a new helper function strset_str_append().
--- tools/lib/bpf/strset.c | 62 ++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 21 deletions(-)
tools/lib/bpf/strset.c +41 -21
@@ -107,6 +107,41 @@ static void *strset_add_str_mem(struct strset *set, size_t add_sz) set->strs_data_len, set->strs_data_max_len, add_sz); } +static long strset_str_append (struct strset *set,const char *s) +{ +uintptr_t old_data = (uintptr_t )set->strs_data; +size_t old_data_len = set->strs_data_len; +uintptr_t old_s = (uintptr_t )s; +long len =strlen (s) +1 ; +void *p; + +/* +* Hashmap keys are always offsets within set->strs_data, so to even +* look up some string from the "outside", we need to first append it +* at the end, so that it can be addressed with an offset. Luckily, +* until set->strs_data_len is incremented, that string is just a piece +* of garbage for the rest of the code, so no harm, no foul. On the +* other hand, if the string is unique, it's already appended and +* ready to be used, only a simple set->strs_data_len increment away. +*/ + p =strset_add_str_mem (set, len); +if (!p) +return -ENOMEM ; + +/* +* The set->strs_data might have reallocated and if 's' pointed +* to an internal string within the old buffer, then it became +* dangling and needs to be reconstructed before the copy. +*/ +if (old_data && old_data != (uintptr_t )set->strs_data && + old_s >= old_data && old_s < old_data + old_data_len) + s = set->strs_data + (old_s - old_data); + +memcpy (p, s, len); + +return len; +} +/* Find string offset that corresponds to a given string *s*. * Returns: * - >0 offset into string data, if string is found;
@@ -116,16 +151,12 @@ static void *strset_add_str_mem(struct strset *set, size_t add_sz)int strset__find_str (struct strset *set,const char *s) {long old_off, new_off, len; -void *p; -/* see strset__add_str() for why we do this */ - len =strlen (s) +1 ; - p =strset_add_str_mem (set, len); -if (!p) -return -ENOMEM ; + len =strset_str_append (set, s); +if (len <0 ) +return len; new_off = set->strs_data_len; -memcpy (p, s, len);if (hashmap__find (set->strs_hash, new_off, &old_off))return old_off;
@@ -142,24 +173,13 @@ int strset__find_str(struct strset *set, const char *s)int strset__add_str (struct strset *set,const char *s) {long old_off, new_off, len; -void *p;int err; -/* Hashmap keys are always offsets within set->strs_data, so to even -* look up some string from the "outside", we need to first append it -* at the end, so that it can be addressed with an offset. Luckily, -* until set->strs_data_len is incremented, that string is just a piece -* of garbage for the rest of the code, so no harm, no foul. On the -* other hand, if the string is unique, it's already appended and -* ready to be used, only a simple set->strs_data_len increment away. -*/ - len =strlen (s) +1 ; - p =strset_add_str_mem (set, len); -if (!p) -return -ENOMEM ; + len =strset_str_append (set, s); +if (len <0 ) +return len; new_off = set->strs_data_len; -memcpy (p, s, len);/* Now attempt to add the string, but only if the string with the same * contents doesn't exist already (HASHMAP_ADD strategy). If such
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 454/1266 dax/kmem: account for partial discontiguous resource upon removal
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davidlohr Bueso <[email protected]>
[ Upstream commit 8aa442cfce79e2d69e72fc8e0c0864ac2971149d ]
When dev_dax_kmem_probe() partially succeeds (at least one range is mapped) but a subsequent range fails request_mem_region() or add_memory_driver_managed(), the probe silently continues, ultimately returning success, but with the corresponding range resource NULL'ed out.
dev_dax_kmem_remove() iterates over all dax_device ranges regardless of if the underlying resource exists. When remove_memory() is called later, it returns 0 because the memory was never added which causes dev_dax_kmem_remove() to incorrectly assume the (nonexistent) resource can be removed and attempts cleanup on a NULL pointer.
Fix this by skipping these ranges altogether, noting that these cases are considered success, such that the cleanup is still reached when all actually-added ranges are successfully removed.
--- drivers/dax/kmem.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/dax/kmem.c +6 -0
@@ -193,6 +193,12 @@ static void dev_dax_kmem_remove(struct dev_dax *dev_dax)if (rc)continue ; +/* range was never added during probe */ +if (!data->res[i]) { + success++; +continue ; + } + rc =remove_memory (range.start,range_len (&range));if (rc ==0 ) {remove_resource (data->res[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 455/1266 rapidio/tsi721: prevent a bad dereference in tsi721_db_dpc()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit fc15e3a30ddd950f009c76765331783b9af94a87 ]
With a list_for_each() loop, if we don't find the item we are looking for in the list, then the loop exits with the iterator, which is "dbell" in this loop, pointing to invalid memory.
This code uses the "found" variable to determine if we have found the doorbell we are looking for or not. However, the problem that the "found" variable needs to be set to false at the start of each iteration, otherwise after the first correct doorbell, then everything is marked as found.
Reset the "found" to false at the start of the iteration and move the variable inside the loop.
--- drivers/rapidio/devices/tsi721.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/rapidio/devices/tsi721.c +2 -1
@@ -384,7 +384,6 @@ static void tsi721_db_dpc(struct work_struct *work) idb_work);struct rio_mport *mport;struct rio_dbell *dbell; -int found =0 ;u32 wr_ptr, rd_ptr;u64 *idb_entry;u32 regval;
@@ -402,6 +401,8 @@ static void tsi721_db_dpc(struct work_struct *work) rd_ptr =ioread32 (priv->regs +TSI721_IDQ_RP (IDB_QUEUE )) %IDB_QSIZE ;while (wr_ptr != rd_ptr) { +int found =0 ; + idb_entry = (u64 *)(priv->idb_base + (TSI721_IDB_ENTRY_SIZE * rd_ptr)); rd_ptr++;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 456/1266 ocfs2: dont BUG_ON an invalid journal dinode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: ZhengYuan Huang <[email protected]>
[ Upstream commit c0438198c28b1d22c272751af5e717c11d9fa8dd ]
[BUG]
A fuzzed OCFS2 image can corrupt the current slot journal dinode while mount is still in progress. The mount path first reports the invalid journal block and then crashes in shutdown:
kernel BUG at fs/ocfs2/journal.c:1034!
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI RIP: 0010:ocfs2_journal_toggle_dirty+0x2d6/0x340 fs/ocfs2/journal.c:1034 Call Trace: ocfs2_journal_shutdown+0x414/0xc30 fs/ocfs2/journal.c:1116 ocfs2_mount_volume fs/ocfs2/super.c:1785 [inline] ocfs2_fill_super+0x30a9/0x3cd0 fs/ocfs2/super.c:1083 get_tree_bdev_flags+0x38b/0x640 fs/super.c:1698 get_tree_bdev+0x24/0x40 fs/super.c:1721 ocfs2_get_tree+0x21/0x30 fs/ocfs2/super.c:1184 vfs_get_tree+0x9a/0x370 fs/super.c:1758 fc_mount fs/namespace.c:1199 [inline] do_new_mount_fc fs/namespace.c:3642 [inline] do_new_mount fs/namespace.c:3718 [inline] path_mount+0x5b8/0x1ea0 fs/namespace.c:4028 do_mount fs/namespace.c:4041 [inline] __do_sys_mount fs/namespace.c:4229 [inline] __se_sys_mount fs/namespace.c:4206 [inline] __x64_sys_mount+0x282/0x320 fs/namespace.c:4206 ...
[CAUSE]ocfs2_journal_toggle_dirty() used to return -EIO when journal->j_bh no longer contained a valid dinode, because the startup and shutdown paths already handled that failure. Commit 10995aa2451a
("ocfs2: Morph the haphazard OCFS2_IS_VALID_DINODE() checks.") changed the check to a BUG_ON() under the assumption that the journal dinode had already been validated. That turns an unexpected invalid journal dinode during mount teardown into a kernel crash instead of a normal mount failure.
[FIX]
Replace the BUG_ON() with WARN_ON() and return -EIO. This keeps the invariant warning for debugging, but restores the original behavior of failing startup or shutdown cleanly instead of panicking the kernel.
--- fs/ocfs2/journal.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
fs/ocfs2/journal.c +2 -5
@@ -1027,11 +1027,8 @@ static int ocfs2_journal_toggle_dirty(struct ocfs2_super *osb,struct ocfs2_dinode *fe; fe = (struct ocfs2_dinode *)bh->b_data; - -/* The journal bh on the osb always comes from ocfs2_journal_init() -* and was validated there inside ocfs2_inode_lock_full(). It's a -* code bug if we mess it up. */ -BUG_ON (!OCFS2_IS_VALID_DINODE (fe)); +if (WARN_ON (!OCFS2_IS_VALID_DINODE (fe))) +return -EIO ; flags =le32_to_cpu (fe->id1.journal1.ij_flags);if (dirty)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 457/1266 ocfs2: kill osb->system_file_mutex lock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit f5b1910e23f1233c8d4185268b2e659df2bc5dbf ]
Commit 43b10a20372d ("ocfs2: avoid system inode ref confusion by adding mutex lock") tried to avoid a refcount leak caused by allowing multiple threads to call igrab(inode). But addition of osb->system_file_mutex made locking dependency complicated and is causing lockdep to warn about possibility of AB-BA deadlock.
Since _ocfs2_get_system_file_inode() returns the same inode for the same input arguments, we don't need to serialize _ocfs2_get_system_file_inode(). What we need to make sure is that igrab(inode) is called for only once(). Therefore, replace osb->system_file_mutex with cmpxchg()-based locking.
--- fs/ocfs2/ocfs2.h | 2 -- fs/ocfs2/super.c | 2 -- fs/ocfs2/sysfile.c | 9 +++------ 3 files changed, 3 insertions(+), 10 deletions(-)
fs/ocfs2/ocfs2.h +0 -2
@@ -494,8 +494,6 @@ struct ocfs2_superstruct rb_root osb_rf_lock_tree;struct ocfs2_refcount_tree *osb_ref_tree_lru; -struct mutex system_file_mutex; -/* * OCFS2 needs to schedule several different types of work which * require cluster locking, disk I/O, recovery waits, etc. Since these
fs/ocfs2/super.c +0 -2
@@ -2053,8 +2053,6 @@ static int ocfs2_initialize_super(struct super_block *sb,spin_lock_init (&osb->osb_xattr_lock);ocfs2_init_steal_slots (osb); -mutex_init (&osb->system_file_mutex); -atomic_set (&osb->alloc_stats.moves,0 );atomic_set (&osb->alloc_stats.local_data,0 );atomic_set (&osb->alloc_stats.bitmap_data,0 );
fs/ocfs2/sysfile.c +3 -6
@@ -98,11 +98,9 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, }else arr =get_local_system_inode (osb, type, slot); -mutex_lock (&osb->system_file_mutex);if (arr && ((inode = *arr) !=NULL )) {/* get a ref in addition to the array ref */ inode =igrab (inode); -mutex_unlock (&osb->system_file_mutex);BUG_ON (!inode);return inode;
@@ -112,11 +110,10 @@ struct inode *ocfs2_get_system_file_inode(struct ocfs2_super *osb, inode =_ocfs2_get_system_file_inode (osb, type, slot);/* add one more if putting into array for first time */ -if (arr && inode) { - *arr =igrab (inode); -BUG_ON (!*arr); +if (inode && arr && !*arr && !cmpxchg (&(*arr),NULL , inode)) { + inode =igrab (inode); +BUG_ON (!inode); } -mutex_unlock (&osb->system_file_mutex);return inode; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 458/1266 crypto: hisilicon/qm - disable error report before flr
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weili Qian <[email protected]>
[ Upstream commit e71dc5602b9a29027f6aedd5990d3e8c4f638c8c ]
Before function level reset, driver first disable device error report and then waits for the device reset to complete. However, when the error is recovered, the error bits will be enabled again, resulting in invalid disable. It is modified to detect that there is no error before disable error report, and then do FLR.
--- drivers/crypto/hisilicon/qm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/crypto/hisilicon/qm.c +2 -2
@@ -4568,8 +4568,6 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev)u32 delay =0 ;int ret; -hisi_qm_dev_err_uninit (pf_qm); -/* * Check whether there is an ECC mbit error, If it occurs, need to * wait for soft reset to fix it.
@@ -4586,6 +4584,8 @@ void hisi_qm_reset_prepare(struct pci_dev *pdev)return ; } +hisi_qm_dev_err_uninit (pf_qm); +/* PF obtains the information of VF by querying the register. */ if (qm->fun_type ==QM_HW_PF )qm_cmd_uninit (qm);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 459/1266 drm/msm/dp: fix HPD state status bit shift value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jessica Zhang <[email protected]>
[ Upstream commit 2e6c2e81d81251623c458a60e2a57447dcbc988e ]
The HPD state status is the 3 most significant bits, not 4 bits of the HPD_INT_STATUS register.
Fix the bit shift macro so that the correct bits are returned in msm_dp_aux_is_link_connected().
Patchwork: https://patchwork.freedesktop.org/patch/727611/
--- drivers/gpu/drm/msm/dp/dp_reg.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/dp/dp_reg.h +2 -2
@@ -46,8 +46,8 @@#define DP_DP_IRQ_HPD_INT_ACK (0x00000002)#define DP_DP_HPD_REPLUG_INT_ACK (0x00000004)#define DP_DP_HPD_UNPLUG_INT_ACK (0x00000008) -#define DP_DP_HPD_STATE_STATUS_BITS_MASK (0x0000000F) -#define DP_DP_HPD_STATE_STATUS_BITS_SHIFT (0x1C) +#define DP_DP_HPD_STATE_STATUS_BITS_MASK (0x00000007) +#define DP_DP_HPD_STATE_STATUS_BITS_SHIFT (0x1D)#define REG_DP_DP_HPD_INT_MASK (0x0000000C)#define DP_DP_HPD_PLUG_INT_MASK (0x00000001)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 460/1266 drm/msm/dp: Fix the ISR_* enum values
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jessica Zhang <[email protected]>
[ Upstream commit 3fbfdc3b1d48cc115a86953e5df0c76cd2efc42b ]
The ISR_HPD_* enum should represent values that can be read from the REG_DP_DP_HPD_INT_STATUS register. Swap ISR_HPD_IO_GLITCH_COUNT and ISR_HPD_REPLUG_COUNT to map them correctly to register values.
While we are at it, correct the spelling for ISR_HPD_REPLUG_COUNT.
Patchwork: https://patchwork.freedesktop.org/patch/727602/
--- drivers/gpu/drm/msm/dp/dp_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/msm/dp/dp_display.c +2 -2
@@ -37,9 +37,9 @@ enum {ISR_DISCONNECTED ,ISR_CONNECT_PENDING ,ISR_CONNECTED , -ISR_HPD_REPLUG_COUNT , +ISR_HPD_IO_GLITCH_COUNT ,ISR_IRQ_HPD_PULSE_COUNT , - ISR_HPD_LO_GLITH_COUNT, + ISR_HPD_REPLUG_COUNT, };/* event thread connection state */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 461/1266 EDAC/{skx_common,skx}: Fix UBSAN shift-out-of-bounds in skx_get_dimm_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: zhoumin <[email protected]>
[ Upstream commit c63ed6e1f5fe648a4a099b6717f679999be482ef ]
When the skx_get_dimm_attr() helper returns -EINVAL, skx_get_dimm_info() does not validate these return values before using them in a shift operation:
size = ((1ull << (rows + cols + ranks)) * banks) >> (20 - 3);
If all three values are -22, the shift exponent becomes -66, triggering a UBSAN shift-out-of-bounds error:
UBSAN: shift-out-of-bounds in drivers/edac/skx_common.c
shift exponent -66 is negative--- drivers/edac/skx_common.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/edac/skx_common.c +3 -0
@@ -417,6 +417,9 @@ int skx_get_dimm_info(u32 mtr, u32 mcmtr, u32 amap, struct dimm_info *dimm, rows =numrow (mtr); cols = imc->hbm_mc ?6 :numcol (mtr); +if (ranks <0 || rows <0 || cols <0 ) +return 0 ; +if (imc->hbm_mc) { banks =32 ; mtype =MEM_HBM2 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 462/1266 RDMA/rxe: Fix TOCTOU heap overflow in get_srq_wqe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 22b8fbded65b8c441b634a185f8da67657df6c50 ]
get_srq_wqe() reads wqe->dma.num_sge from the shared receive queue buffer, which is mapped into userspace. It validates num_sge against max_sge, but then re-reads the same field to calculate the memcpy size. A concurrent userspace thread can modify num_sge between validation and use, causing a heap buffer overflow when copying the WQE into qp->resp.srq_wqe.
Read num_sge into a local variable and use it for both the bounds check and the size calculation.
--- drivers/infiniband/sw/rxe/rxe_resp.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/infiniband/sw/rxe/rxe_resp.c +4 -2
@@ -273,6 +273,7 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)struct rxe_recv_wqe *wqe;struct ib_event ev;unsigned int count; +unsigned int num_sge;size_t size;unsigned long flags;
@@ -288,12 +289,13 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp) }/* don't trust user space data */ -if (unlikely (wqe->dma.num_sge > srq->rq.max_sge)) { + num_sge = wqe->dma.num_sge; +if (unlikely (num_sge > srq->rq.max_sge)) {spin_unlock_irqrestore (&srq->rq.consumer_lock, flags);rxe_dbg_qp (qp,"invalid num_sge in SRQ entry\n" );return RESPST_ERR_MALFORMED_WQE ; } - size =sizeof (*wqe) + wqe->dma.num_sge*sizeof (struct rxe_sge ); + size =sizeof (*wqe) + num_sge *sizeof (struct rxe_sge );memcpy (&qp->resp.srq_wqe, wqe, size); qp->resp.wqe = &qp->resp.srq_wqe.wqe;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 463/1266 RDMA/rxe: Copy WQE to local buffer in non-SRQ receive path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit d6ab440240a04b8737ee4c7bb21af9182e451733 ]
For non-SRQ QPs, the responder reads WQE fields directly from the shared queue buffer mapped into userspace. This allows a malicious user to modify fields like num_sge or sge entries while the kernel is processing the WQE, leading to out-of-bounds reads in rxe_resp_check_length() and copy_data().
Introduce get_recv_wqe() that validates num_sge and copies the WQE to a kernel-local buffer before processing, matching the approach already used for SRQ WQEs in get_srq_wqe(). The srq_wqe buffer is reused since SRQ and non-SRQ paths are mutually exclusive per QP.
--- drivers/infiniband/sw/rxe/rxe_resp.c | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-)
drivers/infiniband/sw/rxe/rxe_resp.c +24 -3
@@ -319,6 +319,29 @@ static enum resp_states get_srq_wqe(struct rxe_qp *qp)return RESPST_CHK_LENGTH ; } +static enum resp_states rxe_get_recv_wqe (struct rxe_qp *qp) +{ +struct rxe_queue *q = qp->rq.queue; +struct rxe_recv_wqe *wqe; +unsigned int num_sge; +size_t size; + + wqe =queue_head (q,QUEUE_TYPE_FROM_CLIENT ); +if (!wqe) +return RESPST_ERR_RNR ; + + num_sge = wqe->dma.num_sge; +if (unlikely (num_sge > qp->rq.max_sge)) { +rxe_dbg_qp (qp,"invalid num_sge in recv WQE\n" ); +return RESPST_ERR_MALFORMED_WQE ; + } + size =sizeof (*wqe) + num_sge *sizeof (struct rxe_sge ); +memcpy (&qp->resp.srq_wqe, wqe, size); + + qp->resp.wqe = &qp->resp.srq_wqe.wqe; +return RESPST_CHK_LENGTH ; +} +static enum resp_states check_resource (struct rxe_qp *qp,struct rxe_pkt_info *pkt) {
@@ -339,9 +362,7 @@ static enum resp_states check_resource(struct rxe_qp *qp,if (srq)return get_srq_wqe (qp); - qp->resp.wqe =queue_head (qp->rq.queue, -QUEUE_TYPE_FROM_CLIENT ); -return (qp->resp.wqe) ?RESPST_CHK_LENGTH :RESPST_ERR_RNR ; +return rxe_get_recv_wqe (qp); }return RESPST_CHK_LENGTH ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 464/1266 media: qcom: venus: drop extra padding in NV12 raw size calculation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Renjiang Han <[email protected]>
[ Upstream commit e1c9adabb268cc5d56723b7df1da49e59070f309 ]
get_framesize_raw_nv12() currently adds SZ_4K to the UV plane size and an additional SZ_8K to the total buffer size. This inflates the calculated sizeimage and leads userspace to over-allocate buffers without a clear requirement.
Remove the extra SZ_4K/SZ_8K padding and compute the NV12 size as the sum of Y and UV planes, keeping the final ALIGN(size, SZ_4K) intact.
--- drivers/media/platform/qcom/venus/helpers.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/qcom/venus/helpers.c +2 -2
@@ -954,8 +954,8 @@ static u32 get_framesize_raw_nv12(u32 width, u32 height) uv_sclines =ALIGN (((height +1 ) >>1 ),16 ); y_plane = y_stride * y_sclines; - uv_plane = uv_stride * uv_sclines +SZ_4K ; - size = y_plane + uv_plane +SZ_8K ; + uv_plane = uv_stride * uv_sclines; + size = y_plane + uv_plane;return ALIGN (size,SZ_4K ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 465/1266 media: qcom: venus: relax encoder frame/blur dimension steps on v4
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Renjiang Han <[email protected]>
[ Upstream commit 35428ae3a6a40912f1f7b47bb6c65f1a63d0b8f8 ]
Encoder HFI capabilities on v4 advertise a 16-pixel step for frame and blur dimensions. This is overly restrictive and can cause userspace caps negotiation to fail even for valid resolutions.
Relax the advertised step size to 1 and keep alignment enforcement in buffer layout and size calculations.
--- .../platform/qcom/venus/hfi_platform_v4.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/media/platform/qcom/venus/hfi_platform_v4.c +10 -10
@@ -135,8 +135,8 @@ static const struct hfi_plat_caps caps[] = { .codec = HFI_VIDEO_CODEC_H264, .domain = VIDC_SESSION_TYPE_ENC, .cap_bufs_mode_dynamic = true, - .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 16}, - .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 16}, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 1}, .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 1, 36864, 1}, .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 120000000, 1}, .caps[4] = {HFI_CAPABILITY_SCALE_X, 8192, 65536, 1},
@@ -172,8 +172,8 @@ static const struct hfi_plat_caps caps[] = { .codec = HFI_VIDEO_CODEC_HEVC, .domain = VIDC_SESSION_TYPE_ENC, .cap_bufs_mode_dynamic = true, - .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 16}, - .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 16}, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 1}, .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 1, 36864, 1}, .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 120000000, 1}, .caps[4] = {HFI_CAPABILITY_SCALE_X, 8192, 65536, 1},
@@ -194,8 +194,8 @@ static const struct hfi_plat_caps caps[] = { .caps[19] = {HFI_CAPABILITY_RATE_CONTROL_MODES, 0x1000001, 0x1000005, 1}, .caps[20] = {HFI_CAPABILITY_COLOR_SPACE_CONVERSION, 0, 2, 1}, .caps[21] = {HFI_CAPABILITY_ROTATION, 1, 4, 90}, - .caps[22] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 16}, - .caps[23] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 16}, + .caps[22] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 1}, + .caps[23] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 1}, .num_caps = 24, .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_6 | HFI_HEVC_TIER_HIGH0}, .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_6 | HFI_HEVC_TIER_HIGH0},
@@ -209,8 +209,8 @@ static const struct hfi_plat_caps caps[] = { .codec = HFI_VIDEO_CODEC_VP8, .domain = VIDC_SESSION_TYPE_ENC, .cap_bufs_mode_dynamic = true, - .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 16}, - .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 16}, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 96, 4096, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 96, 4096, 1}, .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 1, 36864, 1}, .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 120000000, 1}, .caps[4] = {HFI_CAPABILITY_SCALE_X, 8192, 65536, 1},
@@ -228,8 +228,8 @@ static const struct hfi_plat_caps caps[] = { .caps[16] = {HFI_CAPABILITY_P_FRAME_QP, 0, 127, 1}, .caps[17] = {HFI_CAPABILITY_MAX_WORKMODES, 1, 2, 1}, .caps[18] = {HFI_CAPABILITY_RATE_CONTROL_MODES, 0x1000001, 0x1000005, 1}, - .caps[19] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 16}, - .caps[20] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 16}, + .caps[19] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 1}, + .caps[20] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 1}, .caps[21] = {HFI_CAPABILITY_COLOR_SPACE_CONVERSION, 0, 2, 1}, .caps[22] = {HFI_CAPABILITY_ROTATION, 1, 4, 90}, .num_caps = 23,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 466/1266 media: qcom: venus: relax encoder frame/blur step size on v6
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Renjiang Han <[email protected]>
[ Upstream commit c53e0550288b2e08b984b24035c471941b7820c7 ]
Encoder HFI capabilities on v6 enforce a 16-pixel step for frame and blur dimensions, which does not reflect actual hardware requirements and can reject valid userspace configurations.
Relax the step size to 1 while leaving min/max limits unchanged.
--- .../media/platform/qcom/venus/hfi_platform_v6.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/media/platform/qcom/venus/hfi_platform_v6.c +8 -8
@@ -172,8 +172,8 @@ static const struct hfi_plat_caps caps[] = { .codec = HFI_VIDEO_CODEC_HEVC, .domain = VIDC_SESSION_TYPE_ENC, .cap_bufs_mode_dynamic = true, - .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 8192, 16}, - .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 8192, 16}, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 8192, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 8192, 1}, .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 138240, 1}, .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 160000000, 1}, .caps[4] = {HFI_CAPABILITY_SCALE_X, 8192, 65536, 1},
@@ -194,8 +194,8 @@ static const struct hfi_plat_caps caps[] = { .caps[19] = {HFI_CAPABILITY_RATE_CONTROL_MODES, 0x1000001, 0x1000005, 1}, .caps[20] = {HFI_CAPABILITY_COLOR_SPACE_CONVERSION, 0, 2, 1}, .caps[21] = {HFI_CAPABILITY_ROTATION, 1, 4, 90}, - .caps[22] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 16}, - .caps[23] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 16}, + .caps[22] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 1}, + .caps[23] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 1}, .num_caps = 24, .pl[0] = {HFI_HEVC_PROFILE_MAIN, HFI_HEVC_LEVEL_6 | HFI_HEVC_TIER_HIGH0}, .pl[1] = {HFI_HEVC_PROFILE_MAIN10, HFI_HEVC_LEVEL_6 | HFI_HEVC_TIER_HIGH0},
@@ -209,8 +209,8 @@ static const struct hfi_plat_caps caps[] = { .codec = HFI_VIDEO_CODEC_VP8, .domain = VIDC_SESSION_TYPE_ENC, .cap_bufs_mode_dynamic = true, - .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 4096, 16}, - .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 4096, 16}, + .caps[0] = {HFI_CAPABILITY_FRAME_WIDTH, 128, 4096, 1}, + .caps[1] = {HFI_CAPABILITY_FRAME_HEIGHT, 128, 4096, 1}, .caps[2] = {HFI_CAPABILITY_MBS_PER_FRAME, 64, 36864, 1}, .caps[3] = {HFI_CAPABILITY_BITRATE, 1, 74000000, 1}, .caps[4] = {HFI_CAPABILITY_SCALE_X, 8192, 65536, 1},
@@ -228,8 +228,8 @@ static const struct hfi_plat_caps caps[] = { .caps[16] = {HFI_CAPABILITY_P_FRAME_QP, 0, 127, 1}, .caps[17] = {HFI_CAPABILITY_MAX_WORKMODES, 1, 2, 1}, .caps[18] = {HFI_CAPABILITY_RATE_CONTROL_MODES, 0x1000001, 0x1000005, 1}, - .caps[19] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 16}, - .caps[20] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 16}, + .caps[19] = {HFI_CAPABILITY_BLUR_WIDTH, 96, 4096, 1}, + .caps[20] = {HFI_CAPABILITY_BLUR_HEIGHT, 96, 4096, 1}, .caps[21] = {HFI_CAPABILITY_COLOR_SPACE_CONVERSION, 0, 2, 1}, .caps[22] = {HFI_CAPABILITY_ROTATION, 1, 4, 90}, .num_caps = 23,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 467/1266 rpmsg: use generic driver_override infrastructure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danilo Krummrich <[email protected]>
[ Upstream commit 55ced13c42921714e90f8fae94b6ed803330dc6a ]
When a driver is probed through __driver_attach(), the bus' match() callback is called without the device lock held, thus accessing the driver_override field without a lock, which can cause a UAF.
Fix this by using the driver-core driver_override infrastructure taking care of proper locking internally.
Note that calling match() from __driver_attach() without the device lock held is intentional. [1]
--- drivers/rpmsg/qcom_glink_native.c | 2 -- drivers/rpmsg/rpmsg_core.c | 43 +++++-------------------------- drivers/rpmsg/virtio_rpmsg_bus.c | 1 - include/linux/rpmsg.h | 4 --- 4 files changed, 7 insertions(+), 43 deletions(-)
drivers/rpmsg/qcom_glink_native.c +0 -2
@@ -1526,7 +1526,6 @@ static void qcom_glink_rpdev_release(struct device *dev) {struct rpmsg_device *rpdev =to_rpmsg_device (dev); -kfree (rpdev->driver_override);kfree (rpdev); }
@@ -1770,7 +1769,6 @@ static void qcom_glink_device_release(struct device *dev)/* Release qcom_glink_alloc_channel() reference */ kref_put (&channel->refcount, qcom_glink_channel_release); -kfree (rpdev->driver_override);kfree (rpdev); }
drivers/rpmsg/rpmsg_core.c +7 -36
81 lines not on this page · raw message
drivers/rpmsg/virtio_rpmsg_bus.c +0 -1
@@ -378,7 +378,6 @@ static void virtio_rpmsg_release_device(struct device *dev)struct rpmsg_device *rpdev =to_rpmsg_device (dev);struct virtio_rpmsg_channel *vch =to_virtio_rpmsg_channel (rpdev); -kfree (rpdev->driver_override);kfree (vch); }
include/linux/rpmsg.h +0 -4
@@ -41,9 +41,6 @@ struct rpmsg_channel_info {* rpmsg_device - device that belong to the rpmsg bus * @dev: the device struct * @id: device id (used to match between rpmsg drivers and devices) -* @driver_override: driver name to force a match; do not set directly, -* because core frees it; use driver_set_override() to -* set or clear it. * @src: local address * @dst: destination address * @ept: the rpmsg endpoint of this channel
@@ -53,7 +50,6 @@ struct rpmsg_channel_info {struct rpmsg_device {struct device dev;struct rpmsg_device_id id; -const char *driver_override;u32 src;u32 dst;struct rpmsg_endpoint *ept;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 468/1266 md/raid10: reset read_slot when reusing r10bio for discard
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Cheng <[email protected]>
[ Upstream commit 6b8a26af065ddc93de2aa5c9f0df98dce9723442 ]
put_all_bios() always drops devs[i].bio, but it only drops devs[i].repl_bio when r10_bio->read_slot < 0. If discard reuses an r10bio that was previously used for a read, read_slot can still be non-negative, and discard cleanup can skip bio_put() on repl_bio.
Reset read_slot to -1 when preparing an r10bio for discard so the replacement bio is always released correctly.
--- drivers/md/raid10.c | 1 + 1 file changed, 1 insertion(+)
drivers/md/raid10.c +1 -0
@@ -1744,6 +1744,7 @@ static int raid10_handle_discard(struct mddev *mddev, struct bio *bio) r10_bio->mddev = mddev; r10_bio->state =0 ; r10_bio->sectors =0 ; + r10_bio->read_slot =-1 ;memset (r10_bio->devs,0 ,sizeof (r10_bio->devs[0 ]) * geo->raid_disks);wait_blocked_dev (mddev, r10_bio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 469/1266 ext4: fix LOGFLUSH shutdown ordering to allow ordered-mode data writeback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
[ Upstream commit d99748ef1695ce17eaf51c64b7a06952fa7cddab ]
In EXT4_GOING_FLAGS_LOGFLUSH mode, the EXT4_FLAGS_SHUTDOWN flag was set before calling ext4_force_commit(). This caused ordered-mode data writeback (triggered by journal commit) to fail with -EIO, since ext4_do_writepages() checks for the shutdown flag. The journal would then be aborted prematurely before the commit could succeed.
Fix this by calling ext4_force_commit() first, then setting the shutdown flag, so that pending data can be written back correctly.
Note that moving ext4_force_commit() before setting the shutdown flag creates a small window in which new writes may occur and generate new journal transactions. When the journal is subsequently aborted, the new transactions will not be able to write to disk. This is intentional because LOGFLUSH's semantics are to flush pre-existing journal entries before shutdown, not to guarantee atomicity for writes that race with the ioctl.
--- fs/ext4/ioctl.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
fs/ext4/ioctl.c +9 -3
@@ -826,11 +826,17 @@ int ext4_force_shutdown(struct super_block *sb, u32 flags)thaw_bdev (sb->s_bdev);break ;case EXT4_GOING_FLAGS_LOGFLUSH : +/* +* Call ext4_force_commit() before setting EXT4_FLAGS_SHUTDOWN. +* This is because in data=ordered mode, journal commit +* triggers data writeback which fails if shutdown is already +* set, causing the journal to be aborted prematurely before +* the commit succeeds. +*/ + (void )ext4_force_commit (sb);set_bit (EXT4_FLAGS_SHUTDOWN , &sbi->s_ext4_flags); -if (sbi->s_journal && !is_journal_aborted (sbi->s_journal)) { - (void )ext4_force_commit (sb); +if (sbi->s_journal && !is_journal_aborted (sbi->s_journal))jbd2_journal_abort (sbi->s_journal, -ESHUTDOWN ); - }break ;case EXT4_GOING_FLAGS_NOLOGFLUSH :set_bit (EXT4_FLAGS_SHUTDOWN , &sbi->s_ext4_flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 470/1266 ASoC: rsnd: Fix RSND_SOC_MASK width to single nibble
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Madieu <[email protected]>
[ Upstream commit c0758279367e9d82eb7d7b4959718d7d32e96b7d ]
RSND_SOC_MASK was defined as (0xFF << 4), spanning bits 4-11. This is wider than needed since only nibble B (bits 7:4) is used for SoC identifiers. Narrow it to (0xF << 4) to match the intended single-nibble allocation and prevent overlap with bits 8-11 which will be used by upcoming RZ series flags.
No functional change, since the only current user (RSND_SOC_E) fits within a single nibble.
--- sound/soc/sh/rcar/rsnd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/sh/rcar/rsnd.h +1 -1
@@ -637,7 +637,7 @@ struct rsnd_priv {#define RSND_GEN2 (2 << 0)#define RSND_GEN3 (3 << 0)#define RSND_GEN4 (4 << 0) -#define RSND_SOC_MASK (0xFF << 4) +#define RSND_SOC_MASK (0xF << 4)#define RSND_SOC_E (1 << 4)/* E1/E2/E3 */ /*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 471/1266 ARM: imx3: Fix CCM node reference leak
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 36d46348eb5fc4bc505cd2290ddd70c25fbe6bb3 ]
of_find_compatible_node() returns a referenced device node. The i.MX31 and i.MX35 early init paths use the node to map the CCM registers with of_iomap(), but never drop the node reference.
Release the node after the mapping is created.
--- arch/arm/mach-imx/mm-imx3.c | 2 ++ 1 file changed, 2 insertions(+)
arch/arm/mach-imx/mm-imx3.c +2 -0
@@ -106,6 +106,7 @@ void __init imx31_init_early(void) arm_pm_idle = imx31_idle; np =of_find_compatible_node (NULL ,NULL ,"fsl,imx31-ccm" ); mx3_ccm_base =of_iomap (np,0 ); +of_node_put (np); BUG_ON(!mx3_ccm_base); }#endif /* ifdef CONFIG_SOC_IMX31 */
@@ -143,6 +144,7 @@ void __init imx35_init_early(void) arch_ioremap_caller = imx3_ioremap_caller; np =of_find_compatible_node (NULL ,NULL ,"fsl,imx35-ccm" ); mx3_ccm_base =of_iomap (np,0 ); +of_node_put (np); BUG_ON(!mx3_ccm_base); }#endif /* ifdef CONFIG_SOC_IMX35 */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 472/1266 HID: wiimote: Fix table layout and whitespace errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: J. Neuschäfer <[email protected]>
[ Upstream commit 12b7731995ca577d86e02196e99ba9c126f47282 ]
Some tab characters snuck into the data layout table for turntable extensions, which resulted in the table only looking right at a tabstop of 4, which is uncommon in the kernel. Change them to the equivalent amount of spaces, which should look correct in any editor.
While at it, also fix the other whitespace errors (trailing spaces at end of line) introduced in the same commit.
--- drivers/hid/hid-wiimote-modules.c | 58 +++++++++++++++---------------- 1 file changed, 29 insertions(+), 29 deletions(-)
drivers/hid/hid-wiimote-modules.c +29 -29
@@ -2403,7 +2403,7 @@ static const struct wiimod_ops wiimod_guitar = { .in_ext = wiimod_guitar_in_ext, }; -/* +/* * Turntable * DJ Hero came with a Turntable Controller that was plugged in * as an extension.
@@ -2439,15 +2439,15 @@ static const __u16 wiimod_turntable_map[] = {static void wiimod_turntable_in_ext (struct wiimote_data *wdata,const __u8 *ext) {__u8 be, cs, sx, sy, ed, rtt, rbg, rbr, rbb, ltt, lbg, lbr, lbb, bp, bm; -/* +/* * Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | *------+------+-----+-----+-----+-----+------+------+--------+ -* 0 | RTT<4:3> | SX <5:0> | -* 1 | RTT<2:1> | SY <5:0> | +* 0 | RTT<4:3> | SX <5:0> | +* 1 | RTT<2:1> | SY <5:0> | *------+------+-----+-----+-----+-----+------+------+--------+ * 2 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> | *------+------+-----+-----+-----+-----+------+------+--------+ -* 3 | ED<2:0> | LTT<4:0> | +* 3 | ED<2:0> | LTT<4:0> | *------+------+-----+-----+-----+-----+------+------+--------+ * 4 | 0 | 0 | LBR | B- | 0 | B+ | RBR | LTT<5> | *------+------+-----+-----+-----+-----+------+------+--------+
@@ -2458,20 +2458,20 @@ static void wiimod_turntable_in_ext(struct wiimote_data *wdata, const __u8 *ext)* With Motion+ enabled, it will look like this: * Byte | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | *------+------+-----+-----+-----+-----+------+------+--------+ -* 1 | RTT<4:3> | SX <5:1> | 0 | -* 2 | RTT<2:1> | SY <5:1> | 0 | +* 1 | RTT<4:3> | SX <5:1> | 0 | +* 2 | RTT<2:1> | SY <5:1> | 0 | *------+------+-----+-----+-----+-----+------+------+--------+ * 3 |RTT<0>| ED<4:3> | CS<3:0> | RTT<5> | *------+------+-----+-----+-----+-----+------+------+--------+ -* 4 | ED<2:0> | LTT<4:0> | +* 4 | ED<2:0> | LTT<4:0> | *------+------+-----+-----+-----+-----+------+------+--------+ * 5 | 0 | 0 | LBR | B- | 0 | B+ | RBR | XXXX | *------+------+-----+-----+-----+-----+------+------+--------+ * 6 | LBB | 0 | RBG | BE | LBG | RBB | XXXX | XXXX | *------+------+-----+-----+-----+-----+------+------+--------+ */ - - be = !(ext[5 ] &0x10 ); + + be = !(ext[5 ] &0x10 ); cs = ((ext[2 ] &0x1e )); sx = ext[0 ] &0x3f ; sy = ext[1 ] &0x3f ;
@@ -2499,32 +2499,32 @@ static void wiimod_turntable_in_ext(struct wiimote_data *wdata, const __u8 *ext)input_report_abs (wdata->extension.input,ABS_HAT1X , ltt);input_report_abs (wdata->extension.input,ABS_HAT2X , cs);input_report_abs (wdata->extension.input,ABS_HAT3X , ed); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_RIGHT ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_RIGHT ], rbg);input_report_key (wdata->extension.input, wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_RIGHT ], rbr); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_RIGHT ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_RIGHT ], rbb); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_LEFT ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_G_LEFT ], lbg); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_LEFT ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_R_LEFT ], lbr); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_LEFT ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_B_LEFT ], lbb); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_EUPHORIA ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_EUPHORIA ], be); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_PLUS ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_PLUS ], bp); -input_report_key (wdata->extension.input, - wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_MINUS ], +input_report_key (wdata->extension.input, + wiimod_turntable_map[WIIMOD_TURNTABLE_KEY_MINUS ], bm);input_sync (wdata->extension.input);
@@ -2557,7 +2557,7 @@ static void wiimod_turntable_close(struct input_dev *dev)static int wiimod_turntable_probe (const struct wiimod_ops *ops,struct wiimote_data *wdata) { -int ret, i; +int ret, i; wdata->extension.input =input_allocate_device ();if (!wdata->extension.input)
@@ -2594,9 +2594,9 @@ static int wiimod_turntable_probe(const struct wiimod_ops *ops,input_set_abs_params (wdata->extension.input,ABS_HAT1X ,-8 ,8 ,0 ,0 );input_set_abs_params (wdata->extension.input, -ABS_HAT2X ,0 ,31 ,1 ,1 ); +ABS_HAT2X ,0 ,31 ,1 ,1 );input_set_abs_params (wdata->extension.input, -ABS_HAT3X ,0 ,7 ,0 ,0 ); +ABS_HAT3X ,0 ,7 ,0 ,0 ); ret =input_register_device (wdata->extension.input);if (ret) goto err_free;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 473/1266 ata: libata: Fix ata_exec_internal()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bart Van Assche <[email protected]>
[ Upstream commit aa0ae1c35f7b3e9afed2324bed5f5c87ad55b92c ]
Some but not all ata_exec_internal() calls happen from the context of the ATA error handler. Commit c0c362b60e25 ("libata: implement cross-port EH exclusion") added ata_eh_release() and ata_eh_acquire() calls in ata_exec_internal(). Calling these functions is necessary if the caller holds the eh_mutex but is not allowed if the caller doesn't hold that mutex. Fix this by only calling ata_eh_release() and ata_eh_acquire() if the caller holds the eh_mutex. An example of an indirect caller of ata_exec_internal() that does not hold the eh_mutex is ata_host_register().
--- drivers/ata/libata-core.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/ata/libata-core.c +17 -2
@@ -1508,6 +1508,7 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev, {struct ata_link *link = dev->link;struct ata_port *ap = link->ap; +const bool owns_eh_mutex = ap->host->eh_owner == current;u8 command = tf->command;int auto_timeout =0 ;struct ata_queued_cmd *qc;
@@ -1586,11 +1587,25 @@ static unsigned ata_exec_internal_sg(struct ata_device *dev, } } -ata_eh_release (ap); +if (owns_eh_mutex) { +/* +* To prevent that the compiler complains about the +* ata_eh_release() call below. +*/ +__acquire (&ap->host->eh_mutex); +ata_eh_release (ap); + } rc =wait_for_completion_timeout (&wait,msecs_to_jiffies (timeout)); -ata_eh_acquire (ap); +if (owns_eh_mutex) { +ata_eh_acquire (ap); +/* +* To prevent that the compiler complains about the above +* ata_eh_acquire() call. +*/ +__release (&ap->host->eh_mutex); + }ata_sff_flush_pio_task (ap);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 474/1266 ARM: imx31: Fix IIM mapping leak in revision check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit ccb4b54b8ecf1ebafef96d538cd6c5c8455bb390 ]
mx31_read_cpu_rev() maps the IIM registers with of_iomap() to read the silicon revision, but returns without unmapping the MMIO mapping.
Keep the normalized revision value in a local variable and route the return path through iounmap() after the revision register has been read.
--- arch/arm/mach-imx/cpu-imx31.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
arch/arm/mach-imx/cpu-imx31.c +7 -2
@@ -36,6 +36,7 @@ static int mx31_read_cpu_rev(void)void __iomem *iim_base;struct device_node *np;u32 i, srev; +int rev =IMX_CHIP_REVISION_UNKNOWN ; np =of_find_compatible_node (NULL ,NULL ,"fsl,imx31-iim" ); iim_base =of_iomap (np,0 );
@@ -48,13 +49,17 @@ static int mx31_read_cpu_rev(void)for (i =0 ; i <ARRAY_SIZE (mx31_cpu_type); i++)if (srev == mx31_cpu_type[i].srev) { + rev = mx31_cpu_type[i].rev;imx_print_silicon_rev (mx31_cpu_type[i].name, mx31_cpu_type[i].rev); -return mx31_cpu_type[i].rev; + goto out; }imx_print_silicon_rev ("i.MX31" ,IMX_CHIP_REVISION_UNKNOWN ); -return IMX_CHIP_REVISION_UNKNOWN ; + +out: +iounmap (iim_base); +return rev; }int mx31_revision (void )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 475/1266 nvdimm/btt: Handle preemption in BTT lane acquisition
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alison Schofield <[email protected]>
[ Upstream commit 8d4b989d9c9afe5f185aa5853b666fc4617afe9e ]
BTT lanes serialize access to per-lane metadata and workspace state during BTT I/O. The btt-check unit test reports data mismatches during BTT writes due to a race in lane acquisition that can lead to silent data corruption.
The existing lane model uses a spinlock together with a per-CPU recursion count. That recursion model stopped being valid after BTT lanes became preemptible: another task can run on the same CPU, observe a non-zero recursion count, bypass locking, and use the same lane concurrently.
BTT lanes are also held across arena_write_bytes() calls. That path reaches nsio_rw_bytes(), which flushes writes with nvdimm_flush(). Some provider flush callbacks can sleep, making a spinlock the wrong primitive for the lane lifetime.
Replace the spinlock-based recursion model with a dynamically allocated per-lane mutex array and take the lane lock unconditionally.
Add might_sleep() to catch any future atomic-context caller.
Found with the ndctl unit test btt-check.sh.
--- Documentation/driver-api/nvdimm/btt.rst | 5 +- drivers/nvdimm/nd.h | 11 ++--- drivers/nvdimm/region_devs.c | 66 +++++++++---------------- 3 files changed, 29 insertions(+), 53 deletions(-)
Documentation/driver-api/nvdimm/btt.rst +2 -3
@@ -161,9 +161,8 @@ process:: nlanes = min(nfree, num_cpus) A lane number is obtained at the start of any IO, and is used for indexing into -all the on-disk and in-memory data structures for the duration of the IO. If -there are more CPUs than the max number of available lanes, than lanes are -protected by spinlocks. +all the on-disk and in-memory data structures for the duration of the IO. Lanes +are protected by mutexes. d. In-memory data structure: Read Tracking Table (RTT)
drivers/nvdimm/nd.h +5 -6
@@ -365,11 +365,6 @@ unsigned sizeof_namespace_label(struct nvdimm_drvdata *ndd);for (res = (ndd)->dpa.child, next = res ? res->sibling :NULL ; \ res; res = next, next = next ? next->sibling :NULL ) -struct nd_percpu_lane { -int count; -spinlock_t lock; -}; - enum nd_label_flags { ND_LABEL_REAP, };
@@ -400,6 +395,10 @@ struct nd_mapping {struct nvdimm_drvdata *ndd; }; +struct nd_lane { +struct mutex lock;/* serialize lane access */ +}____cacheline_aligned_in_smp ; +struct nd_region {struct device dev;struct ida ns_ida;
@@ -420,7 +419,7 @@ struct nd_region {struct kernfs_node *bb_state;struct badblocks bb;struct nd_interleave_set *nd_set; -struct nd_percpu_lane __percpu *lane; +struct nd_lane *lane;int (*flush)(struct nd_region *nd_region,struct bio *bio);struct nd_mapping mapping[]; };
drivers/nvdimm/region_devs.c +22 -44
105 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 476/1266 scsi: Revert "scsi: Fix sas_user_scan() to handle wildcard and multi-channel scans"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Wilck <[email protected]>
[ Upstream commit 8c292e89bd831c8a13e92f3429ef66bbe0b83677 ]
This reverts commit 37c4e72b0651e7697eb338cd1fb09feef472cc1a.
Said commit causes excessive resource usage and even system freeze with some controllers, e.g. smartpqi and hisi_sas. The justification provided by the patch authors [1] was supporting a special mode of the mpi3mr and mpt3sas, so-called "Tri-mode", in which NVMe drives are exposed as SCSI devices on a separate channel. While that's useful for these drivers, it seems wrong to cause major breakage for other drivers for the sake of this feature.
--- drivers/scsi/scsi_scan.c | 2 +- drivers/scsi/scsi_transport_sas.c | 60 +++++++------------------------ 2 files changed, 13 insertions(+), 49 deletions(-)
drivers/scsi/scsi_scan.c +1 -1
@@ -1848,7 +1848,7 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,return 0 ; } -EXPORT_SYMBOL (scsi_scan_host_selected); +static void scsi_sysfs_add_devices (struct Scsi_Host *shost) {struct scsi_device *sdev;
drivers/scsi/scsi_transport_sas.c +12 -48
83 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 477/1266 scsi: pm8001: Fix error code in non_fatal_log_show()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 1b6f03b7ae9ee27054c55bb55a69d05555a78516 ]
The non_fatal_log_show() function is supposed to return negative error codes on failure. But because the error codes are saved in a u32 and then cast to signed long, they end up being high positive values instead of negative. Remove the intermediary u32 variable to fix this bug.
--- drivers/scsi/pm8001/pm8001_ctl.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/scsi/pm8001/pm8001_ctl.c +1 -4
@@ -588,10 +588,7 @@ static DEVICE_ATTR(fatal_log, S_IRUGO, pm8001_ctl_fatal_log_show, NULL);static ssize_t non_fatal_log_show (struct device *cdev,struct device_attribute *attr,char *buf) { -u32 count; - - count =pm80xx_get_non_fatal_dump (cdev, attr, buf); -return count; +return pm80xx_get_non_fatal_dump (cdev, attr, buf); }static DEVICE_ATTR_RO (non_fatal_log);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 478/1266 scsi: ufs: Fix wrong value printed in unexpected UPIU response case
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chanwoo Lee <[email protected]>
[ Upstream commit 2483ae0a56231a915c706411421c6c002a2bf83e ]
In ufshcd_transfer_rsp_status(), the default case of the inner switch statement prints the UPIU response code when an unexpected response is received. However, the code was printing 'result' variable which is always 0 at that point, making the error message useless for debugging.
Fix this by printing the actual UPIU response code returned by ufshcd_get_req_rsp().
--- drivers/ufs/core/ufshcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ufs/core/ufshcd.c +1 -1
@@ -5407,7 +5407,7 @@ ufshcd_transfer_rsp_status(struct ufs_hba *hba, struct ufshcd_lrb *lrbp,default :dev_err (hba->dev,"Unexpected request response code = %x\n" , - result); +ufshcd_get_req_rsp (lrbp->ucd_rsp_ptr)); result =DID_ERROR <<16 ;break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 479/1266 bpf: fix UAF by restoring RCU-delayed inode freeing in bpffs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
[ Upstream commit b93c55b4932dd7e32dca8cf34a3443cc87a02906 ]
commit 4f375ade6aa9 ("bpf: Avoid RCU context warning when unpinning htab with internal structs") moved inode cleanup from ->free_inode() into ->destroy_inode() to avoid sleeping in RCU context when calling bpf_any_put(). However this removed the RCU delay on freeing the inode itself and the cached symlink body (i_link), both of which can be accessed by RCU pathwalk (pick_link, may_lookup etc.).
This causes a use-after-free when a concurrent unlinkat() drops the last inode reference and destroy_inode() frees the inode immediately, while another task is still walking the path in RCU mode and reads inode->i_opflags (offset +2) inside current_time() -> is_mgtime().
KASAN reports:
BUG: KASAN: slab-use-after-free in is_mgtime include/linux/fs.h:2313 Read of size 2 at addr ffff8880407e4282 (offset +2 = i_opflags)
The rules (per Al Viro):
->destroy_inode() called immediately, can sleep, use for blocking
cleanup e.g. bpf_any_put()
->free_inode() called after RCU grace period, use for freeing
inode and anything RCU-accessible e.g. i_link
Fix: split the two concerns properly:
- keep bpf_any_put() in bpf_destroy_inode() since it is blocking and needs to run promptly
- introduce bpf_free_inode() to handle kfree(i_link) and free_inode_nonrcu() with proper RCU delay, preventing the UAF
--- kernel/bpf/inode.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
kernel/bpf/inode.c +11 -2
@@ -611,10 +611,18 @@ static void bpf_destroy_inode(struct inode *inode) {enum bpf_type type; -if (S_ISLNK (inode->i_mode)) -kfree (inode->i_link);if (!bpf_inode_type (inode, &type))bpf_any_put (inode->i_private, type); +} + +/* +* Called after RCU grace period - safe to free inode and anything +* that might be accessed by RCU pathwalk (inode fields, i_link). +*/ +static void bpf_free_inode (struct inode *inode) +{ +if (S_ISLNK (inode->i_mode)) +kfree (inode->i_link);free_inode_nonrcu (inode); }
@@ -623,6 +631,7 @@ static const struct super_operations bpf_super_ops = { .drop_inode = generic_delete_inode, .show_options = bpf_show_options, .destroy_inode = bpf_destroy_inode, + .free_inode = bpf_free_inode, };enum {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 480/1266 mm/fake-numa: fix under-allocation detection in uniform split
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sang-Heon Jeon <[email protected]>
[ Upstream commit 3a3fc1dfd6a958615ebaab8fb251e89fc2b3f2f2 ]
When splitting NUMA node uniformly, split_nodes_size_interleave_uniform() returns the next absolute node ID, not the number of nodes created.
The existing under-allocation detection logic compares next absolute node ID (ret) and request count (n), which only works when nid starts at 0.
For example, on a system with 2 physical NUMA nodes (node 0: 2GB, node 1: 128MB) and numa=fake=8U, 8 fake nodes are successfully created from node 0 and split_nodes_size_interleave_uniform() returns 8. For node 1, fake node nid starts at 8, but only 4 fake nodes are created due to current FAKE_NODE_MIN_SIZE being 32MB, and split_nodes_size_interleave_uniform() returns 12. By existing under-allocation detection logic, "ret < n" (12 < 8) is false, so the under-allocation will not be detected.
Fix under-allocation detection logic to compare the number of actually created nodes (ret - nid) against the request count (n). Also skip under-allocation detection logic for memoryless physical nodes where no fake nodes are created.
Also, fix the outdated comment describing split_nodes_size_interleave_uniform() to match the actual return value.
--- arch/x86/mm/numa_emulation.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
arch/x86/mm/numa_emulation.c +13 -4
@@ -211,7 +211,7 @@ static u64 uniform_size(u64 max_addr, u64 base, u64 hole, int nr_nodes)* Sets up fake nodes of `size' interleaved over physical nodes ranging from * `addr' to `max_addr'. * -* Returns zero on success or negative on error. +* Returns node ID of the next node on success or negative error code. */ static int __init split_nodes_size_interleave_uniform(struct numa_meminfo *ei, struct numa_meminfo *pi,
@@ -395,7 +395,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)if (strchr (emu_cmdline,'U' )) {nodemask_t physnode_mask = numa_nodes_parsed;unsigned long n; -int nid =0 ; +int nid =0 , nr_created; n =simple_strtoul (emu_cmdline, &emu_cmdline,0 ); ret =-1 ;
@@ -413,9 +413,18 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt) n, &pi.blk[0], nid);if (ret <0 )break ; -if (ret < n) { + +/* +* If no memory was found for this physical node, +* skip the under-allocation check. +*/ +if (ret == nid) +continue ; + + nr_created = ret - nid; +if (nr_created < n) {pr_info ("%s: phys: %d only got %d of %ld nodes, failing\n" , - __func__, i, ret, n); + __func__, i, nr_created, n); ret =-1 ;break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 481/1266 ext2: fix ignored return value of generic_write_sync()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danila Chernetsov <[email protected]>
[ Upstream commit a4659be0bc7cb1856ffb15b67f903229ae8891ec ]
Fix ext2_dio_write_iter() to propagate the error returned by generic_write_sync() instead of silently discarding it, which could cause write(2) to return success to userspace on O_SYNC/O_DSYNC files even when the sync failed.
The correct pattern, already used in ext2_dax_write_iter() in the same file and in ext4, xfs, f2fs among others, is:
if (ret > 0)
ret = generic_write_sync(iocb, ret);Found by Linux Verification Center (linuxtesting.org) with SVACE.
[JK: Reflect also filemap_write_and_wait() return value]
--- fs/ext2/file.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
fs/ext2/file.c +6 -3
@@ -262,12 +262,15 @@ static ssize_t ext2_dio_write_iter(struct kiocb *iocb, struct iov_iter *from) endbyte = pos + status -1 ; ret2 =filemap_write_and_wait_range (inode->i_mapping, pos, endbyte); -if (!ret2) +if (!ret2) {invalidate_mapping_pages (inode->i_mapping, pos >>PAGE_SHIFT , endbyte >>PAGE_SHIFT ); -if (ret >0 ) -generic_write_sync (iocb, ret); +if (ret >0 ) + ret =generic_write_sync (iocb, ret); + }else { + ret = ret2; + } } out_unlock:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 482/1266 sched: restore timer_slack_ns when resetting RT policy on fork
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanyou.Chen <[email protected]>
[ Upstream commit 63c1a12bc0e09af7dee919c4fb4a300a719d5125 ]
Commit ed4fb6d7ef68 ("hrtimer: Use and report correct timerslack values for realtime tasks") sets timer_slack_ns to 0 for RT tasks in __setscheduler_params(). However, when an RT task with SCHED_RESET_ON_FORK creates child threads, the children inherit timer_slack_ns=0 from the parent. sched_fork() resets the child's policy to SCHED_NORMAL but does not restore timer_slack_ns, leaving the child permanently running with zero slack.
Fix this by restoring timer_slack_ns from default_timer_slack_ns in sched_fork() when resetting from RT/DL to NORMAL policy, matching the existing behavior in __setscheduler_params().
Note: this fix alone requires a correct default_timer_slack_ns to be effective. See the following patch for that fix.
--- kernel/sched/core.c | 1 + 1 file changed, 1 insertion(+)
kernel/sched/core.c +1 -0
@@ -4751,6 +4751,7 @@ int sched_fork(unsigned long clone_flags, struct task_struct *p) p->policy =SCHED_NORMAL ; p->static_prio =NICE_TO_PRIO (0 ); p->rt_priority =0 ; + p->timer_slack_ns = p->default_timer_slack_ns; }else if (PRIO_TO_NICE (p->static_prio) <0 ) p->static_prio =NICE_TO_PRIO (0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 483/1266 lib/test_meminit: use && for bools
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Potapenko <[email protected]>
[ Upstream commit 8e0c2085c978ed6d9764d79fc785920360096f21 ]
As pointed out by Dan Carpenter, test_kmemcache() was using a bitwise AND on two bools instead of a boolean AND. Fix this for the sake of code cleanliness.
--- lib/test_meminit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/test_meminit.c +1 -1
@@ -387,7 +387,7 @@ static int __init test_kmemcache(int *total_failures) ctor = flags &1 ; rcu = flags &2 ; zero = flags &4 ; -if (ctor & zero) +if (ctor && zero)continue ; num_tests +=do_kmem_cache_size (size, ctor, rcu, zero, &failures);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 484/1266 configfs_lookup(): dont leave ->s_dentry dangling on failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 10da12d352b7b2bb330a8609fdda9a58bf0e9856 ]
Normally ->s_dentry is cleared when dentry it's pointing to becomes negative (on eviction, realistically). However, that only happens if dentry gets to be positive in the first place; in case of inode allocation failure dentry never becomes positive, so ->d_iput() is not called at all.
We do part of what normally would've been done by configfs_d_iput() (dropping the reference to configfs_dirent) manually, but we do not clear ->s_dentry there. Sloppy as it is, it does not matter in case of configfs_create_{dir,link}() - there configfs_dirent does not survive dropping the sole reference to it.
However, for configfs_lookup() it *does* survive, with a dangling pointer to soon to be freed dentry sitting it its ->s_dentry.
Subsequent getdents(2) in that directory will end up dereferencing that pointer in order to pick the inode number. Use after free...
This is the minimal fix; the right approach is to set the linkage between dentry and configfs_dirent only after we know that we have an inode, but that takes more surgery and the bug had been there since 2006, so...
--- fs/configfs/dir.c | 3 +++ 1 file changed, 3 insertions(+)
fs/configfs/dir.c +3 -0
@@ -462,6 +462,9 @@ static struct dentry * configfs_lookup(struct inode *dir, inode =configfs_create (dentry, mode);if (IS_ERR (inode)) { +spin_lock (&configfs_dirent_lock); + sd->s_dentry =NULL ; +spin_unlock (&configfs_dirent_lock);configfs_put (sd);return ERR_CAST (inode); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 485/1266 drm/amdgpu: set sub_block_index for mca ras sub-blocks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yunxiang Li <[email protected]>
[ Upstream commit baa286df5fb366e4aee5b747443dfc7194fdaa59 ]
The mca ras sub-blocks (mp0, mp1, mpio) all share the AMDGPU_RAS_BLOCK__MCA block id and are distinguished only by sub_block_index. The ras manager object for an mca block is selected with:
con->objs[AMDGPU_RAS_BLOCK__LAST + head->sub_block_index]
Since the rework in commit 7f544c5488cf ("drm/amdgpu: Rework mca ras sw_init") moved the ras_comm setup into amdgpu_mca_mp*_ras_sw_init() but left sub_block_index unset, mp0/mp1/mpio all default to index 0 and collide on the same object slot. mp0 grabs the slot and creates its sysfs node first; mp1 (and mpio) then find the slot already in use, so amdgpu_ras_block_late_init() -> amdgpu_ras_sysfs_create() returns -EINVAL:
amdgpu: mca.mp1 failed to execute ras_block_late_init_default! ret:-22
amdgpu: amdgpu_ras_late_init failed -22
amdgpu: amdgpu_device_ip_late_init failed
amdgpu: Fatal error during GPU init
The error is currently masked because amdgpu_ras_late_init() does not check the return value of amdgpu_ras_block_late_init_default(), but it already leaves mp1/mpio without their sysfs nodes and becomes a fatal init failure as soon as that return value is honored.
Restore the per-sub-block sub_block_index assignment so each mca sub-block maps to its own object slot.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_mca.c +3 -0
@@ -89,6 +89,7 @@ int amdgpu_mca_mp0_ras_sw_init(struct amdgpu_device *adev)strcpy (ras->ras_block.ras_comm.name,"mca.mp0" ); ras->ras_block.ras_comm.block =AMDGPU_RAS_BLOCK__MCA ; + ras->ras_block.ras_comm.sub_block_index =AMDGPU_RAS_MCA_BLOCK__MP0 ; ras->ras_block.ras_comm.type =AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE ; adev->mca.mp0.ras_if = &ras->ras_block.ras_comm;
@@ -113,6 +114,7 @@ int amdgpu_mca_mp1_ras_sw_init(struct amdgpu_device *adev)strcpy (ras->ras_block.ras_comm.name,"mca.mp1" ); ras->ras_block.ras_comm.block =AMDGPU_RAS_BLOCK__MCA ; + ras->ras_block.ras_comm.sub_block_index =AMDGPU_RAS_MCA_BLOCK__MP1 ; ras->ras_block.ras_comm.type =AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE ; adev->mca.mp1.ras_if = &ras->ras_block.ras_comm;
@@ -137,6 +139,7 @@ int amdgpu_mca_mpio_ras_sw_init(struct amdgpu_device *adev)strcpy (ras->ras_block.ras_comm.name,"mca.mpio" ); ras->ras_block.ras_comm.block =AMDGPU_RAS_BLOCK__MCA ; + ras->ras_block.ras_comm.sub_block_index =AMDGPU_RAS_MCA_BLOCK__MPIO ; ras->ras_block.ras_comm.type =AMDGPU_RAS_ERROR__MULTI_UNCORRECTABLE ; adev->mca.mpio.ras_if = &ras->ras_block.ras_comm;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 486/1266 bpftool: Use libbpf error code for flow dissector query
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Woojin Ji <[email protected]>
[ Upstream commit 8a7f2bff2165e53595d1e91c160b340f978c0ab7 ]
bpf_prog_query() returns a negative errno on failure. query_flow_dissector() currently closes the namespace fd and then reads errno to decide whether -EINVAL means that the running kernel does not support flow dissector queries.
That errno check controls behavior, not just diagnostics: -EINVAL is handled as a non-fatal old-kernel case, while any other error makes bpftool net fail.
The namespace fd is opened read-only, so close() is not expected to commonly fail in normal use. Still, the BPF_PROG_QUERY error is already available in err, and reading errno after an intervening close() is fragile. If close() does change errno, the compatibility branch may be based on close()'s error instead of the BPF_PROG_QUERY result.
This was reproduced with an LD_PRELOAD fault injector that forced BPF_PROG_QUERY for BPF_FLOW_DISSECTOR to fail with EINVAL and then forced close() on the netns fd to fail with EIO. The unpatched bpftool reported "can't query prog: Input/output error". With this change, the same injected failure is handled as the intended non-fatal EINVAL compatibility case.
Use the libbpf-returned error code instead. Keep the existing errno reset in the non-fatal path to preserve batch mode behavior. The success path is unchanged.
--- tools/bpf/bpftool/net.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/bpf/bpftool/net.c +2 -2
@@ -594,14 +594,14 @@ static int query_flow_dissector(struct bpf_attach_info *attach_info) &attach_flags, prog_ids, &prog_cnt);close (fd);if (err) { -if (errno ==EINVAL ) { +if (err == -EINVAL ) {/* Older kernel's don't support querying * flow dissector programs. */ errno =0 ;return 0 ; } -p_err ("can't query prog: %s" ,strerror (errno)); +p_err ("can't query prog: %s" ,strerror (-err));return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 487/1266 perf/x86/amd/core: Always use the NMI latency mitigation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sandipan Das <[email protected]>
[ Upstream commit 73a4c02f94a98d94480c3e5c81450215a4da05ba ]
Commit df4d29732fda ("perf/x86/amd: Change/fix NMI latency mitigation to use a timestamp") fixed handling of late-arriving NMIs but limited the mitigation to processors having X86_FEATURE_PERFCTR_CORE. However, it is unclear if processors without this feature are also affected. When Mediated vPMU is enabled on affected hardware, it is also possible to bypass the fix inside KVM guests if X86_FEATURE_PERFCTR_CORE is removed from the guest CPUID (e.g. using "-cpu host,-perfctr-core" with QEMU). Hence, use the mitigation at all times.
--- arch/x86/events/amd/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
arch/x86/events/amd/core.c +3 -3
@@ -1364,12 +1364,12 @@ static int __init amd_core_pmu_init(void)u64 even_ctr_mask =0ULL ;int i; -if (!boot_cpu_has (X86_FEATURE_PERFCTR_CORE )) -return 0 ; -/* Avoid calculating the value each time in the NMI handler */ perf_nmi_window =msecs_to_jiffies (100 ); +if (!boot_cpu_has (X86_FEATURE_PERFCTR_CORE )) +return 0 ; +/* * If core performance counter extensions exists, we must use * MSR_F15H_PERF_CTL/MSR_F15H_PERF_CTR msrs. See also
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 488/1266 ocfs2: rebase copied fsdlm LVB pointers in locking_state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit 93612d48fa42b3d1a637eb9279e15281c611c000 ]
The locking_state debugfs iterator snapshots struct ocfs2_lock_res by value under ocfs2_dlm_tracking_lock and later formats that copy in ocfs2_dlm_seq_show(). That is fine for the inline fields, but the userspace fsdlm stack stores the LVB through lksb_fsdlm.sb_lvbptr. Once the iterator drops the tracking lock, a copied non-NULL sb_lvbptr still points into the original lockres owner, so teardown can free that container before the debugfs dump walks the raw LVB bytes.
Rebase the copied sb_lvbptr to the copied l_lksb before dumping the raw LVB. The seq snapshot already carries the inline LVB storage reserved in struct ocfs2_dlm_lksb, so the debugfs reader can dump the copied bytes without borrowing the original lockres lifetime.
The buggy scenario involves two paths, with each column showing the order within that path:
locking_state reader: lockres teardown:
1. ocfs2_dlm_seq_start()/next() 1. file release or another owner
copies struct ocfs2_lock_res teardown reaches
2. ocfs2_dlm_seq_show() formats ocfs2_lock_res_free()
the copied row 2. the lockres is removed from the
3. ocfs2_dlm_lvb() follows the tracking list
copied sb_lvbptr 3. the owner frees the original
lockres container
Validation reproduced this kernel report:
KASAN slab-use-after-free in ocfs2_dlm_seq_show+0x1bd/0x430
RIP: 0033:0x7f8ec4b1e29d The buggy address belongs to the object at ffff88810a1e0800 which belongs to the cache kmalloc-1k of size 1024 The buggy address is located 368 bytes inside of freed 1024-byte region [ffff88810a1e0800, ffff88810a1e0c00) Read of size 1 Call trace: dump_stack_lvl+0x66/0xa0 print_report+0xce/0x630 ocfs2_dlm_seq_show+0x1bd/0x430 (fs/ocfs2/dlmglue.c:3137) srso_alias_return_thunk+0x5/0xfbef5 __virt_addr_valid+0x19f/0x330 kasan_report+0xe0/0x110 seq_read_iter+0x29d/0x790 seq_read+0x20a/0x280 find_held_lock+0x2b/0x80 rcu_read_unlock+0x18/0x70 full_proxy_read+0x9e/0xd0 vfs_read+0x12c/0x590 ksys_read+0xd2/0x170 do_user_addr_fault+0x65a/0x890 do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f Allocated by task stack: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 __kasan_kmalloc+0xaa/0xb0 ocfs2_file_open+0x13e/0x300 do_dentry_open+0x233/0x7f0 vfs_open+0x5a/0x1b0 path_openat+0x66d/0x1540 do_file_open+0x186/0x2b0 do_sys_openat2+0xce/0x150 __x64_sys_openat+0xd0/0x140 do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f Freed by task stack: kasan_save_stack+0x33/0x60 kasan_save_track+0x14/0x30 kasan_save_free_info+0x3b/0x60 __kasan_slab_free+0x5f/0x80 kfree+0x313/0x590 ocfs2_file_release+0x138/0x260 __fput+0x1df/0x4b0 fput_close_sync+0xd2/0x170 __x64_sys_close+0x55/0x90 do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f
--- fs/ocfs2/dlmglue.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
fs/ocfs2/dlmglue.c +17 -0
@@ -3135,6 +3135,22 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)* - Add last pr/ex unlock times and first lock wait time in usecs */ #define OCFS2_DLM_DEBUG_STR_VERSION 4 + +/* +* The debug iterator snapshots lockres by value, so a userspace-stack LVB +* pointer copied from the original lockres must be rebased to the copied +* lksb before the dump walks the raw bytes. +*/ +static void ocfs2_dlm_seq_rebase_lvb (struct ocfs2_lock_res *lockres) +{ +if (!ocfs2_stack_supports_plocks ()) +return ; + +if (lockres->l_lksb.lksb_fsdlm.sb_lvbptr) + lockres->l_lksb.lksb_fsdlm.sb_lvbptr = + (char *)&lockres->l_lksb +sizeof (struct dlm_lksb ); +} +static int ocfs2_dlm_seq_show (struct seq_file *m,void *v) {int i;
@@ -3195,6 +3211,7 @@ static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) lockres->l_blocking);/* Dump the raw LVB */ +ocfs2_dlm_seq_rebase_lvb (lockres); lvb =ocfs2_dlm_lvb (&lockres->l_lksb);for (i =0 ; i <DLM_LVB_LEN ; i++)seq_printf (m,"0x%x\t" , lvb[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 489/1266 ocfs2: fix buffer head management in ocfs2_read_blocks()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Antipov <[email protected]>
[ Upstream commit 6371a07148ee979af22a9d6f4c277462953a9a4a ]
In ocfs2_read_blocks(), caller should't assume that buffer head returned by 'sb_getblk()' is exclusively owned and so 'put_bh()' always drops b_count from 1 to 0. If it is not so, buffer head remains on hold and likely to be returned by the next call to 'sb_getblk()' unchanged - that is, with BH_Uptodate bit set even if it has failed validation previously, thus allowing to insert that buffer head into OCFS2 metadata cache and submit it to upper layers. To avoid such a scenario, BH_Uptodate should be cleared immediately after 'validate()' callback has detected some data inconsistency.
--- fs/ocfs2/buffer_head_io.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/ocfs2/buffer_head_io.c +4 -3
@@ -350,8 +350,6 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,wait_on_buffer (bh);put_bh (bh); bhs[i] =NULL ; - }else if (bh &&buffer_uptodate (bh)) { -clear_buffer_uptodate (bh); }continue ; }
@@ -380,8 +378,11 @@ int ocfs2_read_blocks(struct ocfs2_caching_info *ci, u64 block, int nr,BUG_ON (buffer_jbd (bh));clear_buffer_needs_validate (bh); status =validate (sb, bh); -if (status) +if (status) { +if (buffer_uptodate (bh)) +clear_buffer_uptodate (bh); goto read_failure; + } } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 490/1266 ocfs2: reject FITRIM ranges shorter than a cluster
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit ca1afd88f5eaaff9168e1466e5401385edf59543 ]
ocfs2_trim_mainbm() trims the global bitmap in cluster units, but its too-short range validation only checks sb->s_blocksize.
On filesystems with a cluster size larger than the block size, a FITRIM range that is at least one block but shorter than one cluster is accepted and shifted down to len == 0. The later start + len - 1 and len -= ... arithmetic then underflows and can drive trimming past the requested range.
Reject ranges shorter than s_clustersize instead. That preserves the existing -EINVAL behavior for requests that cannot discard even one allocation unit and keeps zero-cluster trims out of the group walk.
--- fs/ocfs2/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/alloc.c +1 -1
@@ -7546,7 +7546,7 @@ int ocfs2_trim_mainbm(struct super_block *sb, struct fstrim_range *range) len = range->len >> osb->s_clustersize_bits; minlen = range->minlen >> osb->s_clustersize_bits; -if (minlen >= osb->bitmap_cpg || range->len < sb->s_blocksize) +if (minlen >= osb->bitmap_cpg || range->len < osb->s_clustersize)return -EINVAL ;trace_ocfs2_trim_mainbm (start, len, minlen);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 491/1266 ocfs2/dlm: require a ref for locking_state debugfs open
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
[ Upstream commit 03ad858ce8064861ea580021976dc19b7aabb549 ]
debug_lockres_open() copies inode->i_private into struct debug_lockres and debug_lockres_release() later drops that pointer with dlm_put(). That only works if open successfully pins the struct dlm_ctxt.
Today open calls dlm_grab(dlm) but ignores its return value. Once the last domain unregister has removed the context from dlm_domains, dlm_grab() returns NULL, yet open still stores the raw pointer and returns success. The later release path is outside the debugfs removal barrier, so it can call dlm_put() after dlm_free_ctxt_mem() has freed the context. KASAN reports this as a slab-use-after-free in dlm_put() called from debug_lockres_release().
Fail the open when dlm_grab() cannot acquire the reference and unwind the seq_file private state before returning. That keeps locking_state from handing out a file descriptor whose release path does not own the dlm_ctxt.
The buggy scenario involves two paths, with each column showing the order within that path:
locking_state debugfs open: last domain unregister:
1. debug_lockres_open() reads 1. dlm_unregister_domain() calls
inode->i_private. dlm_complete_dlm_shutdown().
2. debug_lockres_open() calls 2. shutdown removes the dlm_ctxt from
dlm_grab(dlm) and gets NULL. dlm_domains.
3. open still stores the raw dlm 3. final teardown reaches
pointer in dl->dl_ctxt and dlm_free_ctxt_mem() and frees it.
returns success.
4. debug_lockres_release() later
calls dlm_put(dl->dl_ctxt).
Validation reproduced this kernel report:
KASAN slab-use-after-free in dlm_put+0x82/0x200
RIP: 0033:0x7f4d349bc9e0 The buggy address belongs to the object at ffff888103a3c000 which belongs to the cache kmalloc-2k of size 2048 The buggy address is located 816 bytes inside of freed 2048-byte region [ffff888103a3c000, ffff888103a3c800) Write of size 4 Call trace: dump_stack_lvl+0x66/0xa0 (?:?) print_report+0xd0/0x630 (?:?) dlm_put+0x82/0x200 (?:?) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x188/0x2f0 (?:?) kasan_report+0xe4/0x120 (?:?) kasan_check_range+0x105/0x1b0 (?:?) debug_lockres_release+0x53/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) dlm_put+0x9/0x200 (?:?) debug_lockres_release+0x5c/0x80 (fs/ocfs2/dlm/dlmdebug.c:587) full_proxy_release+0x67/0x90 (?:?) __fput+0x1df/0x4b0 (?:?) do_raw_spin_lock+0x10f/0x1b0 (?:?) fput_close_sync+0xd2/0x170 (?:?) __x64_sys_close+0x55/0x90 (?:?) do_syscall_64+0x10c/0x640 (arch/x86/entry/syscall_64.c:87) irqentry_exit+0xac/0x6e0 (?:?) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?) Freed by task stack: kasan_save_stack+0x33/0x60 (?:?) kasan_save_track+0x14/0x30 (?:?) kasan_save_free_info+0x3b/0x60 (?:?) __kasan_slab_free+0x5f/0x80 (?:?) kfree+0x30f/0x580 (?:?) dlm_put+0x1ce/0x200 (?:?) dlm_unregister_domain+0xf6/0xb30 (?:?) o2cb_cluster_disconnect+0x6b/0x90 (?:?) ocfs2_cluster_disconnect+0x41/0x70 (?:?) ocfs2_dlm_shutdown+0x1c4/0x220 (?:?) ocfs2_dismount_volume+0x38a/0x550 (?:?) generic_shutdown_super+0xc3/0x220 (?:?) kill_block_super+0x29/0x60 (?:?) deactivate_locked_super+0x66/0xe0 (?:?) cleanup_mnt+0x13d/0x210 (?:?) task_work_run+0xfa/0x170 (?:?) exit_to_user_mode_loop+0xd6/0x430 (?:?) do_syscall_64+0x3cb/0x640 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
--- fs/ocfs2/dlm/dlmdebug.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
fs/ocfs2/dlm/dlmdebug.c +12 -4
@@ -612,6 +612,7 @@ static int debug_lockres_open(struct inode *inode, struct file *file)struct dlm_ctxt *dlm = inode->i_private;struct debug_lockres *dl;void *buf; +int status = -ENOMEM ; buf =kmalloc (PAGE_SIZE ,GFP_KERNEL );if (!buf)
@@ -624,16 +625,23 @@ static int debug_lockres_open(struct inode *inode, struct file *file) dl->dl_len =PAGE_SIZE ; dl->dl_buf = buf; -dlm_grab (dlm); - dl->dl_ctxt = dlm; +/* ->release uses dl_ctxt after open, so it needs a real pin. */ + dl->dl_ctxt =dlm_grab (dlm); +if (!dl->dl_ctxt) { + status = -ENOENT ; + goto bailseq; + }return 0 ; +bailseq: +seq_release_private (inode, file); bailfree:kfree (buf); bail: -mlog_errno (-ENOMEM ); -return -ENOMEM ; +if (status != -ENOENT ) +mlog_errno (status); +return status; }static int debug_lockres_release (struct inode *inode,struct file *file)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 492/1266 ocfs2: fix race between ocfs2_control_install_private() and ocfs2_control_release()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Qi <[email protected]>
[ Upstream commit 57dcfd9049d497c31151787a0696d59f0a98f8e6 ]
Move atomic_inc(&ocfs2_control_opened) and the handshake state update inside ocfs2_control_lock to close a race window where ocfs2_control_release() can observe ocfs2_control_opened dropping to zero (resetting ocfs2_control_this_node and running_proto) while ocfs2_control_install_private() is about to bump the counter and mark the connection valid.
--- fs/ocfs2/stack_user.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-)
fs/ocfs2/stack_user.c +3 -7
@@ -327,18 +327,14 @@ static int ocfs2_control_install_private(struct file *file) ocfs2_control_this_node = p->op_this_node; running_proto.pv_major = p->op_proto.pv_major; running_proto.pv_minor = p->op_proto.pv_minor; - } - -out_unlock: -mutex_unlock (&ocfs2_control_lock); - -if (!rc && set_p) { -/* We set the global values successfully */ atomic_inc (&ocfs2_control_opened);ocfs2_control_set_handshake_state (file,OCFS2_CONTROL_HANDSHAKE_VALID ); } +out_unlock: +mutex_unlock (&ocfs2_control_lock); +return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 493/1266 netfilter: nfnetlink_osf: fix mss parsing on big-endian architectures
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit a625c94144c9b66d32e1f374f909f38db46161c1 ]
The MSS calculation in nf_osf_match_one() manually shifts bytes to construct a 16-bit value before passing it to ntohs().
This works on little-endian hosts but it does not work on big-endian as the bytes are being always shifted and set in the same way for all architectures.
Use get_unaligned_be16() to fix this on big-endian systems. It also simplifies the code.
--- net/netfilter/nfnetlink_osf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
net/netfilter/nfnetlink_osf.c +1 -5
@@ -95,11 +95,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,switch (*optp) {case OSFOPT_MSS : - mss = optp[3 ]; - mss <<=8 ; - mss |= optp[2 ]; - - mss =ntohs ((__force __be16 )mss); + mss =get_unaligned_be16 (&optp[2 ]);break ;case OSFOPT_TS :break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 494/1266 netfilter: synproxy: protect nf_ct_seqadj_init() with conntrack lock
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit 9e37388b8070afe73d4ab2d973b28593ed65f3ad ]
nf_ct_seqadj_init() is called without holding the ct lock. This can race with nf_ct_seq_adjust() when a connection is in CLOSE state due to an RST or connection reopening. In addition for SYN_RECV state, concurrent processing of packets can trigger nf_ct_seq_adjust() too. These situations create a read/write data race.
As synproxy is the only user of nf_ct_seqadj_init() at the moment, fix this by holding ct->lock inside nf_ct_seqadj_init() until all is done.
--- net/netfilter/nf_conntrack_seqadj.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nf_conntrack_seqadj.c +2 -0
@@ -17,12 +17,14 @@ int nf_ct_seqadj_init(struct nf_conn *ct, enum ip_conntrack_info ctinfo,if (off ==0 )return 0 ; +spin_lock_bh (&ct->lock);set_bit (IPS_SEQ_ADJUST_BIT , &ct->status); seqadj =nfct_seqadj (ct); this_way = &seqadj->seq[dir]; this_way->offset_before = off; this_way->offset_after = off; +spin_unlock_bh (&ct->lock);return 0 ; }EXPORT_SYMBOL_GPL (nf_ct_seqadj_init);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 495/1266 netfilter: conntrack: revert ct extension genid infrastructure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 35e21a4dccc5c255ba59ccfbfeb4629ed21da972 ]
This infrastructure is not used anymore after moving ct timeout and helper to use datapath refcount to track object use.
Revert commit c56716c69ce1 ("netfilter: extensions: introduce extension genid count") this patch disables all ct extensions (leading to NULL) for unconfirmed conntracks, when this is only targeted at ct helper and ct timeout. There is also codebase that dereferences the ct extension without checking for NULL which could lead to crash.
--- include/net/netfilter/nf_conntrack_extend.h | 12 ---- net/netfilter/nf_conntrack_core.c | 61 +-------------------- net/netfilter/nf_conntrack_extend.c | 32 +---------- 3 files changed, 2 insertions(+), 103 deletions(-)
include/net/netfilter/nf_conntrack_extend.h +0 -12
@@ -38,7 +38,6 @@ enum nf_ct_ext_id {struct nf_ct_ext {u8 offset[NF_CT_EXT_NUM ];u8 len; -unsigned int gen_id;char data[]__aligned(8) ; };
@@ -52,8 +51,6 @@ static inline bool nf_ct_ext_exist(const struct nf_conn *ct, u8 id)return (ct->ext &&__nf_ct_ext_exist (ct->ext, id)); } -void *__nf_ct_ext_find (const struct nf_ct_ext *ext,u8 id); -static inline void *nf_ct_ext_find (const struct nf_conn *ct,u8 id) {struct nf_ct_ext *ext = ct->ext;
@@ -61,19 +58,10 @@ static inline void *nf_ct_ext_find(const struct nf_conn *ct, u8 id)if (!ext || !__nf_ct_ext_exist (ext, id))return NULL ; -if (unlikely (ext->gen_id)) -return __nf_ct_ext_find (ext, id); - return (void *)ct->ext + ct->ext->offset[id]; }/* Add this type, returns pointer to data or NULL. */ void *nf_ct_ext_add (struct nf_conn *ct,enum nf_ct_ext_id id,gfp_t gfp); -/* ext genid. if ext->id != ext_genid, extensions cannot be used -* anymore unless conntrack has CONFIRMED bit set. -*/ -extern atomic_t nf_conntrack_ext_genid; -void nf_ct_ext_bump_genid (void ); -#endif /* _NF_CONNTRACK_EXTEND_H */
net/netfilter/nf_conntrack_core.c +1 -60
101 lines not on this page · raw message
net/netfilter/nf_conntrack_extend.c +1 -31
@@ -27,8 +27,6 @@#define NF_CT_EXT_PREALLOC 128u/* conntrack events are on by default */ -atomic_t nf_conntrack_ext_genid__read_mostly =ATOMIC_INIT (1 ); -static const u8 nf_ct_ext_type_len[NF_CT_EXT_NUM ] = { [NF_CT_EXT_HELPER ] =sizeof (struct nf_conn_help ), #if IS_ENABLED(CONFIG_NF_NAT)
@@ -118,10 +116,8 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)if (!new)return NULL ; -if (!ct->ext) { +if (!ct->ext)memset (new->offset,0 ,sizeof (new->offset)); - new->gen_id =atomic_read (&nf_conntrack_ext_genid); - } new->offset[id] = newoff; new->len = newlen;
@@ -131,29 +127,3 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)return (void *)new + newoff; }EXPORT_SYMBOL (nf_ct_ext_add); - -/* Use nf_ct_ext_find wrapper. This is only useful for unconfirmed entries. */ -void *__nf_ct_ext_find (const struct nf_ct_ext *ext,u8 id) -{ -unsigned int gen_id =atomic_read (&nf_conntrack_ext_genid); -unsigned int this_id =READ_ONCE (ext->gen_id); - -if (!__nf_ct_ext_exist (ext, id)) -return NULL ; - -if (this_id ==0 || ext->gen_id == gen_id) -return (void *)ext + ext->offset[id]; - -return NULL ; -} -EXPORT_SYMBOL (__nf_ct_ext_find); - -void nf_ct_ext_bump_genid (void ) -{ -unsigned int value =atomic_inc_return (&nf_conntrack_ext_genid); - -if (value ==UINT_MAX ) -atomic_set (&nf_conntrack_ext_genid,1 ); - -msleep (HZ ); -}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 496/1266 netfilter: conntrack: call nf_ct_gre_keymap_destroy() if master helper is pptp
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit b0f02608fbcd607b5131cceb91fc0a035264e61c ]
For GRE flows, validate that the ct master helper (if any) is pptp before calling nf_ct_gre_keymap_destroy(), so the helper data area can be accessed safely. Note that only the pptp helper provides a .destroy callback.
--- net/netfilter/nf_conntrack_core.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
net/netfilter/nf_conntrack_core.c +16 -2
@@ -565,9 +565,23 @@ static void destroy_gre_conntrack(struct nf_conn *ct) {#ifdef CONFIG_NF_CT_PROTO_GRE struct nf_conn *master = ct->master; +struct nf_conn_help *help; + +if (!master) +return ; + + help =nfct_help (master); +if (help) { +struct nf_conntrack_helper *helper; -if (master) -nf_ct_gre_keymap_destroy (master); +rcu_read_lock (); + helper =rcu_dereference (help->helper); +/* Only pptp helper has a destroy callback. */ +if (helper && helper->destroy) +nf_ct_gre_keymap_destroy (master); + +rcu_read_unlock (); + }#endif }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 497/1266 IB/cm: Fix av cm device leak on an error path in cm_init_av_by_path()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 9b2207bc5cdb955bdae34b3eec80f04979e17081 ]
Codex pointed out that cm_init_av_by_path() can call cm_set_av_port() which takes a reference on the cm device, but then can immediately return error if ib_init_ah_attr_from_path() fails.
Since callers like ib_send_cm_req() put the av on the stack this leaks that cm device reference.
Re-order cm_init_av_by_path() so it doesn't touch the av until it has done all its failable work, and then update the av in one shot so it is either left alone or fully init'd.
Sashiko also pointed out that the cm_destroy_av() prior to cm_init_av_by_path() is harmful as it leaves the AV broken in the error case and thus the REJ won't send. Since cm_init_av_by_path() is now atomic it is safe to delete the cm_destroy_av(). On succees the av from cm_init_av_for_response() is cleaned up by cm_init_av_by_path(), on failure the 'goto rejected' guarentees the av is destroyed during ib_destroy_cm_id().
--- drivers/infiniband/core/cm.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/infiniband/core/cm.c +8 -5
@@ -514,6 +514,7 @@ static int cm_init_av_by_path(struct sa_path_rec *path,struct rdma_ah_attr new_ah_attr;struct cm_device *cm_dev;struct cm_port *port; +u16 pkey_index;int ret; port =get_cm_port_from_path (path, sgid_attr);
@@ -522,12 +523,10 @@ static int cm_init_av_by_path(struct sa_path_rec *path, cm_dev = port->cm_dev; ret =ib_find_cached_pkey (cm_dev->ib_device, port->port_num, -be16_to_cpu (path->pkey), &av->pkey_index); +be16_to_cpu (path->pkey), &pkey_index);if (ret)return ret; -cm_set_av_port (av, port); -/* * av->ah_attr might be initialized based on wc or during * request processing time which might have reference to sgid_attr.
@@ -542,6 +541,8 @@ static int cm_init_av_by_path(struct sa_path_rec *path,if (ret)return ret; + av->pkey_index = pkey_index; +cm_set_av_port (av, port); av->timeout = path->packet_life_time +1 ;rdma_move_ah_attr (&av->ah_attr, &new_ah_attr);return 0 ;
@@ -2169,8 +2170,10 @@ static int cm_req_handler(struct cm_work *work) cm_id_priv->av.ah_attr.roce.dmac); work->path[0 ].hop_limit = grh->hop_limit; -/* This destroy call is needed to pair with cm_init_av_for_response */ -cm_destroy_av (&cm_id_priv->av); +/* +* cm_init_av_by_path() will internally pair with the above +* cm_init_av_for_response() if it succeeds. +*/ ret =cm_init_av_by_path (&work->path[0 ], gid_attr, &cm_id_priv->av);if (ret) {int err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 498/1266 RDMA/irdma: Fix OOB read during CQ MR registration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 4385ddd654d90245eeb83b3cb539670ab5c85ba4 ]
Sashiko pointed out an unrelated bug during a previous patch:
https://sashiko.dev/#/patchset/20260512183852.614045-1-jmoroni%40google.com
This change fixes the bug by eliminating the cqmr->split field which was not being set properly and instead just checks the CQ resize feature flag directly.
The cqmr->split field essentially tracks whether IRDMA_FEATURE_CQ_RESIZE is set, but it was not being set until CQ creation time, which is _after_ CQ memory registration (the only other place where it is referenced).
As a result, it would always be false during MR registration and would therefore cause irdma_handle_q_mem to populate cqmr->shadow even for GEN_2 HW and beyond:
cqmr->shadow = (dma_addr_t)arr[req->cq_pages];
The issue is that for GEN_2 and beyond, req->cq_pages may be exactly equal to iwmr->page_cnt and therefore equal to the size of arr, which would cause an OOB read by one.
--- drivers/infiniband/hw/irdma/verbs.c | 4 ++-- drivers/infiniband/hw/irdma/verbs.h | 1 - 2 files changed, 2 insertions(+), 3 deletions(-)
drivers/infiniband/hw/irdma/verbs.c +2 -2
@@ -2133,7 +2133,6 @@ static int irdma_create_cq(struct ib_cq *ibcq, } cqmr_shadow = &iwpbl_shadow->cq_mr; info.shadow_area_pa = cqmr_shadow->cq_pbl.addr; - cqmr->split = true; }else { info.shadow_area_pa = cqmr->shadow; }
@@ -2509,7 +2508,8 @@ static int irdma_handle_q_mem(struct irdma_device *iwdev,case IRDMA_MEMREG_TYPE_CQ : hmc_p = &cqmr->cq_pbl; -if (!cqmr->split) +if (!(iwdev->rf->sc_dev.hw_attrs.uk_attrs.feature_flags & +IRDMA_FEATURE_CQ_RESIZE )) cqmr->shadow = (dma_addr_t )arr[req->cq_pages];if (lvl)
drivers/infiniband/hw/irdma/verbs.h +0 -1
@@ -62,7 +62,6 @@ struct irdma_hmc_pble {struct irdma_cq_mr {struct irdma_hmc_pble cq_pbl;dma_addr_t shadow; -bool split; };struct irdma_qp_mr {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 499/1266 RDMA/irdma: Initialize iwmr->access during MR registration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Moroni <[email protected]>
[ Upstream commit 1521d560b7a1a39e437d37fffd9b55435d329ad1 ]
Initialize iwmr->access during initial user mem registration so that it contains a valid value during a subsequent rereg_mr.
Otherwise, a rereg_mr that doesn't set IB_MR_REREG_ACCESS (for example, one that only changes the PD) ends up clearing the access flags in HW since iwmr->access is zero-initialized, which is not intended.
--- drivers/infiniband/hw/irdma/verbs.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/irdma/verbs.c +1 -0
@@ -2853,6 +2853,7 @@ static int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access,int err; lvl = iwmr->page_cnt !=1 ?PBLE_LEVEL_1 |PBLE_LEVEL_2 :PBLE_LEVEL_0 ; + iwmr->access = access; err =irdma_setup_pbles (iwdev->rf, iwmr, lvl);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 500/1266 arm64: dts: tqma8mpql-mba8mpxl: configure sai clock in audio codec as well
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Stein <[email protected]>
[ Upstream commit 748835fcb2eb2120234aef9556d282272501b96b ]
With deferrable card binding the sound card driver tries to get the mclk configuration before it is setup in sai3 node. Fix this by setting the sai clock config for the audio codec as well.
--- arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts | 3 +++ 1 file changed, 3 insertions(+)
arch/arm64/boot/dts/freescale/imx8mp-tqma8mpql-mba8mpxl.dts +3 -0
@@ -473,6 +473,9 @@ tlv320aic3x04: audio-codec@18 { reset-gpios = <&gpio4 29 GPIO_ACTIVE_LOW>; iov-supply = <®_vcc_1v8>; ldoin-supply = <®_vcc_3v3>; + assigned-clocks = <&clk IMX8MP_CLK_SAI3>; + assigned-clock-parents = <&clk IMX8MP_AUDIO_PLL1_OUT>; + assigned-clock-rates = <12288000>; }; se97_1c: temperature-sensor@1c {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 501/1266 bpf: Check tail zero of bpf_prog_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 786be2b05980a5828e67fc564ad7517e2adbe9bd ]
Since there're 4 bytes padding at the end of struct bpf_prog_info, they won't be checked by bpf_check_uarg_tail_zero().
pahole -C bpf_prog_info ./vmlinux
struct bpf_prog_info {
...
__u32 attach_btf_obj_id; /* 220 4 */
__u32 attach_btf_id; /* 224 4 */
/* size: 232, cachelines: 4, members: 38 */
/* sum members: 224 */
/* sum bitfield members: 1 bits, bit holes: 1, sum bit holes: 31 bits */
/* padding: 4 */
/* forced alignments: 9 */
/* last cacheline: 40 bytes */
} __attribute__((__aligned__(8)));If a future kernel extension adds a new 4-byte field, older userspace programs allocating this structure on the stack might inadvertently pass uninitialized stack garbage into the new field, permanently breaking backward compatibility. -- sashiko [1]
Fix it by changing sizeof(info) tooffsetofend(struct bpf_prog_info, attach_btf_id).
And, add "__u32 :32" to the tail of struct bpf_prog_info.
[1] https://lore.kernel.org/bpf/[email protected]/
--- include/uapi/linux/bpf.h | 1 + kernel/bpf/syscall.c | 5 +++-- tools/include/uapi/linux/bpf.h | 1 + 3 files changed, 5 insertions(+), 2 deletions(-)
include/uapi/linux/bpf.h +1 -0
@@ -6460,6 +6460,7 @@ struct bpf_prog_info {__u32 verified_insns;__u32 attach_btf_obj_id;__u32 attach_btf_id; + __u32 :32 ; } __attribute__((aligned(8)));struct bpf_map_info {
kernel/bpf/syscall.c +3 -2
@@ -4403,10 +4403,11 @@ static int bpf_prog_get_info_by_fd(struct file *file,u32 info_len = attr->info.info_len;struct bpf_prog_kstats stats;char __user *uinsns; -u32 ulen; +u32 ulen, len;int err; - err =bpf_check_uarg_tail_zero (USER_BPFPTR (uinfo),sizeof (info), info_len); + len = offsetofend(struct bpf_prog_info, attach_btf_id); + err =bpf_check_uarg_tail_zero (USER_BPFPTR (uinfo), len, info_len);if (err)return err; info_len =min_t (u32,sizeof (info), info_len);
tools/include/uapi/linux/bpf.h +1 -0
@@ -6463,6 +6463,7 @@ struct bpf_prog_info {__u32 verified_insns;__u32 attach_btf_obj_id;__u32 attach_btf_id; + __u32 :32 ; } __attribute__((aligned(8)));struct bpf_map_info {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 502/1266 bpf: Update transport_header when encapsulating UDP tunnel in lwt
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit 82d7d0adbc678064543e9d254864f6b4ea4a388c ]
Currently, bpf_lwt_push_ip_encap() does not update skb->transport_header. When a driver, e.g. ice, reuses the stale skb->transport_header to offload checksum computation to NIC hardware, VxLAN packets encapsulated by bpf_lwt_push_encap() helper may be dropped due to incorrect checksum.
Update skb->transport_header in bpf_lwt_push_ip_encap() whenever the encapsulated packet uses UDP, so checksum offload works correctly.
--- net/core/lwt_bpf.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
net/core/lwt_bpf.c +12 -0
@@ -590,6 +590,7 @@ static int handle_gso_encap(struct sk_buff *skb, bool ipv4, int encap_len)int bpf_lwt_push_ip_encap (struct sk_buff *skb,void *hdr,u32 len,bool ingress) { +bool is_udp_tunnel;struct iphdr *iph;bool ipv4;int err;
@@ -603,10 +604,16 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress) ipv4 = true;if (unlikely (len < iph->ihl *4 ))return -EINVAL ; + is_udp_tunnel = iph->protocol ==IPPROTO_UDP ; +if (unlikely (is_udp_tunnel && len < iph->ihl *4 +sizeof (struct udphdr ))) +return -EINVAL ; }else if (iph->version ==6 ) { ipv4 = false;if (unlikely (len <sizeof (struct ipv6hdr )))return -EINVAL ; + is_udp_tunnel = ((struct ipv6hdr *)iph)->nexthdr ==NEXTHDR_UDP ; +if (unlikely (is_udp_tunnel && len <sizeof (struct ipv6hdr ) +sizeof (struct udphdr ))) +return -EINVAL ; }else {return -EINVAL ; }
@@ -628,6 +635,11 @@ int bpf_lwt_push_ip_encap(struct sk_buff *skb, void *hdr, u32 len, bool ingress)if (ingress)skb_postpush_rcsum (skb, iph, len);skb_reset_network_header (skb); +if (is_udp_tunnel) { +size_t iph_sz = ipv4 ? iph->ihl *4 :sizeof (struct ipv6hdr ); + +skb_set_transport_header (skb,skb_network_offset (skb) + iph_sz); + }memcpy (skb_network_header (skb), hdr, len);bpf_compute_data_pointers (skb);skb_clear_hash (skb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 503/1266 wifi: wcn36xx: fix heap overflow from oversized firmware HAL response
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 88a240d86d3d64521f9194abe185ac71cc74d0bd ]
The firmware response dispatcher copies all synchronous HAL responses into the 4096-byte hal_buf without validating the response length. A response exceeding WCN36XX_HAL_BUF_SIZE causes a heap buffer overflow with firmware-controlled content.
Add a bounds check on the response length.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +4 -0
@@ -3353,6 +3353,10 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev,case WCN36XX_HAL_EXIT_IMPS_RSP :case WCN36XX_HAL_UPDATE_CHANNEL_LIST_RSP :case WCN36XX_HAL_ADD_BCN_FILTER_RSP : +if (len >WCN36XX_HAL_BUF_SIZE ) { +wcn36xx_warn ("HAL response too large: %d\n" , len); +break ; + }memcpy (wcn->hal_buf, buf, len); wcn->hal_rsp_len = len;complete (&wcn->hal_rsp_compl);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 504/1266 wifi: wcn36xx: fix OOB read from firmware count in PRINT_REG_INFO indication
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit df2187acfca6c6cca372c5d35f42394d9c270b09 ]
The firmware-controlled rsp->count field is used as the loop bound for indexing into the flexible rsp->regs[] array without validation against the message length. A count exceeding the actual data causes out-of- bounds reads from the heap-allocated message buffer.
Add a check that count fits within the received message.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +6 -0
@@ -2865,6 +2865,12 @@ static int wcn36xx_smd_print_reg_info_ind(struct wcn36xx *wcn,return -EIO ; } +if (rsp->count > (len -sizeof (*rsp)) /sizeof (rsp->regs[0 ])) { +wcn36xx_warn ("Truncated print reg info indication: count %u, len %zu\n" , + rsp->count, len); +return -EIO ; + } +wcn36xx_dbg (WCN36XX_DBG_HAL ,"reginfo indication, scenario: 0x%x reason: 0x%x\n" , rsp->scenario, rsp->reason);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 505/1266 wifi: wcn36xx: fix OOB read from short trigger BA firmware response
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit b5e6f21923ca89d90256e7346301056f6502691e ]
The firmware response length is only checked against sizeof(*rsp) (20 bytes), but when candidate_cnt >= 1, a 22-byte candidate struct is read at buf + 20 without verifying the response contains it. This causes an out-of-bounds read of stale heap data, corrupting the BA session state.
Add validation that the response includes the candidate data.
--- drivers/net/wireless/ath/wcn36xx/smd.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/ath/wcn36xx/smd.c +3 -0
@@ -2659,6 +2659,9 @@ static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *baif (rsp->candidate_cnt <1 )return rsp->status ? rsp->status : -EINVAL ; +if (len <sizeof (*rsp) +sizeof (*candidate)) +return -EINVAL ; + candidate = (struct wcn36xx_hal_trigger_ba_rsp_candidate *)(buf +sizeof (*rsp));for (i =0 ; i <STACFG_MAX_TC ; i++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 506/1266 ALSA: seq: Fix partial userptr event expansion
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 2b7bd6f548292aec92a386deebe62324d21d62a9 ]
snd_seq_expand_var_event_at() clamps the number of bytes to copy to the remaining variable-event length, but passes the original buffer size to expand_var_event().
For SNDRV_SEQ_EXT_USRPTR events, expand_var_event() copies exactly the size argument from userspace. On the final chunk, when the remaining event data is shorter than the caller's buffer, this can read past the declared event data and can spuriously fail with -EFAULT if the extra bytes cross an unmapped page.
Pass the clamped length instead. The chained and kernel-backed paths already reclamp in dump_var_event(), but the user-pointer path handles the size directly.
--- sound/core/seq/seq_memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/core/seq/seq_memory.c +1 -1
@@ -211,7 +211,7 @@ int snd_seq_expand_var_event_at(const struct snd_seq_event *event, int count, len -= offset;if (len > count) len = count; - err =expand_var_event (event, offset, count, buf, true); + err =expand_var_event (event, offset, len, buf, true);if (err <0 )return err;return len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 507/1266 riscv: stacktrace: Remove bogus -0x4 offset in non-FP walk_stackframe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rui Qi <[email protected]>
[ Upstream commit 8ac35bac70e7e581d673b76878f7691cdadc33b8 ]
In the non-frame-pointer version of walk_stackframe, each value read from the stack is treated as a potential return address and has 0x4 subtracted before being used as the program counter. This was intended to convert the return address (the instruction after a call) back to the call site, but it is incorrect:
1. RISC-V has variable-length instructions due to the RVC (compressed instruction) extension. A call instruction can be either 4 bytes (regular) or 2 bytes (compressed, e.g. c.jal). Subtracting a fixed 0x4 assumes all call instructions are 4 bytes, which is wrong for compressed instructions.
2. Stack traces conventionally report return addresses, not call sites. Other architectures (ARM64, x86, ARM) do not subtract instruction size from return addresses in their stack unwinding code.
3. The frame-pointer version of walk_stackframe already dropped the -0x4 offset. Commit b785ec129bd9 ("riscv/ftrace: Add HAVE_FUNCTION_GRAPH_RET_ADDR_PTR support") replaced "pc = frame->ra - 0x4" with ftrace_graph_ret_addr(), and the commit message explicitly noted that "the original calculation, pc = frame->ra - 4, is buggy when the instruction at the return address happened to be a compressed inst." The non-FP version was simply overlooked.
Remove the bogus -0x4 offset to match the FP version and the conventions used by other architectures.
--- arch/riscv/kernel/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/kernel/stacktrace.c +1 -1
@@ -129,7 +129,7 @@ void notrace walk_stackframe(struct task_struct *task,while (!kstack_end (ksp)) {if (__kernel_text_address (pc) &&unlikely (!fn (arg, pc)))break ; - pc =READ_ONCE_NOCHECK (*ksp++) -0x4 ; + pc =READ_ONCE_NOCHECK (*ksp++); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 508/1266 ALSA: seq: Clear variable event pointer on read
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit 705dd6dcbc0ea87351c660c1a6443f85f1001c76 ]
snd_seq_read() copies a queued variable-length event header to userspace before expanding the payload. Queued variable-length events use SNDRV_SEQ_EXT_CHAINED internally, and data.ext.ptr points at the first extension cell.
The read side strips SNDRV_SEQ_EXT_* bits from data.ext.len before the copy, but it leaves data.ext.ptr untouched. A userspace sequencer client can therefore write a direct variable event to itself and read back the extension-cell kernel address from the returned header.
Clear the temporary header pointer before copy_to_user(). The original queued event remains unchanged and is still passed to snd_seq_expand_var_event(), so payload expansion keeps using the internal chain.
--- sound/core/seq/seq_clientmgr.c | 1 + 1 file changed, 1 insertion(+)
sound/core/seq/seq_clientmgr.c +1 -0
@@ -488,6 +488,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,memcpy (&tmpev, &cell->event, aligned_size); tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK ; + tmpev.data.ext.ptr =NULL ;if (copy_to_user (buf, &tmpev, aligned_size)) { err = -EFAULT ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 509/1266 ACPI: IPMI: Fix message kref handling on dead device
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 63320db6a5d84ec3fed8b3d36ba5244d07ddd108 ]
acpi_ipmi_space_handler() takes an extra reference on tx_msg before checking whether the selected IPMI device is dead. The reference belongs to the tx_msg_list entry and is normally dropped by ipmi_cancel_tx_msg() or ipmi_flush_tx_msg() after the message is removed from the list.
On the dead-device path, the message has not been queued yet, but the error path still calls ipmi_msg_release() directly. That bypasses kref_put() and frees tx_msg while the queued-message reference is still recorded in the kref count.
Take the queued-message reference only after the dead-device check succeeds, immediately before adding tx_msg to the list.
--- drivers/acpi/acpi_ipmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/acpi_ipmi.c +1 -1
@@ -545,7 +545,6 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,return AE_TYPE ; } -acpi_ipmi_msg_get (tx_msg);mutex_lock (&driver_data.ipmi_lock);/* Do not add a tx_msg that can not be flushed. */ if (ipmi_device->dead) {
@@ -553,6 +552,7 @@ acpi_ipmi_space_handler(u32 function, acpi_physical_address address,ipmi_msg_release (tx_msg);return AE_NOT_EXIST ; } +acpi_ipmi_msg_get (tx_msg);spin_lock_irqsave (&ipmi_device->tx_msg_lock, flags);list_add_tail (&tx_msg->head, &ipmi_device->tx_msg_list);spin_unlock_irqrestore (&ipmi_device->tx_msg_lock, flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 510/1266 cpufreq: Documentation: fix conservative governor freq_step description
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengjie Zhang <[email protected]>
[ Upstream commit 03120e1425262c7d11f93362a88e579a1720390b ]
The conservative governor documentation incorrectly states that setting freq_step to 0 will use the default 5% frequency step. In reality, since at least commit 8e677ce83bf4 ("[CPUFREQ] conservative: fixup governor to function more like ondemand logic"), freq_step=0 has always caused the governor to skip frequency updates entirely.
Correct the documentation to reflect the actual behavior: freq_step=0 disables frequency changes by the governor entirely.
--- Documentation/admin-guide/pm/cpufreq.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/admin-guide/pm/cpufreq.rst +2 -2
@@ -569,8 +569,8 @@ This governor exposes the following tunables: 100 (5 by default). This is how much the frequency is allowed to change in one go. Setting - it to 0 will cause the default frequency step (5 percent) to be used - and setting it to 100 effectively causes the governor to periodically + it to 0 disables frequency changes by the governor entirely and setting + it to 100 effectively causes the governor to periodically switch the frequency between the ``scaling_min_freq`` and ``scaling_max_freq`` policy limits.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 511/1266 IB/mlx5: Dont take the rereg_mr fallback without a new translation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit 55d339d200c908de83a408d023cfb7be779b0dd7 ]
Jumping to mlx5_ib_reg_user_mr() without IB_MR_REREG_TRANS set will use garbage values for start, length, and iova. Recovering the original mr parameters for ODP and DMABUF to properly recreate it is too hard in this flow, so just fail it.
--- drivers/infiniband/hw/mlx5/mr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/hw/mlx5/mr.c +1 -1
@@ -1721,7 +1721,7 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start, }/* DM or ODP MR's don't have a normal umem so we can't re-use it */ if (!mr->umem ||is_odp_mr (mr) ||is_dmabuf_mr (mr)) - goto recreate; +return ERR_PTR (-EOPNOTSUPP );/* * Only one active MR can refer to a umem at one time, revoke
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 512/1266 IB/mlx5: Properly support implicit ODP rereg_mr
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit ee7a8335069150c3f1893a697ab30bbeca00d796 ]
Due to all the child mkeys in the implicit ODP configuration we cannot change anything in place for the parent mkey. Instead the whole thing needs to be rebuilt if any change is requested. If the user does not specify a translation then force the implicit values which will then fall through the logic into mlx5_ib_reg_user_mr() to allocate a completely new MR.
Since implicit children were also touching the mr->pd, this removes another case where the access was racy.
--- drivers/infiniband/hw/mlx5/mr.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/infiniband/hw/mlx5/mr.c +15 -0
@@ -1707,6 +1707,21 @@ struct ib_mr *mlx5_ib_rereg_user_mr(struct ib_mr *ib_mr, int flags, u64 start,if (!(flags &IB_MR_REREG_PD )) new_pd = ib_mr->pd; +if (mr->is_odp_implicit && !(flags &IB_MR_REREG_TRANS )) { +if (!(new_access_flags &IB_ACCESS_ON_DEMAND )) +return ERR_PTR (-EOPNOTSUPP ); + +/* +* Due to all the child mkeys we cannot actually change an +* implicit MR in place. If the user did not specify a new +* translation then force the fixed implicit MR values. +*/ + start =0 ; + iova =0 ; + length =U64_MAX ; + flags |=IB_MR_REREG_TRANS ; + } +if (!(flags &IB_MR_REREG_TRANS )) {struct ib_umem *umem;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 513/1266 spi: ep93xx: fix double-free of zeropage on DMA setup failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 7886054b06f762f62054957a8f6de0f14e6b7541 ]
If DMA setup fails after allocating the zeropage, the error path frees the page but leaves espi->zeropage dangling. A subsequent call to ep93xx_spi_release_dma() sees the non-NULL pointer and frees the page again.
Clear the pointer after freeing in the error path of ep93xx_spi_setup_dma().
--- drivers/spi/spi-ep93xx.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-ep93xx.c +1 -0
@@ -625,6 +625,7 @@ static int ep93xx_spi_setup_dma(struct ep93xx_spi *espi) espi->dma_rx =NULL ; fail_free_page:free_page ((unsigned long )espi->zeropage); + espi->zeropage =NULL ;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 514/1266 firmware_loader: Fix recursive lock in device_cache_fw_images()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Vyukov <[email protected]>
[ Upstream commit d3ec78f8f8d48a04a9fac38d47275c34645e5103 ]
A recursive locking deadlock can occur in the firmware loader's power management notification handler.
During system suspend or hibernation preparation, fw_pm_notify() calls device_cache_fw_images(). This function acquires fw_lock to set the firmware cache state to FW_LOADER_START_CACHE and then iterates over all devices using dpm_for_each_dev() while still holding the lock.
For each device, dev_cache_fw_image() schedules asynchronous work to cache the firmware. If memory allocation for the async work entry fails (e.g., in out-of-memory conditions), async_schedule_node_domain() falls back to executing the work function synchronously in the current thread.
The synchronous execution path (__async_dev_cache_fw_image() -> cache_firmware() -> request_firmware() -> assign_fw()) attempts to acquire fw_lock again. Since the current thread already holds fw_lock, this results in a recursive locking deadlock.
Fix this by releasing fw_lock immediately after updating the cache state and before calling dpm_for_each_dev(). The lock is only needed to protect the state update. Concurrent firmware requests will correctly see the FW_LOADER_START_CACHE state and use the piggyback mechanism, which is independently protected by its own fwc->name_lock.
--- drivers/base/firmware_loader/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/base/firmware_loader/main.c +2 -1
@@ -1506,9 +1506,10 @@ static void device_cache_fw_images(void)mutex_lock (&fw_lock); fwc->state =FW_LOADER_START_CACHE ; -dpm_for_each_dev (NULL , dev_cache_fw_image);mutex_unlock (&fw_lock); +dpm_for_each_dev (NULL , dev_cache_fw_image); +/* wait for completion of caching firmware for all devices */ async_synchronize_full_domain (&fw_cache_domain);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 515/1266 configfs: fix lockless traversals of ->s_children
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
[ Upstream commit 9b9e8bb81c41fd27e7b57a1c936fde140548535f ]
Having the parent directory locked protects entries from removal by another thread, but it does *not* protect cursors from being moved around by lseek() - or freed, for that matter.
--- fs/configfs/dir.c | 54 +++++++++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 13 deletions(-)
fs/configfs/dir.c +41 -13
@@ -225,15 +225,16 @@ static int configfs_dirent_exists(struct configfs_dirent *parent_sd, {struct configfs_dirent * sd; +spin_lock (&configfs_dirent_lock);list_for_each_entry (sd, &parent_sd->s_children, s_sibling) {if (sd->s_element) { -const unsigned char *existing =configfs_get_name (sd); -if (strcmp (existing, new)) -continue ; -else +if (strcmp (configfs_get_name (sd), new) ==0 ) { +spin_unlock (&configfs_dirent_lock);return -EEXIST ; + } } } +spin_unlock (&configfs_dirent_lock);return 0 ; }
@@ -551,11 +552,28 @@ static void configfs_detach_rollback(struct dentry *dentry)configfs_detach_rollback (sd->s_dentry); } +/* +* Find the next non-cursor. configfs_dirent_lock held by caller. +*/ +static struct configfs_dirent *next_dirent (struct configfs_dirent *parent, +struct configfs_dirent *last) +{ +struct configfs_dirent *s; + + s =list_prepare_entry (last, &parent->s_children, s_sibling); + +list_for_each_entry_continue (s, &parent->s_children, s_sibling) { +if (s->s_element) +return s; + } +return NULL ; +} +static void detach_attrs (struct config_item * item) {struct dentry * dentry =dget (item->ci_dentry); -struct configfs_dirent * parent_sd; -struct configfs_dirent * sd, * tmp; +struct configfs_dirent *parent_sd; +struct configfs_dirent *sd, *next;if (!dentry)return ;
@@ -564,15 +582,19 @@ static void detach_attrs(struct config_item * item) dentry->d_name.name); parent_sd = dentry->d_fsdata; -list_for_each_entry_safe (sd, tmp, &parent_sd->s_children, s_sibling) { -if (!sd->s_element || !(sd->s_type &CONFIGFS_NOT_PINNED )) + +spin_lock (&configfs_dirent_lock); +for (sd =next_dirent (parent_sd,NULL ); sd; sd = next) { + next =next_dirent (parent_sd, sd); +if (!(sd->s_type &CONFIGFS_NOT_PINNED ))continue ; -spin_lock (&configfs_dirent_lock);list_del_init (&sd->s_sibling);spin_unlock (&configfs_dirent_lock);configfs_drop_dentry (sd, dentry);configfs_put (sd); +spin_lock (&configfs_dirent_lock); } +spin_unlock (&configfs_dirent_lock);/** * Drop reference from dget() on entrance.
@@ -621,18 +643,20 @@ static void detach_groups(struct config_group *group)struct dentry * dentry =dget (group->cg_item.ci_dentry);struct dentry *child;struct configfs_dirent *parent_sd; -struct configfs_dirent *sd, *tmp; +struct configfs_dirent *sd, *next;if (!dentry)return ; parent_sd = dentry->d_fsdata; -list_for_each_entry_safe (sd, tmp, &parent_sd->s_children, s_sibling) { -if (!sd->s_element || - !(sd->s_type &CONFIGFS_USET_DEFAULT )) +spin_lock (&configfs_dirent_lock); +for (sd =next_dirent (parent_sd,NULL ); sd; sd = next) { + next =next_dirent (parent_sd, sd); +if (!(sd->s_type &CONFIGFS_USET_DEFAULT ))continue ; child = sd->s_dentry; +spin_unlock (&configfs_dirent_lock);inode_lock (d_inode (child));
@@ -644,7 +668,9 @@ static void detach_groups(struct config_group *group)d_delete (child);dput (child); +spin_lock (&configfs_dirent_lock); } +spin_unlock (&configfs_dirent_lock);/** * Drop reference from dget() on entrance.
@@ -1096,6 +1122,7 @@ configfs_find_subsys_dentry(struct configfs_dirent *root_sd,struct configfs_dirent *p;struct configfs_dirent *ret =NULL ; +spin_lock (&configfs_dirent_lock);list_for_each_entry (p, &root_sd->s_children, s_sibling) {if (p->s_type &CONFIGFS_DIR && p->s_element == subsys_item) {
@@ -1103,6 +1130,7 @@ configfs_find_subsys_dentry(struct configfs_dirent *root_sd,break ; } } +spin_unlock (&configfs_dirent_lock);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 516/1266 watchdog: unregister PM notifier on watchdog unregister
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit a298c7302ee9584a7a1ac1e8acbede8d98ab51a4 ]
watchdog_register_device() registers wdd->pm_nb when WDOG_NO_PING_ON_SUSPEND is set, but watchdog_unregister_device() does not remove it. This leaves an embedded notifier block on the PM notifier chain after the watchdog device has been unregistered.
A later suspend/resume notification can then call watchdog_pm_notifier() with a stale watchdog_device pointer, or at minimum after wdd->wd_data has been cleared by watchdog_dev_unregister().
Unregister the PM notifier before tearing down the watchdog device.
--- drivers/watchdog/watchdog_core.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/watchdog/watchdog_core.c +3 -0
@@ -381,6 +381,9 @@ static void __watchdog_unregister_device(struct watchdog_device *wdd)if (test_bit (WDOG_STOP_ON_REBOOT , &wdd->status))unregister_reboot_notifier (&wdd->reboot_nb); +if (test_bit (WDOG_NO_PING_ON_SUSPEND , &wdd->status)) +unregister_pm_notifier (&wdd->pm_nb); +watchdog_dev_unregister (wdd);ida_simple_remove (&watchdog_ida, wdd->id); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 517/1266 scsi: target: Fix hexadecimal CHAP_I handling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Disseldorp <[email protected]>
[ Upstream commit 7e161211f1dd5288b4ea802b30e70ef919ebc3da ]
A mutual CHAP handshake requires target processing of an initiator-sent CHAP_I identifier. The RFC 3720 specification states:
11.1.4. Challenge Handshake Authentication Protocol (CHAP)
...
CHAP_A=<A> CHAP_I=<I> CHAP_C=<C>
...
Where N, (A,A1,A2), I, C, and R are (correspondingly) the Name, Algorithm, Identifier, Challenge, and Response as defined in [RFC1994], N is a text string, A,A1,A2, and I are numbers
CHAP_I parsing currently calls extract_param(), which returns the @identifier string (stripped of any 0b/0B or 0x/0X prefix) and a @type which indicates DECIMAL, HEX, or BASE64 encoding (based on any stripped prefix).
Any HEX encoded CHAP_I string is further processed via:
ret = kstrtoul(&identifier[2], 0, &id);
This is incorrect for two reasons:
* The @identifier string has already been stripped of the 0x/0X prefix, so skipping the first two bytes omits part of the number.
* The kstrtoul() call specifies a base of 0, which will see &identifier[2] parsed as a decimal, unless a '0x' or (octal) '0' is erroneously present at that offset.
Fix this by passing the (zero-offset) identifier string to kstrtoul() along with a base=16 parameter. Also add an explicit error handler for BASE64 encoding.
Hex-encoded CHAP_I handling can be testing using the libiscsi EncodedI test linked below.
--- drivers/target/iscsi/iscsi_target_auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/target/iscsi/iscsi_target_auth.c +4 -2
@@ -437,9 +437,11 @@ static int chap_server_compute_hash( }if (type ==HEX ) - ret =kstrtoul (&identifier[2 ],0 , &id); + ret =kstrtoul (identifier,16 , &id); +else if (type ==DECIMAL ) + ret =kstrtoul (identifier,10 , &id);else - ret =kstrtoul (identifier,0 , &id); + ret = -EINVAL ;if (ret <0 ) {pr_err ("kstrtoul() failed for CHAP identifier: %d\n" , ret);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 518/1266 scsi: target: Remove tcm_loop target reset handling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Christie <[email protected]>
[ Upstream commit 7c08d430835a90414cd962e3a9602e5b002dee3b ]
tcm_loop_target_reset is supposed to handle all the LUNs on a target but it's only doing a TMR_LUN_RESET so only that one LUN is handled. This will cause us to return early while IOs to other LUNs are still hung in lower layers. This just removes the target reset handler for the driver because LIO doesn't support target resets and for the common case where this is run from the scsi-ml error hamdler we have already tried an abort and lun reset so waiting again is most likely useless.
--- drivers/target/loopback/tcm_loop.c | 64 ------------------------------ 1 file changed, 64 deletions(-)
drivers/target/loopback/tcm_loop.c +0 -64
@@ -268,69 +268,6 @@ static int tcm_loop_device_reset(struct scsi_cmnd *sc)return (ret ==TMR_FUNCTION_COMPLETE ) ?SUCCESS :FAILED ; } -static bool tcm_loop_flush_work_iter (struct request *rq,void *data) -{ -struct scsi_cmnd *sc =blk_mq_rq_to_pdu (rq); -struct tcm_loop_cmd *tl_cmd =scsi_cmd_priv (sc); -struct se_cmd *se_cmd = &tl_cmd->tl_se_cmd; - -flush_work (&se_cmd->work); -return true; -} - -static int tcm_loop_target_reset (struct scsi_cmnd *sc) -{ -struct tcm_loop_hba *tl_hba; -struct tcm_loop_tpg *tl_tpg; -struct Scsi_Host *sh = sc->device->host; -int ret; - -/* -* Locate the tcm_loop_hba_t pointer -*/ - tl_hba = *(struct tcm_loop_hba **)shost_priv (sh); -if (!tl_hba) { -pr_err ("Unable to perform device reset without active I_T Nexus\n" ); -return FAILED ; - } -/* -* Locate the tl_tpg pointer from TargetID in sc->device->id -*/ - tl_tpg = &tl_hba->tl_hba_tpgs[sc->device->id]; -if (!tl_tpg) -return FAILED ; - -/* -* Issue a LUN_RESET to drain all commands that the target core -* knows about. This handles commands not yet marked CMD_T_COMPLETE. -*/ - ret =tcm_loop_issue_tmr (tl_tpg, sc->device->lun,0 ,TMR_LUN_RESET ); -if (ret !=TMR_FUNCTION_COMPLETE ) -return FAILED ; - -/* -* Flush any deferred target core completion work that may still be -* queued. Commands that already had CMD_T_COMPLETE set before the TMR -* are skipped by the TMR drain, but their async completion work -* (transport_lun_remove_cmd → percpu_ref_put, release_cmd → scsi_done) -* may still be pending in target_completion_wq. -* -* The SCSI EH will reuse in-flight scsi_cmnd structures for recovery -* commands (e.g. TUR) immediately after this handler returns SUCCESS — -* if deferred work is still pending, the memset in queuecommand would -* zero the se_cmd while the work accesses it, leaking the LUN -* percpu_ref and hanging configfs unlink forever. -* -* Use blk_mq_tagset_busy_iter() to find all started requests and -* flush_work() on each — the same pattern used by mpi3mr, scsi_debug, -* and other SCSI drivers to drain outstanding commands during reset. -*/ -blk_mq_tagset_busy_iter (&sh->tag_set, tcm_loop_flush_work_iter,NULL ); - - tl_tpg->tl_transport_status =TCM_TRANSPORT_ONLINE ; -return SUCCESS ; -} -static const struct scsi_host_template tcm_loop_driver_template = { .show_info = tcm_loop_show_info, .proc_name ="tcm_loopback" ,
@@ -339,7 +276,6 @@ static const struct scsi_host_template tcm_loop_driver_template = { .change_queue_depth = scsi_change_queue_depth, .eh_abort_handler = tcm_loop_abort_task, .eh_device_reset_handler = tcm_loop_device_reset, - .eh_target_reset_handler = tcm_loop_target_reset, .this_id = -1, .sg_tablesize = 256, .max_sectors = 0xFFFF,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 519/1266 pinctrl: mediatek: mt8516: Fix Schmitt trigger register offset of pins 34-39
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Leonardo Scorcia <[email protected]>
[ Upstream commit 1c3044cab23a056ea28da47da1cdd667a39df0b8 ]
The correct Schmitt trigger register offset for pins 34-39 is 0xA00.
--- drivers/pinctrl/mediatek/pinctrl-mt8516.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-mt8516.c +1 -1
@@ -244,7 +244,7 @@ static const struct mtk_pin_ies_smt_set mt8516_smt_set[] = {MTK_PIN_IES_SMT_SPEC (24 ,25 ,0xA00 ,12 ),MTK_PIN_IES_SMT_SPEC (26 ,30 ,0xA00 ,0 ),MTK_PIN_IES_SMT_SPEC (31 ,33 ,0xA00 ,1 ), -MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA900 ,2 ), +MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA00 ,2 ),MTK_PIN_IES_SMT_SPEC (40 ,40 ,0xA10 ,11 ),MTK_PIN_IES_SMT_SPEC (41 ,43 ,0xA00 ,10 ), MTK_PIN_IES_SMT_SPEC(44, 47, 0xA00, 11),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 520/1266 pinctrl: mediatek: mt8167: Fix Schmitt trigger register offset of pins 34-39
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luca Leonardo Scorcia <[email protected]>
[ Upstream commit 439bc91d20188901dac698bed4921caac76d9074 ]
The correct Schmitt trigger register offset for pins 34-39 is 0xA00. Value was verified with SoC data sheet.
--- drivers/pinctrl/mediatek/pinctrl-mt8167.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-mt8167.c +1 -1
@@ -244,7 +244,7 @@ static const struct mtk_pin_ies_smt_set mt8167_smt_set[] = {MTK_PIN_IES_SMT_SPEC (24 ,25 ,0xA00 ,12 ),MTK_PIN_IES_SMT_SPEC (26 ,30 ,0xA00 ,0 ),MTK_PIN_IES_SMT_SPEC (31 ,33 ,0xA00 ,1 ), -MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA900 ,2 ), +MTK_PIN_IES_SMT_SPEC (34 ,39 ,0xA00 ,2 ),MTK_PIN_IES_SMT_SPEC (40 ,40 ,0xA10 ,11 ),MTK_PIN_IES_SMT_SPEC (41 ,43 ,0xA00 ,10 ), MTK_PIN_IES_SMT_SPEC(44, 47, 0xA00, 11),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 521/1266 vmalloc: fix NULL pointer dereference in is_vm_area_hugepages()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hui Zhu <[email protected]>
[ Upstream commit c55dd3b46c1208d6d2ea737a8aefef4aa4c70cb8 ]
find_vm_area() can return NULL if the given address is not a valid vmalloc area. Check the return value before dereferencing it to avoid a kernel crash.
--- include/linux/vmalloc.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
include/linux/vmalloc.h +3 -1
@@ -209,7 +209,9 @@ static inline bool is_vm_area_hugepages(const void *addr)* allocated in the vmalloc layer. */ #ifdef CONFIG_HAVE_ARCH_HUGE_VMALLOC -return find_vm_area (addr)->page_order >0 ; +struct vm_struct *area =find_vm_area (addr); + +return area && area->page_order >0 ;#else return false;#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 522/1266 hwspinlock: qcom: avoid uninitialized struct members
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 8752c396ce3b2136b3d4c906fe103f6efb6782d9 ]
The reg_field is allocated on stack, so using the REG_FIELD macro will ensure that unused members do not have uninitialized values.
--- drivers/hwspinlock/qcom_hwspinlock.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-)
drivers/hwspinlock/qcom_hwspinlock.c +1 -4
@@ -178,7 +178,6 @@ static struct regmap *qcom_hwspinlock_probe_mmio(struct platform_device *pdev,static int qcom_hwspinlock_probe (struct platform_device *pdev) {struct hwspinlock_device *bank; -struct reg_field field;struct regmap *regmap;size_t array_size;u32 stride;
@@ -200,9 +199,7 @@ static int qcom_hwspinlock_probe(struct platform_device *pdev)platform_set_drvdata (pdev, bank);for (i =0 ; i <QCOM_MUTEX_NUM_LOCKS ; i++) { - field.reg = base + i * stride; - field.lsb =0 ; - field.msb =31 ; +struct reg_field field =REG_FIELD (base + i * stride,0 ,31 ); bank->lock[i].priv =devm_regmap_field_alloc (&pdev->dev, regmap, field);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 523/1266 sched/fair: Fix cpu_util runnable_avg arithmetic
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongyan Xia <[email protected]>
[ Upstream commit 29922fdfc2a4008d66418bedd0ebf5038fc54efa ]
If we take runnable_avg in max(runnable_avg, util_avg) in cpu_util(), we should then add or subtract task runnable_avg, but the arithmetic below is still with task util_avg. This mixes runnable_avg with util_avg which is incorrect.
Fix by always doing arithmetic with runnable_avg and only take max(runnable_avg, util_avg) at the last step.
--- kernel/sched/fair.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
kernel/sched/fair.c +15 -8
@@ -7711,25 +7711,32 @@ static int select_idle_sibling(struct task_struct *p, int prev, int target)static unsigned long cpu_util (int cpu,struct task_struct *p,int dst_cpu,int boost) { +bool add_task = p &&task_cpu (p) != cpu && dst_cpu == cpu; +bool sub_task = p &&task_cpu (p) == cpu && dst_cpu != cpu;struct cfs_rq *cfs_rq = &cpu_rq (cpu)->cfs;unsigned long util =READ_ONCE (cfs_rq->avg.util_avg);unsigned long runnable; -if (boost) { - runnable =READ_ONCE (cfs_rq->avg.runnable_avg); - util =max (util, runnable); - } -/* * If @dst_cpu is -1 or @p migrates from @cpu to @dst_cpu remove its * contribution. If @p migrates from another CPU to @cpu add its * contribution. In all the other cases @cpu is not impacted by the * migration so its util_avg is already correct. */ -if (p &&task_cpu (p) == cpu && dst_cpu != cpu) -lsub_positive (&util,task_util (p)); -else if (p &&task_cpu (p) != cpu && dst_cpu == cpu) +if (add_task) util +=task_util (p); +else if (sub_task) +lsub_positive (&util,task_util (p)); + +if (boost) { + runnable =READ_ONCE (cfs_rq->avg.runnable_avg); +if (add_task) + runnable +=READ_ONCE (p->se.avg.runnable_avg); +else if (sub_task) +lsub_positive (&runnable, +READ_ONCE (p->se.avg.runnable_avg)); + util =max (util, runnable); + }if (sched_feat (UTIL_EST )) {unsigned long util_est;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 524/1266 wifi: mt76: fix argument to ieee80211_is_first_frag()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bjoern A. Zeeb <[email protected]>
[ Upstream commit 5832743279da8c6ae72f715bad2f7141eca6f4b8 ]
ieee80211_is_first_frag() operates on the seq_ctrl not the frame_control header field. Pass the correct one in; otherwise the results may vary.
Sponsored by: The FreeBSD Foundation
--- drivers/net/wireless/mediatek/mt76/mac80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/mediatek/mt76/mac80211.c +1 -1
@@ -1137,7 +1137,7 @@ mt76_check_ccmp_pn(struct sk_buff *skb)* All further fragments will be validated by mac80211 only. */ if (ieee80211_is_frag (hdr) && - !ieee80211_is_first_frag (hdr->frame_control)) + !ieee80211_is_first_frag (hdr->seq_ctrl))return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 525/1266 wifi: mt76: mt7915: fix potential tx_retries underflow
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 05e72b6167970043348bfbe8f72a3b67a38a9f1c ]
When FIELD_GET returns 0 for the retry count, subtracting 1 causes an unsigned integer underflow, resulting in tx_retries becoming a very large value (0xFFFFFFFF for u32).
Fix by checking if count is non-zero before subtracting 1.
--- drivers/net/wireless/mediatek/mt76/mt7915/mac.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mac.c +5 -5
@@ -916,16 +916,16 @@ mt7915_mac_tx_free(struct mt7915_dev *dev, void *data, int len) }if (!mtk_wed_device_active (&mdev->mmio.wed) && wcid) { -u32 tx_retries =0 , tx_failed =0 ; +u32 tx_retries =0 , tx_failed =0 , count;if (v3 && (info &MT_TX_FREE_MPDU_HEADER_V3 )) { - tx_retries = -FIELD_GET (MT_TX_FREE_COUNT_V3 , info) -1 ; + count =FIELD_GET (MT_TX_FREE_COUNT_V3 , info); + tx_retries = count ? count -1 :0 ; tx_failed = tx_retries + !!FIELD_GET (MT_TX_FREE_STAT_V3 , info); }else if (!v3 && (info &MT_TX_FREE_MPDU_HEADER )) { - tx_retries = -FIELD_GET (MT_TX_FREE_COUNT , info) -1 ; + count =FIELD_GET (MT_TX_FREE_COUNT , info); + tx_retries = count ? count -1 :0 ; tx_failed = tx_retries + !!FIELD_GET (MT_TX_FREE_STAT , info); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 526/1266 wifi: mt76: mt7921: fix potential tx_retries underflow
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryder Lee <[email protected]>
[ Upstream commit 3c5671ed81b1fff97fa868dae771690599db94f7 ]
When FIELD_GET returns 0 for the retry count, subtracting 1 causes an unsigned integer underflow, resulting in tx_retries becoming a very large value (0xFFFFFFFF for u32).
Fix by checking if count is non-zero before subtracting 1.
--- drivers/net/wireless/mediatek/mt76/mt7921/mac.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7921/mac.c +3 -2
@@ -536,8 +536,9 @@ static void mt7921_mac_tx_free(struct mt792x_dev *dev, void *data, int len) stat =FIELD_GET (MT_TX_FREE_STATUS , info);if (wcid) { - wcid->stats.tx_retries += -FIELD_GET (MT_TX_FREE_COUNT , info) -1 ; +u32 count =FIELD_GET (MT_TX_FREE_COUNT , info); + + wcid->stats.tx_retries += count ? count -1 :0 ; wcid->stats.tx_failed += !!stat; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 527/1266 btrfs: fix invalid pointer dereference in __btrfs_run_delayed_refs()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 486f8298b6188ff11ef1f4be7f1d5d2e4d1b1fae ]
In the beginning of the loop, we try to obtain a locked delayed ref head, if 'locked_ref' is currently NULL, by calling btrfs_select_ref_head(), which can return an error pointer. If the error pointer is -EAGAIN we do a continue and go back to the beginning of the loop, which will not try again to call btrfs_select_ref_head() since 'locked_ref' is no longer NULL but it's ERR_PTR(-EAGAIN), and then we do:
spin_lock(&locked_ref->lock);
against a ERR_PTR(-EAGAIN) value, generating an invalid pointer dereference.
Fix this by ensuring that 'locked_ref' is set to NULL when btrfs_select_ref_head() returns ERR_PTR(-EAGAIN) and incrementing 'count' as well, to prevent infinite looping. We do this by doing a goto to the bottom of the loop that already sets 'locked_ref' to NULL and does a cond_resched(), with an increment to 'count' right before the goto. These measures were in place before the refactoring in commit 0110a4c43451 ("btrfs: refactor __btrfs_run_delayed_refs loop") but were unintentionally lost afterwards.
--- fs/btrfs/extent-tree.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/btrfs/extent-tree.c +3 -2
@@ -2061,7 +2061,8 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans, locked_ref =btrfs_obtain_ref_head (trans);if (IS_ERR_OR_NULL (locked_ref)) {if (PTR_ERR (locked_ref) == -EAGAIN ) { -continue ; + count++; + goto again; }else {break ; }
@@ -2109,7 +2110,7 @@ static noinline int __btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,* Either success case or btrfs_run_delayed_refs_for_head * returned -EAGAIN, meaning we need to select another head */ - +again: locked_ref =NULL ;cond_resched (); }while ((nr !=-1 && count < nr) || locked_ref);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 528/1266 fbdev: sm501fb: Fix buffer errors in OF binding code
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Laight <[email protected]>
[ Upstream commit d8421e09382cfe0bd2a044c8b0a822f64855dd4e ]
The code that gets the frame buffer mode from OF has 'use after free', 'buffer overrun' and memory leaks.
info->edid_data isn't free if the probe functions fail or if pd->def_mode is set.
If both the CRT and PANEL are enabled info->edid_data is used after being freed and is freed twice.
The string returned by of_get_property(np, "mode", &len) is just written over either the static "640x480-16@60" or the module parameter string without any regard for the length (which is most likely longer).
Use kstrump() for the OF mode and free everything before freeing 'info.
--- drivers/video/fbdev/sm501fb.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
drivers/video/fbdev/sm501fb.c +12 -4
@@ -95,6 +95,7 @@ struct sm501fb_info {void __iomem *fbmem;/* remapped framebuffer */ size_t fbmem_len;/* length of remapped region */ u8 *edid_data; +char *fb_mode; };/* per-framebuffer private data */
@@ -1788,12 +1789,11 @@ static int sm501fb_init_fb(struct fb_info *fb, enum sm501_controller head, fb->var.yres_virtual = fb->var.yres; }else {if (info->edid_data) { - ret =fb_find_mode (&fb->var, fb, fb_mode, + ret =fb_find_mode (&fb->var, fb, + info->fb_mode ?: fb_mode, fb->monspecs.modedb, fb->monspecs.modedb_len, &sm501_default_mode, default_bpp); -/* edid_data is no longer needed, free it */ -kfree (info->edid_data); }else { ret =fb_find_mode (&fb->var, fb,NULL ,NULL ,0 ,NULL ,8 );
@@ -1969,7 +1969,7 @@ static int sm501fb_probe(struct platform_device *pdev)/* Get EDID */ cp =of_get_property (np,"mode" , &len);if (cp) -strcpy (fb_mode, cp); + info->fb_mode =kstrdup (cp,GFP_KERNEL ); prop =of_get_property (np,"edid" , &len);if (prop && len ==EDID_LENGTH ) { info->edid_data = kmemdup(prop, EDID_LENGTH,
@@ -2026,6 +2026,12 @@ static int sm501fb_probe(struct platform_device *pdev) goto err_started_crt; } +/* These aren't needed any more */ +kfree (info->edid_data); +kfree (info->fb_mode); + info->edid_data =NULL ; + info->fb_mode =NULL ; +/* we registered, return ok */ return 0 ;
@@ -2043,6 +2049,8 @@ static int sm501fb_probe(struct platform_device *pdev)framebuffer_release (info->fb[HEAD_CRT ]); err_alloc: +kfree (info->edid_data); +kfree (info->fb_mode);kfree (info);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 529/1266 hwmon: (it87) Clamp negative values to zero in set_fan()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikita Zhandarovich <[email protected]>
[ Upstream commit 7f8581c70a3bd50a932d3d2d253e99c5ec3eda74 ]
set_fan() parses user input with kstrtol() and passes the resulting value to FAN16_TO_REG() on chips with 16-bit fan support.
Negative fan speeds are not meaningful and should be rejected before conversion. Worst scenario, one may be able to abuse undefined behaviour of signed overflow to possibly induce rpm * 2 == 0 in FAN16_TO_REG(), thus causing a division by zero.
Instead, clamp val < 0 to zero and keep the conversion in its valid input domain, avoiding unsafe arithmetic in the register conversion path.
Found by Linux Verification Center (linuxtesting.org) with static analysis tool SVACE.
--- drivers/hwmon/it87.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/hwmon/it87.c +3 -0
@@ -1400,6 +1400,9 @@ static ssize_t set_fan(struct device *dev, struct device_attribute *attr,if (kstrtol (buf,10 , &val) <0 )return -EINVAL ; +if (val <0 ) + val =0 ; + err =it87_lock (data);if (err)return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 530/1266 btrfs: zoned: dont account data relocation space-info in statfs free space
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn <[email protected]>
[ Upstream commit 52416a27aabc43eab3792fd0ca9f5dabeab58f31 ]
Don't account the free space in a data relocation space-info sub-group as usable free space in statfs.
This is misleading as no user allocations can be made in this space-info sub-group. It is only a target for relocation.
--- fs/btrfs/super.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/btrfs/super.c +2 -1
@@ -2048,7 +2048,8 @@ static int btrfs_statfs(struct dentry *dentry, struct kstatfs *buf)int mixed =0 ;list_for_each_entry (found, &fs_info->space_info, list) { -if (found->flags &BTRFS_BLOCK_GROUP_DATA ) { +if (found->flags &BTRFS_BLOCK_GROUP_DATA && + found->subgroup_id !=BTRFS_SUB_GROUP_DATA_RELOC ) {int i; total_free_data += found->disk_total - found->disk_used;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 531/1266 IB/mlx4: Fill in the access_flags if IB_MR_REREG_ACCESS is not specified
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit bade9a3150d44ed20b8c6484c4c8a943b7289abb ]
Sashiko noticed mlx4 was using whatever random access flags were provided when IB_MR_REREG_ACCESS is not used. Since IB_MR_REREG_TRANS needs access_flags it used the random ones which means it doesn't work sensibly if userspace provides only IB_MR_REREG_TRANS.
Keep track of the current access_flag of the MR and use it if the user does not specify one.
Also fixup a little confusion around mmr.access, it is the HW access flags so the convert_access() was missing. But nothing reads this by the time rereg_mr can happen.
--- drivers/infiniband/hw/mlx4/mlx4_ib.h | 1 + drivers/infiniband/hw/mlx4/mr.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-)
drivers/infiniband/hw/mlx4/mlx4_ib.h +1 -0
@@ -137,6 +137,7 @@ struct mlx4_ib_mr {dma_addr_t page_map;u32 npages;u32 max_pages; +int access_flags;struct mlx4_mr mmr;struct ib_umem *umem;size_t page_map_size;
drivers/infiniband/hw/mlx4/mr.c +7 -2
@@ -439,6 +439,7 @@ struct ib_mr *mlx4_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,if (err) goto err_mr; + mr->access_flags = access_flags; mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; mr->ibmr.page_size =1U << shift;
@@ -499,6 +500,8 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start,if (err) goto release_mpt_entry; + }else { + mr_access_flags = mmr->access_flags; }if (flags &IB_MR_REREG_TRANS ) {
@@ -540,8 +543,10 @@ struct ib_mr *mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, u64 start,* return a failure. But dereg_mr will free the resources. */ err =mlx4_mr_hw_write_mpt (dev->dev, &mmr->mmr, pmpt_entry); -if (!err && flags &IB_MR_REREG_ACCESS ) - mmr->mmr.access = mr_access_flags; +if (!err && flags &IB_MR_REREG_ACCESS ) { + mmr->access_flags = mr_access_flags; + mmr->mmr.access =convert_access (mr_access_flags); + } release_mpt_entry:mlx4_mr_hw_put_mpt (dev->dev, pmpt_entry);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 532/1266 spi: meson-spifc: fix runtime PM leak on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 606c0826bd90384a54571c0c5475ca41f50164ea ]
pm_runtime_get_sync() increments the runtime PM usage counter even when it returns an error. meson_spifc_remove() uses it to resume the controller before disabling runtime PM, but never drops the usage counter again.
Balance the get with pm_runtime_put_noidle() after disabling runtime PM, matching the teardown pattern used by other SPI controller drivers.
Found by static analysis. I do not have hardware to test this.
--- drivers/spi/spi-meson-spifc.c | 1 + 1 file changed, 1 insertion(+)
drivers/spi/spi-meson-spifc.c +1 -0
@@ -363,6 +363,7 @@ static void meson_spifc_remove(struct platform_device *pdev)pm_runtime_get_sync (&pdev->dev);clk_disable_unprepare (spifc->clk);pm_runtime_disable (&pdev->dev); +pm_runtime_put_noidle (&pdev->dev); }#ifdef CONFIG_PM_SLEEP
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 533/1266 ASoC: codecs: aw88261: fix incorrect masks for boost regs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Val Packett <[email protected]>
[ Upstream commit 79c053a1ff9d3ab31cefbc791e8d7816ba830491 ]
The boost-related register fields used in aw88261_reg_force_set use the exact same definitions as the rest of the fields, where the mask must be inverted when passing it to regmap_update_bits, but they weren't inverted here.
--- sound/soc/codecs/aw88261.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
sound/soc/codecs/aw88261.c +6 -6
@@ -284,22 +284,22 @@ static void aw88261_reg_force_set(struct aw88261 *aw88261)if (aw88261->frcset_en ==AW88261_FRCSET_ENABLE ) {/* set FORCE_PWM */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL3_REG , -AW88261_FORCE_PWM_MASK ,AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE ); + ~AW88261_FORCE_PWM_MASK ,AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE );/* set BOOST_OS_WIDTH */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL5_REG , -AW88261_BST_OS_WIDTH_MASK ,AW88261_BST_OS_WIDTH_50NS_VALUE ); + ~AW88261_BST_OS_WIDTH_MASK ,AW88261_BST_OS_WIDTH_50NS_VALUE );/* set BURST_LOOPR */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL6_REG , -AW88261_BST_LOOPR_MASK ,AW88261_BST_LOOPR_340K_VALUE ); + ~AW88261_BST_LOOPR_MASK ,AW88261_BST_LOOPR_340K_VALUE );/* set RSQN_DLY */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL7_REG , -AW88261_RSQN_DLY_MASK ,AW88261_RSQN_DLY_35NS_VALUE ); + ~AW88261_RSQN_DLY_MASK ,AW88261_RSQN_DLY_35NS_VALUE );/* set BURST_SSMODE */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL8_REG , -AW88261_BURST_SSMODE_MASK ,AW88261_BURST_SSMODE_FAST_VALUE ); + ~AW88261_BURST_SSMODE_MASK ,AW88261_BURST_SSMODE_FAST_VALUE );/* set BST_BURST */ regmap_update_bits (aw88261->regmap,AW88261_BSTCTRL9_REG , -AW88261_BST_BURST_MASK ,AW88261_BST_BURST_30MA_VALUE ); + ~AW88261_BST_BURST_MASK ,AW88261_BST_BURST_30MA_VALUE ); }else {dev_dbg (aw88261->aw_pa->dev,"needn't set reg value" ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 534/1266 vduse: hold vduse_lock across IDR lookup in open path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang Tang <[email protected]>
[ Upstream commit e440e077748939839d9f76e24383b76b785f80ce ]
vduse_dev_open() looks up struct vduse_dev through the IDR and then acquires dev->lock only after vduse_lock has been dropped.
This leaves a window where a concurrent VDUSE_DESTROY_DEV can remove the same object from the IDR and free it before the open path locks the device, leading to a use-after-free.
Close this race by keeping vduse_lock held until dev->lock has been acquired in the open path, matching the lock ordering already used by the destroy path.
Message-ID: <[email protected]>
--- drivers/vdpa/vdpa_user/vduse_dev.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-)
drivers/vdpa/vdpa_user/vduse_dev.c +7 -14
@@ -1395,26 +1395,18 @@ static int vduse_dev_release(struct inode *inode, struct file *file)return 0 ; } -static struct vduse_dev *vduse_dev_get_from_minor (int minor) +static int vduse_dev_open (struct inode *inode,struct file *file) { +int ret = -EBUSY ;struct vduse_dev *dev;mutex_lock (&vduse_lock); - dev =idr_find (&vduse_idr, minor); -mutex_unlock (&vduse_lock); - -return dev; -} - -static int vduse_dev_open (struct inode *inode,struct file *file) -{ -int ret; -struct vduse_dev *dev =vduse_dev_get_from_minor (iminor (inode)); - -if (!dev) + dev =idr_find (&vduse_idr,iminor (inode)); +if (!dev) { +mutex_unlock (&vduse_lock);return -ENODEV ; + } - ret = -EBUSY ;mutex_lock (&dev->lock);if (dev->connected) goto unlock;
@@ -1424,6 +1416,7 @@ static int vduse_dev_open(struct inode *inode, struct file *file) file->private_data = dev; unlock:mutex_unlock (&dev->lock); +mutex_unlock (&vduse_lock);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 535/1266 vhost/vdpa: validate virtqueue index in mmap and fault paths
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang Tang <[email protected]>
[ Upstream commit 929e4f044621c8cc30b612fb74e1410bef09e41b ]
vhost_vdpa_mmap() and vhost_vdpa_fault() use vma->vm_pgoff as a virtqueue index for get_vq_notification(), but they do not validate that the index is smaller than v->nvqs.
The ioctl path already performs both a bounds check and array_index_nospec(), but the mmap/fault path only checks that the index fits in u16. This allows an out-of-range queue index to reach driver-specific get_vq_notification() callbacks.
Fix this by extracting a unified vhost_vdpa_get_vq_notification() helper that validates the queue index against v->nvqs and applies array_index_nospec() before calling the driver callback. Both the mmap and fault paths use this helper, and the bounds checking is consolidated into a single location.
Quoted 1 line
From source inspection, the most defensible impact is out-of-bounds
access in the callback path, potentially leading to invalid PFN remaps and crash/DoS.
Message-ID: <[email protected]>
--- drivers/vhost/vdpa.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-)
drivers/vhost/vdpa.c +22 -7
@@ -1377,16 +1377,32 @@ static int vhost_vdpa_release(struct inode *inode, struct file *filep) }#ifdef CONFIG_MMU -static vm_fault_t vhost_vdpa_fault (struct vm_fault *vmf) +static int +vhost_vdpa_get_vq_notification (struct vhost_vdpa *v,unsigned long index, +struct vdpa_notification_area *notify) { -struct vhost_vdpa *v = vmf->vma->vm_file->private_data;struct vdpa_device *vdpa = v->vdpa;const struct vdpa_config_ops *ops = vdpa->config; + +if (index >65535 || index >= v->nvqs) +return -EINVAL ; + + index =array_index_nospec (index, v->nvqs); + + *notify = ops->get_vq_notification (vdpa, index); + +return 0 ; +} + +static vm_fault_t vhost_vdpa_fault (struct vm_fault *vmf) +{ +struct vhost_vdpa *v = vmf->vma->vm_file->private_data;struct vdpa_notification_area notify;struct vm_area_struct *vma = vmf->vma; -u16 index = vma->vm_pgoff; +unsigned long index = vma->vm_pgoff; - notify = ops->get_vq_notification (vdpa, index); +if (vhost_vdpa_get_vq_notification (v, index, ¬ify)) +return VM_FAULT_SIGBUS ;return vmf_insert_pfn (vma, vmf->address &PAGE_MASK ,PFN_DOWN (notify.addr)); }
@@ -1409,8 +1425,6 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)return -EINVAL ;if (vma->vm_flags &VM_READ )return -EINVAL ; -if (index >65535 ) -return -EINVAL ;if (!ops->get_vq_notification)return -ENOTSUPP ;
@@ -1418,7 +1432,8 @@ static int vhost_vdpa_mmap(struct file *file, struct vm_area_struct *vma)* support the doorbell which sits on the page boundary and * does not share the page with other registers. */ - notify = ops->get_vq_notification (vdpa, index); +if (vhost_vdpa_get_vq_notification (v, index, ¬ify)) +return -EINVAL ;if (notify.addr & (PAGE_SIZE -1 ))return -EINVAL ;if (vma->vm_end - vma->vm_start != notify.size)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 536/1266 vduse: Requeue failed read to send_list head
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Tianci <[email protected]>
[ Upstream commit 373ec43ded742b2f3aecf14731ffe1a57f438f38 ]
When copy_to_iter() fails in vduse_dev_read_iter(), put the message back at the head of send_list to preserve FIFO ordering and retry the oldest pending request first.
Message-ID: <[email protected]>
--- drivers/vdpa/vdpa_user/vduse_dev.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/vdpa/vdpa_user/vduse_dev.c +7 -1
@@ -193,6 +193,12 @@ static void vduse_enqueue_msg(struct list_head *head,list_add_tail (&msg->list, head); } +static void vduse_enqueue_msg_head (struct list_head *head, +struct vduse_dev_msg *msg) +{ +list_add (&msg->list, head); +} +static void vduse_dev_broken (struct vduse_dev *dev) {struct vduse_dev_msg *msg, *tmp;
@@ -353,7 +359,7 @@ static ssize_t vduse_dev_read_iter(struct kiocb *iocb, struct iov_iter *to)spin_lock (&dev->msg_lock);if (ret != size) { ret = -EFAULT ; -vduse_enqueue_msg (&dev->send_list, msg); +vduse_enqueue_msg_head (&dev->send_list, msg); goto unlock; }vduse_enqueue_msg (&dev->recv_list, msg);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 537/1266 vhost/net: complete zerocopy ubufs only once
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Ming <[email protected]>
[ Upstream commit 8f6898fe80794f2d7c3d38c1158c806e4074a1c4 ]
vhost-net initializes one ubuf_info per outstanding zerocopy TX descriptor and hands it to the backend socket. The networking stack may then clone a zerocopy skb before all skb references are released. For example, batman-adv fragmentation reaches skb_split(), which calls skb_zerocopy_clone() and increments the same ubuf_info refcount.
vhost_zerocopy_complete() currently treats every ubuf callback as a completed vhost descriptor. It dereferences ubuf->ctx, writes the descriptor completion state, and drops the vhost_net_ubuf_ref even when the callback only releases a cloned skb reference. A backend reset can therefore wait for and free the vhost_net_ubuf_ref while another cloned skb still carries the same ubuf_info. A later completion then dereferences the freed ubufs pointer.
KASAN reports the stale completion as:
BUG: KASAN: slab-use-after-free in vhost_zerocopy_complete+0x1d7/0x1f0 BUG: KASAN: slab-use-after-free in vhost_zerocopy_complete+0x101/0x1f0 vhost_zerocopy_complete skb_copy_ubufs __dev_forward_skb2 veth_xmit
The freed object was allocated from vhost_net_ioctl() while setting the backend and freed through kfree_rcu()/kvfree_rcu_bulk after backend removal, while delayed skb completion still reached vhost_zerocopy_complete().
Honor the generic ubuf_info refcount before touching vhost state, and run the vhost descriptor completion only for the final ubuf reference. This matches the msg_zerocopy_complete() ownership rule for cloned zerocopy skbs.
Message-ID: <[email protected]>
--- drivers/vhost/net.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
drivers/vhost/net.c +11 -4
@@ -390,13 +390,20 @@ static void vhost_zerocopy_signal_used(struct vhost_net *net,static void vhost_zerocopy_callback (struct sk_buff *skb,struct ubuf_info *ubuf_base,bool success) { -struct ubuf_info_msgzc *ubuf =uarg_to_msgzc (ubuf_base); -struct vhost_net_ubuf_ref *ubufs = ubuf->ctx; -struct vhost_virtqueue *vq = ubufs->vq; +struct ubuf_info_msgzc *ubuf; +struct vhost_net_ubuf_ref *ubufs; +struct vhost_virtqueue *vq;int cnt; -rcu_read_lock_bh (); +/* Only the final cloned skb reference completes the vhost descriptor. */ +if (!refcount_dec_and_test (&ubuf_base->refcnt)) +return ; + + ubuf =uarg_to_msgzc (ubuf_base); + ubufs = ubuf->ctx; + vq = ubufs->vq; +rcu_read_lock_bh ();/* set len to mark this desc buffers done DMA */ vq->heads[ubuf->desc].len = success ?VHOST_DMA_DONE_LEN :VHOST_DMA_FAILED_LEN ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 538/1266 tools/virtio: check mmap return value in vringh_test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: longlong yan <[email protected]>
[ Upstream commit ec6177dfe98b9be1c3ede6c0dfe4394ea2a76959 ]
In parallel_test(), the return values of mmap() for both host_map and guest_map are not checked against MAP_FAILED. If mmap() fails, the subsequent code will dereference the invalid pointer, leading to a segmentation fault.
Add MAP_FAILED checks after both mmap() calls, using err() to report the error and exit, consistent with the existing error handling style in this file (e.g., the open() call on line 149).
Message-ID: <[email protected]>
--- tools/virtio/vringh_test.c | 5 +++++ 1 file changed, 5 insertions(+)
tools/virtio/vringh_test.c +5 -0
@@ -159,7 +159,12 @@ static int parallel_test(u64 features,/* Parent and child use separate addresses, to check our mapping logic! */ host_map =mmap (NULL , mapsize,PROT_READ |PROT_WRITE ,MAP_SHARED , fd,0 ); +if (host_map ==MAP_FAILED ) +err (1 ,"mmap host_map" ); + guest_map =mmap (NULL , mapsize,PROT_READ |PROT_WRITE ,MAP_SHARED , fd,0 ); +if (guest_map ==MAP_FAILED ) +err (1 ,"mmap guest_map" );pipe (to_guest);pipe (to_host);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 539/1266 ASoC: cs35l56: Fix missing calls to wm_adsp2_remove()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 85f7bf03632bfcdd6cedfb3945b7e387d9487d73 ]
Call wm_adsp2_remove() in cs35l56_remove() and the error path of cs35l56_common_probe().
Depends on commit 7d3fb78b5503 ("ASoC: wm_adsp: Fix NULL dereference when removing firmware controls").
The call to wm_halo_init() during driver probe should be paired with a call to wm_adsp2_remove() but this was missing. The consequence would be a memory leak of the control lists in the cs_dsp driver.
--- sound/soc/codecs/cs35l56.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
sound/soc/codecs/cs35l56.c +6 -1
@@ -1318,11 +1318,14 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56) cs35l56_dai, ARRAY_SIZE(cs35l56_dai));if (ret <0 ) {dev_err_probe (cs35l56->base.dev, ret,"Register codec failed\n" ); - goto err; + goto err_remove_wm_adsp; }return 0 ; +err_remove_wm_adsp: +wm_adsp2_remove (&cs35l56->dsp); + err:gpiod_set_value_cansleep (cs35l56->base.reset_gpio,0 );regulator_bulk_disable (ARRAY_SIZE (cs35l56->supplies), cs35l56->supplies);
@@ -1420,6 +1423,8 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)flush_workqueue (cs35l56->dsp_wq);destroy_workqueue (cs35l56->dsp_wq); +wm_adsp2_remove (&cs35l56->dsp); +pm_runtime_dont_use_autosuspend (cs35l56->base.dev);pm_runtime_suspend (cs35l56->base.dev);pm_runtime_disable (cs35l56->base.dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 540/1266 ASoC: cs35l56: Dont leave parent IRQ disabled if system_suspend fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Fitzgerald <[email protected]>
[ Upstream commit 53cebeb017164254cde5e31c94d8deef9e4fff97 ]
In cs35l56_system_suspend() re-enable the parent IRQ if the call to pm_runtime_force_suspend() returns an error.
--- sound/soc/codecs/cs35l56.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
sound/soc/codecs/cs35l56.c +6 -1
@@ -1055,6 +1055,7 @@ static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev)int cs35l56_system_suspend (struct device *dev) {struct cs35l56_private *cs35l56 =dev_get_drvdata (dev); +int ret;dev_dbg (dev,"system_suspend\n" );
@@ -1070,7 +1071,11 @@ int cs35l56_system_suspend(struct device *dev)if (cs35l56->base.irq)disable_irq (cs35l56->base.irq); -return pm_runtime_force_suspend (dev); + ret =pm_runtime_force_suspend (dev); +if ((ret <0 ) && cs35l56->base.irq) +enable_irq (cs35l56->base.irq); + +return ret; }EXPORT_SYMBOL_GPL (cs35l56_system_suspend);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 541/1266 bonding: 3ad: fix mux port state on oper down
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Louis Scalbert <[email protected]>
[ Upstream commit 807afc7544b865d4d09068a415fd5b71bf5665cc ]
When the bonding interface has carrier down due to the absence of usable slaves and a slave transitions from down to up, the bonding interface briefly goes carrier up, then down again, and finally up once LACP negotiates collecting and distributing on the port.
When lacp_strict mode is on, the interface should not transition to carrier up until LACP negotiation is complete.
This happens because the actor and partner port states remain in Collecting_Distributing when the port goes down. When the port comes back up, it temporarily remains in this state until LACP renegotiation occurs.
Previously this was mostly cosmetic, but since the bonding carrier state may depend on the LACP negotiation state, it causes the interface to flap.
According to IEEE 802.3ad-2000 and IEEE 802.1ax-2014, Collecting and Distributing should be reset when a port goes down:
- In the Receive state machine, port_enabled == FALSE causes a transition to the PORT_DISABLED state, which is expected to clear Partner_Oper_Port_State.Synchronization.
- In the Mux state machine, Partner_Oper_Port_State.Synchronization == FALSE causes a transition to the ATTACHED state, which disables Collecting and Distributing.
However, Partner_Oper_Port_State.Synchronization is not cleared in the PORT_DISABLED state.
Clear Partner_Oper_Port_State.Synchronization in the Receive PORT_DISABLED state.
--- drivers/net/bonding/bond_3ad.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/bonding/bond_3ad.c +1 -0
@@ -1284,6 +1284,7 @@ static void ad_rx_machine(struct lacpdu *lacpdu, struct port *port) fallthrough;case AD_RX_PORT_DISABLED : port->sm_vars &= ~AD_PORT_MATCHED ; + port->partner_oper.port_state &= ~LACP_STATE_SYNCHRONIZATION ;break ;case AD_RX_LACP_DISABLED : port->sm_vars &= ~AD_PORT_SELECTED ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 542/1266 ext4: fix kernel BUG in ext4_write_inline_data_end
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Prakash Srivastava <[email protected]>
[ Upstream commit ad09aa45965d3fafaf9963bc78109b73c0f9ac8d ]
When the data=journal mount option is used, the ext4_journalled_write_end() function incorrectly calls ext4_write_inline_data_end() without checking if the EXT4_STATE_MAY_INLINE_DATA flag is still set on the inode.
If a previous attempt to convert the inline data to an extent failed (e.g. due to ENOSPC), the EXT4_STATE_MAY_INLINE_DATA flag is cleared, but the EXT4_INODE_INLINE_DATA flag remains set. In this scenario, the next call to ext4_write_begin() will not prepare the inline data xattr for writing, but ext4_journalled_write_end() will incorrectly attempt to write to it, triggering a BUG_ON(pos + len > EXT4_I(inode)->i_inline_size) in ext4_write_inline_data() since i_inline_size was not expanded.
Fix this by ensuring that ext4_journalled_write_end() only calls ext4_write_inline_data_end() if the EXT4_STATE_MAY_INLINE_DATA flag is set, mirroring the behavior of ext4_write_end() and ext4_da_write_end().
--- fs/ext4/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ext4/inode.c +2 -1
@@ -1431,7 +1431,8 @@ static int ext4_journalled_write_end(struct file *file,BUG_ON (!ext4_handle_valid (handle)); -if (ext4_has_inline_data (inode)) +if (ext4_has_inline_data (inode) && +ext4_test_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ))return ext4_write_inline_data_end (inode, pos, len, copied, folio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 543/1266 selftests/bpf: Fix bpf_iter/task_vma test
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yonghong Song <[email protected]>
[ Upstream commit 2e8ad1ff712d2a397e407c9fde60901f68d077dc ]
For selftest bpf_iter/task_vma, I got a failure like below on my qemu run:
test_task_vma_common:FAIL:compare_output unexpected compare_output:
actual
'561593546000-561593585000r--p0000000000:241256579534/root/devshare/bpf-next/tools/testing/selftests/bpf/test_progs'
!= expected
'561593546000-561593585000r--p0000000000:245551546830/root/devshare/bpf-next/tools/testing/selftests/bpf/test_progs'Further debugging found out file->f_inode->i_ino value may exceed 32bit, e.g., i_ino = 0x14c2eae35, but the format string is '%u'. This caused inode mismatch between bpf iter and proc result.
Fix the issue by using format string '%llu' to accommodate 64bit i_ino.
--- tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/progs/bpf_iter_task_vma.c +1 -1
@@ -52,7 +52,7 @@ SEC("iter/task_vma") int proc_maps(struct bpf_iter__task_vma *ctx)bpf_d_path (&file->f_path, d_path_buf,D_PATH_BUF_SIZE );BPF_SEQ_PRINTF (seq,"%08llx " , vma->vm_pgoff <<12 ); -BPF_SEQ_PRINTF (seq,"%02x:%02x %u" ,MAJOR (dev),MINOR (dev), +BPF_SEQ_PRINTF (seq,"%02x:%02x %llu" ,MAJOR (dev),MINOR (dev), file->f_inode->i_ino);BPF_SEQ_PRINTF (seq,"\t%s\n" , d_path_buf); }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 544/1266 cxl/test: Fix integer overflow in mock LSA bounds checks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit 81eafcada109b653977c4dfbd2b6a72470025a01 ]
Pre-existing issue discovered by sashiko-bot.
mock_get_lsa() and mock_set_lsa() validate the requested LSA range with "offset + length > LSA_SIZE". Both offset and length are u32 and, in mock_get_lsa(), both are taken directly from the user-supplied payload. The addition is evaluated modulo 2^32, so a large offset combined with a small length wraps around and passes the check.
Rewrite the checks to first bound offset, then compare length against the remaining LSA size.
--- tools/testing/cxl/test/mem.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/cxl/test/mem.c +2 -2
@@ -940,7 +940,7 @@ static int mock_get_lsa(struct cxl_mockmem_data *mdata,return -EINVAL ; offset =le32_to_cpu (get_lsa->offset); length =le32_to_cpu (get_lsa->length); -if (offset + length >LSA_SIZE ) +if (offset >LSA_SIZE || length >LSA_SIZE - offset)return -EINVAL ;if (length > cmd->size_out)return -EINVAL ;
@@ -960,7 +960,7 @@ static int mock_set_lsa(struct cxl_mockmem_data *mdata,return -EINVAL ; offset =le32_to_cpu (set_lsa->offset); length = cmd->size_in -sizeof (*set_lsa); -if (offset + length >LSA_SIZE ) +if (offset >LSA_SIZE || length >LSA_SIZE - offset)return -EINVAL ;memcpy (lsa + offset, &set_lsa->data[0 ], length);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 545/1266 cxl/test: Zero out LSA backing memory to avoid leaking to user
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit 60f065dbaf46e65830da62a0041761f0c039e086 ]
Memory through vmalloc() is not zeroed out. When this memory is copied into output payload, it leaks memory content to user. Use vzalloc() instead to zero out the memory.
--- tools/testing/cxl/test/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/cxl/test/mem.c +1 -1
@@ -1396,7 +1396,7 @@ static int cxl_mock_mem_probe(struct platform_device *pdev)return -ENOMEM ;dev_set_drvdata (dev, mdata); - mdata->lsa =vmalloc (LSA_SIZE ); + mdata->lsa =vzalloc (LSA_SIZE );if (!mdata->lsa)return -ENOMEM ; mdata->fw =vmalloc (FW_SIZE );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 546/1266 of: cpu: add check in __of_find_n_match_cpu_property()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sergey Shtylyov <[email protected]>
[ Upstream commit 5901eda2ed99ba0d3661da6eb265970559323bb3 ]
In __of_find_n_match_cpu_property(), checking the variable ac for 0 won't prevent a possible overflow when multiplying it by sizeof(*cell). Besides, of_read_number() (called in the *for* loop) can't return correct result if that variable (which equals the #address-cells prop's value) exceeds 2, so additionally checking for that seems logical...
Found by Linux Verification Center (linuxtesting.org) with the Svace static analysis tool.
--- drivers/of/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/of/cpu.c +1 -1
@@ -60,7 +60,7 @@ static bool __of_find_n_match_cpu_property(struct device_node *cpun, cell =of_get_property (cpun, prop_name, &prop_len);if (!cell && !ac &&arch_match_cpu_phys_id (cpu,0 ))return true; -if (!cell || !ac) +if (!cell || !ac || ac >2 )return false; prop_len /=sizeof (*cell) * ac;for (tid =0 ; tid < prop_len; tid++) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 547/1266 bpf: Tighten cgroup storage cookie checks for prog arrays
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 10627ddc0167aab5c1c390a10ef461e9937aba08 ]
The fix in commit abad3d0bad72 ("bpf: Fix oob access in cgroup local storage") is still incomplete. The prog-array compatibility check treats a program with no cgroup storage as compatible with any stored storage cookie. This allows a storage-less program to bridge a tail call chain between an entry program and a storage-using callee even though cgroup local storage at runtime still follows the caller's context, that is, A -> B(no storage) -> C(storage) path.
Requiring exact cookie equality would break the legitimate case of a storage-less leaf program being tail called from a storage-using one. Instead, only accept a zero storage cookie if the program cannot perform tail calls itself. This keeps A -> B(no storage) working while rejecting the A -> B(no storage) -> C(storage) bridge.
--- kernel/bpf/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/core.c +1 -1
@@ -2365,7 +2365,7 @@ static bool __bpf_prog_map_compatible(struct bpf_map *map, cookie = aux->cgroup_storage[i] ? aux->cgroup_storage[i]->cookie :0 ; ret = map->owner->storage_cookie[i] == cookie || - !cookie; + (!cookie && !aux->tail_call_reachable); }if (ret && map->owner->attach_func_proto != aux->attach_func_proto) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 548/1266 s390/process: Fix kernel thread function pointer type
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
[ Upstream commit d0478f5d3cba1095bfdeb43a9b063c10cdebef14 ]
In case of a kernel thread __ret_from_fork() calls the specified function indirectly. Fix the kernel thread function pointer, since kernel threads return an int instead of void.
--- arch/s390/kernel/process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/s390/kernel/process.c +1 -1
@@ -48,7 +48,7 @@ void ret_from_fork(void) asm("ret_from_fork");void __ret_from_fork (struct task_struct *prev,struct pt_regs *regs) { -void (*func)(void *arg); +int (*func)(void *arg);schedule_tail (prev);
Signature · 1 line
2.53.0