6.19.4-rc1 review
Greg Kroah-Hartman
maintainerPATCH 623/781 powercap: intel_rapl: Remove incorrect CPU check in PMU context
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuppuswamy Sathyanarayanan <[email protected]>
[ Upstream commit 7537bae8b6eb635583e0e6260f61d13ddbd52087 ]
The RAPL MSR read path incorrectly validates CPU context when called from the PMU subsystem:
if (atomic) {
if (unlikely(smp_processor_id() != cpu))
return -EIO;
rdmsrq(ra->reg.msr, ra->value);
}This check fails for package-scoped MSRs like RAPL energy counters, which are readable from any CPU within the package.
The perf tool avoids hitting this check by validating against /sys/bus/event_source/devices/power/cpumask before opening events. However, turbostat does not perform this validation and may attempt reads from non-lead CPUs, causing the check to fail and return zero power values.
Since package-scoped MSRs are architecturally accessible from any CPU in the package, remove the CPU matching check.
Also rename 'atomic' to 'pmu_ctx' to clarify this indicates PMU context where rdmsrq() can be used directly instead of rdmsrl_safe_on_cpu().
--- drivers/powercap/intel_rapl_common.c | 6 +++--- drivers/powercap/intel_rapl_msr.c | 12 +++++------- include/linux/intel_rapl.h | 2 +- 3 files changed, 9 insertions(+), 11 deletions(-)
drivers/powercap/intel_rapl_common.c +3 -3
@@ -254,7 +254,7 @@ static void rapl_init_domains(struct rapl_package *rp);static int rapl_read_data_raw (struct rapl_domain *rd,enum rapl_primitives prim,bool xlate,u64 *data, -bool atomic); +bool pmu_ctx);static int rapl_write_data_raw (struct rapl_domain *rd,enum rapl_primitives prim,unsigned long long value);
@@ -832,7 +832,7 @@ prim_fixups(struct rapl_domain *rd, enum rapl_primitives prim)*/ static int rapl_read_data_raw (struct rapl_domain *rd,enum rapl_primitives prim,bool xlate,u64 *data, -bool atomic) +bool pmu_ctx) {u64 value;enum rapl_primitives prim_fixed =prim_fixups (rd, prim);
@@ -854,7 +854,7 @@ static int rapl_read_data_raw(struct rapl_domain *rd, ra.mask = rpi->mask; -if (rd->rp->priv->read_raw (get_rid (rd->rp), &ra, atomic)) { +if (rd->rp->priv->read_raw (get_rid (rd->rp), &ra, pmu_ctx)) {pr_debug ("failed to read reg 0x%llx for %s:%s\n" , ra.reg.val, rd->rp->name, rd->name);return -EIO ; }
drivers/powercap/intel_rapl_msr.c +5 -7
@@ -110,16 +110,14 @@ static int rapl_cpu_down_prep(unsigned int cpu)return 0 ; } -static int rapl_msr_read_raw (int cpu,struct reg_action *ra,bool atomic) +static int rapl_msr_read_raw (int cpu,struct reg_action *ra,bool pmu_ctx) {/* -* When called from atomic-context (eg PMU event handler) -* perform MSR read directly using rdmsrq(). +* When called from PMU context, perform MSR read directly using +* rdmsrq() without IPI overhead. Package-scoped MSRs are readable +* from any CPU in the package. */ -if (atomic) { -if (unlikely (smp_processor_id () != cpu)) -return -EIO ; - +if (pmu_ctx) {rdmsrq (ra->reg.msr, ra->value); goto out; }
include/linux/intel_rapl.h +1 -1
@@ -152,7 +152,7 @@ struct rapl_if_priv {union rapl_reg reg_unit;union rapl_reg regs[RAPL_DOMAIN_MAX ][RAPL_DOMAIN_REG_MAX ];int limits[RAPL_DOMAIN_MAX ]; -int (*read_raw)(int id,struct reg_action *ra,bool atomic); +int (*read_raw)(int id,struct reg_action *ra,bool pmu_ctx);int (*write_raw)(int id,struct reg_action *ra);void *defaults;void *rpi;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 624/781 ACPI: CPPC: Fix remaining for_each_possible_cpu() to use online CPUs
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean V Kelley <[email protected]>
[ Upstream commit 56eb0c0ed345da7815274aa821a8546a073d7e97 ]
per_cpu(cpc_desc_ptr, cpu) object is initialized for only the online CPUs via acpi_soft_cpu_online() --> __acpi_processor_start() --> acpi_cppc_processor_probe().
However, send_pcc_cmd() and acpi_get_psd_map() still iterate over all possible CPUs. In acpi_get_psd_map(), encountering an offline CPU returns -EFAULT, causing cppc_cpufreq initialization to fail.
This breaks systems booted with "nosmt" or "nosmt=force".
Fix by using for_each_online_cpu() in both functions.
--- drivers/acpi/cppc_acpi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/acpi/cppc_acpi.c +2 -2
@@ -362,7 +362,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd) end:if (cmd ==CMD_WRITE ) {if (unlikely (ret)) { -for_each_possible_cpu (i) { +for_each_online_cpu (i) {struct cpc_desc *desc =per_cpu (cpc_desc_ptr, i);if (!desc)
@@ -524,7 +524,7 @@ int acpi_get_psd_map(unsigned int cpu, struct cppc_cpudata *cpu_data)else if (pdomain->coord_type ==DOMAIN_COORD_TYPE_SW_ANY ) cpu_data->shared_type =CPUFREQ_SHARED_TYPE_ANY ; -for_each_possible_cpu (i) { +for_each_online_cpu (i) {if (i == cpu)continue ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 625/781 powercap: intel_rapl_tpmi: Remove FW_BUG from invalid version check
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuppuswamy Sathyanarayanan <[email protected]>
[ Upstream commit c7d54dafa042cf379859dba265fe5afef6fa8770 ]
On partitioned systems, multiple TPMI instances may exist per package, but RAPL registers are only valid on one instance since RAPL has package-scope control. Other instances return invalid versions during domain parsing, which is expected behavior on such systems.
Currently this generates a firmware bug warning:
intel_rapl_tpmi: [Firmware Bug]: Invalid version
Remove the FW_BUG tag, downgrade to pr_debug(), and update the message to clarify that invalid versions are expected on partitioned systems where only one instance can be valid.
--- drivers/powercap/intel_rapl_tpmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/powercap/intel_rapl_tpmi.c +1 -1
@@ -157,7 +157,7 @@ static int parse_one_domain(struct tpmi_rapl_package *trp, u32 offset) tpmi_domain_flags = tpmi_domain_header >>32 &0xffff ;if (tpmi_domain_version ==TPMI_VERSION_INVALID ) { -pr_warn (FW_BUG "Invalid version\n" ); +pr_debug ("Invalid version, other instances may be valid\n" );return -ENODEV ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 626/781 kbuild: Add objtool to top-level clean target
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Poimboeuf <[email protected]>
[ Upstream commit 68b4fe32d73789dea23e356f468de67c8367ef8f ]
Objtool is an integral part of the build, make sure it gets cleaned by "make clean" and "make mrproper".
--- Makefile | 11 ++++++++++- tools/objtool/Makefile | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-)
Makefile +10 -1
@@ -1474,6 +1474,15 @@ ifneq ($(wildcard $(resolve_btfids_O)),) $(Q)$(MAKE) -sC $(srctree)/tools/bpf/resolve_btfids O=$(resolve_btfids_O) clean endif +PHONY += objtool_clean + +objtool_O = $(abspath $(objtree))/tools/objtool + +objtool_clean: +ifneq ($(wildcard $(objtool_O)),) + $(Q)$(MAKE) -sC $(abs_srctree)/tools/objtool O=$(objtool_O) srctree=$(abs_srctree) clean +endif + tools/: FORCE $(Q)mkdir -p $(objtree)/tools $(Q)$(MAKE) O=$(abspath $(objtree)) subdir=tools -C $(srctree)/tools/
@@ -1637,7 +1646,7 @@ vmlinuxclean: $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean $(Q)$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) clean) -clean: archclean vmlinuxclean resolve_btfids_clean +clean: archclean vmlinuxclean resolve_btfids_clean objtool_clean # mrproper - Delete all generated files, including .config #
tools/objtool/Makefile +2 -0
@@ -29,6 +29,8 @@ srctree := $(patsubst %/,%,$(dir $(CURDIR))) srctree := $(patsubst %/,%,$(dir $(srctree))) endif +RM ?= rm -f + LIBSUBCMD_DIR = $(srctree)/tools/lib/subcmd/ ifneq ($(OUTPUT),) LIBSUBCMD_OUTPUT = $(abspath $(OUTPUT))/libsubcmd
Signature · 1 line
2.51.0
Re: [PATCH 6.19 626/781] kbuild: Add objtool to top-level clean target
Quoted 7 lines · Greg Kroah-Hartman
6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josh Poimboeuf <[email protected]>
[ Upstream commit
68b4fe32d73789dea23e356f468de67c8367ef8f]
Oh, I didn't notice earlier. This breaks external kernel modules build after make clean (which distros do).
A fix is on the way:
https://lore.kernel.org/all/20260227-avoid-objtool-binary-removal-clean-v1-1-122f3e55eae9@kernel.org/
thanks,
Signature · 2 lines
js suse labs
Greg Kroah-Hartman
maintainerPATCH 627/781 smb: client: fix regression with mount options parsing
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
[ Upstream commit 72f4d48034864b93700d1d23fc418d90fa28d7ae ]
After commit 1ef15fbe6771 ("cifs: client: enforce consistent handling of multichannel and max_channels"), invalid mount options started to be ignored, allowing cifs.ko to proceed with the mount instead of baling out.
The problem was related to smb3_handle_conflicting_options() being called even when an invalid parameter had been parsed, overwriting the return value of vfs_parse_fs_string() in smb3_fs_context_parse_monolithic().
Fix this by calling smb3_handle_conflicting_options() only when a valid mount option has been passed.
Reproducer:
$ mount.cifs //srv/share /mnt -o ${opts}
$ mount -o remount,foo,${opts} /mnt # must fail--- fs/smb/client/fs_context.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
fs/smb/client/fs_context.c +1 -3
@@ -826,9 +826,7 @@ static int smb3_fs_context_parse_monolithic(struct fs_context *fc,if (ret <0 )break ; } - ret =smb3_handle_conflicting_options (fc); - -return ret; +return ret ?:smb3_handle_conflicting_options (fc); }/*
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 628/781 selftests/memfd: use IPC semaphore instead of SIGSTOP/SIGCONT
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aristeu Rozanski <[email protected]>
[ Upstream commit b24335521de92fd2ee22460072b75367ca8860b0 ]
selftests/memfd: use IPC semaphore instead of SIGSTOP/SIGCONT
In order to synchronize new processes to test inheritance of memfd_noexec sysctl, memfd_test sets up the sysctl with a value before creating the new process. The new process then sends itself a SIGSTOP in order to wait for the parent to flip the sysctl value and send a SIGCONT signal.
This would work as intended if it wasn't the fact that the new process is being created with CLONE_NEWPID, which creates a new PID namespace and the new process has PID 1 in this namespace. There're restrictions on sending signals to PID 1 and, although it's relaxed for other than root PID namespace, it's biting us here. In this specific case the SIGSTOP sent by the new process is ignored (no error to kill() is returned) and it never stops its execution. This is usually not noticiable as the parent usually manages to set the new sysctl value before the child has a chance to run and the test succeeds. But if you run the test in a loop, it eventually reproduces:
while [ 1 ]; do ./memfd_test >log 2>&1 || break; done; cat log
So this patch replaces the SIGSTOP/SIGCONT synchronization with IPC semaphore.
--- tools/testing/selftests/memfd/memfd_test.c | 113 +++++++++++++++++++-- 1 file changed, 105 insertions(+), 8 deletions(-)
tools/testing/selftests/memfd/memfd_test.c +105 -8
@@ -18,6 +18,9 @@#include <sys/stat.h> #include <sys/syscall.h> #include <sys/wait.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/sem.h> #include <unistd.h> #include <ctype.h>
@@ -39,6 +42,20 @@ F_SEAL_EXEC)#define MFD_NOEXEC_SEAL 0x0008U +union semun { +int val; +struct semid_ds *buf; +unsigned short int *array; +struct seminfo *__buf; +}; + +/* +* we use semaphores on nested wait tasks due the use of CLONE_NEWPID: the +* child will be PID 1 and can't send SIGSTOP to themselves due special +* treatment of the init task, so the SIGSTOP/SIGCONT synchronization +* approach can't be used here. +*/ +#define SEM_KEY 0xdeadbeef/* * Default is not to test hugetlbfs
@@ -1333,8 +1350,22 @@ static int sysctl_nested(void *arg)static int sysctl_nested_wait (void *arg) { -/* Wait for a SIGCONT. */ -kill (getpid (),SIGSTOP ); +int sem =semget (SEM_KEY ,1 ,0600 ); +struct sembuf sembuf; + +if (sem <0 ) { +perror ("semget:" ); +abort (); + } + sembuf.sem_num =0 ; + sembuf.sem_flg =0 ; + sembuf.sem_op =0 ; + +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +abort (); + } +return sysctl_nested (arg); }
@@ -1355,7 +1386,9 @@ static void test_sysctl_sysctl2_failset(void)static int sysctl_nested_child (void *arg) { -int pid; +int pid, sem; +union semun semun; +struct sembuf sembuf;printf ("%s nested sysctl 0\n" , memfd_str);sysctl_assert_write ("0" );
@@ -1389,23 +1422,53 @@ static int sysctl_nested_child(void *arg) test_sysctl_sysctl2_failset);join_thread (pid); + sem =semget (SEM_KEY ,1 ,IPC_CREAT |0600 ); +if (sem <0 ) { +perror ("semget:" ); +return 1 ; + } + semun.val =1 ; + sembuf.sem_op =-1 ; + sembuf.sem_flg =0 ; + sembuf.sem_num =0 ; +/* Verify that the rules are actually inherited after fork. */ printf ("%s nested sysctl 0 -> 1 after fork\n" , memfd_str);sysctl_assert_write ("0" ); +if (semctl (sem,0 ,SETVAL , semun) <0 ) { +perror ("semctl:" ); +return 1 ; + } + pid =spawn_thread (CLONE_NEWPID , sysctl_nested_wait, test_sysctl_sysctl1_failset);sysctl_assert_write ("1" ); -kill (pid,SIGCONT ); + +/* Allow child to continue */ +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +return 1 ; + }join_thread (pid);printf ("%s nested sysctl 0 -> 2 after fork\n" , memfd_str);sysctl_assert_write ("0" ); +if (semctl (sem,0 ,SETVAL , semun) <0 ) { +perror ("semctl:" ); +return 1 ; + } + pid =spawn_thread (CLONE_NEWPID , sysctl_nested_wait, test_sysctl_sysctl2_failset);sysctl_assert_write ("2" ); -kill (pid,SIGCONT ); + +/* Allow child to continue */ +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +return 1 ; + }join_thread (pid);/*
@@ -1415,28 +1478,62 @@ static int sysctl_nested_child(void *arg)*/ printf ("%s nested sysctl 2 -> 1 after fork\n" , memfd_str);sysctl_assert_write ("2" ); + +if (semctl (sem,0 ,SETVAL , semun) <0 ) { +perror ("semctl:" ); +return 1 ; + } + pid =spawn_thread (CLONE_NEWPID , sysctl_nested_wait, test_sysctl_sysctl2);sysctl_assert_write ("1" ); -kill (pid,SIGCONT ); + +/* Allow child to continue */ +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +return 1 ; + }join_thread (pid);printf ("%s nested sysctl 2 -> 0 after fork\n" , memfd_str);sysctl_assert_write ("2" ); + +if (semctl (sem,0 ,SETVAL , semun) <0 ) { +perror ("semctl:" ); +return 1 ; + } + pid =spawn_thread (CLONE_NEWPID , sysctl_nested_wait, test_sysctl_sysctl2);sysctl_assert_write ("0" ); -kill (pid,SIGCONT ); + +/* Allow child to continue */ +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +return 1 ; + }join_thread (pid);printf ("%s nested sysctl 1 -> 0 after fork\n" , memfd_str);sysctl_assert_write ("1" ); + +if (semctl (sem,0 ,SETVAL , semun) <0 ) { +perror ("semctl:" ); +return 1 ; + } + pid =spawn_thread (CLONE_NEWPID , sysctl_nested_wait, test_sysctl_sysctl1);sysctl_assert_write ("0" ); -kill (pid,SIGCONT ); +/* Allow child to continue */ +if (semop (sem, &sembuf,1 ) <0 ) { +perror ("semop:" ); +return 1 ; + }join_thread (pid); +semctl (sem,0 ,IPC_RMID ); +return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 629/781 objpool: fix the overestimation of object pooling metadata size
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: zhouwenhao <[email protected]>
[ Upstream commit 5ed4b6b37c647d168ae31035b3f61b705997e043 ]
objpool uses struct objpool_head to store metadata information, and its cpu_slots member points to an array of pointers that store the addresses of the percpu ring arrays. However, the memory size allocated during the initialization of cpu_slots is nr_cpu_ids * sizeof(struct objpool_slot). On a 64-bit machine, the size of struct objpool_slot is 16 bytes, which is twice the size of the actual pointer required, and the extra memory is never be used, resulting in a waste of memory. Therefore, the memory size required for cpu_slots needs to be corrected.
--- lib/objpool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
lib/objpool.c +1 -1
@@ -142,7 +142,7 @@ int objpool_init(struct objpool_head *pool, int nr_objs, int object_size, pool->gfp = gfp & ~__GFP_ZERO; pool->context = context; pool->release = release; - slot_size = nr_cpu_ids *sizeof (struct objpool_slot ); + slot_size = nr_cpu_ids *sizeof (struct objpool_slot *); pool->cpu_slots =kzalloc (slot_size, pool->gfp);if (!pool->cpu_slots)return -ENOMEM ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 630/781 ACPI: PM: Add unused power resource quirk for THUNDEROBOT ZERO
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhai Can <[email protected]>
[ Upstream commit cd7ef20ba8c6e936dba133b4136537a8ada22976 ]
On the THUNDEROBOT ZERO laptop, the second NVMe slot and the discrete NVIDIA GPU are both controlled by power-resource PXP. Due to the SSDT table bug (lack of reference), PXP will be shut dow as an "unused" power resource during initialization, making the NVMe slot #2 + NVIDIA both inaccessible.
This issue was introduced by commit a1224f34d72a ("ACPI: PM: Check states of power resources during initialization"). Here are test results on the three consecutive commits:
(bad again!) a1224f34d72a ACPI: PM: Check states of power resources during initialization (good) bc2836859643 ACPI: PM: Do not turn off power resources in unknown state (bad) 519d81956ee2 Linux 5.15-rc6
On commit bc2836859643 ("ACPI: PM: Do not turn off power resources in unknown state") this was not an issue because the power resource state left UNKNOWN thus being ignored.
See also commit 9b04d99788cf ("ACPI: PM: Do not turn of unused power resources on the Toshiba Click Mini") which is another almost identical case to this one.
--- drivers/acpi/power.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/acpi/power.c +13 -0
@@ -1113,6 +1113,19 @@ static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE Click Mini L9W-B"), }, }, + { + /* + * THUNDEROBOT ZERO laptop: Due to its SSDT table bug, power + * resource 'PXP' will be shut down on initialization, making + * the NVMe #2 and the NVIDIA dGPU both unavailable (they're + * both controlled by 'PXP'). + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "THUNDEROBOT"), + DMI_MATCH(DMI_PRODUCT_NAME, "ZERO"), + } + + }, {} };
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 631/781 cpuidle: Skip governor when only one idle state is available
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aboorva Devarajan <[email protected]>
[ Upstream commit e5c9ffc6ae1bcdb1062527d611043681ac301aca ]
On certain platforms (PowerNV systems without a power-mgt DT node), cpuidle may register only a single idle state. In cases where that single state is a polling state (state 0), the ladder governor may incorrectly treat state 1 as the first usable state and pass an out-of-bounds index. This can lead to a NULL enter callback being invoked, ultimately resulting in a system crash.
[ 13.342636] cpuidle-powernv : Only Snooze is available [ 13.351854] Faulting instruction address: 0x00000000 [ 13.376489] NIP [0000000000000000] 0x0 [ 13.378351] LR [c000000001e01974] cpuidle_enter_state+0x2c4/0x668
Fix this by adding a bail-out in cpuidle_select() that returns state 0 directly when state_count <= 1, bypassing the governor and keeping the tick running.
--- drivers/cpuidle/cpuidle.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/cpuidle/cpuidle.c +10 -0
@@ -359,6 +359,16 @@ noinstr int cpuidle_enter_state(struct cpuidle_device *dev,int cpuidle_select (struct cpuidle_driver *drv,struct cpuidle_device *dev,bool *stop_tick) { +/* +* If there is only a single idle state (or none), there is nothing +* meaningful for the governor to choose. Skip the governor and +* always use state 0 with the tick running. +*/ +if (drv->state_count <=1 ) { + *stop_tick = false; +return 0 ; + } +return cpuidle_curr_governor->select (drv, dev, stop_tick); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 632/781 ovpn: set sk_user_data before overriding callbacks
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Lici <[email protected]>
[ Upstream commit 93686c472eb7b09a51b97a096449e7092fefcd1f ]
During initialization, we override socket callbacks and set sk_user_data to an ovpn_socket instance. Currently, these two operations are
decoupled: callbacks are overridden before sk_user_data is set. While existing callbacks perform safety checks for NULL or non-ovpn sk_user_data, this condition causes a "half-formed" state where valid packets arriving during attachment trigger error logs (e.g., "invoked on non ovpn socket").
Set sk_user_data before overriding the callbacks so that it can be accessed safely from them. Since we already check that the socket has no sk_user_data before setting it, this remains safe even if an interrupt accesses the socket after sk_user_data is set but before the callbacks are overridden.
This also requires initializing all protocol-specific fields (such as tcp_tx_work and peer links) before calling ovpn_socket_attach, ensuring the ovpn_socket is fully formed before it becomes visible to any callback.
--- drivers/net/ovpn/socket.c | 39 +++++++++++++++++++++------------------ drivers/net/ovpn/tcp.c | 9 +++++++-- drivers/net/ovpn/udp.c | 1 + 3 files changed, 29 insertions(+), 20 deletions(-)
drivers/net/ovpn/socket.c +21 -18
@@ -200,6 +200,22 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer) ovpn_sock->sk = sk;kref_init (&ovpn_sock->refcount); +/* TCP sockets are per-peer, therefore they are linked to their unique +* peer +*/ +if (sk->sk_protocol ==IPPROTO_TCP ) { +INIT_WORK (&ovpn_sock->tcp_tx_work, ovpn_tcp_tx_work); + ovpn_sock->peer = peer; +ovpn_peer_hold (peer); + }else if (sk->sk_protocol ==IPPROTO_UDP ) { +/* in UDP we only link the ovpn instance since the socket is +* shared among multiple peers +*/ + ovpn_sock->ovpn = peer->ovpn; +netdev_hold (peer->ovpn->dev, &ovpn_sock->dev_tracker, +GFP_KERNEL ); + } +/* the newly created ovpn_socket is holding reference to sk, * therefore we increase its refcounter. *
@@ -212,29 +228,16 @@ struct ovpn_socket *ovpn_socket_new(struct socket *sock, struct ovpn_peer *peer) ret =ovpn_socket_attach (ovpn_sock, sock, peer);if (ret <0 ) { +if (sk->sk_protocol ==IPPROTO_TCP ) +ovpn_peer_put (peer); +else if (sk->sk_protocol ==IPPROTO_UDP ) +netdev_put (peer->ovpn->dev, &ovpn_sock->dev_tracker); +sock_put (sk);kfree (ovpn_sock); ovpn_sock =ERR_PTR (ret); - goto sock_release; - } - -/* TCP sockets are per-peer, therefore they are linked to their unique -* peer -*/ -if (sk->sk_protocol ==IPPROTO_TCP ) { -INIT_WORK (&ovpn_sock->tcp_tx_work, ovpn_tcp_tx_work); - ovpn_sock->peer = peer; -ovpn_peer_hold (peer); - }else if (sk->sk_protocol ==IPPROTO_UDP ) { -/* in UDP we only link the ovpn instance since the socket is -* shared among multiple peers -*/ - ovpn_sock->ovpn = peer->ovpn; -netdev_hold (peer->ovpn->dev, &ovpn_sock->dev_tracker, -GFP_KERNEL ); } -rcu_assign_sk_user_data (sk, ovpn_sock); sock_release:release_sock (sk);return ovpn_sock;
drivers/net/ovpn/tcp.c +7 -2
@@ -487,6 +487,7 @@ int ovpn_tcp_socket_attach(struct ovpn_socket *ovpn_sock,/* make sure no pre-existing encapsulation handler exists */ if (ovpn_sock->sk->sk_user_data)return -EBUSY ; +rcu_assign_sk_user_data (ovpn_sock->sk, ovpn_sock);/* only a fully connected socket is expected. Connection should be * handled in userspace
@@ -495,13 +496,14 @@ int ovpn_tcp_socket_attach(struct ovpn_socket *ovpn_sock,net_err_ratelimited ("%s: provided TCP socket is not in ESTABLISHED state: %d\n" ,netdev_name (peer->ovpn->dev), ovpn_sock->sk->sk_state); -return -EINVAL ; + ret = -EINVAL ; + goto err; } ret =strp_init (&peer->tcp.strp, ovpn_sock->sk, &cb);if (ret <0 ) {DEBUG_NET_WARN_ON_ONCE (1 ); -return ret; + goto err; }INIT_WORK (&peer->tcp.defer_del_work, ovpn_tcp_peer_del_work);
@@ -536,6 +538,9 @@ int ovpn_tcp_socket_attach(struct ovpn_socket *ovpn_sock,strp_check_rcv (&peer->tcp.strp);return 0 ; +err: +rcu_assign_sk_user_data (ovpn_sock->sk,NULL ); +return ret; }static void ovpn_tcp_close (struct sock *sk,long timeout)
drivers/net/ovpn/udp.c +1 -0
@@ -386,6 +386,7 @@ int ovpn_udp_socket_attach(struct ovpn_socket *ovpn_sock, struct socket *sock, struct ovpn_priv *ovpn) {struct udp_tunnel_sock_cfg cfg = { + .sk_user_data = ovpn_sock, .encap_type =UDP_ENCAP_OVPNINUDP , .encap_rcv = ovpn_udp_encap_recv, .encap_destroy = ovpn_udp_encap_destroy,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 633/781 ovpn: fix possible use-after-free in ovpn_net_xmit
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Lici <[email protected]>
[ Upstream commit a5ec7baa44ea3a1d6aa0ca31c0ad82edf9affe41 ]
When building the skb_list in ovpn_net_xmit, skb_share_check will free the original skb if it is shared. The current implementation continues to use the stale skb pointer for subsequent operations:
- peer lookup,
- skb_dst_drop (even though all segments produced by skb_gso_segment will have a dst attached),
- ovpn_peer_stats_increment_tx.
Fix this by moving the peer lookup and skb_dst_drop before segmentation so that the original skb is still valid when used. Return early if all segments fail skb_share_check and the list ends up empty. Also switch ovpn_peer_stats_increment_tx to use skb_list.next; the next patch fixes the stats logic.
--- drivers/net/ovpn/io.c | 52 ++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 21 deletions(-)
drivers/net/ovpn/io.c +31 -21
@@ -365,7 +365,27 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)/* verify IP header size in network packet */ proto =ovpn_ip_check_protocol (skb);if (unlikely (!proto || skb->protocol != proto)) - goto drop; + goto drop_no_peer; + +/* retrieve peer serving the destination IP of this packet */ + peer =ovpn_peer_get_by_dst (ovpn, skb); +if (unlikely (!peer)) { +switch (skb->protocol) { +case htons (ETH_P_IP ): +net_dbg_ratelimited ("%s: no peer to send data to dst=%pI4\n" , +netdev_name (ovpn->dev), + &ip_hdr (skb)->daddr); +break ; +case htons (ETH_P_IPV6 ): +net_dbg_ratelimited ("%s: no peer to send data to dst=%pI6c\n" , +netdev_name (ovpn->dev), + &ipv6_hdr (skb)->daddr); +break ; + } + goto drop_no_peer; + } +/* dst was needed for peer selection - it can now be dropped */ +skb_dst_drop (skb);if (skb_is_gso (skb)) { segments =skb_gso_segment (skb,0 );
@@ -396,34 +416,24 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)__skb_queue_tail (&skb_list, curr); } - skb_list.prev->next =NULL ; -/* retrieve peer serving the destination IP of this packet */ - peer =ovpn_peer_get_by_dst (ovpn, skb); -if (unlikely (!peer)) { -switch (skb->protocol) { -case htons (ETH_P_IP ): -net_dbg_ratelimited ("%s: no peer to send data to dst=%pI4\n" , -netdev_name (ovpn->dev), - &ip_hdr (skb)->daddr); -break ; -case htons (ETH_P_IPV6 ): -net_dbg_ratelimited ("%s: no peer to send data to dst=%pI6c\n" , -netdev_name (ovpn->dev), - &ipv6_hdr (skb)->daddr); -break ; - } - goto drop; +/* no segments survived: don't jump to 'drop' because we already +* incremented the counter for each failure in the loop +*/ +if (unlikely (skb_queue_empty (&skb_list))) { +ovpn_peer_put (peer); +return NETDEV_TX_OK ; } -/* dst was needed for peer selection - it can now be dropped */ -skb_dst_drop (skb); + skb_list.prev->next =NULL ; -ovpn_peer_stats_increment_tx (&peer->vpn_stats, skb->len); +ovpn_peer_stats_increment_tx (&peer->vpn_stats, skb_list.next->len);ovpn_send (ovpn, skb_list.next, peer);return NETDEV_TX_OK ; drop: +ovpn_peer_put (peer); +drop_no_peer:dev_dstats_tx_dropped (ovpn->dev);skb_tx_error (skb);kfree_skb_list (skb);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 634/781 ovpn: fix VPN TX bytes counting
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Lici <[email protected]>
[ Upstream commit b660b13d4c6379ca6360f24aaef8c5807fefd237 ]
In ovpn_net_xmit, after GSO segmentation and segment processing, the first segment on the list is used to increment VPN TX statistics, which fails to account for any subsequent segments in the chain.
Fix this by accumulating the length of every segment that successfully passes skb_share_check into a tx_bytes variable. This ensures the peer statistics accurately reflect the total data volume sent, regardless of whether the original packet was segmented.
--- drivers/net/ovpn/io.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ovpn/io.c +4 -1
@@ -355,6 +355,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)struct ovpn_priv *ovpn =netdev_priv (dev);struct sk_buff *segments, *curr, *next;struct sk_buff_head skb_list; +unsigned int tx_bytes =0 ;struct ovpn_peer *peer;__be16 proto;int ret;
@@ -414,6 +415,8 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev)continue ; } +/* only count what we actually send */ + tx_bytes += curr->len;__skb_queue_tail (&skb_list, curr); }
@@ -426,7 +429,7 @@ netdev_tx_t ovpn_net_xmit(struct sk_buff *skb, struct net_device *dev) } skb_list.prev->next =NULL ; -ovpn_peer_stats_increment_tx (&peer->vpn_stats, skb_list.next->len); +ovpn_peer_stats_increment_tx (&peer->vpn_stats, tx_bytes);ovpn_send (ovpn, skb_list.next, peer);return NETDEV_TX_OK ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 635/781 net: mctp: ensure our nlmsg responses are initialised
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeremy Kerr <[email protected]>
[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]
Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from DEVCORE Research Team working with Trend Micro Zero Day Initiative report that a RTM_GETNEIGH will return uninitalised data in the pad bytes of the ndmsg data.
Ensure we're initialising the netlink data to zero, in the link, addr and neigh response messages.
--- net/mctp/device.c | 1 + net/mctp/neigh.c | 1 + net/mctp/route.c | 1 + 3 files changed, 3 insertions(+)
net/mctp/device.c +1 -0
@@ -70,6 +70,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,return -EMSGSIZE ; hdr =nlmsg_data (nlh); +memset (hdr,0 ,sizeof (*hdr)); hdr->ifa_family =AF_MCTP ; hdr->ifa_prefixlen =0 ; hdr->ifa_flags =0 ;
net/mctp/neigh.c +1 -0
@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,return -EMSGSIZE ; hdr =nlmsg_data (nlh); +memset (hdr,0 ,sizeof (*hdr)); hdr->ndm_family =AF_MCTP ; hdr->ndm_ifindex = dev->ifindex; hdr->ndm_state =0 ;// TODO other state bits?
net/mctp/route.c +1 -0
@@ -1643,6 +1643,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,return -EMSGSIZE ; hdr =nlmsg_data (nlh); +memset (hdr,0 ,sizeof (*hdr)); hdr->rtm_family =AF_MCTP ;/* we use the _len fields as a number of EIDs, rather than
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 636/781 selftests: mlxsw: tc_restrictions: Fix test failure with new iproute2
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit a2646773a005b59fd1dc7ff3ba15df84889ca5d2 ]
As explained in [1], iproute2 started rejecting tc-police burst sizes that result in an overflow. This can happen when the burst size is high enough and the rate is low enough.
A couple of test cases specify such configurations, resulting in iproute2 errors and test failure.
Fix by reducing the burst size so that the test will pass with both new and old iproute2 versions.
[1] https://lore.kernel.org/netdev/[email protected]/
--- tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/drivers/net/mlxsw/tc_restrictions.sh +2 -2
@@ -317,7 +317,7 @@ police_limits_test() tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ flower skip_sw \ - action police rate 0.5kbit burst 1m conform-exceed drop/ok + action police rate 0.5kbit burst 2k conform-exceed drop/ok check_fail $? "Incorrect success to add police action with too low rate" tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \
@@ -327,7 +327,7 @@ police_limits_test() tc filter add dev $swp1 ingress pref 1 proto ip handle 101 \ flower skip_sw \ - action police rate 1.5kbit burst 1m conform-exceed drop/ok + action police rate 1.5kbit burst 2k conform-exceed drop/ok check_err $? "Failed to add police action with low rate" tc filter del dev $swp1 ingress protocol ip pref 1 handle 101 flower
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 637/781 selftests: net: lib: Fix jq parsing error
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yue Haibing <[email protected]>
[ Upstream commit 10ec0fc0ccc525abc807b0ca8ad5a26a0bd56361 ]
The testcase failed as below:$./vlan_bridge_binding.sh
...
+ adf_ip_link_set_up d1
+ local name=d1
+ shift
+ ip_link_is_up d1
+ ip_link_has_flag d1 UP
+ local name=d1
+ shift
+ local flag=UP
+ shift
++ ip -j link show d1
++ jq --arg flag UP 'any(.[].flags.[]; . == $flag)'
jq: error: syntax error, unexpected '[', expecting FORMAT or QQSTRING_START
(Unix shell quoting issues?) at <top-level>, line 1:
any(.[].flags.[]; . == $flag)
jq: 1 compile error
Remove the extra dot (.) after flags array to fix this.
--- tools/testing/selftests/net/lib.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/net/lib.sh +1 -1
@@ -577,7 +577,7 @@ ip_link_has_flag() local flag=$1; shift local state=$(ip -j link show "$name" | - jq --arg flag "$flag" 'any(.[].flags.[]; . == $flag)') + jq --arg flag "$flag" 'any(.[].flags[]; . == $flag)') [[ $state == true ]] }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 638/781 net: stmmac: fix oops when split header is enabled
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jie Zhang <[email protected]>
[ Upstream commit babab1b42ed68877ef669a08384becf281ad2582 ]
For GMAC4, when split header is enabled, in some rare cases, the hardware does not fill buf2 of the first descriptor with payload. Thus we cannot assume buf2 is always fully filled if it is not the last descriptor. Otherwise, the length of buf2 of the second descriptor will be calculated wrong and cause an oops:
Unable to handle kernel paging request at virtual address ffff00019246bfc0 ... x2 : 0000000000000040 x1 : ffff00019246bfc0 x0 : ffff00009246c000 Call trace: dcache_inval_poc+0x28/0x58 (P) dma_direct_sync_single_for_cpu+0x38/0x6c __dma_sync_single_for_cpu+0x34/0x6c stmmac_napi_poll_rx+0x8f0/0xb60 __napi_poll.constprop.0+0x30/0x144 net_rx_action+0x160/0x274 handle_softirqs+0x1b8/0x1fc
...
To fix this, the PL bit-field in RDES3 register is used for all descriptors, whether it is the last descriptor or not.
--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +17 -3
@@ -5023,13 +5023,27 @@ static unsigned int stmmac_rx_buf2_len(struct stmmac_priv *priv,if (!priv->sph_active)return 0 ; -/* Not last descriptor */ -if (status & rx_not_ls) +/* For GMAC4, when split header is enabled, in some rare cases, the +* hardware does not fill buf2 of the first descriptor with payload. +* Thus we cannot assume buf2 is always fully filled if it is not +* the last descriptor. Otherwise, the length of buf2 of the second +* descriptor will be calculated wrong and cause an oops. +* +* If this is the last descriptor, 'plen' is the length of the +* received packet that was transferred to system memory. +* Otherwise, it is the accumulated number of bytes that have been +* transferred for the current packet. +* +* Thus 'plen - len' always gives the correct length of buf2. +*/ + +/* Not GMAC4 and not last descriptor */ +if (priv->plat->core_type !=DWMAC_CORE_GMAC4 && (status & rx_not_ls))return priv->dma_conf.dma_buf_sz; +/* GMAC4 or last descriptor */ plen =stmmac_get_rx_frame_len (priv, p, coe); -/* Last descriptor */ return plen - len; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 639/781 net: sparx5/lan969x: fix DWRR cost max to match hardware register width
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Machon <[email protected]>
[ Upstream commit 6c28aa8dfdf24f554d4c5d4ff7d723a95360d94a ]
DWRR (Deficit Weighted Round Robin) scheduling distributes bandwidth across traffic classes based on per-queue cost values, where lower cost means higher bandwidth share.
The SPX5_DWRR_COST_MAX constant is 63 (6 bits) but the hardware register field HSCH_DWRR_ENTRY_DWRR_COST is GENMASK(24, 20), only 5 bits wide (max 31). This causes sparx5_weight_to_hw_cost() to compute cost values that silently overflow via FIELD_PREP, resulting in incorrect scheduling weights.
Set SPX5_DWRR_COST_MAX to 31 to match the hardware register width.
--- drivers/net/ethernet/microchip/sparx5/sparx5_qos.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/microchip/sparx5/sparx5_qos.h +1 -1
@@ -35,7 +35,7 @@#define SPX5_SE_BURST_UNIT 4096/* Dwrr */ -#define SPX5_DWRR_COST_MAX 63 +#define SPX5_DWRR_COST_MAX 31struct sparx5_shaper {u32 mode;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 640/781 net: mscc: ocelot: extract ocelot_xmit_timestamp() helper
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 29372f07f7969a2f0490793226ecf6c8c6bde0fa ]
Extract the PTP timestamp handling logic from ocelot_port_xmit() into a separate ocelot_xmit_timestamp() helper function. This is a pure refactor with no behavioral change.
The helper returns false if the skb was consumed (freed) due to a timestamp request failure, and true if the caller should continue with frame injection. The rew_op value is returned via pointer.
This prepares for splitting ocelot_port_xmit() into separate FDMA and register injection paths in a subsequent patch.
Stable-dep-of: 026f6513c588 ("net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj()")
--- drivers/net/ethernet/mscc/ocelot_net.c | 36 ++++++++++++++++---------- 1 file changed, 22 insertions(+), 14 deletions(-)
drivers/net/ethernet/mscc/ocelot_net.c +22 -14
@@ -551,33 +551,41 @@ static int ocelot_port_stop(struct net_device *dev)return 0 ; } -static netdev_tx_t ocelot_port_xmit (struct sk_buff *skb,struct net_device *dev) +static bool ocelot_xmit_timestamp (struct ocelot *ocelot,int port, +struct sk_buff *skb,u32 *rew_op) { -struct ocelot_port_private *priv =netdev_priv (dev); -struct ocelot_port *ocelot_port = &priv->port; -struct ocelot *ocelot = ocelot_port->ocelot; -int port = priv->port.index; -u32 rew_op =0 ; - -if (!static_branch_unlikely (&ocelot_fdma_enabled) && - !ocelot_can_inject (ocelot,0 )) -return NETDEV_TX_BUSY ; - -/* Check if timestamping is needed */ if (ocelot->ptp && (skb_shinfo (skb)->tx_flags &SKBTX_HW_TSTAMP )) {struct sk_buff *clone =NULL ;if (ocelot_port_txtstamp_request (ocelot, port, skb, &clone)) {kfree_skb (skb); -return NETDEV_TX_OK ; +return false; }if (clone)OCELOT_SKB_CB (skb)->clone = clone; - rew_op =ocelot_ptp_rew_op (skb); + *rew_op =ocelot_ptp_rew_op (skb); } +return true; +} + +static netdev_tx_t ocelot_port_xmit (struct sk_buff *skb,struct net_device *dev) +{ +struct ocelot_port_private *priv =netdev_priv (dev); +struct ocelot_port *ocelot_port = &priv->port; +struct ocelot *ocelot = ocelot_port->ocelot; +int port = priv->port.index; +u32 rew_op =0 ; + +if (!static_branch_unlikely (&ocelot_fdma_enabled) && + !ocelot_can_inject (ocelot,0 )) +return NETDEV_TX_BUSY ; + +if (!ocelot_xmit_timestamp (ocelot, port, skb, &rew_op)) +return NETDEV_TX_OK ; +if (static_branch_unlikely (&ocelot_fdma_enabled)) {ocelot_fdma_inject_frame (ocelot, port, rew_op, skb, dev); }else {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 641/781 net: mscc: ocelot: split xmit into FDMA and register injection paths
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 47f79b20e7fb885aa1623b759a68e8e27401ec4d ]
Split ocelot_port_xmit() into two separate functions:
- ocelot_port_xmit_fdma(): handles the FDMA injection path
- ocelot_port_xmit_inj(): handles the register-based injection path
The top-level ocelot_port_xmit() now dispatches to the appropriate function based on the ocelot_fdma_enabled static key.
This is a pure refactor with no behavioral change. Separating the two code paths makes each one simpler and prepares for adding proper locking to the register injection path without affecting the FDMA path.
Stable-dep-of: 026f6513c588 ("net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj()")
--- drivers/net/ethernet/mscc/ocelot_net.c | 39 ++++++++++++++++++++------ 1 file changed, 30 insertions(+), 9 deletions(-)
drivers/net/ethernet/mscc/ocelot_net.c +30 -9
@@ -571,7 +571,25 @@ static bool ocelot_xmit_timestamp(struct ocelot *ocelot, int port,return true; } -static netdev_tx_t ocelot_port_xmit (struct sk_buff *skb,struct net_device *dev) +static netdev_tx_t ocelot_port_xmit_fdma (struct sk_buff *skb, +struct net_device *dev) +{ +struct ocelot_port_private *priv =netdev_priv (dev); +struct ocelot_port *ocelot_port = &priv->port; +struct ocelot *ocelot = ocelot_port->ocelot; +int port = priv->port.index; +u32 rew_op =0 ; + +if (!ocelot_xmit_timestamp (ocelot, port, skb, &rew_op)) +return NETDEV_TX_OK ; + +ocelot_fdma_inject_frame (ocelot, port, rew_op, skb, dev); + +return NETDEV_TX_OK ; +} + +static netdev_tx_t ocelot_port_xmit_inj (struct sk_buff *skb, +struct net_device *dev) {struct ocelot_port_private *priv =netdev_priv (dev);struct ocelot_port *ocelot_port = &priv->port;
@@ -579,24 +597,27 @@ static netdev_tx_t ocelot_port_xmit(struct sk_buff *skb, struct net_device *dev)int port = priv->port.index;u32 rew_op =0 ; -if (!static_branch_unlikely (&ocelot_fdma_enabled) && - !ocelot_can_inject (ocelot,0 )) +if (!ocelot_can_inject (ocelot,0 ))return NETDEV_TX_BUSY ;if (!ocelot_xmit_timestamp (ocelot, port, skb, &rew_op))return NETDEV_TX_OK ; -if (static_branch_unlikely (&ocelot_fdma_enabled)) { -ocelot_fdma_inject_frame (ocelot, port, rew_op, skb, dev); - }else { -ocelot_port_inject_frame (ocelot, port,0 , rew_op, skb); +ocelot_port_inject_frame (ocelot, port,0 , rew_op, skb); -consume_skb (skb); - } +consume_skb (skb);return NETDEV_TX_OK ; } +static netdev_tx_t ocelot_port_xmit (struct sk_buff *skb,struct net_device *dev) +{ +if (static_branch_unlikely (&ocelot_fdma_enabled)) +return ocelot_port_xmit_fdma (skb, dev); + +return ocelot_port_xmit_inj (skb, dev); +} +enum ocelot_action_type {OCELOT_MACT_LEARN ,OCELOT_MACT_FORGET ,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 642/781 net: mscc: ocelot: add missing lock protection in ocelot_port_xmit_inj()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 026f6513c5880c2c89e38ad66bbec2868f978605 ]
ocelot_port_xmit_inj() calls ocelot_can_inject() and ocelot_port_inject_frame() without holding the injection group lock. Both functions contain lockdep_assert_held() for the injection lock, and the correct caller felix_port_deferred_xmit() properly acquires the lock using ocelot_lock_inj_grp() before calling these functions.
Add ocelot_lock_inj_grp()/ocelot_unlock_inj_grp() around the register injection path to fix the missing lock protection. The FDMA path is not affected as it uses its own locking mechanism.
--- drivers/net/ethernet/mscc/ocelot_net.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/net/ethernet/mscc/ocelot_net.c +10 -2
@@ -597,14 +597,22 @@ static netdev_tx_t ocelot_port_xmit_inj(struct sk_buff *skb,int port = priv->port.index;u32 rew_op =0 ; -if (!ocelot_can_inject (ocelot,0 )) +ocelot_lock_inj_grp (ocelot,0 ); + +if (!ocelot_can_inject (ocelot,0 )) { +ocelot_unlock_inj_grp (ocelot,0 );return NETDEV_TX_BUSY ; + } -if (!ocelot_xmit_timestamp (ocelot, port, skb, &rew_op)) +if (!ocelot_xmit_timestamp (ocelot, port, skb, &rew_op)) { +ocelot_unlock_inj_grp (ocelot,0 );return NETDEV_TX_OK ; + }ocelot_port_inject_frame (ocelot, port,0 , rew_op, skb); +ocelot_unlock_inj_grp (ocelot,0 ); +consume_skb (skb);return NETDEV_TX_OK ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 643/781 selftests: netconsole: Increase port listening timeout
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pin-yen Lin <[email protected]>
[ Upstream commit a68a9bd086c2822d0c629443bd16ad1317afe501 ]
wait_for_port() can wait up to 2 seconds with the sleep and the polling in wait_local_port_listen() combined. So, in netcons_basic.sh, the socat process could die before the test writes to the netconsole.
Increase the timeout to 3 seconds to make netcons_basic.sh pass consistently.
--- tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh +2 -2
@@ -247,8 +247,8 @@ function listen_port_and_save_to() { SOCAT_MODE="UDP6-LISTEN" fi - # Just wait for 2 seconds - timeout 2 ip netns exec "${NAMESPACE}" \ + # Just wait for 3 seconds + timeout 3 ip netns exec "${NAMESPACE}" \ socat "${SOCAT_MODE}":"${PORT}",fork "${OUTPUT}" 2> /dev/null }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 644/781 ipv6: Fix out-of-bound access in fib6_add_rt2node().
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 8244f959e2c125c849e569f5b23ed49804cce695 ]
syzbot reported out-of-bound read in fib6_add_rt2node(). [0]
When IPv6 route is created with RTA_NH_ID, struct fib6_info does not have the trailing struct fib6_nh.
The cited commit started to check !iter->fib6_nh->fib_nh_gw_family to ensure that rt6_qualify_for_ecmp() will return false for iter.
If iter->nh is not NULL, rt6_qualify_for_ecmp() returns false anyway.
Let's check iter->nh before reading iter->fib6_nh and avoid OOB read.
[0]:
BUG: KASAN: slab-out-of-bounds in fib6_add_rt2node+0x349c/0x3500 net/ipv6/ip6_fib.c:1142 Read of size 1 at addr ffff8880384ba6de by task syz.0.18/5500 CPU: 0 UID: 0 PID: 5500 Comm: syz.0.18 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <TASK> dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0xba/0x230 mm/kasan/report.c:482 kasan_report+0x117/0x150 mm/kasan/report.c:595 fib6_add_rt2node+0x349c/0x3500 net/ipv6/ip6_fib.c:1142 fib6_add_rt2node_nh net/ipv6/ip6_fib.c:1363 [inline] fib6_add+0x910/0x18c0 net/ipv6/ip6_fib.c:1531 __ip6_ins_rt net/ipv6/route.c:1351 [inline] ip6_route_add+0xde/0x1b0 net/ipv6/route.c:3957 inet6_rtm_newroute+0x268/0x19e0 net/ipv6/route.c:5660 rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958 netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550 netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline] netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344 netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894 sock_sendmsg_nosec net/socket.c:727 [inline] __sock_sendmsg net/socket.c:742 [inline] ____sys_sendmsg+0xa68/0xad0 net/socket.c:2592 ___sys_sendmsg+0x2a5/0x360 net/socket.c:2646 __sys_sendmsg net/socket.c:2678 [inline] __do_sys_sendmsg net/socket.c:2683 [inline] __se_sys_sendmsg net/socket.c:2681 [inline] __x64_sys_sendmsg+0x1bd/0x2a0 net/socket.c:2681 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f9316b9aeb9 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffd8809b678 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007f9316e15fa0 RCX: 00007f9316b9aeb9 RDX: 0000000000000000 RSI: 0000200000004380 RDI: 0000000000000003 RBP: 00007f9316c08c1f R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007f9316e15fac R14: 00007f9316e15fa0 R15: 00007f9316e15fa0 </TASK> Allocated by task 5499: kasan_save_stack mm/kasan/common.c:57 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:78 poison_kmalloc_redzone mm/kasan/common.c:398 [inline] __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:415 kasan_kmalloc include/linux/kasan.h:263 [inline] __do_kmalloc_node mm/slub.c:5657 [inline] __kmalloc_noprof+0x40c/0x7e0 mm/slub.c:5669 kmalloc_noprof include/linux/slab.h:961 [inline] kzalloc_noprof include/linux/slab.h:1094 [inline] fib6_info_alloc+0x30/0xf0 net/ipv6/ip6_fib.c:155 ip6_route_info_create+0x142/0x860 net/ipv6/route.c:3820 ip6_route_add+0x49/0x1b0 net/ipv6/route.c:3949 inet6_rtm_newroute+0x268/0x19e0 net/ipv6/route.c:5660 rtnetlink_rcv_msg+0x7d5/0xbe0 net/core/rtnetlink.c:6958 netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550 netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline] netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344 netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894 sock_sendmsg_nosec net/socket.c:727 [inline] __sock_sendmsg net/socket.c:742 [inline] ____sys_sendmsg+0xa68/0xad0 net/socket.c:2592 ___sys_sendmsg+0x2a5/0x360 net/socket.c:2646 __sys_sendmsg net/socket.c:2678 [inline] __do_sys_sendmsg net/socket.c:2683 [inline] __se_sys_sendmsg net/socket.c:2681 [inline] __x64_sys_sendmsg+0x1bd/0x2a0 net/socket.c:2681 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f
--- net/ipv6/ip6_fib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/ip6_fib.c +1 -1
@@ -1139,7 +1139,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct fib6_info *rt,fib6_add_gc_list (iter); }if (!(rt->fib6_flags & (RTF_ADDRCONF |RTF_PREFIX_RT )) && - !iter->fib6_nh->fib_nh_gw_family) { + (iter->nh || !iter->fib6_nh->fib_nh_gw_family)) { iter->fib6_flags &= ~RTF_ADDRCONF ; iter->fib6_flags &= ~RTF_PREFIX_RT ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 645/781 net: sparx5/lan969x: fix PTP clock max_adj value
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Machon <[email protected]>
[ Upstream commit a49d2a2c37a6252c41cbdd505f9d1c58d5a3817a ]
The max_adj field in ptp_clock_info tells userspace how much the PHC clock frequency can be adjusted. ptp4l reads this and will never request a correction larger than max_adj.
On both sparx5 and lan969x the clock offset may never converge because the servo needs a frequency correction larger than the current max_adj of 200000 (200 ppm) allows. The servo rails at the max and the offset stays in the tens of microseconds.
The hardware has no inherent max adjustment limit; frequency correction is done by writing a 64-bit clock period increment to CLK_PER_CFG, and the register has plenty of range. The 200000 value was just an overly conservative software limit. The max_adj is shared between sparx5 and lan969x, and the increased value is safe for both.
Fix this by increasing max_adj to 10000000 (10000 ppm), giving the servo sufficient headroom.
--- drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c +1 -1
@@ -576,7 +576,7 @@ static int sparx5_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)static struct ptp_clock_info sparx5_ptp_clock_info = { .owner =THIS_MODULE , .name ="sparx5 ptp" , - .max_adj =200000 , + .max_adj =10000000 , .gettime64 = sparx5_ptp_gettime64, .settime64 = sparx5_ptp_settime64, .adjtime = sparx5_ptp_adjtime,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 646/781 fbnic: close fw_log race between users and teardown
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
[ Upstream commit ee5492fd88cfc079c19fbeac78e9e53b7f6c04f3 ]
Fixes a theoretical race on fw_log between the teardown path and fw_log write functions.
fw_log is written inside fbnic_fw_log_write() and can be reached from the mailbox handler fbnic_fw_msix_intr(), but fw_log is freed before IRQ/MBX teardown during cleanup, resulting in a potential data race of dereferencing a freed/null variable.
Possible Interleaving Scenario:
CPU0: fbnic_fw_msix_intr() // Entry
fbnic_fw_log_write()
if (fbnic_fw_log_ready()) // true
... preempt ...
CPU1: fbnic_remove() // Entry
fbnic_fw_log_free()
vfree(log->data_start);
log->data_start = NULL; CPU0: continues, walks log->entries or writes to log->data_start
The initialization also has an incorrect order problem, as the fw_log is currently allocated after MBX setup during initialization. Fix the problems by adjusting the synchronization order to put initialization in place before the mailbox is enabled, and not cleared until after the mailbox has been disabled.
--- .../net/ethernet/meta/fbnic/fbnic_fw_log.c | 3 --- drivers/net/ethernet/meta/fbnic/fbnic_pci.c | 19 ++++++++++++------- 2 files changed, 12 insertions(+), 10 deletions(-)
drivers/net/ethernet/meta/fbnic/fbnic_fw_log.c +0 -3
@@ -51,8 +51,6 @@ int fbnic_fw_log_init(struct fbnic_dev *fbd) log->data_start = data; log->data_end = data +FBNIC_FW_LOG_SIZE ; -fbnic_fw_log_enable (fbd, true); -return 0 ; }
@@ -63,7 +61,6 @@ void fbnic_fw_log_free(struct fbnic_dev *fbd)if (!fbnic_fw_log_ready (fbd))return ; -fbnic_fw_log_disable (fbd);INIT_LIST_HEAD (&log->entries); log->size =0 ;vfree (log->data_start);
drivers/net/ethernet/meta/fbnic/fbnic_pci.c +12 -7
@@ -307,11 +307,17 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto free_irqs; } + err =fbnic_fw_log_init (fbd); +if (err) +dev_warn (fbd->dev, +"Unable to initialize firmware log buffer: %d\n" , + err); + err =fbnic_fw_request_mbx (fbd);if (err) {dev_err (&pdev->dev,"Firmware mailbox initialization failure\n" ); - goto free_irqs; + goto free_fw_log; }/* Send the request to enable the FW logging to host. Note if this
@@ -319,11 +325,7 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)* possible the FW is just too old to support the logging and needs * to be updated. */ - err =fbnic_fw_log_init (fbd); -if (err) -dev_warn (fbd->dev, -"Unable to initialize firmware log buffer: %d\n" , - err); +fbnic_fw_log_enable (fbd, true);fbnic_devlink_register (fbd);fbnic_devlink_otp_check (fbd,"error detected during probe" );
@@ -370,6 +372,8 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)* firmware updates for fixes. */ return 0 ; +free_fw_log: +fbnic_fw_log_free (fbd); free_irqs:fbnic_free_irqs (fbd); err_destroy_health:
@@ -404,8 +408,9 @@ static void fbnic_remove(struct pci_dev *pdev)fbnic_hwmon_unregister (fbd);fbnic_dbg_fbd_exit (fbd);fbnic_devlink_unregister (fbd); -fbnic_fw_log_free (fbd); +fbnic_fw_log_disable (fbd);fbnic_fw_free_mbx (fbd); +fbnic_fw_log_free (fbd);fbnic_free_irqs (fbd);fbnic_devlink_health_destroy (fbd);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 647/781 libbpf: Fix invalid write loop logic in bpf_linker__add_buf()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amery Hung <[email protected]>
[ Upstream commit 04999b99e81eaa7b6223ec1c03af3bcb4ac57aaa ]
Fix bpf_linker__add_buf()'s logic of copying data from memory buffer into memfd. In the event of short write not writing entire buf_sz bytes into memfd file, we'll append bytes from the beginning of buf *again* (corrupting ELF file contents) instead of correctly appending the rest of not-yet-read buf contents.
--- tools/lib/bpf/linker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/lib/bpf/linker.c +1 -1
@@ -581,7 +581,7 @@ int bpf_linker__add_buf(struct bpf_linker *linker, void *buf, size_t buf_sz, written =0 ;while (written < buf_sz) { - ret =write (fd, buf, buf_sz); + ret =write (fd, buf + written, buf_sz - written);if (ret <0 ) { ret = -errno;pr_warn ("failed to write '%s': %s\n" , filename,errstr (ret));
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 648/781 bpf: Fix a potential use-after-free of BTF object
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anton Protopopov <[email protected]>
[ Upstream commit ccd2d799ed4467c07f5ee18c2f5c59bcc990822c ]
Refcounting in the check_pseudo_btf_id() function is incorrect:
the __check_pseudo_btf_id() function might get called with a zero refcounted btf. Fix this, and patch related code accordingly.
v3: rephrase a comment (AI)
v2: fix a refcount leak introduced in v1 (AI)
--- kernel/bpf/verifier.c | 52 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 26 deletions(-)
kernel/bpf/verifier.c +26 -26
@@ -20685,29 +20685,29 @@ static int find_btf_percpu_datasec(struct btf *btf) }/* -* Add btf to the used_btfs array and return the index. (If the btf was -* already added, then just return the index.) Upon successful insertion -* increase btf refcnt, and, if present, also refcount the corresponding -* kernel module. +* Add btf to the env->used_btfs array. If needed, refcount the +* corresponding kernel module. To simplify caller's logic +* in case of error or if btf was added before the function +* decreases the btf refcount. */ static int __add_used_btf (struct bpf_verifier_env *env,struct btf *btf) {struct btf_mod_pair *btf_mod; +int ret =0 ;int i;/* check whether we recorded this BTF (and maybe module) already */ for (i =0 ; i < env->used_btf_cnt; i++)if (env->used_btfs[i].btf == btf) -return i; + goto ret_put;if (env->used_btf_cnt >=MAX_USED_BTFS ) {verbose (env,"The total number of btfs per program has reached the limit of %u\n" ,MAX_USED_BTFS ); -return -E2BIG ; + ret = -E2BIG ; + goto ret_put; } -btf_get (btf); - btf_mod = &env->used_btfs[env->used_btf_cnt]; btf_mod->btf = btf; btf_mod->module =NULL ;
@@ -20716,12 +20716,18 @@ static int __add_used_btf(struct bpf_verifier_env *env, struct btf *btf)if (btf_is_module (btf)) { btf_mod->module =btf_try_get_module (btf);if (!btf_mod->module) { -btf_put (btf); -return -ENXIO ; + ret = -ENXIO ; + goto ret_put; } } -return env->used_btf_cnt++; + env->used_btf_cnt++; +return 0 ; + +ret_put: +/* Either error or this BTF was already added */ +btf_put (btf); +return ret; }/* replace pseudo btf_id with kernel symbol address */
@@ -20818,9 +20824,7 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env, btf_fd = insn[1 ].imm;if (btf_fd) { -CLASS (fd, f)(btf_fd); - - btf =__btf_get_by_fd (f); + btf =btf_get_by_fd (btf_fd);if (IS_ERR (btf)) {verbose (env,"invalid module BTF object FD specified.\n" );return -EINVAL ;
@@ -20830,17 +20834,17 @@ static int check_pseudo_btf_id(struct bpf_verifier_env *env,verbose (env,"kernel is missing BTF, make sure CONFIG_DEBUG_INFO_BTF=y is specified in Kconfig.\n" );return -EINVAL ; } +btf_get (btf_vmlinux); btf = btf_vmlinux; } err =__check_pseudo_btf_id (env, insn, aux, btf); -if (err) +if (err) { +btf_put (btf);return err; + } - err =__add_used_btf (env, btf); -if (err <0 ) -return err; -return 0 ; +return __add_used_btf (env, btf); }static bool is_tracing_prog_type (enum bpf_prog_type type)
@@ -24654,13 +24658,9 @@ static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd)return 0 ; } - btf =__btf_get_by_fd (f); -if (!IS_ERR (btf)) { - err =__add_used_btf (env, btf); -if (err <0 ) -return err; -return 0 ; - } + btf =btf_get_by_fd (fd); +if (!IS_ERR (btf)) +return __add_used_btf (env, btf);verbose (env,"fd %d is not pointing to valid bpf_map or btf\n" , fd);return PTR_ERR (map);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 649/781 bpf: Add a map/btf from a fd array more consistently
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anton Protopopov <[email protected]>
[ Upstream commit b0b1a8583d8e797114e613139e3e3318a1704690 ]
The add_fd_from_fd_array() function takes a file descriptor as a parameter and tries to add either map or btf to the corresponding list of used objects. As was reported by Dan Carpenter, since the commit c81e4322acf0 ("bpf: Fix a potential use-after-free of BTF object"), the fdget() is called twice on the file descriptor, and thus userspace, potentially, can replace the file pointed to by the file descriptor in between the two calls. On practice, this shouldn't break anything on the kernel side, but for consistency fix the code such that only one fdget() is executed.
--- kernel/bpf/verifier.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
kernel/bpf/verifier.c +4 -2
@@ -24658,9 +24658,11 @@ static int add_fd_from_fd_array(struct bpf_verifier_env *env, int fd)return 0 ; } - btf =btf_get_by_fd (fd); -if (!IS_ERR (btf)) + btf =__btf_get_by_fd (f); +if (!IS_ERR (btf)) { +btf_get (btf);return __add_used_btf (env, btf); + }verbose (env,"fd %d is not pointing to valid bpf_map or btf\n" , fd);return PTR_ERR (map);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 650/781 eth: fbnic: set FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT on RDE_CTL0
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bobby Eshleman <[email protected]>
[ Upstream commit bbeb3bfbffe0279fa47c041658b037fb38a93965 ]
Fix EN_HDR_SPLIT configuration by writing the field to RDE_CTL0 instead of RDE_CTL1.
Because drop mode configuration and header splitting enablement both use RDE_CTL0, we consolidate these configurations into the single function fbnic_config_drop_mode.
--- drivers/net/ethernet/meta/fbnic/fbnic_txrx.c | 25 +++++++++++--------- 1 file changed, 14 insertions(+), 11 deletions(-)
drivers/net/ethernet/meta/fbnic/fbnic_txrx.c +14 -11
@@ -2575,7 +2575,8 @@ static void fbnic_enable_bdq(struct fbnic_ring *hpq, struct fbnic_ring *ppq) }static void fbnic_config_drop_mode_rcq (struct fbnic_napi_vector *nv, -struct fbnic_ring *rcq,bool tx_pause) +struct fbnic_ring *rcq,bool tx_pause, +bool hdr_split) {struct fbnic_net *fbn =netdev_priv (nv->napi.dev);u32 drop_mode, rcq_ctl;
@@ -2588,22 +2589,26 @@ static void fbnic_config_drop_mode_rcq(struct fbnic_napi_vector *nv,/* Specify packet layout */ rcq_ctl =FIELD_PREP (FBNIC_QUEUE_RDE_CTL0_DROP_MODE_MASK , drop_mode) |FIELD_PREP (FBNIC_QUEUE_RDE_CTL0_MIN_HROOM_MASK ,FBNIC_RX_HROOM ) | -FIELD_PREP (FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK ,FBNIC_RX_TROOM ); +FIELD_PREP (FBNIC_QUEUE_RDE_CTL0_MIN_TROOM_MASK ,FBNIC_RX_TROOM ) | +FIELD_PREP (FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT , hdr_split);fbnic_ring_wr32 (rcq,FBNIC_QUEUE_RDE_CTL0 , rcq_ctl); } -void fbnic_config_drop_mode (struct fbnic_net *fbn,bool tx_pause) +void fbnic_config_drop_mode (struct fbnic_net *fbn,bool txp) { +bool hds;int i, t; + hds = fbn->hds_thresh <FBNIC_HDR_BYTES_MIN ; +for (i =0 ; i < fbn->num_napi; i++) {struct fbnic_napi_vector *nv = fbn->napi[i];for (t =0 ; t < nv->rxt_count; t++) {struct fbnic_q_triad *qt = &nv->qt[nv->txt_count + t]; -fbnic_config_drop_mode_rcq (nv, &qt->cmpl, tx_pause); +fbnic_config_drop_mode_rcq (nv, &qt->cmpl, txp, hds); } } }
@@ -2654,20 +2659,18 @@ static void fbnic_enable_rcq(struct fbnic_napi_vector *nv, {struct fbnic_net *fbn =netdev_priv (nv->napi.dev);u32 log_size =fls (rcq->size_mask); -u32 hds_thresh = fbn->hds_thresh;u32 rcq_ctl =0 ; - -fbnic_config_drop_mode_rcq (nv, rcq, fbn->tx_pause); +bool hdr_split; +u32 hds_thresh;/* Force lower bound on MAX_HEADER_BYTES. Below this, all frames should * be split at L4. It would also result in the frames being split at * L2/L3 depending on the frame size. */ -if (fbn->hds_thresh <FBNIC_HDR_BYTES_MIN ) { - rcq_ctl =FBNIC_QUEUE_RDE_CTL0_EN_HDR_SPLIT ; - hds_thresh =FBNIC_HDR_BYTES_MIN ; - } + hdr_split = fbn->hds_thresh <FBNIC_HDR_BYTES_MIN ; +fbnic_config_drop_mode_rcq (nv, rcq, fbn->tx_pause, hdr_split); + hds_thresh =max (fbn->hds_thresh,FBNIC_HDR_BYTES_MIN ); rcq_ctl |=FIELD_PREP (FBNIC_QUEUE_RDE_CTL1_PADLEN_MASK ,FBNIC_RX_PAD ) |FIELD_PREP (FBNIC_QUEUE_RDE_CTL1_MAX_HDR_MASK , hds_thresh) | FIELD_PREP(FBNIC_QUEUE_RDE_CTL1_PAYLD_OFF_MASK,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 651/781 eth: fbnic: increase FBNIC_HDR_BYTES_MIN from 128 to 256 bytes
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bobby Eshleman <[email protected]>
[ Upstream commit bd254115f38db3c046332bb62e8719e0dc7c2b53 ]
Increase FBNIC_HDR_BYTES_MIN from 128 to 256 bytes. The previous minimum was too small to guarantee that very long L2+L3+L4 headers always fit within the header buffer. When EN_HDR_SPLIT is disabled and a packet exceeds MAX_HEADER_BYTES, splitting occurs at that byte offset instead of the header boundary, resulting in some of the header landing in the payload page. The increased minimum ensures headers always fit with the MAX_HEADER_BYTES cut off and land in the header page.
--- drivers/net/ethernet/meta/fbnic/fbnic_txrx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/meta/fbnic/fbnic_txrx.h +1 -1
@@ -66,7 +66,7 @@ struct fbnic_net; (4096 - FBNIC_RX_HROOM - FBNIC_RX_TROOM - FBNIC_RX_PAD)#define FBNIC_HDS_THRESH_DEFAULT \ (1536 - FBNIC_RX_PAD) -#define FBNIC_HDR_BYTES_MIN 128 +#define FBNIC_HDR_BYTES_MIN 256struct fbnic_pkt_buff {struct xdp_buff buff;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 652/781 eth: fbnic: set DMA_HINT_L4 for all flows
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bobby Eshleman <[email protected]>
[ Upstream commit 0f30a31b55c4179fc55613a75ef41d496687d465 ]
fbnic always advertises ETHTOOL_TCP_DATA_SPLIT_ENABLED via ethtool .get_ringparam. To enable proper splitting for all flow types, even for IP/Ethernet flows, this patch sets DMA_HINT_L4 unconditionally for all RSS and NFC flow steering rules. According to the spec, L4 falls back to L3 if no valid L4 is found, and L3 falls back to L2 if no L3 is found. This makes sure that the correct header boundary is used regardless of traffic type. This is important for zero-copy use cases where we must ensure that all ZC packets are split correctly.
--- drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c | 3 +++ drivers/net/ethernet/meta/fbnic/fbnic_rpc.c | 5 ++--- 2 files changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c +3 -0
@@ -1142,6 +1142,9 @@ static int fbnic_set_cls_rule_ins(struct fbnic_net *fbn,return -EINVAL ; } + dest |=FIELD_PREP (FBNIC_RPC_ACT_TBL0_DMA_HINT , +FBNIC_RCD_HDR_AL_DMA_HINT_L4 ); +/* Write action table values */ act_tcam->dest = dest; act_tcam->rss_en_mask =fbnic_flow_hash_2_rss_en_mask (fbn, hash_idx);
drivers/net/ethernet/meta/fbnic/fbnic_rpc.c +2 -3
@@ -338,9 +338,8 @@ void fbnic_rss_reinit(struct fbnic_dev *fbd, struct fbnic_net *fbn)else if (tstamp_mask & (1u << flow_type)) dest |=FBNIC_RPC_ACT_TBL0_TS_ENA ; -if (act1_value[flow_type] &FBNIC_RPC_TCAM_ACT1_L4_VALID ) - dest |=FIELD_PREP (FBNIC_RPC_ACT_TBL0_DMA_HINT , -FBNIC_RCD_HDR_AL_DMA_HINT_L4 ); + dest |=FIELD_PREP (FBNIC_RPC_ACT_TBL0_DMA_HINT , +FBNIC_RCD_HDR_AL_DMA_HINT_L4 ); rss_en_mask =fbnic_flow_hash_2_rss_en_mask (fbn, flow_type);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 653/781 ovpn: tcp - dont deref NULL sk_socket member after tcp_close()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antonio Quartulli <[email protected]>
[ Upstream commit 94560267d6c41b1ff3fafbab726e3f8a55a6af34 ]
When deleting a peer in case of keepalive expiration, the peer is removed from the OpenVPN hashtable and is temporary inserted in a "release list" for further processing.
This happens in:ovpn_peer_keepalive_work()
unlock_ovpn(release_list)
This processing includes detaching from the socket being used to talk to this peer, by restoring its original proto and socket ops/callbacks.
In case of TCP it may happen that, while the peer is sitting in the release list, userspace decides to close the socket. This will result in a concurrent execution of:
tcp_close(sk)
__tcp_close(sk)
sock_orphan(sk)
sk_set_socket(sk, NULL)
The last function call will set sk->sk_socket to NULL.
When the releasing routine is resumed, ovpn_tcp_socket_detach() will attempt to dereference sk->sk_socket to restore its original ops member. This operation will crash due to sk->sk_socket being NULL.
Fix this race condition by testing-and-accessing sk->sk_socket atomically under sk->sk_callback_lock.
--- drivers/net/ovpn/tcp.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-)
drivers/net/ovpn/tcp.c +13 -1
@@ -199,7 +199,19 @@ void ovpn_tcp_socket_detach(struct ovpn_socket *ovpn_sock) sk->sk_data_ready = peer->tcp.sk_cb.sk_data_ready; sk->sk_write_space = peer->tcp.sk_cb.sk_write_space; sk->sk_prot = peer->tcp.sk_cb.prot; - sk->sk_socket->ops = peer->tcp.sk_cb.ops; + +/* tcp_close() may race this function and could set +* sk->sk_socket to NULL. It does so by invoking +* sock_orphan(), which holds sk_callback_lock before +* doing the assignment. +* +* For this reason we acquire the same lock to avoid +* sk_socket to disappear under our feet +*/ +write_lock_bh (&sk->sk_callback_lock); +if (sk->sk_socket) + sk->sk_socket->ops = peer->tcp.sk_cb.ops; +write_unlock_bh (&sk->sk_callback_lock);rcu_assign_sk_user_data (sk,NULL ); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 654/781 net: usb: catc: enable basic endpoint checking
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 9e7021d2aeae57c323a6f722ed7915686cdcc123 ]
catc_probe() fills three URBs with hardcoded endpoint pipes without verifying the endpoint descriptors:
- usb_sndbulkpipe(usbdev, 1) and usb_rcvbulkpipe(usbdev, 1) for TX/RX
- usb_rcvintpipe(usbdev, 2) for interrupt status
A malformed USB device can present these endpoints with transfer types that differ from what the driver assumes.
Add a catc_usb_ep enum for endpoint numbers, replacing magic constants throughout. Add usb_check_bulk_endpoints() and usb_check_int_endpoints() calls after usb_set_interface() to verify endpoint types before use, rejecting devices with mismatched descriptors at probe time.
Similar to
- commit 90b7f2961798 ("net: usb: rtl8150: enable basic endpoint checking") which fixed the issue in rtl8150.
--- drivers/net/usb/catc.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)
drivers/net/usb/catc.c +31 -6
@@ -64,6 +64,16 @@ static const char driver_name[] = "catc";#define CTRL_QUEUE 16/* Max control requests in flight (power of two) */ #define RX_PKT_SZ 1600/* Max size of receive packet for F5U011 */ +/* +* USB endpoints. +*/ + +enum catc_usb_ep { +CATC_USB_EP_CONTROL =0 , +CATC_USB_EP_BULK =1 , +CATC_USB_EP_INT_IN =2 , +}; +/* * Control requests. */
@@ -772,6 +782,13 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *idu8 broadcast[ETH_ALEN ];u8 *macbuf;int pktsz, ret = -ENOMEM ; +static const u8 bulk_ep_addr[] = { +CATC_USB_EP_BULK |USB_DIR_OUT , +CATC_USB_EP_BULK |USB_DIR_IN , +0 }; +static const u8 int_ep_addr[] = { +CATC_USB_EP_INT_IN |USB_DIR_IN , +0 }; macbuf =kmalloc (ETH_ALEN ,GFP_KERNEL );if (!macbuf)
@@ -784,6 +801,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id goto fail_mem; } +/* Verify that all required endpoints are present */ +if (!usb_check_bulk_endpoints (intf, bulk_ep_addr) || + !usb_check_int_endpoints (intf, int_ep_addr)) { +dev_err (dev,"Missing or invalid endpoints\n" ); + ret = -ENODEV ; + goto fail_mem; + } + netdev =alloc_etherdev (sizeof (struct catc ));if (!netdev) goto fail_mem;
@@ -828,14 +853,14 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *idusb_fill_control_urb (catc->ctrl_urb, usbdev,usb_sndctrlpipe (usbdev,0 ),NULL ,NULL ,0 , catc_ctrl_done, catc); -usb_fill_bulk_urb (catc->tx_urb, usbdev,usb_sndbulkpipe (usbdev,1 ), -NULL ,0 , catc_tx_done, catc); +usb_fill_bulk_urb (catc->tx_urb, usbdev,usb_sndbulkpipe (usbdev,CATC_USB_EP_BULK ), +NULL ,0 , catc_tx_done, catc); -usb_fill_bulk_urb (catc->rx_urb, usbdev,usb_rcvbulkpipe (usbdev,1 ), - catc->rx_buf, pktsz, catc_rx_done, catc); +usb_fill_bulk_urb (catc->rx_urb, usbdev,usb_rcvbulkpipe (usbdev,CATC_USB_EP_BULK ), + catc->rx_buf, pktsz, catc_rx_done, catc); -usb_fill_int_urb (catc->irq_urb, usbdev,usb_rcvintpipe (usbdev,2 ), - catc->irq_buf,2 , catc_irq_done, catc,1 ); +usb_fill_int_urb (catc->irq_urb, usbdev,usb_rcvintpipe (usbdev,CATC_USB_EP_INT_IN ), + catc->irq_buf,2 , catc_irq_done, catc,1 );if (!catc->is_f5u011) {u32 *buf;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 655/781 xen-netback: reject zero-queue configuration from guest
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 6d1dc8014334c7fb25719999bca84d811e60a559 ]
A malicious or buggy Xen guest can write "0" to the xenbus key "multi-queue-num-queues". The connect() function in the backend only validates the upper bound (requested_num_queues > xenvif_max_queues) but not zero, allowing requested_num_queues=0 to reach vzalloc(array_size(0, sizeof(struct xenvif_queue))), which triggers WARN_ON_ONCE(!size) in __vmalloc_node_range().
On systems with panic_on_warn=1, this allows a guest-to-host denial of service.
The Xen network interface specification requires
the queue count to be "greater than zero".
Add a zero check to match the validation already present in xen-blkback, which has included this
guard since its multi-queue support was added.
--- drivers/net/xen-netback/xenbus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/xen-netback/xenbus.c +3 -2
@@ -735,10 +735,11 @@ static void connect(struct backend_info *be)*/ requested_num_queues =xenbus_read_unsigned (dev->otherend,"multi-queue-num-queues" ,1 ); -if (requested_num_queues > xenvif_max_queues) { +if (requested_num_queues > xenvif_max_queues || + requested_num_queues ==0 ) {/* buggy or malicious guest */ xenbus_dev_fatal (dev, -EINVAL , -"guest requested %u queues, exceeding the maximum of %u." , +"guest requested %u queues, but valid range is 1 - %u." , requested_num_queues, xenvif_max_queues);return ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 656/781 net/rds: rds_sendmsg should not discard payload_len
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allison Henderson <[email protected]>
[ Upstream commit da29e453dcb3aa7cabead7915f5f945d0add3a52 ]
Commit 3db6e0d172c9 ("rds: use RCU to synchronize work-enqueue with connection teardown") modifies rds_sendmsg to avoid enqueueing work while a tear down is in progress. However, it also changed the return value of rds_sendmsg to that of rds_send_xmit instead of the payload_len. This means the user may incorrectly receive errno values when it should have simply received a payload of 0 while the peer attempts a reconnections. So this patch corrects the teardown handling code to only use the out error path in that case, thus restoring the original payload_len return value.
--- net/rds/send.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/rds/send.c +4 -2
@@ -1382,9 +1382,11 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)else queue_delayed_work (rds_wq, &cpath->cp_send_w,1 );rcu_read_unlock (); + +if (ret) + goto out; } -if (ret) - goto out; +rds_message_put (rm);for (ind =0 ; ind < vct.indx; ind++)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 657/781 net: bridge: mcast: always update mdb_n_entries for vlan contexts
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 8b769e311a86bb9d15c5658ad283b86fc8f080a2 ]
syzbot triggered a warning[1] about the number of mdb entries in a context. It turned out that there are multiple ways to trigger that warning today (some got added during the years), the root cause of the problem is that the increase is done conditionally, and over the years these different conditions increased so there were new ways to trigger the warning, that is to do a decrease which wasn't paired with a previous increase.
For example one way to trigger it is with flush:
$ ip l add br0 up type bridge vlan_filtering 1 mcast_snooping 1
$ ip l add dumdum up master br0 type dummy
$ bridge mdb add dev br0 port dumdum grp 239.0.0.1 permanent vid 1
$ ip link set dev br0 down
$ ip link set dev br0 type bridge mcast_vlan_snooping 1
^^^^ this will enable snooping, but will not update mdb_n_entries
because in __br_multicast_enable_port_ctx() we check !netif_running
$ bridge mdb flush dev br0
^^^ this will trigger the warning because it will delete the pg which
we added above, which will try to decrease mdb_n_entriesFix the problem by removing the conditional increase and always keep the count up-to-date while the vlan exists. In order to do that we have to first initialize it on port-vlan context creation, and then always increase or decrease the value regardless of mcast options. To keep the current behaviour we have to enforce the mdb limit only if the context is port's or if the port-vlan's mcast snooping is enabled.
[1]
------------[ cut here ]------------ n == 0 WARNING: net/bridge/br_multicast.c:718 at br_multicast_port_ngroups_dec_one net/bridge/br_multicast.c:718 [inline], CPU#0: syz.4.4607/22043 WARNING: net/bridge/br_multicast.c:718 at br_multicast_port_ngroups_dec net/bridge/br_multicast.c:771 [inline], CPU#0: syz.4.4607/22043 WARNING: net/bridge/br_multicast.c:718 at br_multicast_del_pg+0x1bbe/0x1e20 net/bridge/br_multicast.c:825, CPU#0: syz.4.4607/22043 Modules linked in: CPU: 0 UID: 0 PID: 22043 Comm: syz.4.4607 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026 RIP: 0010:br_multicast_port_ngroups_dec_one net/bridge/br_multicast.c:718 [inline] RIP: 0010:br_multicast_port_ngroups_dec net/bridge/br_multicast.c:771 [inline] RIP: 0010:br_multicast_del_pg+0x1bbe/0x1e20 net/bridge/br_multicast.c:825 Code: 41 5f 5d e9 04 7a 48 f7 e8 3f 73 5c f7 90 0f 0b 90 e9 cf fd ff ff e8 31 73 5c f7 90 0f 0b 90 e9 16 fd ff ff e8 23 73 5c f7 90 <0f> 0b 90 e9 60 fd ff ff e8 15 73 5c f7 eb 05 e8 0e 73 5c f7 48 8b RSP: 0018:ffffc9000c207220 EFLAGS: 00010293 RAX: ffffffff8a68042d RBX: ffff88807c6f1800 RCX: ffff888066e90000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 RBP: 0000000000000000 R08: ffff888066e90000 R09: 000000000000000c R10: 000000000000000c R11: 0000000000000000 R12: ffff8880303ef800 R13: dffffc0000000000 R14: ffff888050eb11c4 R15: 1ffff1100a1d6238 FS: 00007fa45921b6c0(0000) GS:ffff8881256f5000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fa4591f9ff8 CR3: 0000000081df2000 CR4: 00000000003526f0 Call Trace: <TASK> br_mdb_flush_pgs net/bridge/br_mdb.c:1525 [inline] br_mdb_flush net/bridge/br_mdb.c:1544 [inline] br_mdb_del_bulk+0x5e2/0xb20 net/bridge/br_mdb.c:1561 rtnl_mdb_del+0x48a/0x640 net/core/rtnetlink.c:-1 rtnetlink_rcv_msg+0x77e/0xbe0 net/core/rtnetlink.c:6967 netlink_rcv_skb+0x232/0x4b0 net/netlink/af_netlink.c:2550 netlink_unicast_kernel net/netlink/af_netlink.c:1318 [inline] netlink_unicast+0x80f/0x9b0 net/netlink/af_netlink.c:1344 netlink_sendmsg+0x813/0xb40 net/netlink/af_netlink.c:1894 sock_sendmsg_nosec net/socket.c:727 [inline] __sock_sendmsg net/socket.c:742 [inline] ____sys_sendmsg+0xa68/0xad0 net/socket.c:2592 ___sys_sendmsg+0x2a5/0x360 net/socket.c:2646 __sys_sendmsg net/socket.c:2678 [inline] __do_sys_sendmsg net/socket.c:2683 [inline] __se_sys_sendmsg net/socket.c:2681 [inline] __x64_sys_sendmsg+0x1bd/0x2a0 net/socket.c:2681 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0xe2/0xf80 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fa45839aeb9 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fa45921b028 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 00007fa458615fa0 RCX: 00007fa45839aeb9 RDX: 0000000000000000 RSI: 00002000000000c0 RDI: 0000000000000004 RBP: 00007fa458408c1f R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007fa458616038 R14: 00007fa458615fa0 R15: 00007fff0b59fae8 </TASK>
--- net/bridge/br_multicast.c | 45 ++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 27 deletions(-)
net/bridge/br_multicast.c +18 -27
@@ -244,14 +244,11 @@ br_multicast_port_vid_to_port_ctx(struct net_bridge_port *port, u16 vid)lockdep_assert_held_once (&port->br->multicast_lock); -if (!br_opt_get (port->br,BROPT_MCAST_VLAN_SNOOPING_ENABLED )) -return NULL ; -/* Take RCU to access the vlan. */ rcu_read_lock (); vlan =br_vlan_find (nbp_vlan_group_rcu (port), vid); -if (vlan && !br_multicast_port_ctx_vlan_disabled (&vlan->port_mcast_ctx)) +if (vlan) pmctx = &vlan->port_mcast_ctx;rcu_read_unlock ();
@@ -701,7 +698,10 @@ br_multicast_port_ngroups_inc_one(struct net_bridge_mcast_port *pmctx,u32 max =READ_ONCE (pmctx->mdb_max_entries);u32 n =READ_ONCE (pmctx->mdb_n_entries); -if (max && n >= max) { +/* enforce the max limit when it's a port pmctx or a port-vlan pmctx +* with snooping enabled +*/ +if (!br_multicast_port_ctx_vlan_disabled (pmctx) && max && n >= max) {NL_SET_ERR_MSG_FMT_MOD (extack,"%s is already in %u groups, and mcast_max_groups=%u" , what, n, max);return -E2BIG ;
@@ -736,9 +736,7 @@ static int br_multicast_port_ngroups_inc(struct net_bridge_port *port,return err; } -/* Only count on the VLAN context if VID is given, and if snooping on -* that VLAN is enabled. -*/ +/* Only count on the VLAN context if VID is given */ if (!group->vid)return 0 ;
@@ -2011,6 +2009,18 @@ void br_multicast_port_ctx_init(struct net_bridge_port *port,timer_setup (&pmctx->ip6_own_query.timer, br_ip6_multicast_port_query_expired,0 );#endif +/* initialize mdb_n_entries if a new port vlan is being created */ +if (vlan) { +struct net_bridge_port_group *pg; +u32 n =0 ; + +spin_lock_bh (&port->br->multicast_lock); +hlist_for_each_entry (pg, &port->mglist, mglist) +if (pg->key.addr.vid == vlan->vid) + n++; +WRITE_ONCE (pmctx->mdb_n_entries, n); +spin_unlock_bh (&port->br->multicast_lock); + } }void br_multicast_port_ctx_deinit (struct net_bridge_mcast_port *pmctx)
@@ -2094,25 +2104,6 @@ static void __br_multicast_enable_port_ctx(struct net_bridge_mcast_port *pmctx)br_ip4_multicast_add_router (brmctx, pmctx);br_ip6_multicast_add_router (brmctx, pmctx); } - -if (br_multicast_port_ctx_is_vlan (pmctx)) { -struct net_bridge_port_group *pg; -u32 n =0 ; - -/* The mcast_n_groups counter might be wrong. First, -* BR_VLFLAG_MCAST_ENABLED is toggled before temporary entries -* are flushed, thus mcast_n_groups after the toggle does not -* reflect the true values. And second, permanent entries added -* while BR_VLFLAG_MCAST_ENABLED was disabled, are not reflected -* either. Thus we have to refresh the counter. -*/ - -hlist_for_each_entry (pg, &pmctx->port->mglist, mglist) { -if (pg->key.addr.vid == pmctx->vlan->vid) - n++; - } -WRITE_ONCE (pmctx->mdb_n_entries, n); - } }static void br_multicast_enable_port_ctx (struct net_bridge_mcast_port *pmctx)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 658/781 selftests: forwarding: vxlan_bridge_1d: fix test failure with br_netfilter enabled
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksei Oladko <[email protected]>
[ Upstream commit 02cb2e6bacbb08ebf6acb61be816efd11e1f4a21 ]
The test generates VXLAN traffic using mausezahn, where the encapsulated inner IPv4 packet contains a zero IP header checksum. After VXLAN decapsulation, such packets do not pass sanity checks in br_netfilter and are dropped, which causes the test to fail.
Fix this by calculating and setting a valid IPv4 header checksum for the encapsulated packet generated by mausezahn, so that the packet is accepted by br_netfilter. Fixed by using the payload_template_calc_checksum() / payload_template_expand_checksum() helpers that are only available in v6.3 and newer kernels.
--- .../net/forwarding/vxlan_bridge_1d.sh | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-)
tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +16 -10
@@ -567,6 +567,21 @@ vxlan_encapped_ping_do() local inner_tos=$1; shift local outer_tos=$1; shift + local ipv4hdr=$(: + )"45:"$( : IP version + IHL + )"$inner_tos:"$( : IP TOS + )"00:54:"$( : IP total length + )"99:83:"$( : IP identification + )"40:00:"$( : IP flags + frag off + )"40:"$( : IP TTL + )"01:"$( : IP proto + )"CHECKSUM:"$( : IP header csum + )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 + )"c0:00:02:01"$( : IP daddr: 192.0.2.1 + ) + local checksum=$(payload_template_calc_checksum "$ipv4hdr") + ipv4hdr=$(payload_template_expand_checksum "$ipv4hdr" $checksum) + $MZ $dev -c $count -d 100msec -q \ -b $next_hop_mac -B $dest_ip \ -t udp tos=$outer_tos,sp=23456,dp=$VXPORT,p=$(:
@@ -577,16 +592,7 @@ vxlan_encapped_ping_do() )"$dest_mac:"$( : ETH daddr )"$(mac_get w2):"$( : ETH saddr )"08:00:"$( : ETH type - )"45:"$( : IP version + IHL - )"$inner_tos:"$( : IP TOS - )"00:54:"$( : IP total length - )"99:83:"$( : IP identification - )"40:00:"$( : IP flags + frag off - )"40:"$( : IP TTL - )"01:"$( : IP proto - )"00:00:"$( : IP header csum - )"c0:00:02:03:"$( : IP saddr: 192.0.2.3 - )"c0:00:02:01:"$( : IP daddr: 192.0.2.1 + )"$ipv4hdr:"$( : IPv4 header )"08:"$( : ICMP type )"00:"$( : ICMP code )"8b:f2:"$( : ICMP csum
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 659/781 selftests: forwarding: vxlan_bridge_1d_ipv6: fix test failure with br_netfilter enabled
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksei Oladko <[email protected]>
[ Upstream commit ce9f6aec0fb780dafc1dfc5f47c688422aff464a ]
The test generates VXLAN traffic using mausezahn, where the encapsulated inner IPv6 packet has an incorrect payload length set in the IPv6 header. After VXLAN decapsulation, such packets do not pass sanity checks in br_netfilter and are dropped, which causes the test to fail.
Fix this by setting the correct IPv6 payload length for the encapsulated packet generated by mausezahn, so that the packet is accepted by br_netfilter.
tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh lines 698-706
)"00:03:"$( : Payload length
)"3a:"$( : Next header
)"04:"$( : Hop limit
)"$saddr:"$( : IP saddr
)"$daddr:"$( : IP daddr
)"80:"$( : ICMPv6.type
)"00:"$( : ICMPv6.code
)"00:"$( : ICMPv6.checksum
)Data after IPv6 header:
• 80: — 1 byte (ICMPv6 type)
• 00: — 1 byte (ICMPv6 code)
• 00: — 1 byte (ICMPv6 checksum, truncated)
Total: 3 bytes → 00:03 is correct. The old value 00:08 did not match the actual payload size.
--- tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/net/forwarding/vxlan_bridge_1d_ipv6.sh +1 -1
@@ -695,7 +695,7 @@ vxlan_encapped_ping_do() )"6"$( : IP version )"$inner_tos"$( : Traffic class )"0:00:00:"$( : Flow label - )"00:08:"$( : Payload length + )"00:03:"$( : Payload length )"3a:"$( : Next header )"04:"$( : Hop limit )"$saddr:"$( : IP saddr
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 660/781 selftests: forwarding: fix pedit tests failure with br_netfilter enabled
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksei Oladko <[email protected]>
[ Upstream commit a8c198d16c64cdf57f481a4cd3e769502802369e ]
The tests use the tc pedit action to modify the IPv4 source address ("pedit ex munge ip src set"), but the IP header checksum is not recalculated after the modification. As a result, the modified packet fails sanity checks in br_netfilter after bridging and is dropped, which causes the test to fail.
Fix this by ensuring net.bridge.bridge-nf-call-iptables is set to 0 during the test execution. This prevents the bridge from passing L2 traffic to netfilter, bypassing the checksum validation that causes the test failure.
--- tools/testing/selftests/net/forwarding/pedit_dsfield.sh | 8 ++++++++ tools/testing/selftests/net/forwarding/pedit_ip.sh | 8 ++++++++ 2 files changed, 16 insertions(+)
tools/testing/selftests/net/forwarding/pedit_dsfield.sh +8 -0
@@ -98,12 +98,20 @@ setup_prepare() h1_create h2_create switch_create + + if [ -f /proc/sys/net/bridge/bridge-nf-call-iptables ]; then + sysctl_set net.bridge.bridge-nf-call-iptables 0 + fi } cleanup() { pre_cleanup + if [ -f /proc/sys/net/bridge/bridge-nf-call-iptables ]; then + sysctl_restore net.bridge.bridge-nf-call-iptables + fi + switch_destroy h2_destroy h1_destroy
tools/testing/selftests/net/forwarding/pedit_ip.sh +8 -0
@@ -91,12 +91,20 @@ setup_prepare() h1_create h2_create switch_create + + if [ -f /proc/sys/net/bridge/bridge-nf-call-iptables ]; then + sysctl_set net.bridge.bridge-nf-call-iptables 0 + fi } cleanup() { pre_cleanup + if [ -f /proc/sys/net/bridge/bridge-nf-call-iptables ]; then + sysctl_restore net.bridge.bridge-nf-call-iptables + fi + switch_destroy h2_destroy h1_destroy
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 661/781 netfilter: nft_counter: serialize reset with spinlock
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <[email protected]>
[ Upstream commit 779c60a5190c42689534172f4b49e927c9959e4e ]
Add a global static spinlock to serialize counter fetch+reset operations, preventing concurrent dump-and-reset from underrunning values.
The lock is taken before fetching the total so that two parallel resets cannot both read the same counter values and then both subtract them.
A global lock is used for simplicity since resets are infrequent. If this becomes a bottleneck, it can be replaced with a per-net lock later.
--- net/netfilter/nft_counter.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)
net/netfilter/nft_counter.c +16 -4
@@ -32,6 +32,9 @@ struct nft_counter_percpu_priv { static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync); +/* control plane only: sync fetch+reset */ +static DEFINE_SPINLOCK (nft_counter_lock); +static inline void nft_counter_do_eval (struct nft_counter_percpu_priv *priv,struct nft_regs *regs,const struct nft_pktinfo *pkt)
@@ -148,13 +151,25 @@ static void nft_counter_fetch(struct nft_counter_percpu_priv *priv, } } +static void nft_counter_fetch_and_reset (struct nft_counter_percpu_priv *priv, +struct nft_counter_tot *total) +{ +spin_lock (&nft_counter_lock); +nft_counter_fetch (priv, total); +nft_counter_reset (priv, total); +spin_unlock (&nft_counter_lock); +} +static int nft_counter_do_dump (struct sk_buff *skb,struct nft_counter_percpu_priv *priv,bool reset) {struct nft_counter_tot total; -nft_counter_fetch (priv, &total); +if (unlikely (reset)) +nft_counter_fetch_and_reset (priv, &total); +else +nft_counter_fetch (priv, &total); if (nla_put_be64(skb, NFTA_COUNTER_BYTES, cpu_to_be64(total.bytes), NFTA_COUNTER_PAD) ||
@@ -162,9 +177,6 @@ static int nft_counter_do_dump(struct sk_buff *skb, NFTA_COUNTER_PAD)) goto nla_put_failure; -if (reset) -nft_counter_reset (priv, &total); -return 0 ; nla_put_failure:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 662/781 netfilter: nft_quota: use atomic64_xchg for reset
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <[email protected]>
[ Upstream commit 30c4d7fb59ac4c8d7fa7937df11eed10b368fa11 ]
Use atomic64_xchg() to atomically read and zero the consumed value on reset, which is simpler than the previous read+sub pattern and doesn't require lock serialization.
--- net/netfilter/nft_quota.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
net/netfilter/nft_quota.c +7 -6
@@ -140,11 +140,16 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv,u64 consumed, consumed_cap, quota;u32 flags = priv->flags; -/* Since we inconditionally increment consumed quota for each packet +/* Since we unconditionally increment consumed quota for each packet * that we see, don't go over the quota boundary in what we send to * userspace. */ - consumed =atomic64_read (priv->consumed); +if (reset) { + consumed =atomic64_xchg (priv->consumed,0 ); +clear_bit (NFT_QUOTA_DEPLETED_BIT , &priv->flags); + }else { + consumed =atomic64_read (priv->consumed); + } quota =atomic64_read (&priv->quota);if (consumed >= quota) { consumed_cap = quota;
@@ -160,10 +165,6 @@ static int nft_quota_do_dump(struct sk_buff *skb, struct nft_quota *priv, nla_put_be32(skb, NFTA_QUOTA_FLAGS, htonl(flags))) goto nla_put_failure; -if (reset) { -atomic64_sub (consumed, priv->consumed); -clear_bit (NFT_QUOTA_DEPLETED_BIT , &priv->flags); - }return 0 ; nla_put_failure:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 663/781 netfilter: nf_tables: revert commit_mutex usage in reset path
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Brian Witte <[email protected]>
[ Upstream commit 7f261bb906bf527c4a6e2a646e2d5f3679f2a8bc ]
It causes circular lock dependency between commit_mutex, nfnl_subsys_ipset and nlk_cb_mutex when nft reset, ipset list, and iptables-nft with '-m set' rule run at the same time.
Previous patches made it safe to run individual reset handlers concurrently so commit_mutex is no longer required to prevent this.
--- net/netfilter/nf_tables_api.c | 248 ++++++---------------------------- 1 file changed, 42 insertions(+), 206 deletions(-)
net/netfilter/nf_tables_api.c +42 -206
@@ -3900,23 +3900,6 @@ static int nf_tables_dump_rules(struct sk_buff *skb,return skb->len; } -static int nf_tables_dumpreset_rules (struct sk_buff *skb, -struct netlink_callback *cb) -{ -struct nftables_pernet *nft_net =nft_pernet (sock_net (skb->sk)); -int ret; - -/* Mutex is held is to prevent that two concurrent dump-and-reset calls -* do not underrun counters and quotas. The commit_mutex is used for -* the lack a better lock, this is not transaction path. -*/ -mutex_lock (&nft_net->commit_mutex); - ret =nf_tables_dump_rules (skb, cb); -mutex_unlock (&nft_net->commit_mutex); - -return ret; -} -static int nf_tables_dump_rules_start (struct netlink_callback *cb) {struct nft_rule_dump_ctx *ctx = (void *)cb->ctx;
@@ -3936,16 +3919,10 @@ static int nf_tables_dump_rules_start(struct netlink_callback *cb)return -ENOMEM ; } } -return 0 ; -} - -static int nf_tables_dumpreset_rules_start (struct netlink_callback *cb) -{ -struct nft_rule_dump_ctx *ctx = (void *)cb->ctx; - - ctx->reset = true; +if (NFNL_MSG_TYPE (cb->nlh->nlmsg_type) ==NFT_MSG_GETRULE_RESET ) + ctx->reset = true; -return nf_tables_dump_rules_start (cb); +return 0 ; }static int nf_tables_dump_rules_done (struct netlink_callback *cb)
@@ -4011,6 +3988,8 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,u32 portid =NETLINK_CB (skb).portid;struct net *net = info->net;struct sk_buff *skb2; +bool reset = false; +char *buf;if (info->nlh->nlmsg_flags &NLM_F_DUMP ) {struct netlink_dump_control c = {
@@ -4024,47 +4003,16 @@ static int nf_tables_getrule(struct sk_buff *skb, const struct nfnl_info *info,return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); } - skb2 =nf_tables_getrule_single (portid, info, nla, false); -if (IS_ERR (skb2)) -return PTR_ERR (skb2); - -return nfnetlink_unicast (skb2, net, portid); -} - -static int nf_tables_getrule_reset (struct sk_buff *skb, -const struct nfnl_info *info, -const struct nlattr *const nla[]) -{ -struct nftables_pernet *nft_net =nft_pernet (info->net); -u32 portid =NETLINK_CB (skb).portid; -struct net *net = info->net; -struct sk_buff *skb2; -char *buf; - -if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { -struct netlink_dump_control c = { - .start= nf_tables_dumpreset_rules_start, - .dump = nf_tables_dumpreset_rules, - .done = nf_tables_dump_rules_done, - .module =THIS_MODULE , - .data = (void *)nla, - }; - -return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); - } - -if (!try_module_get (THIS_MODULE )) -return -EINVAL ; -rcu_read_unlock (); -mutex_lock (&nft_net->commit_mutex); - skb2 =nf_tables_getrule_single (portid, info, nla, true); -mutex_unlock (&nft_net->commit_mutex); -rcu_read_lock (); -module_put (THIS_MODULE ); +if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETRULE_RESET ) + reset = true; + skb2 =nf_tables_getrule_single (portid, info, nla, reset);if (IS_ERR (skb2))return PTR_ERR (skb2); +if (!reset) +return nfnetlink_unicast (skb2, net, portid); + buf = kasprintf(GFP_ATOMIC, "%.*s:%u", nla_len(nla[NFTA_RULE_TABLE]), (char *)nla_data(nla[NFTA_RULE_TABLE]),
@@ -6323,6 +6271,10 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)nla_nest_end (skb, nest);nlmsg_end (skb, nlh); +if (dump_ctx->reset && args.iter.count > args.iter.skip) +audit_log_nft_set_reset (table, cb->seq, + args.iter.count - args.iter.skip); +rcu_read_unlock ();if (args.iter.err && args.iter.err != -EMSGSIZE )
@@ -6338,26 +6290,6 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)return -ENOSPC ; } -static int nf_tables_dumpreset_set (struct sk_buff *skb, -struct netlink_callback *cb) -{ -struct nftables_pernet *nft_net =nft_pernet (sock_net (skb->sk)); -struct nft_set_dump_ctx *dump_ctx = cb->data; -int ret, skip = cb->args[0 ]; - -mutex_lock (&nft_net->commit_mutex); - - ret =nf_tables_dump_set (skb, cb); - -if (cb->args[0 ] > skip) -audit_log_nft_set_reset (dump_ctx->ctx.table, cb->seq, - cb->args[0 ] - skip); - -mutex_unlock (&nft_net->commit_mutex); - -return ret; -} -static int nf_tables_dump_set_start (struct netlink_callback *cb) {struct nft_set_dump_ctx *dump_ctx = cb->data;
@@ -6601,8 +6533,13 @@ static int nf_tables_getsetelem(struct sk_buff *skb, {struct netlink_ext_ack *extack = info->extack;struct nft_set_dump_ctx dump_ctx; +int rem, err =0 , nelems =0 ; +struct net *net = info->net;struct nlattr *attr; -int rem, err =0 ; +bool reset = false; + +if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETSETELEM_RESET ) + reset = true;if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { struct netlink_dump_control c = {
@@ -6612,7 +6549,7 @@ static int nf_tables_getsetelem(struct sk_buff *skb, .module = THIS_MODULE, }; - err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, false); + err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, reset);if (err)return err;
@@ -6623,75 +6560,21 @@ static int nf_tables_getsetelem(struct sk_buff *skb,if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS ])return -EINVAL ; - err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, false); + err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, reset);if (err)return err;nla_for_each_nested (attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS ], rem) { - err =nft_get_set_elem (&dump_ctx.ctx, dump_ctx.set, attr, false); -if (err <0 ) { -NL_SET_BAD_ATTR (extack, attr); -break ; - } - } - -return err; -} - -static int nf_tables_getsetelem_reset (struct sk_buff *skb, -const struct nfnl_info *info, -const struct nlattr *const nla[]) -{ -struct nftables_pernet *nft_net =nft_pernet (info->net); -struct netlink_ext_ack *extack = info->extack; -struct nft_set_dump_ctx dump_ctx; -int rem, err =0 , nelems =0 ; -struct nlattr *attr; - -if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { -struct netlink_dump_control c = { - .start = nf_tables_dump_set_start, - .dump = nf_tables_dumpreset_set, - .done = nf_tables_dump_set_done, - .module =THIS_MODULE , - }; - - err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, true); -if (err) -return err; - - c.data = &dump_ctx; -return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); - } - -if (!nla[NFTA_SET_ELEM_LIST_ELEMENTS ]) -return -EINVAL ; - -if (!try_module_get (THIS_MODULE )) -return -EINVAL ; -rcu_read_unlock (); -mutex_lock (&nft_net->commit_mutex); -rcu_read_lock (); - - err =nft_set_dump_ctx_init (&dump_ctx, skb, info, nla, true); -if (err) - goto out_unlock; - -nla_for_each_nested (attr, nla[NFTA_SET_ELEM_LIST_ELEMENTS ], rem) { - err =nft_get_set_elem (&dump_ctx.ctx, dump_ctx.set, attr, true); + err =nft_get_set_elem (&dump_ctx.ctx, dump_ctx.set, attr, reset);if (err <0 ) {NL_SET_BAD_ATTR (extack, attr);break ; } nelems++; } -audit_log_nft_set_reset (dump_ctx.ctx.table,nft_base_seq (info->net), nelems); - -out_unlock: -rcu_read_unlock (); -mutex_unlock (&nft_net->commit_mutex); -rcu_read_lock (); -module_put (THIS_MODULE ); +if (reset) +audit_log_nft_set_reset (dump_ctx.ctx.table,nft_base_seq (net), + nelems);return err; }
@@ -8562,19 +8445,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)return skb->len; } -static int nf_tables_dumpreset_obj (struct sk_buff *skb, -struct netlink_callback *cb) -{ -struct nftables_pernet *nft_net =nft_pernet (sock_net (skb->sk)); -int ret; - -mutex_lock (&nft_net->commit_mutex); - ret =nf_tables_dump_obj (skb, cb); -mutex_unlock (&nft_net->commit_mutex); - -return ret; -} -static int nf_tables_dump_obj_start (struct netlink_callback *cb) {struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
@@ -8591,16 +8461,10 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)if (nla[NFTA_OBJ_TYPE ]) ctx->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); -return 0 ; -} - -static int nf_tables_dumpreset_obj_start (struct netlink_callback *cb) -{ -struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; - - ctx->reset = true; +if (NFNL_MSG_TYPE (cb->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) + ctx->reset = true; -return nf_tables_dump_obj_start (cb); +return 0 ; }static int nf_tables_dump_obj_done (struct netlink_callback *cb)
@@ -8662,42 +8526,16 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,static int nf_tables_getobj (struct sk_buff *skb,const struct nfnl_info *info,const struct nlattr *const nla[]) { -u32 portid =NETLINK_CB (skb).portid; -struct sk_buff *skb2; - -if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { -struct netlink_dump_control c = { - .start = nf_tables_dump_obj_start, - .dump = nf_tables_dump_obj, - .done = nf_tables_dump_obj_done, - .module =THIS_MODULE , - .data = (void *)nla, - }; - -return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); - } - - skb2 =nf_tables_getobj_single (portid, info, nla, false); -if (IS_ERR (skb2)) -return PTR_ERR (skb2); - -return nfnetlink_unicast (skb2, info->net, portid); -} - -static int nf_tables_getobj_reset (struct sk_buff *skb, -const struct nfnl_info *info, -const struct nlattr *const nla[]) -{ -struct nftables_pernet *nft_net =nft_pernet (info->net);u32 portid =NETLINK_CB (skb).portid;struct net *net = info->net;struct sk_buff *skb2; +bool reset = false;char *buf;if (info->nlh->nlmsg_flags &NLM_F_DUMP ) {struct netlink_dump_control c = { - .start = nf_tables_dumpreset_obj_start, - .dump = nf_tables_dumpreset_obj, + .start = nf_tables_dump_obj_start, + .dump = nf_tables_dump_obj, .done = nf_tables_dump_obj_done, .module =THIS_MODULE , .data = (void *)nla,
@@ -8706,18 +8544,16 @@ static int nf_tables_getobj_reset(struct sk_buff *skb,return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); } -if (!try_module_get (THIS_MODULE )) -return -EINVAL ; -rcu_read_unlock (); -mutex_lock (&nft_net->commit_mutex); - skb2 =nf_tables_getobj_single (portid, info, nla, true); -mutex_unlock (&nft_net->commit_mutex); -rcu_read_lock (); -module_put (THIS_MODULE ); +if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) + reset = true; + skb2 =nf_tables_getobj_single (portid, info, nla, reset);if (IS_ERR (skb2))return PTR_ERR (skb2); +if (!reset) +return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid); + buf = kasprintf(GFP_ATOMIC, "%.*s:%u", nla_len(nla[NFTA_OBJ_TABLE]), (char *)nla_data(nla[NFTA_OBJ_TABLE]),
@@ -10035,7 +9871,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_rule_policy, }, [NFT_MSG_GETRULE_RESET] = { - .call = nf_tables_getrule_reset, + .call = nf_tables_getrule, .type = NFNL_CB_RCU, .attr_count = NFTA_RULE_MAX, .policy = nft_rule_policy,
@@ -10089,7 +9925,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_set_elem_list_policy, }, [NFT_MSG_GETSETELEM_RESET] = { - .call = nf_tables_getsetelem_reset, + .call = nf_tables_getsetelem, .type = NFNL_CB_RCU, .attr_count = NFTA_SET_ELEM_LIST_MAX, .policy = nft_set_elem_list_policy,
@@ -10135,7 +9971,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_obj_policy, }, [NFT_MSG_GETOBJ_RESET] = { - .call = nf_tables_getobj_reset, + .call = nf_tables_getobj, .type = NFNL_CB_RCU, .attr_count = NFTA_OBJ_MAX, .policy = nft_obj_policy,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 664/781 netfilter: nf_conntrack_h323: dont pass uninitialised l3num value
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit a6d28eb8efe96b3e35c92efdf1bfacb0cccf541f ]
Mihail Milev reports: Error: UNINIT (CWE-457):
net/netfilter/nf_conntrack_h323_main.c:1189:2: var_decl:
Declaring variable "tuple" without initializer.
net/netfilter/nf_conntrack_h323_main.c:1197:2:
uninit_use_in_call: Using uninitialized value "tuple.src.l3num" when calling "__nf_ct_expect_find".
net/netfilter/nf_conntrack_expect.c:142:2:
read_value: Reading value "tuple->src.l3num" when calling "nf_ct_expect_dst_hash".
1195| tuple.dst.protonum = IPPROTO_TCP; 1196| 1197|-> exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple); 1198| if (exp && exp->master == ct) 1199| return exp;
Switch this to a C99 initialiser and set the l3num value.
--- net/netfilter/nf_conntrack_h323_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
net/netfilter/nf_conntrack_h323_main.c +5 -5
@@ -1186,13 +1186,13 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct, {struct net *net =nf_ct_net (ct);struct nf_conntrack_expect *exp; -struct nf_conntrack_tuple tuple; +struct nf_conntrack_tuple tuple = { + .src.l3num =nf_ct_l3num (ct), + .dst.protonum =IPPROTO_TCP , + .dst.u.tcp.port = port, + }; -memset (&tuple.src.u3,0 ,sizeof (tuple.src.u3)); - tuple.src.u.tcp.port =0 ;memcpy (&tuple.dst.u3, addr,sizeof (tuple.dst.u3)); - tuple.dst.u.tcp.port = port; - tuple.dst.protonum =IPPROTO_TCP ; exp =__nf_ct_expect_find (net,nf_ct_zone (ct), &tuple);if (exp && exp->master == ct)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 665/781 ipvs: skip ipv6 extension headers for csum checks
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 05cfe9863ef049d98141dc2969eefde72fb07625 ]
Protocol checksum validation fails for IPv6 if there are extension headers before the protocol header. iph->len already contains its offset, so use it to fix the problem.
--- net/netfilter/ipvs/ip_vs_proto_sctp.c | 18 ++++++------------ net/netfilter/ipvs/ip_vs_proto_tcp.c | 21 +++++++-------------- net/netfilter/ipvs/ip_vs_proto_udp.c | 20 +++++++------------- 3 files changed, 20 insertions(+), 39 deletions(-)
net/netfilter/ipvs/ip_vs_proto_sctp.c +6 -12
@@ -10,7 +10,8 @@#include <net/ip_vs.h> static int -sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp); +sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int sctphoff); static int sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -108,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!sctp_csum_check (cp->af, skb, pp)) +if (!sctp_csum_check (cp->af, skb, pp, sctphoff))return 0 ;/* Call application helper if needed */
@@ -156,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!sctp_csum_check (cp->af, skb, pp)) +if (!sctp_csum_check (cp->af, skb, pp, sctphoff))return 0 ;/* Call application helper if needed */
@@ -185,19 +186,12 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, }static int -sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp) +sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int sctphoff) { -unsigned int sctphoff;struct sctphdr *sh;__le32 cmp, val; -#ifdef CONFIG_IP_VS_IPV6 -if (af ==AF_INET6 ) - sctphoff =sizeof (struct ipv6hdr ); - else -#endif - sctphoff =ip_hdrlen (skb); - sh = (struct sctphdr *)(skb->data + sctphoff); cmp = sh->checksum; val =sctp_compute_cksum (skb, sctphoff);
net/netfilter/ipvs/ip_vs_proto_tcp.c +7 -14
@@ -28,7 +28,8 @@#include <net/ip_vs.h> static int -tcp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp); +tcp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int tcphoff); static int tcp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -165,7 +166,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!tcp_csum_check (cp->af, skb, pp)) +if (!tcp_csum_check (cp->af, skb, pp, tcphoff))return 0 ;/* Call application helper if needed */
@@ -243,7 +244,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!tcp_csum_check (cp->af, skb, pp)) +if (!tcp_csum_check (cp->af, skb, pp, tcphoff))return 0 ;/*
@@ -300,17 +301,9 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,static int -tcp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp) +tcp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int tcphoff) { -unsigned int tcphoff; - -#ifdef CONFIG_IP_VS_IPV6 -if (af ==AF_INET6 ) - tcphoff =sizeof (struct ipv6hdr ); - else -#endif - tcphoff =ip_hdrlen (skb); -switch (skb->ip_summed) {case CHECKSUM_NONE : skb->csum =skb_checksum (skb, tcphoff, skb->len - tcphoff,0 );
@@ -321,7 +314,7 @@ tcp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)if (csum_ipv6_magic (&ipv6_hdr (skb)->saddr, &ipv6_hdr (skb)->daddr, skb->len - tcphoff, -ipv6_hdr (skb)->nexthdr, +IPPROTO_TCP , skb->csum)) {IP_VS_DBG_RL_PKT (0 , af, pp, skb,0 ,"Failed checksum for" );
net/netfilter/ipvs/ip_vs_proto_udp.c +7 -13
@@ -24,7 +24,8 @@#include <net/ip6_checksum.h> static int -udp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp); +udp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int udphoff); static int udp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -154,7 +155,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!udp_csum_check (cp->af, skb, pp)) +if (!udp_csum_check (cp->af, skb, pp, udphoff))return 0 ;/*
@@ -237,7 +238,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!udp_csum_check (cp->af, skb, pp)) +if (!udp_csum_check (cp->af, skb, pp, udphoff))return 0 ;/*
@@ -296,17 +297,10 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,static int -udp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp) +udp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, +unsigned int udphoff) {struct udphdr _udph, *uh; -unsigned int udphoff; - -#ifdef CONFIG_IP_VS_IPV6 -if (af ==AF_INET6 ) - udphoff =sizeof (struct ipv6hdr ); - else -#endif - udphoff =ip_hdrlen (skb); uh =skb_header_pointer (skb, udphoff,sizeof (_udph), &_udph);if (uh ==NULL )
@@ -324,7 +318,7 @@ udp_csum_check(int af, struct sk_buff *skb, struct ip_vs_protocol *pp)if (csum_ipv6_magic (&ipv6_hdr (skb)->saddr, &ipv6_hdr (skb)->daddr, skb->len - udphoff, -ipv6_hdr (skb)->nexthdr, +IPPROTO_UDP , skb->csum)) {IP_VS_DBG_RL_PKT (0 , af, pp, skb,0 ,"Failed checksum for" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 666/781 ipvs: do not keep dest_dst if dev is going down
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 8fde939b0206afc1d5846217a01a16b9bc8c7896 ]
There is race between the netdev notifier ip_vs_dst_event() and the code that caches dst with dev that is going down. As the FIB can be notified for the closed device after our handler finishes, it is possible valid route to be returned and cached resuling in a leaked dev reference until the dest is not removed.
To prevent new dest_dst to be attached to dest just after the handler dropped the old one, add a netif_running() check to make sure the notifier handler is not currently running for device that is closing.
--- net/netfilter/ipvs/ip_vs_xmit.c | 46 ++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 10 deletions(-)
net/netfilter/ipvs/ip_vs_xmit.c +36 -10
@@ -294,6 +294,12 @@ static inline bool decrement_ttl(struct netns_ipvs *ipvs,return true; } +/* rt has device that is down */ +static bool rt_dev_is_down (const struct net_device *dev) +{ +return dev && !netif_running (dev); +} +/* Get route to destination or remote server */ static int __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,
@@ -309,9 +315,11 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,if (dest) { dest_dst =__ip_vs_dst_check (dest); -if (likely (dest_dst)) +if (likely (dest_dst)) { rt =dst_rtable (dest_dst->dst_cache); -else { +if (ret_saddr) + *ret_saddr = dest_dst->dst_saddr.ip; + }else { dest_dst =ip_vs_dest_dst_alloc ();spin_lock_bh (&dest->dst_lock);if (!dest_dst) {
@@ -327,14 +335,22 @@ __ip_vs_get_out_rt(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,ip_vs_dest_dst_free (dest_dst); goto err_unreach; } -__ip_vs_dst_set (dest, dest_dst, &rt->dst,0 ); +/* It is forbidden to attach dest->dest_dst if +* device is going down. +*/ +if (!rt_dev_is_down (dst_dev_rcu (&rt->dst))) +__ip_vs_dst_set (dest, dest_dst, &rt->dst,0 ); +else + noref =0 ;spin_unlock_bh (&dest->dst_lock);IP_VS_DBG (10 ,"new dst %pI4, src %pI4, refcnt=%d\n" , &dest->addr.ip, &dest_dst->dst_saddr.ip,rcuref_read (&rt->dst.__rcuref)); +if (ret_saddr) + *ret_saddr = dest_dst->dst_saddr.ip; +if (!noref) +ip_vs_dest_dst_free (dest_dst); } -if (ret_saddr) - *ret_saddr = dest_dst->dst_saddr.ip; }else { noref =0 ;
@@ -471,9 +487,11 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb,if (dest) { dest_dst =__ip_vs_dst_check (dest); -if (likely (dest_dst)) +if (likely (dest_dst)) { rt =dst_rt6_info (dest_dst->dst_cache); -else { +if (ret_saddr) + *ret_saddr = dest_dst->dst_saddr.in6; + }else {u32 cookie; dest_dst =ip_vs_dest_dst_alloc ();
@@ -494,14 +512,22 @@ __ip_vs_get_out_rt_v6(struct netns_ipvs *ipvs, int skb_af, struct sk_buff *skb, } rt =dst_rt6_info (dst); cookie =rt6_get_cookie (rt); -__ip_vs_dst_set (dest, dest_dst, &rt->dst, cookie); +/* It is forbidden to attach dest->dest_dst if +* device is going down. +*/ +if (!rt_dev_is_down (dst_dev_rcu (&rt->dst))) +__ip_vs_dst_set (dest, dest_dst, &rt->dst, cookie); +else + noref =0 ;spin_unlock_bh (&dest->dst_lock);IP_VS_DBG (10 ,"new dst %pI6, src %pI6, refcnt=%d\n" , &dest->addr.in6, &dest_dst->dst_saddr.in6,rcuref_read (&rt->dst.__rcuref)); +if (ret_saddr) + *ret_saddr = dest_dst->dst_saddr.in6; +if (!noref) +ip_vs_dest_dst_free (dest_dst); } -if (ret_saddr) - *ret_saddr = dest_dst->dst_saddr.in6; }else { noref =0 ; dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 667/781 net: remove WARN_ON_ONCE when accessing forward path array
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 008e7a7c293b30bc43e4368dac6ea3808b75a572 ]
Although unlikely, recent support for IPIP tunnels increases chances of reaching this WARN_ON_ONCE if userspace manages to build a sufficiently long forward path.
Remove it.
--- net/core/dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/dev.c +1 -1
@@ -738,7 +738,7 @@ static struct net_device_path *dev_fwd_path(struct net_device_path_stack *stack) {int k = stack->num_paths++; -if (WARN_ON_ONCE (k >=NET_DEVICE_PATH_STACK_MAX )) +if (k >=NET_DEVICE_PATH_STACK_MAX )return NULL ;return &stack->path[k];
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 668/781 netfilter: nf_tables: fix use-after-free in nf_tables_addchain()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Inseo An <[email protected]>
[ Upstream commit 71e99ee20fc3f662555118cf1159443250647533 ]
nf_tables_addchain() publishes the chain to table->chains via list_add_tail_rcu() (in nft_chain_add()) before registering hooks. If nf_tables_register_hook() then fails, the error path calls nft_chain_del() (list_del_rcu()) followed by nf_tables_chain_destroy() with no RCU grace period in between.
This creates two use-after-free conditions:
1) Control-plane: nf_tables_dump_chains() traverses table->chains under rcu_read_lock(). A concurrent dump can still be walking the chain when the error path frees it.
2) Packet path: for NFPROTO_INET, nf_register_net_hook() briefly installs the IPv4 hook before IPv6 registration fails. Packets entering nft_do_chain() via the transient IPv4 hook can still be dereferencing chain->blob_gen_X when the error path frees the chain.
Add synchronize_rcu() between nft_chain_del() and the chain destroy so that all RCU readers -- both dump threads and in-flight packet evaluation -- have finished before the chain is freed.
--- net/netfilter/nf_tables_api.c | 1 + 1 file changed, 1 insertion(+)
net/netfilter/nf_tables_api.c +1 -0
@@ -2822,6 +2822,7 @@ static int nf_tables_addchain(struct nft_ctx *ctx, u8 family, u8 policy, err_register_hook:nft_chain_del (chain); +synchronize_rcu (); err_chain_add:nft_trans_destroy (trans); err_trans:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 669/781 ipv6: fix a race in ip6_sock_set_v6only()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 452a3eee22c57a5786ae6db5c97f3b0ec13bb3b7 ]
It is unlikely that this function will be ever called with isk->inet_num being not zero.
Perform the check on isk->inet_num inside the locked section for complete safety.
--- include/net/ipv6.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
include/net/ipv6.h +7 -4
@@ -1280,12 +1280,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex,static inline int ip6_sock_set_v6only (struct sock *sk) { -if (inet_sk (sk)->inet_num) -return -EINVAL ; +int ret =0 ; +lock_sock (sk); - sk->sk_ipv6only = true; +if (inet_sk (sk)->inet_num) + ret = -EINVAL ; +else + sk->sk_ipv6only = true;release_sock (sk); -return 0 ; +return ret; }static inline void ip6_sock_set_recverr (struct sock *sk)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 670/781 bpftool: Fix truncated netlink dumps
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 3b39d73cc3379360a33eb583b17f21fe55e1288e ]
Netlink requires that the recv buffer used during dumps is at least min(PAGE_SIZE, 8k) (see the man page). Otherwise the messages will get truncated. Make sure bpftool follows this requirement, avoid missing information on systems with large pages.
--- tools/bpf/bpftool/net.c | 5 ++++- tools/lib/bpf/netlink.c | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-)
tools/bpf/bpftool/net.c +4 -1
@@ -156,7 +156,7 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 seq,bool multipart = true;struct nlmsgerr *err;struct nlmsghdr *nh; -char buf[4096 ]; +char buf[8192 ];int len, ret;while (multipart) {
@@ -201,6 +201,9 @@ static int netlink_recv(int sock, __u32 nl_pid, __u32 seq,return ret; } } + +if (len) +p_err ("Invalid message or trailing data in Netlink response: %d bytes left" , len); } ret =0 ; done:
tools/lib/bpf/netlink.c +3 -1
@@ -143,7 +143,7 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq,struct nlmsghdr *nh;int len, ret; - ret =alloc_iov (&iov,4096 ); + ret =alloc_iov (&iov,8192 );if (ret) goto done;
@@ -212,6 +212,8 @@ static int libbpf_netlink_recv(int sock, __u32 nl_pid, int seq, } } } +if (len) +pr_warn ("Invalid message or trailing data in Netlink response: %d bytes left\n" , len); } ret =0 ; done:
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 671/781 net: psp: select CONFIG_SKB_EXTENSIONS
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 6e980df452169f82674f2e650079c1fe0aee343d ]
psp now uses skb extensions, failing to build when that is disabled:
In file included from include/net/psp.h:7,
from net/psp/psp_sock.c:9:
include/net/psp/functions.h: In function '__psp_skb_coalesce_diff':
include/net/psp/functions.h:60:13: error: implicit declaration of function 'skb_ext_find'; did you mean 'skb_ext_copy'? [-Wimplicit-function-declaration]
60 | a = skb_ext_find(one, SKB_EXT_PSP);
| ^~~~~~~~~~~~
| skb_ext_copy
include/net/psp/functions.h:60:31: error: 'SKB_EXT_PSP' undeclared (first use in this function)
60 | a = skb_ext_find(one, SKB_EXT_PSP);
| ^~~~~~~~~~~include/net/psp/functions.h:60:31: note: each undeclared identifier is reported only once for each function it appears in include/net/psp/functions.h: In function '__psp_sk_rx_policy_check':include/net/psp/functions.h:94:53: error: 'SKB_EXT_PSP' undeclared (first use in this function)
94 | struct psp_skb_ext *pse = skb_ext_find(skb, SKB_EXT_PSP);
| ^~~~~~~~~~~net/psp/psp_sock.c: In function 'psp_sock_recv_queue_check':net/psp/psp_sock.c:164:41: error: 'SKB_EXT_PSP' undeclared (first use in this function)
164 | pse = skb_ext_find(skb, SKB_EXT_PSP);
| ^~~~~~~~~~~
Select the Kconfig symbol as we do from its other users.
--- net/psp/Kconfig | 1 + 1 file changed, 1 insertion(+)
net/psp/Kconfig +1 -0
@@ -6,6 +6,7 @@ config INET_PSP bool "PSP Security Protocol support" depends on INET select SKB_DECRYPTED + select SKB_EXTENSIONS select SOCK_VALIDATE_XMIT help Enable kernel support for the PSP Security Protocol (PSP).
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 672/781 net: do not delay zero-copy skbs in skb_attempt_defer_free()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 0943404b1f3b178e1e54386dadcbf4f2729c7762 ]
After the blamed commit, TCP tx zero copy notifications could be arbitrarily delayed and cause regressions in applications waiting for them.
--- net/core/skbuff.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/core/skbuff.c +6 -1
@@ -7231,10 +7231,15 @@ void skb_attempt_defer_free(struct sk_buff *skb) {struct skb_defer_node *sdn;unsigned long defer_count; -int cpu = skb->alloc_cpu;unsigned int defer_max;bool kick; +int cpu; +/* zero copy notifications should not be delayed. */ +if (skb_zcopy (skb)) + goto nodefer; + + cpu = skb->alloc_cpu;if (cpu ==raw_smp_processor_id () ||WARN_ON_ONCE (cpu >= nr_cpu_ids) || !cpu_online (cpu)) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 673/781 dpll: zl3073x: Fix ref frequency setting
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Vecera <[email protected]>
[ Upstream commit a047497f952831e377564b606dcb74a7cb309384 ]
The frequency for an input reference is computed as:
frequency = freq_base * freq_mult * freq_ratio_m / freq_ratio_n
Before commit 5bc02b190a3fb ("dpll: zl3073x: Cache all reference properties in zl3073x_ref"), zl3073x_dpll_input_pin_frequency_set() explicitly wrote 1 to both the REF_RATIO_M and REF_RATIO_N hardware registers whenever a new frequency was set. This ensured the FEC ratio was always reset to 1:1 alongside the new base/multiplier values.
The refactoring in that commit introduced zl3073x_ref_freq_set() to update the cached ref state, but this helper only sets freq_base and freq_mult without resetting freq_ratio_m and freq_ratio_n to 1. Because zl3073x_ref_state_set() uses a compare-and-write strategy, unchanged ratio fields are never written to the hardware. If the device previously had non-unity FEC ratio values, they remain in effect after a frequency change, resulting in an incorrect computed frequency.
Explicitly set freq_ratio_m and freq_ratio_n to 1 in zl3073x_ref_freq_set() to restore the original behavior.
--- drivers/dpll/zl3073x/ref.h | 2 ++ 1 file changed, 2 insertions(+)
drivers/dpll/zl3073x/ref.h +2 -0
@@ -91,6 +91,8 @@ zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq) ref->freq_base = base; ref->freq_mult = mult; + ref->freq_ratio_m =1 ; + ref->freq_ratio_n =1 ;return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 674/781 ping: annotate data-races in ping_lookup()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ad5dfde2a5733aaf652ea3e40c8c5e071e935901 ]
isk->inet_num, isk->inet_rcv_saddr and sk->sk_bound_dev_if are read locklessly in ping_lookup().
Add READ_ONCE()/WRITE_ONCE() annotations.
The race on isk->inet_rcv_saddr is probably coming from IPv6 support, but does not deserve a specific backport.
--- net/ipv4/ping.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-)
net/ipv4/ping.c +19 -12
@@ -148,7 +148,7 @@ void ping_unhash(struct sock *sk)pr_debug ("ping_unhash(isk=%p,isk->num=%u)\n" , isk, isk->inet_num);spin_lock (&ping_table.lock);if (sk_del_node_init_rcu (sk)) { - isk->inet_num =0 ; +WRITE_ONCE (isk->inet_num,0 ); isk->inet_sport =0 ;sock_prot_inuse_add (sock_net (sk), sk->sk_prot,-1 ); }
@@ -181,31 +181,35 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) } sk_for_each_rcu(sk, hslot) { + int bound_dev_if; + if (!net_eq(sock_net(sk), net)) continue; isk = inet_sk(sk); pr_debug("iterate\n"); - if (isk->inet_num != ident) + if (READ_ONCE(isk->inet_num) != ident) continue; + bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); if (skb->protocol == htons(ETH_P_IP) && sk->sk_family == AF_INET) { + __be32 rcv_saddr = READ_ONCE(isk->inet_rcv_saddr); + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, - (int) isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); + ident, &rcv_saddr, + bound_dev_if); - if (isk->inet_rcv_saddr && - isk->inet_rcv_saddr != ip_hdr(skb)->daddr) + if (rcv_saddr && rcv_saddr != ip_hdr(skb)->daddr) continue; #if IS_ENABLED(CONFIG_IPV6) } else if (skb->protocol == htons(ETH_P_IPV6) && sk->sk_family == AF_INET6) { pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, - (int) isk->inet_num, + ident, &sk->sk_v6_rcv_saddr, - sk->sk_bound_dev_if); + bound_dev_if); if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr) && !ipv6_addr_equal(&sk->sk_v6_rcv_saddr,
@@ -216,8 +220,8 @@ static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident)continue ; } -if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif && - sk->sk_bound_dev_if != sdif) +if (bound_dev_if && bound_dev_if != dif && + bound_dev_if != sdif)continue ; goto exit;
@@ -392,7 +396,9 @@ static void ping_set_saddr(struct sock *sk, struct sockaddr_unsized *saddr)if (saddr->sa_family ==AF_INET ) {struct inet_sock *isk =inet_sk (sk);struct sockaddr_in *addr = (struct sockaddr_in *) saddr; - isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; + + isk->inet_saddr = addr->sin_addr.s_addr; +WRITE_ONCE (isk->inet_rcv_saddr, addr->sin_addr.s_addr);#if IS_ENABLED (CONFIG_IPV6 ) } else if (saddr->sa_family == AF_INET6) {struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr;
@@ -849,7 +855,8 @@ int ping_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int flags,struct sk_buff *skb;int copied, err; -pr_debug ("ping_recvmsg(sk=%p,sk->num=%u)\n" , isk, isk->inet_num); +pr_debug ("ping_recvmsg(sk=%p,sk->num=%u)\n" , isk, +READ_ONCE (isk->inet_num)); err = -EOPNOTSUPP ;if (flags &MSG_OOB )
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 675/781 selftests: tc_actions: dont dump 2MB of \0 to stdout
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 32b70e62034aa72f8414ad4e9122cce7ad418c48 ]
Since we started running selftests in NIPA we have been seeing tc_actions.sh generate a soft lockup warning on ~20% of the runs. On the pre-netdev foundation setup it was actually a missed irq splat from the console. Now it's either that or a lockup.
I initially suspected a socket locking issue since the test is exercising local loopback with act_mirred.
After hours of staring at this I noticed in strace that ncat when -o $file is specified _both_ saves the output to the file and still prints it to stdout. Because the file being sent is constructed with:
dd conv=sparse status=none if=/dev/zero bs=1M count=2 of=$mirred
^^^^^^^^^
the data printed is all \0. Most terminals don't display nul characters (and neither does vng output capture save them). But QEMU's serial console still has to poke them thru which is very slow and causes the lockup (if the file is >600kB).
Replace the '-o $file' with '> $file'. This speeds the test up from 2m20s to 18s on debug kernels, and prevents the warnings.
--- tools/testing/selftests/net/forwarding/tc_actions.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/net/forwarding/tc_actions.sh +1 -1
@@ -223,7 +223,7 @@ mirred_egress_to_ingress_tcp_test() ip_proto icmp \ action drop - ip vrf exec v$h1 ncat --recv-only -w10 -l -p 12345 -o $mirred_e2i_tf2 & + ip vrf exec v$h1 ncat --recv-only -w10 -l -p 12345 > $mirred_e2i_tf2 & local rpid=$! ip vrf exec v$h1 ncat -w1 --send-only 192.0.2.2 12345 <$mirred_e2i_tf1 wait -n $rpid
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 676/781 macvlan: observe an RCU grace period in macvlan_common_newlink() error path
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit e3f000f0dee1bfab52e2e61ca6a3835d9e187e35 ]
valis reported that a race condition still happens after my prior patch.
macvlan_common_newlink() might have made @dev visible before detecting an error, and its caller will directly call free_netdev(dev).
We must respect an RCU period, either in macvlan or the core networking stack.
After adding a temporary mdelay(1000) in macvlan_forward_source_one() to open the race window, valis repro was:
ip link add p1 type veth peer p2
ip link set address 00:00:00:00:00:20 dev p1
ip link set up dev p1
ip link set up dev p2
ip link add mv0 link p2 type macvlan mode source
(ip link add invalid% link p2 type macvlan mode source macaddr add 00:00:00:00:00:20 &) ; sleep 0.5 ; ping -c1 -I p1 1.2.3.4 PING 1.2.3.4 (1.2.3.4): 56 data bytes
RTNETLINK answers: Invalid argument
BUG: KASAN: slab-use-after-free in macvlan_forward_source (drivers/net/macvlan.c:408 drivers/net/macvlan.c:444) Read of size 8 at addr ffff888016bb89c0 by task e/175 CPU: 1 UID: 1000 PID: 175 Comm: e Not tainted 6.19.0-rc8+ #33 NONE Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 Call Trace: <IRQ> dump_stack_lvl (lib/dump_stack.c:123) print_report (mm/kasan/report.c:379 mm/kasan/report.c:482) ? macvlan_forward_source (drivers/net/macvlan.c:408 drivers/net/macvlan.c:444) kasan_report (mm/kasan/report.c:597) ? macvlan_forward_source (drivers/net/macvlan.c:408 drivers/net/macvlan.c:444) macvlan_forward_source (drivers/net/macvlan.c:408 drivers/net/macvlan.c:444)
? tasklet_init (kernel/softirq.c:983)macvlan_handle_frame (drivers/net/macvlan.c:501)
Allocated by task 169:
kasan_save_stack (mm/kasan/common.c:58)kasan_save_track (./arch/x86/include/asm/current.h:25 mm/kasan/common.c:70 mm/kasan/common.c:79)__kasan_kmalloc (mm/kasan/common.c:419)__kvmalloc_node_noprof (./include/linux/kasan.h:263 mm/slub.c:5657 mm/slub.c:7140)alloc_netdev_mqs (net/core/dev.c:12012)rtnl_create_link (net/core/rtnetlink.c:3648)rtnl_newlink (net/core/rtnetlink.c:3830 net/core/rtnetlink.c:3957 net/core/rtnetlink.c:4072)rtnetlink_rcv_msg (net/core/rtnetlink.c:6958)netlink_rcv_skb (net/netlink/af_netlink.c:2550)netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1344) netlink_sendmsg (net/netlink/af_netlink.c:1894)__sys_sendto (net/socket.c:727 net/socket.c:742 net/socket.c:2206) __x64_sys_sendto (net/socket.c:2209)do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:131)
Freed by task 169:
kasan_save_stack (mm/kasan/common.c:58) kasan_save_track (./arch/x86/include/asm/current.h:25 mm/kasan/common.c:70 mm/kasan/common.c:79) kasan_save_free_info (mm/kasan/generic.c:587) __kasan_slab_free (mm/kasan/common.c:287)
kfree (mm/slub.c:6674 mm/slub.c:6882) rtnl_newlink (net/core/rtnetlink.c:3845 net/core/rtnetlink.c:3957
net/core/rtnetlink.c:4072)rtnetlink_rcv_msg (net/core/rtnetlink.c:6958)netlink_rcv_skb (net/netlink/af_netlink.c:2550)netlink_unicast (net/netlink/af_netlink.c:1319 net/netlink/af_netlink.c:1344) netlink_sendmsg (net/netlink/af_netlink.c:1894)__sys_sendto (net/socket.c:727 net/socket.c:742 net/socket.c:2206) __x64_sys_sendto (net/socket.c:2209)do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:131)
--- drivers/net/macvlan.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/net/macvlan.c +5 -0
@@ -1572,6 +1572,11 @@ int macvlan_common_newlink(struct net_device *dev,if (create)macvlan_port_destroy (port->dev); } +/* @dev might have been made visible before an error was detected. +* Make sure to observe an RCU grace period before our caller +* (rtnl_newlink()) frees it. +*/ +synchronize_net ();return err; }EXPORT_SYMBOL_GPL (macvlan_common_newlink);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 677/781 eth: fbnic: Add validation for MTU changes
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dimitri Daskalakis <[email protected]>
[ Upstream commit ccd8e87748ad083047d6c8544c5809b7f96cc8df ]
Increasing the MTU beyond the HDS threshold causes the hardware to fragment packets across multiple buffers. If a single-buffer XDP program is attached, the driver will drop all multi-frag frames. While we can't prevent a remote sender from sending non-TCP packets larger than the MTU, this will prevent users from inadvertently breaking new TCP streams.
Traditionally, drivers supported XDP with MTU less than 4Kb (packet per page). Fbnic currently prevents attaching XDP when MTU is too high. But it does not prevent increasing MTU after XDP is attached.
--- drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +18 -0
@@ -262,6 +262,23 @@ static int fbnic_set_mac(struct net_device *netdev, void *p)return 0 ; } +static int fbnic_change_mtu (struct net_device *dev,int new_mtu) +{ +struct fbnic_net *fbn =netdev_priv (dev); + +if (fbnic_check_split_frames (fbn->xdp_prog, new_mtu, fbn->hds_thresh)) { +dev_err (&dev->dev, +"MTU %d is larger than HDS threshold %d in XDP mode\n" , + new_mtu, fbn->hds_thresh); + +return -EINVAL ; + } + +WRITE_ONCE (dev->mtu, new_mtu); + +return 0 ; +} +void fbnic_clear_rx_mode (struct fbnic_dev *fbd) {struct net_device *netdev = fbd->netdev;
@@ -533,6 +550,7 @@ static const struct net_device_ops fbnic_netdev_ops = { .ndo_start_xmit = fbnic_xmit_frame, .ndo_features_check = fbnic_features_check, .ndo_set_mac_address = fbnic_set_mac, + .ndo_change_mtu = fbnic_change_mtu, .ndo_set_rx_mode = fbnic_set_rx_mode, .ndo_get_stats64 = fbnic_get_stats64, .ndo_bpf = fbnic_bpf,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 678/781 icmp: prevent possible overflow in icmp_global_allow()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 034bbd806298e9ba4197dd1587b0348ee30996ea ]
Following expression can overflow
if sysctl_icmp_msgs_per_sec is big enough.
sysctl_icmp_msgs_per_sec * delta / HZ;
--- net/ipv4/icmp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv4/icmp.c +2 -1
@@ -248,7 +248,8 @@ bool icmp_global_allow(struct net *net)if (delta <HZ /50 )return false; - incr =READ_ONCE (net->ipv4.sysctl_icmp_msgs_per_sec) * delta /HZ ; + incr =READ_ONCE (net->ipv4.sysctl_icmp_msgs_per_sec); + incr =div_u64 ((u64 )incr * delta,HZ );if (!incr)return false;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 679/781 inet: move icmp_global_{credit,stamp} to a separate cache line
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 87b08913a9ae82082e276d237ece08fc8ee24380 ]
icmp_global_credit was meant to be changed ~1000 times per second, but if an admin sets net.ipv4.icmp_msgs_per_sec to a very high value, icmp_global_credit changes can inflict false sharing to surrounding fields that are read mostly.
Move icmp_global_credit and icmp_global_stamp to a separate cacheline aligned group.
--- include/net/netns/ipv4.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
include/net/netns/ipv4.h +7 -2
@@ -88,6 +88,12 @@ struct netns_ipv4 {int sysctl_tcp_rcvbuf_low_rtt;__cacheline_group_end (netns_ipv4_read_rx); +/* ICMP rate limiter hot cache line. */ +__cacheline_group_begin_aligned (icmp); +atomic_t icmp_global_credit; +u32 icmp_global_stamp; +__cacheline_group_end_aligned (icmp); +struct inet_timewait_death_row tcp_death_row;struct udp_table *udp_table;
@@ -141,8 +147,7 @@ struct netns_ipv4 {int sysctl_icmp_ratemask;int sysctl_icmp_msgs_per_sec;int sysctl_icmp_msgs_burst; -atomic_t icmp_global_credit; -u32 icmp_global_stamp; +u32 ip_rt_min_pmtu;int ip_rt_mtu_expires;int ip_rt_min_advmss;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 680/781 ipv6: icmp: remove obsolete code in icmpv6_xrlim_allow()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 0201eedb69b24a6be9b7c1716287a89c4dde2320 ]
Following part was needed before the blamed commit, because inet_getpeer_v6() second argument was the prefix.
/* Give more bandwidth to wider prefixes. */ if (rt->rt6i_dst.plen < 128) tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
Now inet_getpeer_v6() retrieves hosts, we need to remove @tmo adjustement or wider prefixes likes /24 allow 8x more ICMP to be sent for a given ratelimit.
As we had this issue for a while, this patch changes net.ipv6.icmp.ratelimit default value from 1000ms to 100ms to avoid potential regressions.
Also add a READ_ONCE() when reading net->ipv6.sysctl.icmpv6_time.
--- Documentation/networking/ip-sysctl.rst | 7 ++++--- net/ipv6/af_inet6.c | 2 +- net/ipv6/icmp.c | 7 +------ 3 files changed, 6 insertions(+), 10 deletions(-)
Documentation/networking/ip-sysctl.rst +4 -3
@@ -3232,12 +3232,13 @@ enhanced_dad - BOOLEAN =========== ratelimit - INTEGER - Limit the maximal rates for sending ICMPv6 messages. + Limit the maximal rates for sending ICMPv6 messages to a particular + peer. 0 to disable any limiting, - otherwise the minimal space between responses in milliseconds. + otherwise the space between responses in milliseconds. - Default: 1000 + Default: 100 ratemask - list of comma separated ranges For ICMPv6 message types matching the ranges in the ratemask, limit
net/ipv6/af_inet6.c +1 -1
@@ -955,7 +955,7 @@ static int __net_init inet6_net_init(struct net *net)int err =0 ; net->ipv6.sysctl.bindv6only =0 ; - net->ipv6.sysctl.icmpv6_time =1 *HZ ; + net->ipv6.sysctl.icmpv6_time =HZ /10 ; net->ipv6.sysctl.icmpv6_echo_ignore_all =0 ; net->ipv6.sysctl.icmpv6_echo_ignore_multicast =0 ; net->ipv6.sysctl.icmpv6_echo_ignore_anycast =0 ;
net/ipv6/icmp.c +1 -6
@@ -217,14 +217,9 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type, }else if (dev && (dev->flags &IFF_LOOPBACK )) { res = true; }else { -struct rt6_info *rt =dst_rt6_info (dst); -int tmo = net->ipv6.sysctl.icmpv6_time; +int tmo =READ_ONCE (net->ipv6.sysctl.icmpv6_time);struct inet_peer *peer; -/* Give more bandwidth to wider prefixes. */ -if (rt->rt6i_dst.plen <128 ) - tmo >>= ((128 - rt->rt6i_dst.plen)>>5 ); - peer =inet_getpeer_v6 (net->ipv6.peers, &fl6->daddr); res =inet_peer_xrlim_allow (peer, tmo); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 681/781 octeontx2-af: Fix default entries mcam entry action
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hariprasad Kelam <[email protected]>
[ Upstream commit 45be47bf5d7db0f762a93e9c0ede6cb3c91edf3b ]
As per design, AF should update the default MCAM action only when mcam_index is -1. A bug in the previous patch caused default entries to be changed even when the request was not for them.
--- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 41 ++++++++++--------- 1 file changed, 22 insertions(+), 19 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +22 -19
@@ -1042,32 +1042,35 @@ void rvu_npc_update_flowkey_alg_idx(struct rvu *rvu, u16 pcifunc, int nixlf,rvu_write64 (rvu, blkaddr,NPC_AF_MCAMEX_BANKX_ACTION (index, bank), *(u64 *)&action); -/* update the VF flow rule action with the VF default entry action */ -if (mcam_index <0 ) -npc_update_vf_flow_entry (rvu, mcam, blkaddr, pcifunc, - *(u64 *)&action); -/* update the action change in default rule */ pfvf =rvu_get_pfvf (rvu, pcifunc);if (pfvf->def_ucast_rule) pfvf->def_ucast_rule->rx_action = action; - index =npc_get_nixlf_mcam_index (mcam, pcifunc, - nixlf,NIXLF_PROMISC_ENTRY ); +if (mcam_index <0 ) { +/* update the VF flow rule action with the VF default +* entry action +*/ +npc_update_vf_flow_entry (rvu, mcam, blkaddr, pcifunc, + *(u64 *)&action); -/* If PF's promiscuous entry is enabled, -* Set RSS action for that entry as well -*/ -npc_update_rx_action_with_alg_idx (rvu, action, pfvf, index, blkaddr, - alg_idx); + index =npc_get_nixlf_mcam_index (mcam, pcifunc, + nixlf,NIXLF_PROMISC_ENTRY ); - index =npc_get_nixlf_mcam_index (mcam, pcifunc, - nixlf,NIXLF_ALLMULTI_ENTRY ); -/* If PF's allmulti entry is enabled, -* Set RSS action for that entry as well -*/ -npc_update_rx_action_with_alg_idx (rvu, action, pfvf, index, blkaddr, - alg_idx); +/* If PF's promiscuous entry is enabled, +* Set RSS action for that entry as well +*/ +npc_update_rx_action_with_alg_idx (rvu, action, pfvf, index, + blkaddr, alg_idx); + + index =npc_get_nixlf_mcam_index (mcam, pcifunc, + nixlf,NIXLF_ALLMULTI_ENTRY ); +/* If PF's allmulti entry is enabled, +* Set RSS action for that entry as well +*/ +npc_update_rx_action_with_alg_idx (rvu, action, pfvf, index, + blkaddr, alg_idx); + } } void npc_enadis_default_mce_entry(struct rvu *rvu, u16 pcifunc,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 682/781 eth: fbnic: Advertise supported XDP features.
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dimitri Daskalakis <[email protected]>
[ Upstream commit e977fcb3a318b53b47f23b44ac237fceb1b731fe ]
Drivers are supposed to advertise the XDP features they support. This was missed while adding XDP support.
Before:
$ ynl --family netdev --dump dev-get
...
{'ifindex': 3,
'xdp-features': set(),
'xdp-rx-metadata-features': set(),
'xsk-features': set()},
...After:
$ ynl --family netdev --dump dev-get
...
{'ifindex': 3,
'xdp-features': {'basic', 'rx-sg'},
'xdp-rx-metadata-features': set(),
'xsk-features': set()},
...--- drivers/net/ethernet/meta/fbnic/fbnic_netdev.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/meta/fbnic/fbnic_netdev.c +2 -0
@@ -805,6 +805,8 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd) netdev->hw_enc_features |= netdev->features; netdev->features |=NETIF_F_NTUPLE ; + netdev->xdp_features =NETDEV_XDP_ACT_BASIC |NETDEV_XDP_ACT_RX_SG ; + netdev->min_mtu =IPV6_MIN_MTU ; netdev->max_mtu =FBNIC_MAX_JUMBO_FRAME_SIZE -ETH_HLEN ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 683/781 bnge: fix reserving resources from FW
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vikas Gupta <[email protected]>
[ Upstream commit 604530085b2ef484843c723a105b6fd3218b4710 ]
HWRM_FUNC_CFG is used to reserve resources, whereas HWRM_FUNC_QCFG is intended for querying resource information from the firmware. Since __bnge_hwrm_reserve_pf_rings() reserves resources for a specific PF, the command type should be HWRM_FUNC_CFG.
--- drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +1 -1
@@ -442,7 +442,7 @@ __bnge_hwrm_reserve_pf_rings(struct bnge_dev *bd, struct bnge_hw_rings *hwr)struct hwrm_func_cfg_input *req;u32 enables =0 ; -if (bnge_hwrm_req_init (bd, req,HWRM_FUNC_QCFG )) +if (bnge_hwrm_req_init (bd, req,HWRM_FUNC_CFG ))return NULL ; req->fid =cpu_to_le16 (0xffff );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 684/781 bonding: alb: fix UAF in rlb_arp_recv during bond up/down
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit e6834a4c474697df23ab9948fd3577b26bf48656 ]
The ALB RX path may access rx_hashtbl concurrently with bond teardown. During rapid bond up/down cycles, rlb_deinitialize() frees rx_hashtbl while RX handlers are still running, leading to a null pointer dereference detected by KASAN.
However, the root cause is that rlb_arp_recv() can still be accessed after setting recv_probe to NULL, which is actually a use-after-free (UAF) issue. That is the reason for using the referenced commit in the Fixes tag.
[ 214.174138] Oops: general protection fault, probably for non-canonical address 0xdffffc000000001d: 0000 [#1] SMP KASAN PTI [ 214.186478] KASAN: null-ptr-deref in range [0x00000000000000e8-0x00000000000000ef] [ 214.194933] CPU: 30 UID: 0 PID: 2375 Comm: ping Kdump: loaded Not tainted 6.19.0-rc8+ #2 PREEMPT(voluntary) [ 214.205907] Hardware name: Dell Inc. PowerEdge R730/0WCJNT, BIOS 2.14.0 01/14/2022 [ 214.214357] RIP: 0010:rlb_arp_recv+0x505/0xab0 [bonding] [ 214.220320] Code: 0f 85 2b 05 00 00 48 b8 00 00 00 00 00 fc ff df 40 0f b6 ed 48 c1 e5 06 49 03 ad 78 01 00 00 48 8d 7d 28 48 89 fa 48 c1 ea 03 <0f> b6 04 02 84 c0 74 06 0f 8e 12 05 00 00 80 7d 28 00 0f 84 8c 00 [ 214.241280] RSP: 0018:ffffc900073d8870 EFLAGS: 00010206 [ 214.247116] RAX: dffffc0000000000 RBX: ffff888168556822 RCX: ffff88816855681e [ 214.255082] RDX: 000000000000001d RSI: dffffc0000000000 RDI: 00000000000000e8 [ 214.263048] RBP: 00000000000000c0 R08: 0000000000000002 R09: ffffed11192021c8 [ 214.271013] R10: ffff8888c9010e43 R11: 0000000000000001 R12: 1ffff92000e7b119 [ 214.278978] R13: ffff8888c9010e00 R14: ffff888168556822 R15: ffff888168556810 [ 214.286943] FS: 00007f85d2d9cb80(0000) GS:ffff88886ccb3000(0000) knlGS:0000000000000000 [ 214.295966] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 214.302380] CR2: 00007f0d047b5e34 CR3: 00000008a1c2e002 CR4: 00000000001726f0 [ 214.310347] Call Trace: [ 214.313070] <IRQ> [ 214.315318] ? __pfx_rlb_arp_recv+0x10/0x10 [bonding] [ 214.320975] bond_handle_frame+0x166/0xb60 [bonding] [ 214.326537] ? __pfx_bond_handle_frame+0x10/0x10 [bonding] [ 214.332680] __netif_receive_skb_core.constprop.0+0x576/0x2710 [ 214.339199] ? __pfx_arp_process+0x10/0x10 [ 214.343775] ? sched_balance_find_src_group+0x98/0x630 [ 214.349513] ? __pfx___netif_receive_skb_core.constprop.0+0x10/0x10 [ 214.356513] ? arp_rcv+0x307/0x690 [ 214.360311] ? __pfx_arp_rcv+0x10/0x10 [ 214.364499] ? __lock_acquire+0x58c/0xbd0 [ 214.368975] __netif_receive_skb_one_core+0xae/0x1b0 [ 214.374518] ? __pfx___netif_receive_skb_one_core+0x10/0x10 [ 214.380743] ? lock_acquire+0x10b/0x140 [ 214.385026] process_backlog+0x3f1/0x13a0 [ 214.389502] ? process_backlog+0x3aa/0x13a0 [ 214.394174] __napi_poll.constprop.0+0x9f/0x370 [ 214.399233] net_rx_action+0x8c1/0xe60 [ 214.403423] ? __pfx_net_rx_action+0x10/0x10 [ 214.408193] ? lock_acquire.part.0+0xbd/0x260 [ 214.413058] ? sched_clock_cpu+0x6c/0x540 [ 214.417540] ? mark_held_locks+0x40/0x70 [ 214.421920] handle_softirqs+0x1fd/0x860 [ 214.426302] ? __pfx_handle_softirqs+0x10/0x10 [ 214.431264] ? __neigh_event_send+0x2d6/0xf50 [ 214.436131] do_softirq+0xb1/0xf0 [ 214.439830] </IRQ>
The issue is reproducible by repeatedly running
ip link set bond0 up/down while receiving ARP messages, where rlb_arp_recv() can race with rlb_deinitialize() and dereference a freed rx_hashtbl entry.
Fix this by setting recv_probe to NULL and then calling synchronize_net() to wait for any concurrent RX processing to finish. This ensures that no RX handler can access rx_hashtbl after it is freed in bond_alb_deinitialize().
--- drivers/net/bonding/bond_main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/net/bonding/bond_main.c +5 -1
@@ -4314,9 +4314,13 @@ static int bond_close(struct net_device *bond_dev)bond_work_cancel_all (bond); bond->send_peer_notif =0 ; +WRITE_ONCE (bond->recv_probe,NULL ); + +/* Wait for any in-flight RX handlers */ +synchronize_net (); +if (bond_is_lb (bond))bond_alb_deinitialize (bond); - bond->recv_probe =NULL ;if (BOND_MODE (bond) ==BOND_MODE_8023AD && bond->params.broadcast_neighbor)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 685/781 net/mlx5: Fix multiport device check over light SFs
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shay Drory <[email protected]>
[ Upstream commit 47bf2e813817159f4d195be83a9b5a640ee6baec ]
Driver is using num_vhca_ports capability to distinguish between multiport master device and multiport slave device. num_vhca_ports is a capability the driver sets according to the MAX num_vhca_ports capability reported by FW. On the other hand, light SFs doesn't set the above capbility.
This leads to wrong results whenever light SFs is checking whether he is a multiport master or slave.
Therefore, use the MAX capability to distinguish between master and slave devices.
--- include/linux/mlx5/driver.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/mlx5/driver.h +2 -2
@@ -1281,12 +1281,12 @@ static inline bool mlx5_rl_is_supported(struct mlx5_core_dev *dev)static inline int mlx5_core_is_mp_slave (struct mlx5_core_dev *dev) {return MLX5_CAP_GEN (dev, affiliate_nic_vport_criteria) && -MLX5_CAP_GEN (dev, num_vhca_ports) <=1 ; +MLX5_CAP_GEN_MAX (dev, num_vhca_ports) <=1 ; }static inline int mlx5_core_is_mp_master (struct mlx5_core_dev *dev) { -return MLX5_CAP_GEN (dev, num_vhca_ports) >1 ; +return MLX5_CAP_GEN_MAX (dev, num_vhca_ports) >1 ; }static inline int mlx5_core_mp_enabled (struct mlx5_core_dev *dev)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 686/781 net/mlx5e: Fix misidentification of ASO CQE during poll loop
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit ae3cb71e6c4dbda0c0b7c10475b744377813c7bd ]
The ASO completion poll loop uses usleep_range() which can sleep much longer than requested due to scheduler latency. Under load, we witnessed a 20ms+ delay until the process was rescheduled, causing the jiffies based timeout to expire while the thread is sleeping.
The original do-while loop structure (poll, sleep, check timeout) would exit without a final poll when waking after timeout, missing a CQE that arrived during sleep.
Instead of the open-coded while loop, use the kernel's read_poll_timeout() which always performs an additional check after the sleep expiration, and is less error-prone.
Note: read_poll_timeout() doesn't accept a sleep range, by passing 10 sleep_us the sleep range effectively changes from 2-10 to 3-10 usecs.
--- drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c | 10 +++------- .../net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 10 +++------- 2 files changed, 6 insertions(+), 14 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en/tc/meter.c +3 -7
@@ -1,6 +1,7 @@// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. +#include <linux/iopoll.h> #include <linux/math64.h> #include "lib/aso.h" #include "en/tc/post_act.h"
@@ -115,7 +116,6 @@ mlx5e_tc_meter_modify(struct mlx5_core_dev *mdev,struct mlx5e_flow_meters *flow_meters;u8 cir_man, cir_exp, cbs_man, cbs_exp;struct mlx5_aso_wqe *aso_wqe; -unsigned long expires;struct mlx5_aso *aso;u64 rate, burst;u8 ds_cnt;
@@ -187,12 +187,8 @@ mlx5e_tc_meter_modify(struct mlx5_core_dev *mdev,mlx5_aso_post_wqe (aso, true, &aso_wqe->ctrl);/* With newer FW, the wait for the first ASO WQE is more than 2us, put the wait 10ms. */ - expires = jiffies +msecs_to_jiffies (10 ); -do { - err =mlx5_aso_poll_cq (aso, true); -if (err) -usleep_range (2 ,10 ); - }while (err &&time_is_after_jiffies (expires)); +read_poll_timeout (mlx5_aso_poll_cq, err, !err,10 ,10 *USEC_PER_MSEC , + false, aso, true);mutex_unlock (&flow_meters->aso_lock);return err;
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +3 -7
@@ -5,6 +5,7 @@#include <linux/mlx5/mlx5_ifc.h> #include <linux/xarray.h> #include <linux/if_vlan.h> +#include <linux/iopoll.h> #include "en.h" #include "lib/aso.h"
@@ -1397,7 +1398,6 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macstruct mlx5e_macsec_aso *aso;struct mlx5_aso_wqe *aso_wqe;struct mlx5_aso *maso; -unsigned long expires;int err; aso = &macsec->aso;
@@ -1411,12 +1411,8 @@ static int macsec_aso_query(struct mlx5_core_dev *mdev, struct mlx5e_macsec *macmacsec_aso_build_wqe_ctrl_seg (aso, &aso_wqe->aso_ctrl,NULL );mlx5_aso_post_wqe (maso, false, &aso_wqe->ctrl); - expires = jiffies +msecs_to_jiffies (10 ); -do { - err =mlx5_aso_poll_cq (maso, false); -if (err) -usleep_range (2 ,10 ); - }while (err &&time_is_after_jiffies (expires)); +read_poll_timeout (mlx5_aso_poll_cq, err, !err,10 ,10 *USEC_PER_MSEC , + false, maso, false);if (err) goto err_out;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 687/781 net/mlx5: Fix misidentification of write combining CQE during poll loop
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit d451994ebc7d4392610bd4b2ab339b255deb4143 ]
The write combining completion poll loop uses usleep_range() which can sleep much longer than requested due to scheduler latency. Under load, we witnessed a 20ms+ delay until the process was rescheduled, causing the jiffies based timeout to expire while the thread is sleeping.
The original do-while loop structure (poll, sleep, check timeout) would exit without a final poll when waking after timeout, missing a CQE that arrived during sleep.
Instead of the open-coded while loop, use the kernel's poll_timeout_us() which always performs an additional check after the sleep expiration, and is less error-prone.
Note: poll_timeout_us() doesn't accept a sleep range, by passing 10 sleep_us the sleep range effectively changes from 2-10 to 3-10 usecs.
--- drivers/net/ethernet/mellanox/mlx5/core/wc.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/wc.c +5 -9
@@ -2,6 +2,7 @@// Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. #include <linux/io.h> +#include <linux/iopoll.h> #include <linux/mlx5/transobj.h> #include "lib/clock.h" #include "mlx5_core.h"
@@ -15,7 +16,7 @@#define TEST_WC_NUM_WQES 255#define TEST_WC_LOG_CQ_SZ (order_base_2(TEST_WC_NUM_WQES))#define TEST_WC_SQ_LOG_WQ_SZ TEST_WC_LOG_CQ_SZ -#define TEST_WC_POLLING_MAX_TIME_JIFFIES msecs_to_jiffies(100) +#define TEST_WC_POLLING_MAX_TIME_USEC (100 * USEC_PER_MSEC)struct mlx5_wc_cq {/* data path - accessed per cqe */
@@ -359,7 +360,6 @@ static int mlx5_wc_poll_cq(struct mlx5_wc_sq *sq)static void mlx5_core_test_wc (struct mlx5_core_dev *mdev) {unsigned int offset =0 ; -unsigned long expires;struct mlx5_wc_sq *sq;int i, err;
@@ -389,13 +389,9 @@ static void mlx5_core_test_wc(struct mlx5_core_dev *mdev)mlx5_wc_post_nop (sq, &offset, true); - expires = jiffies +TEST_WC_POLLING_MAX_TIME_JIFFIES ; -do { - err =mlx5_wc_poll_cq (sq); -if (err) -usleep_range (2 ,10 ); - }while (mdev->wc_state ==MLX5_WC_STATE_UNINITIALIZED && -time_is_after_jiffies (expires)); +poll_timeout_us (mlx5_wc_poll_cq (sq), + mdev->wc_state !=MLX5_WC_STATE_UNINITIALIZED ,10 , +TEST_WC_POLLING_MAX_TIME_USEC , false);mlx5_wc_destroy_sq (sq);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 688/781 net/mlx5e: MACsec, add ASO poll loop in macsec_aso_set_arm_event
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit 9854b243ce4225328d0b32fdc998d35b6952d3f7 ]
The macsec_aso_set_arm_event function calls mlx5_aso_poll_cq once without a retry loop. If the CQE is not immediately available after posting the WQE, the function fails unnecessarily.
Use read_poll_timeout() to poll 3-10 usecs for CQE, consistent with other ASO polling code paths in the driver.
--- drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c +2 -1
@@ -1386,7 +1386,8 @@ static int macsec_aso_set_arm_event(struct mlx5_core_dev *mdev, struct mlx5e_mac MLX5_ACCESS_ASO_OPC_MOD_MACSEC);macsec_aso_build_ctrl (aso, &aso_wqe->aso_ctrl, in);mlx5_aso_post_wqe (maso, false, &aso_wqe->ctrl); - err =mlx5_aso_poll_cq (maso, false); +read_poll_timeout (mlx5_aso_poll_cq, err, !err,10 ,10 *USEC_PER_MSEC , + false, maso, false);mutex_unlock (&aso->aso_lock);return err;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 689/781 net/mlx5e: Fix deadlocks between devlink and netdev instance locks
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmin Ratiu <[email protected]>
[ Upstream commit 83ac0304a2d77519dae1e54c9713cbe1aedf19c9 ]
In the mentioned "Fixes" commit, various work tasks triggering devlink health reporter recovery were switched to use netdev_trylock to protect against concurrent tear down of the channels being recovered. But this had the side effect of introducing potential deadlocks because of incorrect lock ordering.
The correct lock order is described by the init flow:probe_one -> mlx5_init_one (acquires devlink lock)
-> mlx5_init_one_devl_locked -> mlx5_register_device -> mlx5_rescan_drivers_locked -...-> mlx5e_probe -> _mlx5e_probe -> register_netdev (acquires rtnl lock)
-> register_netdevice (acquires netdev lock)
=> devlink lock -> rtnl lock -> netdev lock.
But in the current recovery flow, the order is wrong:mlx5e_tx_err_cqe_work (acquires netdev lock)
-> mlx5e_reporter_tx_err_cqe -> mlx5e_health_report
-> devlink_health_report (acquires devlink lock => boom!) -> devlink_health_reporter_recover
-> mlx5e_tx_reporter_recover -> mlx5e_tx_reporter_recover_from_ctx -> mlx5e_tx_reporter_err_cqe_recover
The same pattern exists in:mlx5e_reporter_rx_timeoutmlx5e_reporter_tx_ptpsq_unhealthymlx5e_reporter_tx_timeout
Fix these by moving the netdev_trylock calls from the work handlers lower in the call stack, in the respective recovery functions, where they are actually necessary.
--- .../net/ethernet/mellanox/mlx5/core/en/ptp.c | 14 ----- .../mellanox/mlx5/core/en/reporter_rx.c | 13 +++++ .../mellanox/mlx5/core/en/reporter_tx.c | 52 +++++++++++++++++-- .../net/ethernet/mellanox/mlx5/core/en_main.c | 40 -------------- 4 files changed, 61 insertions(+), 58 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/en/ptp.c +0 -14
@@ -457,22 +457,8 @@ static void mlx5e_ptpsq_unhealthy_work(struct work_struct *work) {struct mlx5e_ptpsq *ptpsq = container_of(work, struct mlx5e_ptpsq, report_unhealthy_work); -struct mlx5e_txqsq *sq = &ptpsq->txqsq; - -/* Recovering the PTP SQ means re-enabling NAPI, which requires the -* netdev instance lock. However, SQ closing has to wait for this work -* task to finish while also holding the same lock. So either get the -* lock or find that the SQ is no longer enabled and thus this work is -* not relevant anymore. -*/ -while (!netdev_trylock (sq->netdev)) { -if (!test_bit (MLX5E_SQ_STATE_ENABLED , &sq->state)) -return ; -msleep (20 ); - }mlx5e_reporter_tx_ptpsq_unhealthy (ptpsq); -netdev_unlock (sq->netdev); } static int mlx5e_ptp_open_txqsq(struct mlx5e_ptp *c, u32 tisn,
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_rx.c +13 -0
@@ -1,6 +1,8 @@// SPDX-License-Identifier: GPL-2.0 // Copyright (c) 2019 Mellanox Technologies. +#include <net/netdev_lock.h> +#include "health.h" #include "params.h" #include "txrx.h"
@@ -177,6 +179,16 @@ static int mlx5e_rx_reporter_timeout_recover(void *ctx) rq = ctx; priv = rq->priv; +/* Acquire netdev instance lock to synchronize with channel close and +* reopen flows. Either successfully obtain the lock, or detect that +* channels are closing for another reason, making this work no longer +* necessary. +*/ +while (!netdev_trylock (rq->netdev)) { +if (!test_bit (MLX5E_STATE_CHANNELS_ACTIVE , &rq->priv->state)) +return 0 ; +msleep (20 ); + }mutex_lock (&priv->state_lock); eq = rq->cq.mcq.eq;
@@ -186,6 +198,7 @@ static int mlx5e_rx_reporter_timeout_recover(void *ctx)clear_bit (MLX5E_SQ_STATE_ENABLED , &rq->icosq->state);mutex_unlock (&priv->state_lock); +netdev_unlock (rq->netdev);return err; }
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +48 -4
109 lines not on this page · raw message
drivers/net/ethernet/mellanox/mlx5/core/en_main.c +0 -40
@@ -688,19 +688,7 @@ static void mlx5e_rq_timeout_work(struct work_struct *timeout_work) struct mlx5e_rq, rx_timeout_work); -/* Acquire netdev instance lock to synchronize with channel close and -* reopen flows. Either successfully obtain the lock, or detect that -* channels are closing for another reason, making this work no longer -* necessary. -*/ -while (!netdev_trylock (rq->netdev)) { -if (!test_bit (MLX5E_STATE_CHANNELS_ACTIVE , &rq->priv->state)) -return ; -msleep (20 ); - } -mlx5e_reporter_rx_timeout (rq); -netdev_unlock (rq->netdev); }static int mlx5e_alloc_mpwqe_rq_drop_page (struct mlx5e_rq *rq)
@@ -1997,20 +1985,7 @@ void mlx5e_tx_err_cqe_work(struct work_struct *recover_work) struct mlx5e_txqsq *sq = container_of(recover_work, struct mlx5e_txqsq, recover_work); -/* Recovering queues means re-enabling NAPI, which requires the netdev -* instance lock. However, SQ closing flows have to wait for work tasks -* to finish while also holding the netdev instance lock. So either get -* the lock or find that the SQ is no longer enabled and thus this work -* is not relevant anymore. -*/ -while (!netdev_trylock (sq->netdev)) { -if (!test_bit (MLX5E_SQ_STATE_ENABLED , &sq->state)) -return ; -msleep (20 ); - } -mlx5e_reporter_tx_err_cqe (sq); -netdev_unlock (sq->netdev); }static struct dim_cq_moder mlx5e_get_def_tx_moderation (u8 cq_period_mode)
@@ -5121,19 +5096,6 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)struct net_device *netdev = priv->netdev;int i; -/* Recovering the TX queues implies re-enabling NAPI, which requires -* the netdev instance lock. -* However, channel closing flows have to wait for this work to finish -* while holding the same lock. So either get the lock or find that -* channels are being closed for other reason and this work is not -* relevant anymore. -*/ -while (!netdev_trylock (netdev)) { -if (!test_bit (MLX5E_STATE_CHANNELS_ACTIVE , &priv->state)) -return ; -msleep (20 ); - } -for (i =0 ; i < netdev->real_num_tx_queues; i++) {struct netdev_queue *dev_queue =netdev_get_tx_queue (netdev, i);
@@ -5146,8 +5108,6 @@ static void mlx5e_tx_timeout_work(struct work_struct *work)/* break if tried to reopened channels */ break ; } - -netdev_unlock (netdev); }static void mlx5e_tx_timeout (struct net_device *dev,unsigned int txqueue)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 690/781 net/mlx5e: Use unsigned for mlx5e_get_max_num_channels
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmin Ratiu <[email protected]>
[ Upstream commit 57a94d4b22b0c6cc5d601e6b6238d78fb923d991 ]
The max number of channels is always an unsigned int, use the correct type to fix compilation errors done with strict type checking, e.g.:
error: call to ‘__compiletime_assert_1110’ declared with attribute
error: min(mlx5e_get_devlink_param_num_doorbells(mdev), mlx5e_get_max_num_channels(mdev)) signedness error
--- drivers/net/ethernet/mellanox/mlx5/core/en.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en.h +2 -1
@@ -179,7 +179,8 @@ static inline u16 mlx5_min_rx_wqes(int wq_type, u32 wq_size) }/* Use this function to get max num channels (rxqs/txqs) only to create netdev */ -static inline int mlx5e_get_max_num_channels (struct mlx5_core_dev *mdev) +static inline unsigned int +mlx5e_get_max_num_channels (struct mlx5_core_dev *mdev) {return is_kdump_kernel () ? MLX5E_MIN_NUM_CHANNELS :
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 691/781 apparmor: fix NULL pointer dereference in __unix_needs_revalidation
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: System Administrator <root@localhost>
[ Upstream commit e2938ad00b21340c0362562dfedd7cfec0554d67 ]
When receiving file descriptors via SCM_RIGHTS, both the socket pointer and the socket's sk pointer can be NULL during socket setup or teardown, causing NULL pointer dereferences in __unix_needs_revalidation().
This is a regression in AppArmor 5.0.0 (kernel 6.17+) where the new __unix_needs_revalidation() function was added without proper NULL checks.
The crash manifests as:
BUG: kernel NULL pointer dereference, address: 0x0000000000000018 RIP: aa_file_perm+0xb7/0x3b0 (or +0xbe/0x3b0, +0xc0/0x3e0) Call Trace: apparmor_file_receive+0x42/0x80 security_file_receive+0x2e/0x50 receive_fd+0x1d/0xf0 scm_detach_fds+0xad/0x1c0
The function dereferences sock->sk->sk_family without checking if either sock or sock->sk is NULL first.
Add NULL checks for both sock and sock->sk before accessing sk_family.
--- security/apparmor/file.c | 3 +++ 1 file changed, 3 insertions(+)
security/apparmor/file.c +3 -0
@@ -578,6 +578,9 @@ static bool __unix_needs_revalidation(struct file *file, struct aa_label *label,return false;if (request &NET_PEER_MASK )return false; +/* sock and sock->sk can be NULL for sockets being set up or torn down */ +if (!sock || !sock->sk) +return false;if (sock->sk->sk_family ==PF_UNIX ) {struct aa_sk_ctx *ctx =aa_sock (sock->sk);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 692/781 apparmor: fix NULL sock in aa_sock_file_perm
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 00b67657535dfea56e84d11492f5c0f61d0af297 ]
Deal with the potential that sock and sock-sk can be NULL during socket setup or teardown. This could lead to an oops. The fix for NULL pointer dereference in __unix_needs_revalidation shows this is at least possible for af_unix sockets. While the fix for af_unix sockets applies for newer mediation this is still the fall back path for older af_unix mediation and other sockets, so ensure it is covered.
--- security/apparmor/net.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
security/apparmor/net.c +4 -2
@@ -326,8 +326,10 @@ int aa_sock_file_perm(const struct cred *subj_cred, struct aa_label *label,struct socket *sock = (struct socket *) file->private_data;AA_BUG (!label); -AA_BUG (!sock); -AA_BUG (!sock->sk); + +/* sock && sock->sk can be NULL for sockets being set up or torn down */ +if (!sock || !sock->sk) +return 0 ;if (sock->sk->sk_family ==PF_UNIX )return aa_unix_file_perm (subj_cred, label, op, request, file);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 693/781 AppArmor: Allow apparmor to handle unaligned dfa tables
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller <[email protected]>
[ Upstream commit 64802f731214a51dfe3c6c27636b3ddafd003eb0 ]
The dfa tables can originate from kernel or userspace and 8-byte alignment isn't always guaranteed and as such may trigger unaligned memory accesses on various architectures. Resulting in the following
[ 73.901376] WARNING: CPU: 0 PID: 341 at security/apparmor/match.c:316 aa_dfa_unpack+0x6cc/0x720
[ 74.015867] Modules linked in: binfmt_misc evdev flash sg drm drm_panel_orientation_quirks backlight i2c_core configfs nfnetlink autofs4 ext4 crc16 mbcache jbd2 hid_generic usbhid sr_mod hid cdrom sd_mod ata_generic ohci_pci ehci_pci ehci_hcd ohci_hcd pata_ali libata sym53c8xx scsi_transport_spi tg3 scsi_mod usbcore libphy scsi_common mdio_bus usb_common
[ 74.428977] CPU: 0 UID: 0 PID: 341 Comm: apparmor_parser Not tainted 6.18.0-rc6+ #9 NONE
[ 74.536543] Call Trace:
[ 74.568561] [<0000000000434c24>] dump_stack+0x8/0x18
[ 74.633757] [<0000000000476438>] __warn+0xd8/0x100
[ 74.696664] [<00000000004296d4>] warn_slowpath_fmt+0x34/0x74
[ 74.771006] [<00000000008db28c>] aa_dfa_unpack+0x6cc/0x720
[ 74.843062] [<00000000008e643c>] unpack_pdb+0xbc/0x7e0
[ 74.910545] [<00000000008e7740>] unpack_profile+0xbe0/0x1300
[ 74.984888] [<00000000008e82e0>] aa_unpack+0xe0/0x6a0
[ 75.051226] [<00000000008e3ec4>] aa_replace_profiles+0x64/0x1160
[ 75.130144] [<00000000008d4d90>] policy_update+0xf0/0x280
[ 75.201057] [<00000000008d4fc8>] profile_replace+0xa8/0x100
[ 75.274258] [<0000000000766bd0>] vfs_write+0x90/0x420
[ 75.340594] [<00000000007670cc>] ksys_write+0x4c/0xe0
[ 75.406932] [<0000000000767174>] sys_write+0x14/0x40
[ 75.472126] [<0000000000406174>] linux_sparc_syscall+0x34/0x44
[ 75.548802] ---[ end trace 0000000000000000 ]---
[ 75.609503] dfa blob stream 0xfff0000008926b96 not aligned.
[ 75.682695] Kernel unaligned access at TPC[8db2a8] aa_dfa_unpack+0x6e8/0x720
Work around it by using the get_unaligned_xx() helpers.
--- security/apparmor/match.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
security/apparmor/match.c +8 -7
@@ -15,6 +15,7 @@#include <linux/vmalloc.h> #include <linux/err.h> #include <linux/kref.h> +#include <linux/unaligned.h> #include "include/lib.h" #include "include/match.h"
@@ -42,11 +43,11 @@ static struct table_header *unpack_table(char *blob, size_t bsize)/* loaded td_id's start at 1, subtract 1 now to avoid doing * it every time we use td_id as an index */ - th.td_id =be16_to_cpu (*(__be16 *) (blob)) -1 ; + th.td_id =get_unaligned_be16 (blob) -1 ;if (th.td_id >YYTD_ID_MAX ) goto out; - th.td_flags =be16_to_cpu (*(__be16 *) (blob +2 )); - th.td_lolen =be32_to_cpu (*(__be32 *) (blob +8 )); + th.td_flags =get_unaligned_be16 (blob +2 ); + th.td_lolen =get_unaligned_be32 (blob +8 ); blob +=sizeof (struct table_header ); if (!(th.td_flags == YYTD_DATA16 || th.td_flags == YYTD_DATA32 ||
@@ -313,14 +314,14 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)if (size <sizeof (struct table_set_header )) goto fail; -if (ntohl (*(__be32 *) data) !=YYTH_MAGIC ) +if (get_unaligned_be32 (data) !=YYTH_MAGIC ) goto fail; - hsize =ntohl (*(__be32 *) (data +4 )); + hsize =get_unaligned_be32 (data +4 );if (size < hsize) goto fail; - dfa->flags =ntohs (*(__be16 *) (data +12 )); + dfa->flags =get_unaligned_be16 (data +12 );if (dfa->flags & ~(YYTH_FLAGS )) goto fail;
@@ -329,7 +330,7 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)* if (dfa->flags & YYTH_FLAGS_OOB_TRANS) { * if (hsize < 16 + 4) * goto fail; -* dfa->max_oob = ntol(*(__be32 *) (data + 16)); +* dfa->max_oob = get_unaligned_be32(data + 16); * if (dfa->max <= MAX_OOB_SUPPORTED) { * pr_err("AppArmor DFA OOB greater than supported\n"); * goto fail;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 694/781 apparmor: Fix & Optimize table creation from possibly unaligned memory
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helge Deller <[email protected]>
[ Upstream commit 6fc367bfd4c8886e6b1742aabbd1c0bdc310db3a ]
Source blob may come from userspace and might be unaligned. Try to optize the copying process by avoiding unaligned memory accesses.
- Added Fixes tag
- Added "Fix &" to description as this doesn't just optimize but fixes a potential unaligned memory access
--- security/apparmor/include/match.h | 12 +++++++----- security/apparmor/match.c | 7 +++---- 2 files changed, 10 insertions(+), 9 deletions(-)
security/apparmor/include/match.h +7 -5
@@ -104,16 +104,18 @@ struct aa_dfa {struct table_header *tables[YYTD_ID_TSIZE ]; }; -#define byte_to_byte (X ) (X) -#define UNPACK_ARRAY (TABLE ,BLOB ,LEN ,TTYPE ,BTYPE ,NTOHX ) \ do { \ typeof(LEN) __i; \ TTYPE *__t = (TTYPE *) TABLE; \ BTYPE *__b = (BTYPE *) BLOB; \ - for (__i = 0; __i < LEN; __i++) { \ - __t[__i] = NTOHX(__b[__i]); \ - } \ + BUILD_BUG_ON(sizeof(TTYPE) != sizeof(BTYPE)); \ + if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)) \ + memcpy(__t, __b, (LEN) * sizeof(BTYPE)); \ + else/* copy & convert from big-endian */ \ +for (__i =0 ; __i <LEN ; __i++) { \ + __t[__i] =NTOHX (&__b[__i]); \ + } \ }while (0 ) static inline size_t table_size(size_t len, size_t el_size)
security/apparmor/match.c +3 -4
@@ -67,14 +67,13 @@ static struct table_header *unpack_table(char *blob, size_t bsize) table->td_flags = th.td_flags; table->td_lolen = th.td_lolen;if (th.td_flags ==YYTD_DATA8 ) -UNPACK_ARRAY (table->td_data, blob, th.td_lolen, - u8, u8, byte_to_byte); +memcpy (table->td_data, blob, th.td_lolen);else if (th.td_flags ==YYTD_DATA16 )UNPACK_ARRAY (table->td_data, blob, th.td_lolen, - u16, __be16, be16_to_cpu); + u16, __be16, get_unaligned_be16);else if (th.td_flags ==YYTD_DATA32 )UNPACK_ARRAY (table->td_data, blob, th.td_lolen, - u32, __be32, be32_to_cpu); + u32, __be32, get_unaligned_be32);else goto fail;/* if table was vmalloced make sure the page tables are synced
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 695/781 apparmor: return -ENOMEM in unpack_perms_table upon alloc failure
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryan Lee <[email protected]>
[ Upstream commit 74b7105e53e80a4072bd3e1a50be7aa15e3f0a01 ]
In policy_unpack.c:unpack_perms_table, the perms struct is allocated via kcalloc, with the position being reset if the allocation fails. However, the error path results in -EPROTO being retured instead of -ENOMEM. Fix this to return the correct error code.
--- security/apparmor/policy_unpack.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
security/apparmor/policy_unpack.c +4 -2
@@ -687,8 +687,10 @@ static ssize_t unpack_perms_table(struct aa_ext *e, struct aa_perms **perms)if (!aa_unpack_array (e,NULL , &size)) goto fail_reset; *perms =kcalloc (size,sizeof (struct aa_perms ),GFP_KERNEL ); -if (!*perms) - goto fail_reset; +if (!*perms) { + e->pos = pos; +return -ENOMEM ; + }for (i =0 ; i < size; i++) {if (!unpack_perm (e, version, &(*perms)[i])) goto fail;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 696/781 apparmor: fix boolean argument in apparmor_mmap_file
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryan Lee <[email protected]>
[ Upstream commit 48d5268e911abcf7674ec33c9b0b3e952be1175e ]
The previous value of GFP_ATOMIC is an int and not a bool, potentially resulting in UB when being assigned to a bool. In addition, the mmap hook is called outside of locks (i.e. in a non-atomic context), so we can pass a fixed constant value of false instead to common_mmap.
Stable-dep-of: 4a134723f9f1 ("apparmor: move check for aa_null file to cover all cases")
--- security/apparmor/lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/apparmor/lsm.c +1 -1
@@ -584,7 +584,7 @@ static int common_mmap(const char *op, struct file *file, unsigned long prot,static int apparmor_mmap_file (struct file *file,unsigned long reqprot,unsigned long prot,unsigned long flags) { -return common_mmap (OP_FMMAP , file, prot, flags,GFP_ATOMIC ); +return common_mmap (OP_FMMAP , file, prot, flags, false); } static int apparmor_file_mprotect(struct vm_area_struct *vma,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 697/781 apparmor: drop in_atomic flag in common_mmap, and common_file_perm
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit c3f27ccdb2dce3f0f2814574d06017f46c11fa29 ]
with the previous changes to mmap the in_atomic flag is now always false, so drop it.
Stable-dep-of: 4a134723f9f1 ("apparmor: move check for aa_null file to cover all cases")
--- security/apparmor/lsm.c | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-)
security/apparmor/lsm.c +9 -12
@@ -520,8 +520,7 @@ static void apparmor_file_free_security(struct file *file)aa_put_label (rcu_access_pointer (ctx->label)); } -static int common_file_perm (const char *op,struct file *file,u32 mask, -bool in_atomic) +static int common_file_perm (const char *op,struct file *file,u32 mask) {struct aa_label *label;int error =0 ;
@@ -532,7 +531,7 @@ static int common_file_perm(const char *op, struct file *file, u32 mask,return -EACCES ; label =__begin_current_label_crit_section (&needput); - error =aa_file_perm (op,current_cred (), label, file, mask, in_atomic); + error =aa_file_perm (op,current_cred (), label, file, mask, false);__end_current_label_crit_section (label, needput);return error;
@@ -540,13 +539,12 @@ static int common_file_perm(const char *op, struct file *file, u32 mask,static int apparmor_file_receive (struct file *file) { -return common_file_perm (OP_FRECEIVE , file,aa_map_file_to_perms (file), - false); +return common_file_perm (OP_FRECEIVE , file,aa_map_file_to_perms (file)); }static int apparmor_file_permission (struct file *file,int mask) { -return common_file_perm (OP_FPERM , file, mask, false); +return common_file_perm (OP_FPERM , file, mask); }static int apparmor_file_lock (struct file *file,unsigned int cmd)
@@ -556,11 +554,11 @@ static int apparmor_file_lock(struct file *file, unsigned int cmd)if (cmd ==F_WRLCK ) mask |=MAY_WRITE ; -return common_file_perm (OP_FLOCK , file, mask, false); +return common_file_perm (OP_FLOCK , file, mask); }static int common_mmap (const char *op,struct file *file,unsigned long prot, -unsigned long flags,bool in_atomic) +unsigned long flags) {int mask =0 ;
@@ -578,21 +576,20 @@ static int common_mmap(const char *op, struct file *file, unsigned long prot,if (prot &PROT_EXEC ) mask |=AA_EXEC_MMAP ; -return common_file_perm (op, file, mask, in_atomic); +return common_file_perm (op, file, mask); }static int apparmor_mmap_file (struct file *file,unsigned long reqprot,unsigned long prot,unsigned long flags) { -return common_mmap (OP_FMMAP , file, prot, flags, false); +return common_mmap (OP_FMMAP , file, prot, flags); }static int apparmor_file_mprotect (struct vm_area_struct *vma,unsigned long reqprot,unsigned long prot) {return common_mmap (OP_FMPROT , vma->vm_file, prot, - !(vma->vm_flags &VM_SHARED ) ?MAP_PRIVATE :0 , - false); + !(vma->vm_flags &VM_SHARED ) ?MAP_PRIVATE :0 ); }#ifdef CONFIG_IO_URING
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 698/781 apparmor: account for in_atomic removal in common_file_perm
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryan Lee <[email protected]>
[ Upstream commit 9b829c0aa96e9385b1e9a308d3eb054b95fbeda2 ]
If we are not in an atomic context in common_file_perm, then we don't have to use the atomic versions, resulting in improved performance outside of atomic contexts.
Stable-dep-of: 4a134723f9f1 ("apparmor: move check for aa_null file to cover all cases")
--- security/apparmor/lsm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
security/apparmor/lsm.c +2 -3
@@ -524,15 +524,14 @@ static int common_file_perm(const char *op, struct file *file, u32 mask) {struct aa_label *label;int error =0 ; -bool needput;/* don't reaudit files closed during inheritance */ if (unlikely (file->f_path.dentry == aa_null.dentry))return -EACCES ; - label =__begin_current_label_crit_section (&needput); + label =begin_current_label_crit_section (); error =aa_file_perm (op,current_cred (), label, file, mask, false); -__end_current_label_crit_section (label, needput); +end_current_label_crit_section (label);return error; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 699/781 apparmor: move check for aa_null file to cover all cases
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 4a134723f9f1ad2f3621566259db673350d19cb1 ]
files with a dentry pointing aa_null.dentry where already rejected as part of file_inheritance. Unfortunately the check in common_file_perm() is insufficient to cover all cases causing unnecessary audit messages without the original files context.
Eg.
[ 442.886474] audit: type=1400 audit(1704822661.616:329): apparmor="DENIED" operation="file_inherit" class="file" namespace="root//lxd-juju-98527a-0_<var-snap-lxd-common-lxd>" profile="snap.lxd.activate" name="/apparmor/.null" pid=9525 comm="snap-exec"
Further examples of this are in the logs of
https://bugs.launchpad.net/ubuntu/+source/apparmor/+bug/2120439
https://bugs.launchpad.net/ubuntu/+source/snapd/+bug/1952084
https://bugs.launchpad.net/snapd/+bug/2049099
These messages have no value and should not be sent to the logs. AppArmor was already filtering the out in some cases but the original patch did not catch all cases. Fix this by push the existing check down into two functions that should cover all cases.
--- security/apparmor/file.c | 12 ++++++++++-- security/apparmor/lsm.c | 4 ---- 2 files changed, 10 insertions(+), 6 deletions(-)
security/apparmor/file.c +10 -2
@@ -154,8 +154,12 @@ static int path_name(const char *op, const struct cred *subj_cred,const char *info =NULL ;int error; - error =aa_path_name (path, flags, buffer, name, &info, -labels_profile (label)->disconnected); +/* don't reaudit files closed during inheritance */ +if (unlikely (path->dentry == aa_null.dentry)) + error = -EACCES ; +else + error =aa_path_name (path, flags, buffer, name, &info, +labels_profile (label)->disconnected);if (error) { fn_for_each_confined(label, profile, aa_audit_file(subj_cred,
@@ -616,6 +620,10 @@ int aa_file_perm(const char *op, const struct cred *subj_cred,AA_BUG (!label);AA_BUG (!file); +/* don't reaudit files closed during inheritance */ +if (unlikely (file->f_path.dentry == aa_null.dentry)) +return -EACCES ; + fctx =file_ctx (file);rcu_read_lock ();
security/apparmor/lsm.c +0 -4
@@ -525,10 +525,6 @@ static int common_file_perm(const char *op, struct file *file, u32 mask)struct aa_label *label;int error =0 ; -/* don't reaudit files closed during inheritance */ -if (unlikely (file->f_path.dentry == aa_null.dentry)) -return -EACCES ; - label =begin_current_label_crit_section (); error =aa_file_perm (op,current_cred (), label, file, mask, false);end_current_label_crit_section (label);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 700/781 apparmor: fix rlimit for posix cpu timers
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 6ca56813f4a589f536adceb42882855d91fb1125 ]
Posix cpu timers requires an additional step beyond setting the rlimit. Refactor the code so its clear when what code is setting the limit and conditionally update the posix cpu timers when appropriate.
--- security/apparmor/resource.c | 5 +++++ 1 file changed, 5 insertions(+)
security/apparmor/resource.c +5 -0
@@ -196,6 +196,11 @@ void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l) rules->rlimits.limits[j].rlim_max);/* soft limit should not exceed hard limit */ rlim->rlim_cur =min (rlim->rlim_cur, rlim->rlim_max); +if (j ==RLIMIT_CPU && + rlim->rlim_cur !=RLIM_INFINITY && +IS_ENABLED (CONFIG_POSIX_TIMERS )) + (void )update_rlimit_cpu (current->group_leader, + rlim->rlim_cur); } } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 701/781 apparmor: remove apply_modes_to_perms from label_match
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit b2e27be2948f2f8c38421cd554b5fc9383215648 ]
The modes shouldn't be applied at the point of label match, it just results in them being applied multiple times. Instead they should be applied after which is already being done by all callers so it can just be dropped from label_match.
Stable-dep-of: a4c9efa4dbad ("apparmor: make label_match return a consistent value")
--- security/apparmor/label.c | 3 --- 1 file changed, 3 deletions(-)
security/apparmor/label.c +0 -3
@@ -1317,7 +1317,6 @@ static int label_compound_match(struct aa_profile *profile, goto fail; } *perms = *aa_lookup_perms (rules->policy, state); -aa_apply_modes_to_perms (profile, perms);if ((perms->allow & request) != request)return -EACCES ;
@@ -1370,7 +1369,6 @@ static int label_components_match(struct aa_profile *profile, next: tmp = *aa_lookup_perms (rules->policy, state); -aa_apply_modes_to_perms (profile, &tmp);aa_perms_accum (perms, &tmp);label_for_each_cont (i, label, tp) {if (!aa_ns_visible (profile->ns, tp->ns, subns))
@@ -1379,7 +1377,6 @@ static int label_components_match(struct aa_profile *profile,if (!state) goto fail; tmp = *aa_lookup_perms (rules->policy, state); -aa_apply_modes_to_perms (profile, &tmp);aa_perms_accum (perms, &tmp); }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 702/781 apparmor: make label_match return a consistent value
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit a4c9efa4dbad6dacad6e8b274e30e814c8353097 ]
compound match is inconsistent in returning a state or an integer error this is problemati if the error is ever used as a state in the state machine
--- security/apparmor/label.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
security/apparmor/label.c +9 -11
@@ -1278,7 +1278,7 @@ static inline aa_state_t match_component(struct aa_profile *profile,* @request: permissions to request * @perms: perms struct to set * -* Returns: 0 on success else ERROR +* Returns: state match stopped at or DFA_NOMATCH if aborted early * * For the label A//&B//&C this does the perm match for A//&B//&C * @perms should be preinitialized with allperms OR a previous permission
@@ -1305,7 +1305,7 @@ static int label_compound_match(struct aa_profile *profile,/* no component visible */ *perms = allperms; -return 0 ; +return state; next:label_for_each_cont (i, label, tp) {
@@ -1317,14 +1317,11 @@ static int label_compound_match(struct aa_profile *profile, goto fail; } *perms = *aa_lookup_perms (rules->policy, state); -if ((perms->allow & request) != request) -return -EACCES ; - -return 0 ; +return state; fail: *perms = nullperms; -return state; +return DFA_NOMATCH ; }/**
@@ -1406,11 +1403,12 @@ int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules, struct aa_label *label, aa_state_t state, bool subns, u32 request, struct aa_perms *perms) { - int error = label_compound_match(profile, rules, label, state, subns, - request, perms); -if (!error) -return error; + aa_state_t tmp = label_compound_match(profile, rules, label, state, subns, + request, perms); +if ((perms->allow & request) == request) +return 0 ; +/* failed compound_match try component matches */ *perms = allperms;return label_components_match (profile, rules, label, state, subns, request, perms);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 703/781 apparmor: avoid per-cpu hold underflow in aa_get_buffer
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhengmian Hu <[email protected]>
[ Upstream commit 640cf2f09575c9dc344b3f7be2498d31e3923ead ]
When aa_get_buffer() pulls from the per-cpu list it unconditionally decrements cache->hold. If hold reaches 0 while count is still non-zero, the unsigned decrement wraps to UINT_MAX. This keeps hold non-zero for a very long time, so aa_put_buffer() never returns buffers to the global list, which can starve other CPUs and force repeated kmalloc(aa_g_path_max) allocations.
Guard the decrement so hold never underflows.
--- security/apparmor/lsm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
security/apparmor/lsm.c +2 -1
@@ -2137,7 +2137,8 @@ char *aa_get_buffer(bool in_atomic)if (!list_empty (&cache->head)) { aa_buf = list_first_entry(&cache->head, union aa_buffer, list);list_del (&aa_buf->list); - cache->hold--; +if (cache->hold) + cache->hold--; cache->count--;put_cpu_ptr (&aa_local_buffers);return &aa_buf->buffer[0 ];
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 704/781 apparmor: fix invalid deref of rawdata when export_binary is unset
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georgia Garcia <[email protected]>
[ Upstream commit df9ac55abd18628bd8cff687ea043660532a3654 ]
If the export_binary parameter is disabled on runtime, profiles that were loaded before that will still have their rawdata stored in apparmorfs, with a symbolic link to the rawdata on the policy directory. When one of those profiles are replaced, the rawdata is set to NULL, but when trying to resolve the symbolic links to rawdata for that profile, it will try to dereference profile->rawdata->name when profile->rawdata is now NULL causing an oops. Fix it by checking if rawdata is set.
[ 168.653080] BUG: kernel NULL pointer dereference, address: 0000000000000088 [ 168.657420] #PF: supervisor read access in kernel mode [ 168.660619] #PF: error_code(0x0000) - not-present page [ 168.663613] PGD 0 P4D 0 [ 168.665450] Oops: Oops: 0000 [#1] SMP NOPTI [ 168.667836] CPU: 1 UID: 0 PID: 1729 Comm: ls Not tainted 6.19.0-rc7+ #3 PREEMPT(voluntary) [ 168.672308] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 168.679327] RIP: 0010:rawdata_get_link_base.isra.0+0x23/0x330 [ 168.682768] Code: 90 90 90 90 90 90 90 0f 1f 44 00 00 55 48 89 e5 41 57 41 56 41 55 41 54 53 48 83 ec 18 48 89 55 d0 48 85 ff 0f 84 e3 01 00 00 <48> 83 3c 25 88 00 00 00 00 0f 84 d4 01 00 00 49 89 f6 49 89 cc e8 [ 168.689818] RSP: 0018:ffffcdcb8200fb80 EFLAGS: 00010282 [ 168.690871] RAX: ffffffffaee74ec0 RBX: 0000000000000000 RCX: ffffffffb0120158 [ 168.692251] RDX: ffffcdcb8200fbe0 RSI: ffff88c187c9fa80 RDI: ffff88c186c98a80 [ 168.693593] RBP: ffffcdcb8200fbc0 R08: 0000000000000000 R09: 0000000000000000 [ 168.694941] R10: 0000000000000000 R11: 0000000000000000 R12: ffff88c186c98a80 [ 168.696289] R13: 00007fff005aaa20 R14: 0000000000000080 R15: ffff88c188f4fce0 [ 168.697637] FS: 0000790e81c58280(0000) GS:ffff88c20a957000(0000) knlGS:0000000000000000 [ 168.699227] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 168.700349] CR2: 0000000000000088 CR3: 000000012fd3e000 CR4: 0000000000350ef0 [ 168.701696] Call Trace: [ 168.702325] <TASK> [ 168.702995] rawdata_get_link_data+0x1c/0x30 [ 168.704145] vfs_readlink+0xd4/0x160 [ 168.705152] do_readlinkat+0x114/0x180 [ 168.706214] __x64_sys_readlink+0x1e/0x30 [ 168.708653] x64_sys_call+0x1d77/0x26b0 [ 168.709525] do_syscall_64+0x81/0x500 [ 168.710348] ? do_statx+0x72/0xb0 [ 168.711109] ? putname+0x3e/0x80 [ 168.711845] ? __x64_sys_statx+0xb7/0x100 [ 168.712711] ? x64_sys_call+0x10fc/0x26b0 [ 168.713577] ? do_syscall_64+0xbf/0x500 [ 168.714412] ? do_user_addr_fault+0x1d2/0x8d0 [ 168.715404] ? irqentry_exit+0xb2/0x740 [ 168.716359] ? exc_page_fault+0x90/0x1b0 [ 168.717307] entry_SYSCALL_64_after_hwframe+0x76/0x7e
--- security/apparmor/apparmorfs.c | 9 +++++++++ 1 file changed, 9 insertions(+)
security/apparmor/apparmorfs.c +9 -0
@@ -1644,6 +1644,15 @@ static const char *rawdata_get_link_base(struct dentry *dentry, label =aa_get_label_rcu (&proxy->label); profile =labels_profile (label); + +/* rawdata can be null when aa_g_export_binary is unset during +* runtime and a profile is replaced +*/ +if (!profile->rawdata) { +aa_put_label (label); +return ERR_PTR (-ENOENT ); + } + depth =profile_depth (profile); target =gen_symlink_name (depth, profile->rawdata->name, name);aa_put_label (label);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 705/781 apparmor: fix aa_label to return state from compount and component match
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 9058798652c8bc0584ed1fb0766a1015046c06e8 ]
aa-label_match is not correctly returning the state in all cases. The only reason this didn't cause a error is that all callers currently ignore the return value.
--- security/apparmor/label.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
security/apparmor/label.c +6 -6
@@ -1334,7 +1334,7 @@ static int label_compound_match(struct aa_profile *profile,* @request: permissions to request * @perms: an initialized perms struct to add accumulation to * -* Returns: 0 on success else ERROR +* Returns: the state the match finished in, may be the none matching state * * For the label A//&B//&C this does the perm match for each of A and B and C * @perms should be preinitialized with allperms OR a previous permission
@@ -1362,7 +1362,7 @@ static int label_components_match(struct aa_profile *profile, }/* no subcomponents visible - no change in perms */ -return 0 ; +return state; next: tmp = *aa_lookup_perms (rules->policy, state);
@@ -1378,13 +1378,13 @@ static int label_components_match(struct aa_profile *profile, }if ((perms->allow & request) != request) -return -EACCES ; +return DFA_NOMATCH ; -return 0 ; +return state; fail: *perms = nullperms; -return -EACCES ; +return DFA_NOMATCH ; }/**
@@ -1406,7 +1406,7 @@ int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules,aa_state_t tmp =label_compound_match (profile, rules, label, state, subns, request, perms);if ((perms->allow & request) == request) -return 0 ; +return tmp;/* failed compound_match try component matches */ *perms = allperms;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 706/781 drm/amdgpu: Fix memory leak in amdgpu_acpi_enumerate_xcc()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit c9be63d565789b56ca7b0197e2cb78a3671f95a8 ]
In amdgpu_acpi_enumerate_xcc(), if amdgpu_acpi_dev_init() returns -ENOMEM, the function returns directly without releasing the allocated xcc_info, resulting in a memory leak.
Fix this by ensuring that xcc_info is properly freed in the error paths.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +3 -1
@@ -1135,8 +1135,10 @@ static int amdgpu_acpi_enumerate_xcc(void)if (!dev_info) ret =amdgpu_acpi_dev_init (&dev_info, xcc_info, sbdf); -if (ret == -ENOMEM ) +if (ret == -ENOMEM ) { +kfree (xcc_info);return ret; + }if (!dev_info) {kfree (xcc_info);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 707/781 drm/amdgpu: Use kvfree instead of kfree in amdgpu_gmc_get_nps_memranges()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit 0c44d61945c4a80775292d96460aa2f22e62f86c ]
amdgpu_discovery_get_nps_info() internally allocates memory for ranges using kvcalloc(), which may use vmalloc() for large allocation. Using kfree() to release vmalloc memory will lead to a memory corruption.
Use kvfree() to safely handle both kmalloc and vmalloc allocations.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c +1 -1
@@ -1387,7 +1387,7 @@ int amdgpu_gmc_get_nps_memranges(struct amdgpu_device *adev,if (!*exp_ranges) *exp_ranges = range_cnt; err: -kfree (ranges); +kvfree (ranges);return ret; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 708/781 drm/amdgpu: Fix memory leak in amdgpu_ras_init()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zilin Guan <[email protected]>
[ Upstream commit ee41e5b63c8210525c936ee637a2c8d185ce873c ]
When amdgpu_nbio_ras_sw_init() fails in amdgpu_ras_init(), the function returns directly without freeing the allocated con structure, leading to a memory leak.
Fix this by jumping to the release_con label to properly clean up the allocated memory before returning the error code.
Compile tested only. Issue found using a prototype static analysis tool and code review.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +1 -1
@@ -4343,7 +4343,7 @@ int amdgpu_ras_init(struct amdgpu_device *adev)* to handle fatal error */ r =amdgpu_nbio_ras_sw_init (adev);if (r) -return r; + goto release_con;if (adev->nbio.ras && adev->nbio.ras->init_ras_controller_interrupt) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 709/781 drm/amdgpu/sdma5: enable queue resets unconditionally
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 46a2cb7d24f21132e970cab52359210c3f5ea3c6 ]
There is no firmware version dependency.
--- drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +3 -12
@@ -1424,18 +1424,9 @@ static int sdma_v5_0_sw_init(struct amdgpu_ip_block *ip_block) adev->sdma.supported_reset =amdgpu_get_soft_full_reset_mask (&adev->sdma.instance[0 ].ring); -switch (amdgpu_ip_version (adev,SDMA0_HWIP ,0 )) { -case IP_VERSION (5 ,0 ,0 ): -case IP_VERSION (5 ,0 ,2 ): -case IP_VERSION (5 ,0 ,5 ): -if ((adev->sdma.instance[0 ].fw_version >=35 ) && - !amdgpu_sriov_vf (adev) && - !adev->debug_disable_gpu_ring_reset) - adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ; -break ; -default : -break ; - } +if (!amdgpu_sriov_vf (adev) && + !adev->debug_disable_gpu_ring_reset) + adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ;/* Allocate memory for SDMA IP Dump buffer */ ptr =kcalloc (adev->sdma.num_instances * reg_count,sizeof (uint32_t ),GFP_KERNEL );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 710/781 drm/amdgpu/sdma5.2: enable queue resets unconditionally
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 314d30ad50622fc0d70da71509f9dff21545be14 ]
There is no firmware version dependency. This also enables sdma queue resets on all SDMA 5.2.x based chips.
--- drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-)
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c +3 -19
@@ -1342,25 +1342,9 @@ static int sdma_v5_2_sw_init(struct amdgpu_ip_block *ip_block) adev->sdma.supported_reset =amdgpu_get_soft_full_reset_mask (&adev->sdma.instance[0 ].ring); -switch (amdgpu_ip_version (adev,SDMA0_HWIP ,0 )) { -case IP_VERSION (5 ,2 ,0 ): -case IP_VERSION (5 ,2 ,2 ): -case IP_VERSION (5 ,2 ,3 ): -case IP_VERSION (5 ,2 ,4 ): -if ((adev->sdma.instance[0 ].fw_version >=76 ) && - !amdgpu_sriov_vf (adev) && - !adev->debug_disable_gpu_ring_reset) - adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ; -break ; -case IP_VERSION (5 ,2 ,5 ): -if ((adev->sdma.instance[0 ].fw_version >=34 ) && - !amdgpu_sriov_vf (adev) && - !adev->debug_disable_gpu_ring_reset) - adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ; -break ; -default : -break ; - } +if (!amdgpu_sriov_vf (adev) && + !adev->debug_disable_gpu_ring_reset) + adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ;/* Allocate memory for SDMA IP Dump buffer */ ptr =kcalloc (adev->sdma.num_instances * reg_count,sizeof (uint32_t ),GFP_KERNEL );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 711/781 drm/amdgpu/sdma6: enable queue resets unconditionally
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
[ Upstream commit 56423871e9eef1dd069bddef895207fa5ce275fe ]
There is no firmware version dependency. This also enables sdma queue resets on all SDMA 6.x based chips.
--- drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-)
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c +3 -12
@@ -1351,18 +1351,9 @@ static int sdma_v6_0_sw_init(struct amdgpu_ip_block *ip_block) adev->sdma.supported_reset =amdgpu_get_soft_full_reset_mask (&adev->sdma.instance[0 ].ring); -switch (amdgpu_ip_version (adev,SDMA0_HWIP ,0 )) { -case IP_VERSION (6 ,0 ,0 ): -case IP_VERSION (6 ,0 ,2 ): -case IP_VERSION (6 ,0 ,3 ): -if ((adev->sdma.instance[0 ].fw_version >=21 ) && - !amdgpu_sriov_vf (adev) && - !adev->debug_disable_gpu_ring_reset) - adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ; -break ; -default : -break ; - } +if (!amdgpu_sriov_vf (adev) && + !adev->debug_disable_gpu_ring_reset) + adev->sdma.supported_reset |=AMDGPU_RESET_TYPE_PER_QUEUE ;if (amdgpu_sdma_ras_sw_init (adev)) {dev_err (adev->dev,"Failed to initialize sdma ras block!\n" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 712/781 drm/amdgpu: clean up the amdgpu_cs_parser_bos
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunil Khatri <[email protected]>
[ Upstream commit f025a2b8d93358467b8e8f4b3a617e88c5f02fab ]
In low memory conditions, kmalloc can fail. In such conditions unlock the mutex for a clean exit.
We do not need to amdgpu_bo_list_put as it's been handled in the amdgpu_cs_parser_fini.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +4 -2
@@ -892,8 +892,10 @@ static int amdgpu_cs_parser_bos(struct amdgpu_cs_parser *p,struct amdgpu_bo *bo = e->bo; e->range =amdgpu_hmm_range_alloc (NULL ); -if (unlikely (!e->range)) -return -ENOMEM ; +if (unlikely (!e->range)) { + r = -ENOMEM ; + goto out_free_user_pages; + } r =amdgpu_ttm_tt_get_user_pages (bo, e->range);if (r)
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 713/781 mshv: fix SRCU protection in irqfd resampler ack handler
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 2e7577cd5ddc1f86d1b6c48caf3cfa87dbb14e34 ]
Replace hlist_for_each_entry_rcu() with hlist_for_each_entry_srcu() in mshv_irqfd_resampler_ack() to correctly handle SRCU-protected linked list traversal.
The function uses SRCU (sleepable RCU) synchronization via partition->pt_irq_srcu, but was incorrectly using the RCU variant for list iteration. This could lead to race conditions when the list is modified concurrently.
Also add srcu_read_lock_held() assertion as required by hlist_for_each_entry_srcu() to ensure we're in the proper read-side critical section.
--- drivers/hv/mshv_eventfd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/hv/mshv_eventfd.c +3 -2
@@ -87,8 +87,9 @@ static void mshv_irqfd_resampler_ack(struct mshv_irq_ack_notifier *mian) idx =srcu_read_lock (&partition->pt_irq_srcu); -hlist_for_each_entry_rcu (irqfd, &resampler->rsmplr_irqfd_list, - irqfd_resampler_hnode) { +hlist_for_each_entry_srcu (irqfd, &resampler->rsmplr_irqfd_list, + irqfd_resampler_hnode, +srcu_read_lock_held (&partition->pt_irq_srcu)) {if (hv_should_clear_interrupt (irqfd->irqfd_lapic_irq.lapic_control.interrupt_type))hv_call_clear_virtual_interrupt (partition->pt_id);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 714/781 regulator: mt6363: Fix interrmittent timeout
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adam Ford <[email protected]>
[ Upstream commit 1a4b0c999101b2532723f9bd9818b70ffa7580f4 ]
Sometimes, the mt6363 regulator would fail to initialize and return with a TIMEOUT error, so add an extra instruction to wake up the bus before issuing the commands.
--- drivers/regulator/mt6363-regulator.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/regulator/mt6363-regulator.c +8 -1
@@ -861,7 +861,7 @@ static int mt6363_regulator_probe(struct platform_device *pdev)struct irq_domain *domain;struct irq_fwspec fwspec;struct spmi_device *sdev; -int i, ret; +int i, ret, val; config.regmap =mt6363_spmi_register_regmap (dev);if (IS_ERR (config.regmap))
@@ -870,6 +870,13 @@ static int mt6363_regulator_probe(struct platform_device *pdev) config.dev = dev; sdev =to_spmi_device (dev->parent); +/* +* The first read may fail if the bootloader sets sleep mode: wake up +* this PMIC with W/R on the SPMI bus and ignore the first result. +* This matches the MT6373 driver behavior. +*/ +regmap_read (config.regmap,MT6363_TOP_TRAP , &val); + interrupt_parent =of_irq_find_parent (dev->of_node);if (!interrupt_parent)return dev_err_probe (dev, -EINVAL ,"Cannot find IRQ parent\n" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 715/781 ASoC: fsl_xcvr: Revert fix missing lock in fsl_xcvr_mode_put()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziyi Guo <[email protected]>
[ Upstream commit 9f16d96e1222391a6b996a1b676bec14fb91e3b2 ]
This reverts commit f51424872760 ("ASoC: fsl_xcvr: fix missing lock in fsl_xcvr_mode_put()").
The original patch attempted to acquire the card->controls_rwsem lock in fsl_xcvr_mode_put(). However, this function is called from the upper ALSA core function snd_ctl_elem_write(), which already holds the write lock on controls_rwsem for the whole put operation. So there is no need to simply hold the lock for fsl_xcvr_activate_ctl() again.
Acquiring the read lock while holding the write lock in the same thread results in a deadlock and a hung task, as reported by Alexander Stein.
--- sound/soc/fsl/fsl_xcvr.c | 3 --- 1 file changed, 3 deletions(-)
sound/soc/fsl/fsl_xcvr.c +0 -3
@@ -223,13 +223,10 @@ static int fsl_xcvr_mode_put(struct snd_kcontrol *kcontrol, xcvr->mode =snd_soc_enum_item_to_val (e, item[0 ]); -down_read (&card->snd_card->controls_rwsem);fsl_xcvr_activate_ctl (dai, fsl_xcvr_arc_mode_kctl.name, (xcvr->mode ==FSL_XCVR_MODE_ARC ));fsl_xcvr_activate_ctl (dai, fsl_xcvr_earc_capds_kctl.name, (xcvr->mode ==FSL_XCVR_MODE_EARC )); -up_read (&card->snd_card->controls_rwsem); -/* Allow playback for SPDIF only */ rtd =snd_soc_get_pcm_runtime (card, card->dai_link); rtd->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream_count =
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 716/781 drm/i915/acpi: free _DSM package when no connectors
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kaushlendra Kumar <[email protected]>
[ Upstream commit 57b85fd53fccfdf14ce7b36d919c31aa752255f8 ]
acpi_evaluate_dsm_typed() returns an ACPI package in pkg. When pkg->package.count == 0, we returned without freeing pkg, leaking memory. Free pkg before returning on the empty case.
--- drivers/gpu/drm/i915/display/intel_acpi.c | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/i915/display/intel_acpi.c +1 -0
@@ -96,6 +96,7 @@ static void intel_dsm_platform_mux_info(acpi_handle dhandle)if (!pkg->package.count) {DRM_DEBUG_DRIVER ("no connection in _DSM\n" ); +ACPI_FREE (pkg);return ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 717/781 ASoC: codecs: aw88261: Fix erroneous bitmask logic in Awinic init
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandre Ferrieux <[email protected]>
[ Upstream commit b82fa9b0c26eeb2fde6017f7de2c3c544484efef ]
The aw88261_dev_reg_update() function sets the Awinic registers in a rather nonuniform way:
- most registers get directly overwritten from the firmware blob
- but a handful of them need more delicate logic to preserve some bits from their current value, according to a register- specific mask
For the latter, the logic is basically
NEW = (OLD & MASK) | (VAL & ~MASK)
However, the ~MASK value is hand-computed, and in the specific case of the SYSCTRL register, in a buggy way.
This patch restores the proper ~MASK value.
--- sound/soc/codecs/aw88261.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
sound/soc/codecs/aw88261.c +2 -1
@@ -423,9 +423,10 @@ static int aw88261_dev_reg_update(struct aw88261 *aw88261,if (ret)break ; +/* keep all three bits from current hw status */ read_val &= (~AW88261_AMPPD_MASK ) | (~AW88261_PWDN_MASK ) | (~AW88261_HMUTE_MASK ); - reg_val &= (AW88261_AMPPD_MASK |AW88261_PWDN_MASK |AW88261_HMUTE_MASK ); + reg_val &= (AW88261_AMPPD_MASK &AW88261_PWDN_MASK &AW88261_HMUTE_MASK ); reg_val |= read_val;/* enable uls hmute */
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 718/781 PCI: Validate window resource type in pbus_select_window_for_type()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kai-Heng Feng <[email protected]>
[ Upstream commit e5f72cb9cea599dc9f5a9b80a33560a1d06f01cc ]
After ebe091ad81e1 ("PCI: Use pbus_select_window_for_type() during IO window sizing") and ae88d0b9c57f ("PCI: Use pbus_select_window_for_type() during mem window sizing"), many bridge windows can't get resources assigned:
pci 0006:05:00.0: bridge window [??? 0x00001000-0x00001fff flags 0x20080000]: can't assign; no space pci 0006:05:00.0: bridge window [??? 0x00001000-0x00001fff flags 0x20080000]: failed to assign
Those commits replace find_bus_resource_of_type() with pbus_select_window_for_type(), and the latter lacks resource type validation.
Add the resource type validation back to pbus_select_window_for_type() to match the original behavior.
--- drivers/pci/setup-bus.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/pci/setup-bus.c +10 -3
@@ -225,14 +225,21 @@ static struct resource *pbus_select_window_for_type(struct pci_bus *bus,switch (iores_type) {case IORESOURCE_IO : -return pci_bus_resource_n (bus,PCI_BUS_BRIDGE_IO_WINDOW ); + win =pci_bus_resource_n (bus,PCI_BUS_BRIDGE_IO_WINDOW ); +if (win && (win->flags &IORESOURCE_IO )) +return win; +return NULL ;case IORESOURCE_MEM : mmio =pci_bus_resource_n (bus,PCI_BUS_BRIDGE_MEM_WINDOW ); mmio_pref =pci_bus_resource_n (bus,PCI_BUS_BRIDGE_PREF_MEM_WINDOW ); -if (!(type &IORESOURCE_PREFETCH ) || - !(mmio_pref->flags &IORESOURCE_MEM )) +if (mmio && !(mmio->flags &IORESOURCE_MEM )) + mmio =NULL ; +if (mmio_pref && !(mmio_pref->flags &IORESOURCE_MEM )) + mmio_pref =NULL ; + +if (!(type &IORESOURCE_PREFETCH ) || !mmio_pref)return mmio; if ((type & IORESOURCE_MEM_64) ||
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 719/781 drm/amd/display: Fix dc_link NULL handling in HPD init
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 226a40c06a183abaeb7529a4f54d6c203bd14407 ]
amdgpu_dm_hpd_init() may see connectors without a valid dc_link.
The code already checks dc_link for the polling decision, but later unconditionally dereferences it when setting up HPD interrupts.
Assign dc_link early and skip connectors where it is NULL.
Fixes the below:drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_irq.c:940 amdgpu_dm_hpd_init()
error: we previously assumed 'dc_link' could be null (see line 931)
drivers/gpu/drm/amd/amdgpu/../display/amdgpu_dm/amdgpu_dm_irq.c
923 /*
924 * Analog connectors may be hot-plugged unlike other connector
925 * types that don't support HPD. Only poll analog connectors.
926 */
927 use_polling |=
928 amdgpu_dm_connector->dc_link &&
^^^^^^^^^^^^^^^^^^^^^^^^^^^^ The patch adds this NULL check but hopefully it can be removed
929 dc_connector_supports_analog(amdgpu_dm_connector->dc_link->link_id.id);
930
931 dc_link = amdgpu_dm_connector->dc_link;dc_link assigned here.
932
933 /*
934 * Get a base driver irq reference for hpd ints for the lifetime
935 * of dm. Note that only hpd interrupt types are registered with
936 * base driver; hpd_rx types aren't. IOW, amdgpu_irq_get/put on
937 * hpd_rx isn't available. DM currently controls hpd_rx
938 * explicitly with dc_interrupt_set()
939 */
--> 940 if (dc_link->irq_source_hpd != DC_IRQ_SOURCE_INVALID) {
^^^^^^^^^^^^^^^^^^^^^^^ If it's NULL then we are trouble because we dereference it here.
941 irq_type = dc_link->irq_source_hpd - DC_IRQ_SOURCE_HPD1;
942 /*
943 * TODO: There's a mismatch between mode_info.num_hpd
944 * and what bios reports as the # of connectors with hpd
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c +4 -5
@@ -919,16 +919,15 @@ void amdgpu_dm_hpd_init(struct amdgpu_device *adev)continue ; amdgpu_dm_connector =to_amdgpu_dm_connector (connector); + dc_link = amdgpu_dm_connector->dc_link; +if (!dc_link) +continue ;/* * Analog connectors may be hot-plugged unlike other connector * types that don't support HPD. Only poll analog connectors. */ - use_polling |= - amdgpu_dm_connector->dc_link && -dc_connector_supports_analog (amdgpu_dm_connector->dc_link->link_id.id); - - dc_link = amdgpu_dm_connector->dc_link; + use_polling |=dc_connector_supports_analog (dc_link->link_id.id);/* * Get a base driver irq reference for hpd ints for the lifetime
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 720/781 drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit ba038065655c45728be346d0b174a6da08d8a5c5 ]
amdgpu_ib_schedule() returns early after calling amdgpu_ring_undo(). This skips the common free_fence cleanup path. Other error paths were already changed to use goto free_fence, but this one was missed.
Change the early return to goto free_fence so all error paths clean up the same way.
Fixes the below:drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c:232 amdgpu_ib_schedule()
warn: missing unwind goto?
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
124 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
125 struct amdgpu_ib *ibs, struct amdgpu_job *job,
126 struct dma_fence **f)
127 {
...
224
225 if (ring->funcs->insert_start)
226 ring->funcs->insert_start(ring);
227
228 if (job) {
229 r = amdgpu_vm_flush(ring, job, need_pipe_sync);
230 if (r) {
231 amdgpu_ring_undo(ring);--> 232 return r;
The patch changed the other error paths to goto free_fence but
this one was accidentally skipped.
233 }
234 }
235
236 amdgpu_ring_ib_begin(ring);
...
338
339 free_fence:
340 if (!job)
341 kfree(af);
342 return r;
343 }--- drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c +1 -1
@@ -229,7 +229,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs, r =amdgpu_vm_flush (ring, job, need_pipe_sync);if (r) {amdgpu_ring_undo (ring); -return r; + goto free_fence; } }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 721/781 drm/amdkfd: Fix watch_id bounds checking in debug address watch v2
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit 5a19302cab5cec7ae7f1a60c619951e6c17d8742 ]
The address watch clear code receives watch_id as an unsigned value (u32), but some helper functions were using a signed int and checked bits by shifting with watch_id.
If a very large watch_id is passed from userspace, it can be converted to a negative value. This can cause invalid shifts and may access memory outside the watch_points array.
drm/amdkfd: Fix watch_id bounds checking in debug address watch v2
Fix this by checking that watch_id is within MAX_WATCH_ADDRESSES before using it. Also use BIT(watch_id) to test and clear bits safely.
This keeps the behavior unchanged for valid watch IDs and avoids undefined behavior for invalid ones.
Fixes the below:drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_debug.c:448 kfd_dbg_trap_clear_dev_address_watch() error: buffer overflow 'pdd->watch_points' 4 <= u32max user_rl='0-3,2147483648-u32max' uncapped
drivers/gpu/drm/amd/amdgpu/../amdkfd/kfd_debug.c
433 int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd,
434 uint32_t watch_id)
435 {
436 int r;
437
438 if (!kfd_dbg_owns_dev_watch_id(pdd, watch_id))kfd_dbg_owns_dev_watch_id() doesn't check for negative values so if watch_id is larger than INT_MAX it leads to a buffer overflow. (Negative shifts are undefined).
439 return -EINVAL;
440
441 if (!pdd->dev->kfd->shared_resources.enable_mes) {
442 r = debug_lock_and_unmap(pdd->dev->dqm);
443 if (r)
444 return r;
445 }
446
447 amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
--> 448 pdd->watch_points[watch_id] = pdd->dev->kfd2kgd->clear_address_watch(
449 pdd->dev->adev,
450 watch_id);v2: (as per, Jonathan Kim)
- Add early watch_id >= MAX_WATCH_ADDRESSES validation in the set path to match the clear path.
- Drop the redundant bounds check in kfd_dbg_owns_dev_watch_id().
--- drivers/gpu/drm/amd/amdkfd/kfd_debug.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-)
drivers/gpu/drm/amd/amdkfd/kfd_debug.c +12 -8
@@ -401,27 +401,25 @@ static int kfd_dbg_get_dev_watch_id(struct kfd_process_device *pdd, int *watch_ireturn -ENOMEM ; } -static void kfd_dbg_clear_dev_watch_id (struct kfd_process_device *pdd,int watch_id) +static void kfd_dbg_clear_dev_watch_id (struct kfd_process_device *pdd,u32 watch_id) {spin_lock (&pdd->dev->watch_points_lock);/* process owns device watch point so safe to clear */ -if ((pdd->alloc_watch_ids >> watch_id) &0x1 ) { - pdd->alloc_watch_ids &= ~(0x1 << watch_id); - pdd->dev->alloc_watch_ids &= ~(0x1 << watch_id); +if (pdd->alloc_watch_ids &BIT (watch_id)) { + pdd->alloc_watch_ids &= ~BIT (watch_id); + pdd->dev->alloc_watch_ids &= ~BIT (watch_id); }spin_unlock (&pdd->dev->watch_points_lock); } -static bool kfd_dbg_owns_dev_watch_id (struct kfd_process_device *pdd,int watch_id) +static bool kfd_dbg_owns_dev_watch_id (struct kfd_process_device *pdd,u32 watch_id) {bool owns_watch_id = false;spin_lock (&pdd->dev->watch_points_lock); - owns_watch_id = watch_id <MAX_WATCH_ADDRESSES && - ((pdd->alloc_watch_ids >> watch_id) &0x1 ); - + owns_watch_id = pdd->alloc_watch_ids &BIT (watch_id);spin_unlock (&pdd->dev->watch_points_lock);return owns_watch_id;
@@ -432,6 +430,9 @@ int kfd_dbg_trap_clear_dev_address_watch(struct kfd_process_device *pdd, {int r; +if (watch_id >=MAX_WATCH_ADDRESSES ) +return -EINVAL ; +if (!kfd_dbg_owns_dev_watch_id (pdd, watch_id))return -EINVAL ;
@@ -469,6 +470,9 @@ int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd,if (r)return r; +if (*watch_id >=MAX_WATCH_ADDRESSES ) +return -EINVAL ; +if (!pdd->dev->kfd->shared_resources.enable_mes) { r =debug_lock_and_unmap (pdd->dev->dqm);if (r) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 722/781 drm/amd/display: Reject cursor plane on DCE when scaled differently than primary
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 41af6215cdbcecd12920f211239479027904abf3 ]
Currently DCE doesn't support the overlay cursor, so the dm_crtc_get_cursor_mode() function returns DM_CURSOR_NATIVE_MODE unconditionally. The outcome is that it doesn't check for the conditions that would necessitate the overlay cursor, meaning that it doesn't reject cases where the native cursor mode isn't supported on DCE.
Remove the early return from dm_crtc_get_cursor_mode() for DCE and instead let it perform the necessary checks and return DM_CURSOR_OVERLAY_MODE. Add a later check that rejects when DM_CURSOR_OVERLAY_MODE would be used with DCE.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +8 -3
@@ -12275,10 +12275,9 @@ static int dm_crtc_get_cursor_mode(struct amdgpu_device *adev,/* Overlay cursor not supported on HW before DCN * DCN401 does not have the cursor-on-scaled-plane or cursor-on-yuv-plane restrictions -* as previous DCN generations, so enable native mode on DCN401 in addition to DCE +* as previous DCN generations, so enable native mode on DCN401 */ -if (amdgpu_ip_version (adev,DCE_HWIP ,0 ) ==0 || -amdgpu_ip_version (adev,DCE_HWIP ,0 ) ==IP_VERSION (4 ,0 ,1 )) { +if (amdgpu_ip_version (adev,DCE_HWIP ,0 ) ==IP_VERSION (4 ,0 ,1 )) { *cursor_mode =DM_CURSOR_NATIVE_MODE ;return 0 ; }
@@ -12598,6 +12597,12 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,* need to be added for DC to not disable a plane by mistake */ if (dm_new_crtc_state->cursor_mode ==DM_CURSOR_OVERLAY_MODE ) { +if (amdgpu_ip_version (adev,DCE_HWIP ,0 ) ==0 ) { +drm_dbg (dev,"Overlay cursor not supported on DCE\n" ); + ret = -EINVAL ; + goto fail; + } + ret =drm_atomic_add_affected_planes (state, crtc);if (ret) goto fail;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 723/781 drm/amd/display: Fix out-of-bounds stream encoder index v3
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivasan Shanmugam <[email protected]>
[ Upstream commit abde491143e4e12eecc41337910aace4e8d59603 ]
eng_id can be negative and that stream_enc_regs[]
can be indexed out of bounds.
eng_id is used directly as an index into stream_enc_regs[], which has only 5 entries. When eng_id is 5 (ENGINE_ID_DIGF) or negative, this can access memory past the end of the array.
Add a bounds check using ARRAY_SIZE() before using eng_id as an index. The unsigned cast also rejects negative values.
This avoids out-of-bounds access.
Fixes the below smatch error:
dcn*_resource.c: stream_encoder_create() may index stream_enc_regs[eng_id] out of bounds (size 5).
drivers/gpu/drm/amd/amdgpu/../display/dc/resource/dcn351/dcn351_resource.c
1246 static struct stream_encoder *dcn35_stream_encoder_create(
1247 enum engine_id eng_id,
1248 struct dc_context *ctx)
1249 {
...
1255
1256 /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */
1257 if (eng_id <= ENGINE_ID_DIGF) {ENGINE_ID_DIGF is 5. should <= be <?
Unrelated but, ugh, why is Smatch saying that "eng_id" can be negative?end_id is type signed long, but there are checks in the caller which prevent it from being negative.
1258 vpg_inst = eng_id;
1259 afmt_inst = eng_id;
1260 } else
1261 return NULL;
1262
...
1281
1282 dcn35_dio_stream_encoder_construct(enc1, ctx, ctx->dc_bios,
1283 eng_id, vpg, afmt,
--> 1284 &stream_enc_regs[eng_id],
^^^^^^^^^^^^^^^^^^^^^^^ This stream_enc_regs[] array has 5 elements so we are one element beyond the end of the array.
...
1287 return &enc1->base;
1288 }v2: use explicit bounds check as suggested by Roman/Dan; avoid unsigned int cast
v3: The compiler already knows how to compare the two values, so the
cast (int) is not needed. (Roman)
--- .../drm/amd/display/dc/resource/dcn315/dcn315_resource.c | 8 ++++---- .../drm/amd/display/dc/resource/dcn316/dcn316_resource.c | 8 ++++---- .../drm/amd/display/dc/resource/dcn32/dcn32_resource.c | 8 ++++---- .../drm/amd/display/dc/resource/dcn321/dcn321_resource.c | 8 ++++---- .../drm/amd/display/dc/resource/dcn35/dcn35_resource.c | 8 ++++---- .../drm/amd/display/dc/resource/dcn351/dcn351_resource.c | 8 ++++---- 6 files changed, 24 insertions(+), 24 deletions(-)
drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c +4 -4
@@ -1230,12 +1230,12 @@ static struct stream_encoder *dcn315_stream_encoder_create(/*PHYB is wired off in HW, allow front end to remapping, otherwise needs more changes*/ /* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn31_vpg_create (ctx, vpg_inst); afmt =dcn31_afmt_create (ctx, afmt_inst);
drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c +4 -4
@@ -1223,12 +1223,12 @@ static struct stream_encoder *dcn316_stream_encoder_create(int afmt_inst;/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn31_vpg_create (ctx, vpg_inst); afmt =dcn31_afmt_create (ctx, afmt_inst);
drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c +4 -4
@@ -1211,12 +1211,12 @@ static struct stream_encoder *dcn32_stream_encoder_create(int afmt_inst;/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn32_vpg_create (ctx, vpg_inst); afmt =dcn32_afmt_create (ctx, afmt_inst);
drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c +4 -4
@@ -1192,12 +1192,12 @@ static struct stream_encoder *dcn321_stream_encoder_create(int afmt_inst;/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn321_vpg_create (ctx, vpg_inst); afmt =dcn321_afmt_create (ctx, afmt_inst);
drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c +4 -4
@@ -1274,12 +1274,12 @@ static struct stream_encoder *dcn35_stream_encoder_create(int afmt_inst;/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn31_vpg_create (ctx, vpg_inst); afmt =dcn31_afmt_create (ctx, afmt_inst);
drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c +4 -4
@@ -1254,12 +1254,12 @@ static struct stream_encoder *dcn35_stream_encoder_create(int afmt_inst;/* Mapping of VPG, AFMT, DME register blocks to DIO block instance */ -if (eng_id <=ENGINE_ID_DIGF ) { - vpg_inst = eng_id; - afmt_inst = eng_id; - }else +if (eng_id <0 || eng_id >=ARRAY_SIZE (stream_enc_regs))return NULL ; + vpg_inst = eng_id; + afmt_inst = eng_id; + enc1 =kzalloc (sizeof (struct dcn10_stream_encoder ),GFP_KERNEL ); vpg =dcn31_vpg_create (ctx, vpg_inst); afmt =dcn31_afmt_create (ctx, afmt_inst);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 724/781 spi: wpcm-fiu: Fix potential NULL pointer dereference in wpcm_fiu_probe()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
[ Upstream commit 888a0a802c467bbe34a42167bdf9d7331333440a ]
platform_get_resource_byname() can return NULL, which would cause a crash when passed the pointer to resource_size().
Move the fiu->memory_size assignment after the error check for devm_ioremap_resource() to prevent the potential NULL pointer dereference.
--- drivers/spi/spi-wpcm-fiu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/spi/spi-wpcm-fiu.c +1 -1
@@ -459,11 +459,11 @@ static int wpcm_fiu_probe(struct platform_device *pdev) res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"memory" ); fiu->memory =devm_ioremap_resource (dev, res); - fiu->memory_size =min_t (size_t,resource_size (res),MAX_MEMORY_SIZE_TOTAL );if (IS_ERR (fiu->memory))return dev_err_probe (dev,PTR_ERR (fiu->memory),"Failed to map flash memory window\n" ); + fiu->memory_size =min_t (size_t,resource_size (res),MAX_MEMORY_SIZE_TOTAL ); fiu->shm_regmap =syscon_regmap_lookup_by_phandle_optional (dev->of_node,"nuvoton,shm" );wpcm_fiu_hw_init (fiu);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 725/781 gpio: cdev: Avoid NULL dereference in linehandle_create()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douglas Anderson <[email protected]>
[ Upstream commit 6af6be278e3ba2ffb6af5b796c89dfb3f5d9063e ]
In linehandle_create(), there is a statement like this:
retain_and_null_ptr(lh);
Soon after, there is a debug printout that dereferences "lh", which will crash things.
Avoid the crash by using handlereq.lines, which is the same value.
--- drivers/gpio/gpiolib-cdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpiolib-cdev.c +1 -1
@@ -388,7 +388,7 @@ static int linehandle_create(struct gpio_device *gdev, void __user *ip)fd_publish (fdf);dev_dbg (&gdev->dev,"registered chardev handle for %d lines\n" , - lh->num_descs); + handlereq.lines);return 0 ; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 726/781 s390/kexec: Make KEXEC_SIG available when CONFIG_MODULES=n
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Egorenkov <[email protected]>
[ Upstream commit dd3411959b57df6e05a3ccbac67b0a836871c0c4 ]
The commit c8424e776b09 ("MODSIGN: Export module signature definitions") replaced the dependency of KEXEC_SIG on SYSTEM_DATA_VERIFICATION with the dependency on MODULE_SIG_FORMAT. This change disables KEXEC_SIG in s390 kernels built with MODULES=n if nothing else selects MODULE_SIG_FORMAT.
Furthermore, the signature verification in s390 kexec does not require MODULE_SIG_FORMAT because it requires only the struct module_signature and, therefore, does not depend on code in kernel/module_signature.c.
But making ARCH_SUPPORTS_KEXEC_SIG depend on SYSTEM_DATA_VERIFICATION is also incorrect because it makes KEXEC_SIG available on s390 only if some other arbitrary option (for instance a file system or device driver) selects it directly or indirectly.
To properly make KEXEC_SIG available for s390 kernels built with MODULES=y as well as MODULES=n _and_ also not depend on arbitrary options selecting SYSTEM_DATA_VERIFICATION, set ARCH_SUPPORTS_KEXEC_SIG=y for s390 and select SYSTEM_DATA_VERIFICATION when KEXEC_SIG=y.
--- arch/s390/Kconfig | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
arch/s390/Kconfig +2 -1
@@ -275,6 +275,7 @@ config S390 select SPARSE_IRQ select SWIOTLB select SYSCTL_EXCEPTION_TRACE + select SYSTEM_DATA_VERIFICATION if KEXEC_SIG select THREAD_INFO_IN_TASK select TRACE_IRQFLAGS_SUPPORT select TTY
@@ -301,7 +302,7 @@ config ARCH_SUPPORTS_KEXEC_FILE def_bool y config ARCH_SUPPORTS_KEXEC_SIG - def_bool MODULE_SIG_FORMAT + def_bool y config ARCH_SUPPORTS_KEXEC_PURGATORY def_bool y
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 727/781 drm/xe/pf: Fix sysfs initialization
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit bf7172cd25ed182f30af2cbb9f80c730dc717d8e ]
In case of devm_add_action_or_reset() failure the provided cleanup action will be run immediately on the not yet initialized kobject. This may lead to errors like:
[ ] kobject: '(null)' (ff110001393608e0): is not initialized, yet kobject_put() is being called. [ ] WARNING: lib/kobject.c:734 at kobject_put+0xd9/0x250, CPU#0: kworker/0:0/9
[ ] RIP: 0010:kobject_put+0xdf/0x250
[ ] Call Trace:
[ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe] [ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe] [ ] xe_sriov_init_late+0x5f/0x2c0 [xe] [ ] xe_device_probe+0x5f2/0xc20 [xe] [ ] xe_pci_probe+0x396/0x610 [xe] [ ] local_pci_probe+0x47/0xb0
[ ] refcount_t: underflow; use-after-free.
[ ] WARNING: lib/refcount.c:28 at refcount_warn_saturate+0x68/0xb0, CPU#0: kworker/0:0/9 [ ] RIP: 0010:refcount_warn_saturate+0x68/0xb0
[ ] Call Trace:
[ ] kobject_put+0x174/0x250 [ ] xe_sriov_pf_sysfs_init+0x21/0x100 [xe] [ ] xe_sriov_pf_init_late+0x87/0x2b0 [xe] [ ] xe_sriov_init_late+0x5f/0x2c0 [xe] [ ] xe_device_probe+0x5f2/0xc20 [xe] [ ] xe_pci_probe+0x396/0x610 [xe] [ ] local_pci_probe+0x47/0xb0
Fix that by calling kobject_init() and kobject_add() separately and register cleanup action after the kobject is initialized.
Also make this cleanup registration a part of the create helper to fix another mistake, as in the loop we were wrongly passing parent kobject while registering cleanup action, and this resulted in some undetected leaks.
--- drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c | 54 +++++++++++++------------- 1 file changed, 26 insertions(+), 28 deletions(-)
drivers/gpu/drm/xe/xe_sriov_pf_sysfs.c +26 -28
@@ -349,18 +349,33 @@ static const struct attribute_group *xe_sriov_vf_attr_groups[] = {/* no user serviceable parts below */ -static struct kobject *create_xe_sriov_kobj (struct xe_device *xe,unsigned int vfid) +static void action_put_kobject (void *arg) +{ +struct kobject *kobj = arg; + +kobject_put (kobj); +} + +static struct kobject *create_xe_sriov_kobj (struct xe_device *xe,unsigned int vfid, +const struct kobj_type *ktype) {struct xe_sriov_kobj *vkobj; +int err;xe_sriov_pf_assert_vfid (xe, vfid); vkobj =kzalloc (sizeof (*vkobj),GFP_KERNEL );if (!vkobj) -return NULL ; +return ERR_PTR (-ENOMEM ); vkobj->xe = xe; vkobj->vfid = vfid; +kobject_init (&vkobj->base, ktype); + + err =devm_add_action_or_reset (xe->drm.dev, action_put_kobject, &vkobj->base); +if (err) +return ERR_PTR (err); +return &vkobj->base; }
@@ -471,28 +486,17 @@ static void pf_sysfs_note(struct xe_device *xe, int err, const char *what)xe_sriov_dbg (xe,"Failed to setup sysfs %s (%pe)\n" , what,ERR_PTR (err)); } -static void action_put_kobject (void *arg) -{ -struct kobject *kobj = arg; - -kobject_put (kobj); -} -static int pf_setup_root (struct xe_device *xe) {struct kobject *parent = &xe->drm.dev->kobj;struct kobject *root;int err; - root =create_xe_sriov_kobj (xe,PFID ); -if (!root) -return pf_sysfs_error (xe, -ENOMEM ,"root obj" ); - - err =devm_add_action_or_reset (xe->drm.dev, action_put_kobject, root); -if (err) -return pf_sysfs_error (xe, err,"root action" ); + root =create_xe_sriov_kobj (xe,PFID , &xe_sriov_dev_ktype); +if (IS_ERR (root)) +return pf_sysfs_error (xe,PTR_ERR (root),"root obj" ); - err =kobject_init_and_add (root, &xe_sriov_dev_ktype, parent,"sriov_admin" ); + err =kobject_add (root, parent,"sriov_admin" );if (err)return pf_sysfs_error (xe, err,"root init" );
@@ -513,20 +517,14 @@ static int pf_setup_tree(struct xe_device *xe) root = xe->sriov.pf.sysfs.root;for (n =0 ; n <= totalvfs; n++) { - kobj =create_xe_sriov_kobj (xe,VFID (n)); -if (!kobj) -return pf_sysfs_error (xe, -ENOMEM ,"tree obj" ); - - err =devm_add_action_or_reset (xe->drm.dev, action_put_kobject, root); -if (err) -return pf_sysfs_error (xe, err,"tree action" ); + kobj =create_xe_sriov_kobj (xe,VFID (n), &xe_sriov_vf_ktype); +if (IS_ERR (kobj)) +return pf_sysfs_error (xe,PTR_ERR (kobj),"tree obj" );if (n) - err =kobject_init_and_add (kobj, &xe_sriov_vf_ktype, - root,"vf%u" , n); + err =kobject_add (kobj, root,"vf%u" , n);else - err =kobject_init_and_add (kobj, &xe_sriov_vf_ktype, - root,"pf" ); + err =kobject_add (kobj, root,"pf" );if (err)return pf_sysfs_error (xe, err,"tree init" );
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 728/781 drm/xe/configfs: Fix parameter name omitted errors
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Wajdeczko <[email protected]>
[ Upstream commit 2a673fb4d787ce6672862cb693112378bff86abb ]
On some configs and old compilers we can get following build errors:
../drivers/gpu/drm/xe/xe_configfs.h: In function 'xe_configfs_get_ctx_restore_mid_bb':
../drivers/gpu/drm/xe/xe_configfs.h:40:76: error: parameter name omitted
static inline u32 xe_configfs_get_ctx_restore_mid_bb(struct pci_dev *pdev, enum xe_engine_class,
^~~~~~~~~~~~~~~~~~~~
../drivers/gpu/drm/xe/xe_configfs.h: In function 'xe_configfs_get_ctx_restore_post_bb':
../drivers/gpu/drm/xe/xe_configfs.h:42:77: error: parameter name omitted
static inline u32 xe_configfs_get_ctx_restore_post_bb(struct pci_dev *pdev, enum xe_engine_class,
^~~~~~~~~~~~~~~~~~~~when trying to define our configfs stub functions. Fix that.
--- drivers/gpu/drm/xe/xe_configfs.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_configfs.h +8 -4
@@ -21,9 +21,11 @@ bool xe_configfs_primary_gt_allowed(struct pci_dev *pdev);bool xe_configfs_media_gt_allowed (struct pci_dev *pdev);u64 xe_configfs_get_engines_allowed (struct pci_dev *pdev);bool xe_configfs_get_psmi_enabled (struct pci_dev *pdev); -u32 xe_configfs_get_ctx_restore_mid_bb (struct pci_dev *pdev,enum xe_engine_class , +u32 xe_configfs_get_ctx_restore_mid_bb (struct pci_dev *pdev, +enum xe_engine_class class,const u32 **cs); -u32 xe_configfs_get_ctx_restore_post_bb (struct pci_dev *pdev,enum xe_engine_class , +u32 xe_configfs_get_ctx_restore_post_bb (struct pci_dev *pdev, +enum xe_engine_class class,const u32 **cs);#ifdef CONFIG_PCI_IOV unsigned int xe_configfs_get_max_vfs (struct pci_dev *pdev);
@@ -37,9 +39,11 @@ static inline bool xe_configfs_primary_gt_allowed(struct pci_dev *pdev) { returnstatic inline bool xe_configfs_media_gt_allowed (struct pci_dev *pdev) {return true; }static inline u64 xe_configfs_get_engines_allowed (struct pci_dev *pdev) {return U64_MAX ; }static inline bool xe_configfs_get_psmi_enabled (struct pci_dev *pdev) {return false; } -static inline u32 xe_configfs_get_ctx_restore_mid_bb (struct pci_dev *pdev,enum xe_engine_class , +static inline u32 xe_configfs_get_ctx_restore_mid_bb (struct pci_dev *pdev, +enum xe_engine_class class,const u32 **cs) {return 0 ; } -static inline u32 xe_configfs_get_ctx_restore_post_bb (struct pci_dev *pdev,enum xe_engine_class , +static inline u32 xe_configfs_get_ctx_restore_post_bb (struct pci_dev *pdev, +enum xe_engine_class class,const u32 **cs) {return 0 ; }static inline unsigned int xe_configfs_get_max_vfs (struct pci_dev *pdev) {return UINT_MAX ; }#endif
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 729/781 drm/xe/mmio: Avoid double-adjust in 64-bit reads
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
[ Upstream commit 4a9b4e1fa52a6aaa1adbb7f759048df14afed54c ]
xe_mmio_read64_2x32() was adjusting register addresses and then calling xe_mmio_read32(), which applies the adjustment again. This may shift accesses twice if adj_offset < adj_limit. There is no issue currently, as for media gt, adj_offset > adj_limit, so the 2nd adjust will be a no-op. But it may not work in future.
To fix it, replace the adjusted-address comparison with a direct sanity check that ensures the MMIO address adjustment cutoff never falls within the 8-byte range of a 64-bit register. And let xe_mmio_read32() handle address translation.
v2: rewrite the sanity check in a more natural way. (Matt)
v3: Add Fixes tag. (Jani)
--- drivers/gpu/drm/xe/xe_mmio.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/gpu/drm/xe/xe_mmio.c +5 -5
@@ -260,11 +260,11 @@ u64 xe_mmio_read64_2x32(struct xe_mmio *mmio, struct xe_reg reg)struct xe_reg reg_udw = { .addr = reg.addr +0x4 };u32 ldw, udw, oldudw, retries; - reg.addr =xe_mmio_adjusted_addr (mmio, reg.addr); - reg_udw.addr =xe_mmio_adjusted_addr (mmio, reg_udw.addr); - -/* we shouldn't adjust just one register address */ -xe_tile_assert (mmio->tile, reg_udw.addr == reg.addr +0x4 ); +/* +* The two dwords of a 64-bit register can never straddle the offset +* adjustment cutoff. +*/ +xe_tile_assert (mmio->tile, !in_range (mmio->adj_limit, reg.addr +1 ,7 )); oldudw =xe_mmio_read32 (mmio, reg_udw);for (retries =5 ; retries; --retries) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 730/781 drm/xe/xe2_hpg: Fix handling of Wa_14019988906 & Wa_14019877138
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Roper <[email protected]>
[ Upstream commit bc6387a2e0c1562faa56ce2a98cef50cab809e08 ]
The PSS_CHICKEN register has been part of the RCS engine's LRC since it was first introduced in Xe_LP. That means that any workarounds that adjust its value (such as Wa_14019988906 and Wa_14019877138) need to be implemented in the lrc_was[] table so that they become part of the default LRC from which all subsequent LRCs are copied. Although these workarounds were implemented correctly on most platforms, they were incorrectly placed on the engine_was[] table for Xe2_HPG.
Move the workarounds to the proper lrc_was[] table and switch the 'xe_rtp_match_first_render_or_compute' rule to specifically match the RCS since that's the engine whose LRC manages the register.
Bspec: 65182
--- drivers/gpu/drm/xe/xe_wa.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-)
drivers/gpu/drm/xe/xe_wa.c +8 -10
@@ -567,16 +567,6 @@ static const struct xe_rtp_entry_sr engine_was[] = { FUNC(xe_rtp_match_first_render_or_compute)),XE_RTP_ACTIONS (SET (ROW_CHICKEN ,EARLY_EOT_DIS )) }, - { XE_RTP_NAME("14019988906"), -XE_RTP_RULES (GRAPHICS_VERSION_RANGE (2001 ,2002 ), -FUNC (xe_rtp_match_first_render_or_compute)), -XE_RTP_ACTIONS (SET (XEHP_PSS_CHICKEN ,FLSH_IGNORES_PSD )) - }, - { XE_RTP_NAME("14019877138"), -XE_RTP_RULES (GRAPHICS_VERSION_RANGE (2001 ,2002 ), -FUNC (xe_rtp_match_first_render_or_compute)), -XE_RTP_ACTIONS (SET (XEHP_PSS_CHICKEN ,FD_END_COLLECT )) - }, { XE_RTP_NAME("14020338487"),XE_RTP_RULES (GRAPHICS_VERSION_RANGE (2001 ,2002 ), FUNC(xe_rtp_match_first_render_or_compute)),
@@ -873,6 +863,14 @@ static const struct xe_rtp_entry_sr lrc_was[] = {XE_RTP_RULES (GRAPHICS_VERSION (2001 ),ENGINE_CLASS (RENDER )),XE_RTP_ACTIONS (SET (WM_CHICKEN3 ,HIZ_PLANE_COMPRESSION_DIS )) }, + { XE_RTP_NAME("14019988906"), +XE_RTP_RULES (GRAPHICS_VERSION_RANGE (2001 ,2002 ),ENGINE_CLASS (RENDER )), +XE_RTP_ACTIONS (SET (XEHP_PSS_CHICKEN ,FLSH_IGNORES_PSD )) + }, + { XE_RTP_NAME("14019877138"), +XE_RTP_RULES (GRAPHICS_VERSION_RANGE (2001 ,2002 ),ENGINE_CLASS (RENDER )), +XE_RTP_ACTIONS (SET (XEHP_PSS_CHICKEN ,FD_END_COLLECT )) + }, { XE_RTP_NAME("14021490052"),XE_RTP_RULES (GRAPHICS_VERSION (2001 ),ENGINE_CLASS (RENDER )), XE_RTP_ACTIONS(SET(FF_MODE,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 731/781 drm/xe/vf: Avoid reading media version when media GT is disabled
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Piotr Piórkowski <[email protected]>
[ Upstream commit 5e905ec67214444362b81345ef8fde63e58425b6 ]
When the media GT is not allowed, a VF must not attempt to read the media version from the GuC. The GuC may not be loaded, and any attempt to communicate with it would result in a timeout and a VF probe failure:
(...)
[ 1912.406046] xe 0000:01:00.1: [drm] *ERROR* Tile0: GT1: GuC mmio request 0x5507: no reply 0x5507 [ 1912.407277] xe 0000:01:00.1: [drm] *ERROR* Tile0: GT1: [GUC COMMUNICATION] MMIO send failed (-ETIMEDOUT) [ 1912.408689] xe 0000:01:00.1: [drm] *ERROR* VF: Tile0: GT1: Failed to reset GuC state (-ETIMEDOUT) [ 1912.413986] xe 0000:01:00.1: probe with driver xe failed with error -110
Let's skip reading the media version for VFs when the media GT is not allowed.
v2: move the condition directly to the VF path
--- drivers/gpu/drm/xe/xe_pci.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/gpu/drm/xe/xe_pci.c +6 -0
@@ -533,6 +533,12 @@ static int read_gmdid(struct xe_device *xe, enum xe_gmdid_type type, u32 *ver, u struct xe_gt *gt __free(kfree) = NULL;int err; +/* Don't try to read media ver if media GT is not allowed */ +if (type ==GMDID_MEDIA && !xe_configfs_media_gt_allowed (to_pci_dev (xe->drm.dev))) { + *ver = *revid =0 ; +return 0 ; + } + gt =kzalloc (sizeof (*gt),GFP_KERNEL );if (!gt)return -ENOMEM ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 732/781 drm/xe: Make xe_modparam.force_vram_bar_size signed
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
[ Upstream commit 1acec6ef0511b92e7974cc5a8768bfd3a659feaf ]
vram_bar_size is registered as an int module parameter and is documented to accept negative values to disable BAR resizing.
Store it as an int in xe_modparam as well, so negative values work as intended and the module_param type matches.
--- drivers/gpu/drm/xe/xe_module.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_module.h +1 -1
@@ -12,7 +12,7 @@struct xe_modparam {bool force_execlist;bool probe_display; -u32 force_vram_bar_size; +int force_vram_bar_size;int guc_log_level;char *guc_firmware_path;char *huc_firmware_path;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 733/781 drm/xe/bo: Redirect faults to dummy page for wedged device
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raag Jadav <[email protected]>
[ Upstream commit 4e83a8d58e1c721a89b3ffe15f549007080272e2 ]
As per uapi documentation[1], the prerequisite for wedged device is to redirected page faults to a dummy page. Follow it.
[1] Documentation/gpu/drm-uapi.rst
v2: Add uapi reference and fixes tag (Matthew Brost)
--- drivers/gpu/drm/xe/xe_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_bo.c +1 -1
@@ -1942,7 +1942,7 @@ static vm_fault_t xe_bo_cpu_fault(struct vm_fault *vmf)int err =0 ;int idx; -if (!drm_dev_enter (&xe->drm, &idx)) +if (xe_device_wedged (xe) || !drm_dev_enter (&xe->drm, &idx))return ttm_bo_vm_dummy_page (vmf, vmf->vma->vm_page_prot); ret =xe_bo_cpu_fault_fastpath (vmf, xe, bo, needs_rpm);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 734/781 gpio: amd-fch: ionly return allowed values from amd_fch_gpio_get()
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
[ Upstream commit fbd03587ba732c612b8a569d1cf5bed72bd3a27c ]
As of 86ef402d805d ("gpiolib: sanitize the return value of gpio_chip::get()") gpiolib requires drivers implementing GPIOs to only return 0, 1 or negative error for the get() callbacks. Ensure that amd-fch complies with this requirement.
--- drivers/gpio/gpio-amd-fch.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/gpio/gpio-amd-fch.c +4 -3
@@ -8,6 +8,7 @@* */ +#include <linux/bitfield.h> #include <linux/err.h> #include <linux/io.h> #include <linux/kernel.h>
@@ -120,15 +121,15 @@ static int amd_fch_gpio_get(struct gpio_chip *gc, unsigned int offset) {unsigned long flags; -int ret; +u32 val;struct amd_fch_gpio_priv *priv =gpiochip_get_data (gc);void __iomem *ptr =amd_fch_gpio_addr (priv, offset);spin_lock_irqsave (&priv->lock, flags); - ret = (readl_relaxed (ptr) &AMD_FCH_GPIO_FLAG_READ ); + val =readl_relaxed (ptr);spin_unlock_irqrestore (&priv->lock, flags); -return ret; +return FIELD_GET (AMD_FCH_GPIO_FLAG_READ , val); } static int amd_fch_gpio_request(struct gpio_chip *chip,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 735/781 efi: Fix reservation of unaccepted memory table
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kiryl Shutsemau (Meta) <[email protected]>
[ Upstream commit 0862438c90487e79822d5647f854977d50381505 ]
The reserve_unaccepted() function incorrectly calculates the size of the memblock reservation for the unaccepted memory table. It aligns the size of the table, but fails to account for cases where the table's starting physical address (efi.unaccepted) is not page-aligned.
If the table starts at an offset within a page and its end crosses into a subsequent page that the aligned size does not cover, the end of the table will not be reserved. This can lead to the table being overwritten or inaccessible, causing a kernel panic in accept_memory().
This issue was observed when starting Intel TDX VMs with specific memory sizes (e.g., > 64GB).
Fix this by calculating the end address first (including the unaligned start) and then aligning it up, ensuring the entire range is covered by the reservation.
--- drivers/firmware/efi/efi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/firmware/efi/efi.c +4 -4
@@ -692,13 +692,13 @@ static __init int match_config_table(const efi_guid_t *guid,static __init void reserve_unaccepted (struct efi_unaccepted_memory *unaccepted) { -phys_addr_t start, size; +phys_addr_t start, end; start =PAGE_ALIGN_DOWN (efi.unaccepted); - size =PAGE_ALIGN (sizeof (*unaccepted) + unaccepted->size); + end =PAGE_ALIGN (efi.unaccepted +sizeof (*unaccepted) + unaccepted->size); -memblock_add (start, size); -memblock_reserve (start, size); +memblock_add (start, end - start); +memblock_reserve (start, end - start); } int __init efi_config_parse_tables(const efi_config_table_t *config_tables,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 736/781 btrfs: reset block group size class when it becomes empty
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiasheng Jiang <[email protected]>
[ Upstream commit 5870ec7c8fe57a8b2c65005e5da5efc054faa3e6 ]
Block group size classes are managed consistently everywhere. Currently, btrfs_use_block_group_size_class() sets a block group's size class to specialize it for a specific allocation size. However, this size class remains "stale" even if the block group becomes completely empty (both used and reserved bytes reach zero).
This happens in two scenarios:
1. When space reservations are freed (e.g., due to errors or transaction aborts) via btrfs_free_reserved_bytes().
2. When the last extent in a block group is freed via btrfs_update_block_group().
While size classes are advisory, a stale size class can cause find_free_extent to unnecessarily skip candidate block groups during initial search loops. This undermines the purpose of size classes to reduce fragmentation by keeping block groups restricted to a specific size class when they could be reused for any size.
Fix this by resetting the size class to BTRFS_BG_SZ_NONE whenever a block group's used and reserved counts both reach zero. This ensures that empty block groups are fully available for any allocation size in the next cycle.
--- fs/btrfs/block-group.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/btrfs/block-group.c +10 -0
@@ -3675,6 +3675,14 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans)return ret; } +static void btrfs_maybe_reset_size_class (struct btrfs_block_group *bg) +{ +lockdep_assert_held (&bg->lock); +if (btrfs_block_group_should_use_size_class (bg) && + bg->used ==0 && bg->reserved ==0 ) + bg->size_class =BTRFS_BG_SZ_NONE ; +} +int btrfs_update_block_group (struct btrfs_trans_handle *trans,u64 bytenr,u64 num_bytes,bool alloc) {
@@ -3739,6 +3747,7 @@ int btrfs_update_block_group(struct btrfs_trans_handle *trans, old_val -= num_bytes; cache->used = old_val; cache->pinned += num_bytes; +btrfs_maybe_reset_size_class (cache);btrfs_space_info_update_bytes_pinned (space_info, num_bytes); space_info->bytes_used -= num_bytes; space_info->disk_used -= num_bytes * factor;
@@ -3867,6 +3876,7 @@ void btrfs_free_reserved_bytes(struct btrfs_block_group *cache, u64 num_bytes,spin_lock (&cache->lock); bg_ro = cache->ro; cache->reserved -= num_bytes; +btrfs_maybe_reset_size_class (cache);if (is_delalloc) cache->delalloc_bytes -= num_bytes;spin_unlock (&cache->lock);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 737/781 btrfs: use the correct type to initialize block reserve for delayed refs
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit 2155d0c0a761a56ce7ede83a26eb23ea0f935260 ]
When initializing the delayed refs block reserve for a transaction handle we are passing a type of BTRFS_BLOCK_RSV_DELOPS, which is meant for delayed items and not for delayed refs. The correct type for delayed refs is BTRFS_BLOCK_RSV_DELREFS.
On release of any excess space reserved in a local delayed refs reserve, we also should transfer that excess space to the global block reserve (it it's full, we return to the space info for general availability).
By initializing a transaction's local delayed refs block reserve with a type of BTRFS_BLOCK_RSV_DELOPS, we were also causing any excess space released from the delayed block reserve (fs_info->delayed_block_rsv, used for delayed inodes and items) to be transferred to the global block reserve instead of the global delayed refs block reserve. This was an unintentional change in commit 28270e25c69a ("btrfs: always reserve space for delayed refs when starting transaction"), but it's not particularly serious as things tend to cancel out each other most of the time and it's relatively rare to be anywhere near exhaustion of the global reserve.
Fix this by initializing a transaction's local delayed refs reserve with a type of BTRFS_BLOCK_RSV_DELREFS and making btrfs_block_rsv_release() attempt to transfer unused space from such a reserve into the global block reserve, just as we did before that commit for when the block reserve is a delayed refs rsv.
--- fs/btrfs/block-rsv.c | 7 ++++--- fs/btrfs/transaction.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-)
fs/btrfs/block-rsv.c +4 -3
@@ -276,10 +276,11 @@ u64 btrfs_block_rsv_release(struct btrfs_fs_info *fs_info,struct btrfs_block_rsv *target =NULL ;/* -* If we are a delayed block reserve then push to the global rsv, -* otherwise dump into the global delayed reserve if it is not full. +* If we are a delayed refs block reserve then push to the global +* reserve, otherwise dump into the global delayed refs reserve if it is +* not full. */ -if (block_rsv->type ==BTRFS_BLOCK_RSV_DELOPS ) +if (block_rsv->type ==BTRFS_BLOCK_RSV_DELREFS ) target = global_rsv;else if (block_rsv != global_rsv && !btrfs_block_rsv_full (delayed_rsv)) target = delayed_rsv;
fs/btrfs/transaction.c +1 -1
@@ -726,7 +726,7 @@ start_transaction(struct btrfs_root *root, unsigned int num_items, h->type = type;INIT_LIST_HEAD (&h->new_bgs); -btrfs_init_metadata_block_rsv (fs_info, &h->delayed_rsv,BTRFS_BLOCK_RSV_DELOPS ); +btrfs_init_metadata_block_rsv (fs_info, &h->delayed_rsv,BTRFS_BLOCK_RSV_DELREFS );smp_mb (); if (cur_trans->state >= TRANS_STATE_COMMIT_START &&
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 738/781 btrfs: fix invalid leaf access in btrfs_quota_enable() if ref key not found
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit ecb7c2484cfc83a93658907580035a8adf1e0a92 ]
If btrfs_search_slot_for_read() returns 1, it means we did not find any key greater than or equals to the key we asked for, meaning we have reached the end of the tree and therefore the path is not valid. If this happens we need to break out of the loop and stop, instead of continuing and accessing an invalid path.
--- fs/btrfs/qgroup.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
fs/btrfs/qgroup.c +7 -4
@@ -1137,11 +1137,14 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info, }if (ret >0 ) {/* -* Shouldn't happen, but in case it does we -* don't need to do the btrfs_next_item, just -* continue. +* Shouldn't happen because the key should still +* be there (return 0), but in case it does it +* means we have reached the end of the tree - +* there are no more leaves with items that have +* a key greater than or equals to @found_key, +* so just stop the search loop. */ -continue ; +break ; } } ret =btrfs_next_item (tree_root, path);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 739/781 drm/amd/display: Use DCE 6 link encoder for DCE 6 analog connectors
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 2de34fbcab2063cd3d52e5872a801b9a5fc755d0 ]
DCE 6 should use the DCE 6 specific link encoder.
This was a copy paste mistake.
--- drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +1 -1
@@ -734,7 +734,7 @@ static struct link_encoder *dce60_link_encoder_create(return NULL ;if (enc_init_data->connector.id ==CONNECTOR_ID_VGA ) { - dce110_link_encoder_construct(enc110, + dce60_link_encoder_construct(enc110, enc_init_data, &link_enc_feature, &link_enc_regs[ENGINE_ID_DACA],
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 740/781 drm/amd/display: Only use analog link encoder with analog engine
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit f402898bd101af3166bde236b7f6a43d926e17a0 ]
Some GPUs have analog connectors that work with a DP bridge chip and don't actually have an internal DAC: Those should not use the analog link encoder code path.
--- .../gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c | 3 ++- drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c | 3 ++- drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +2 -1
@@ -638,7 +638,8 @@ static struct link_encoder *dce100_link_encoder_create(if (!enc110)return NULL ; -if (enc_init_data->connector.id ==CONNECTOR_ID_VGA ) { +if (enc_init_data->connector.id ==CONNECTOR_ID_VGA && + enc_init_data->analog_engine !=ENGINE_ID_UNKNOWN ) { dce110_link_encoder_construct(enc110, enc_init_data, &link_enc_feature,
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +2 -1
@@ -733,7 +733,8 @@ static struct link_encoder *dce60_link_encoder_create(if (!enc110)return NULL ; -if (enc_init_data->connector.id ==CONNECTOR_ID_VGA ) { +if (enc_init_data->connector.id ==CONNECTOR_ID_VGA && + enc_init_data->analog_engine !=ENGINE_ID_UNKNOWN ) { dce60_link_encoder_construct(enc110, enc_init_data, &link_enc_feature,
drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +2 -1
@@ -740,7 +740,8 @@ static struct link_encoder *dce80_link_encoder_create(if (!enc110)return NULL ; -if (enc_init_data->connector.id ==CONNECTOR_ID_VGA ) { +if (enc_init_data->connector.id ==CONNECTOR_ID_VGA && + enc_init_data->analog_engine !=ENGINE_ID_UNKNOWN ) { dce110_link_encoder_construct(enc110, enc_init_data, &link_enc_feature,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 741/781 drm/amd/display: Only use analog stream encoder with analog engine
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 17ff034f805e032ed1358624a71381f9d6e29e9e ]
Some GPUs have analog connectors that work with a DP bridge chip and don't actually have an internal DAC: Those should not use the analog stream encoders.
--- .../gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +4 -1
@@ -979,7 +979,10 @@ struct stream_encoder *dce100_find_first_free_match_stream_enc_for_link(struct dc_link *link = stream->link;enum engine_id preferred_engine = link->link_enc->preferred_engine; -if (dc_is_rgb_signal (stream->signal)) +/* Prefer analog engine if the link encoder has one. +* Otherwise, it's an external encoder. +*/ +if (dc_is_rgb_signal (stream->signal) && link->link_enc->analog_engine !=ENGINE_ID_UNKNOWN ) preferred_engine = link->link_enc->analog_engine;for (i =0 ; i < pool->stream_enc_count; i++) {
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 742/781 x86/hyperv: Fix error pointer dereference
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ethan Tidmore <[email protected]>
[ Upstream commit 705d01c8d78121ee1634bfc602ac4b0ad1438fab ]
The function idle_thread_get() can return an error pointer and is not checked for it. Add check for error pointer.
Detected by Smatch:arch/x86/hyperv/hv_vtl.c:126 hv_vtl_bringup_vcpu() error:
'idle' dereferencing possible ERR_PTR()
--- arch/x86/hyperv/hv_vtl.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
arch/x86/hyperv/hv_vtl.c +5 -3
@@ -110,7 +110,7 @@ static void hv_vtl_ap_entry(void)static int hv_vtl_bringup_vcpu (u32 target_vp_index,int cpu,u64 eip_ignored) { -u64 status; +u64 status, rsp, rip;int ret =0 ;struct hv_enable_vp_vtl *input;unsigned long irq_flags;
@@ -123,9 +123,11 @@ static int hv_vtl_bringup_vcpu(u32 target_vp_index, int cpu, u64 eip_ignored)struct desc_struct *gdt;struct task_struct *idle =idle_thread_get (cpu); -u64 rsp = (unsigned long )idle->thread.sp; +if (IS_ERR (idle)) +return PTR_ERR (idle); -u64 rip = (u64)&hv_vtl_ap_entry; + rsp = (unsigned long )idle->thread.sp; + rip = (u64)&hv_vtl_ap_entry;native_store_gdt (&gdt_ptr);store_idt (&idt_ptr);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 743/781 ASoC: rockchip: i2s-tdm: Use param rate if not provided by set_sysclk
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Detlev Casanova <[email protected]>
[ Upstream commit 0783052534f547f8f201dd4554b1df9f1f8615b5 ]
Drivers will not always call set_sysclk() for all clocks, especially when default mclk-fs can be used.
When that is the case, use the clock rate set in the params multiplied by the default mclk-fs.
--- sound/soc/rockchip/rockchip_i2s_tdm.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
sound/soc/rockchip/rockchip_i2s_tdm.c +10 -0
@@ -22,6 +22,7 @@#define DRV_NAME "rockchip-i2s-tdm" +#define DEFAULT_MCLK_FS 256#define CH_GRP_MAX 4/* The max channel 8 / 2 */ #define MULTIPLEX_CH_MAX 10
@@ -665,6 +666,15 @@ static int rockchip_i2s_tdm_hw_params(struct snd_pcm_substream *substream, mclk_rate = i2s_tdm->mclk_rx_freq; } +/* +* When the dai/component driver doesn't need to set mclk-fs for a specific +* clock, it can skip the call to set_sysclk() for that clock. +* In that case, simply use the clock rate from the params and multiply it by +* the default mclk-fs value. +*/ +if (!mclk_rate) + mclk_rate =DEFAULT_MCLK_FS *params_rate (params); + err =clk_set_rate (mclk, mclk_rate);if (err)return err;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 744/781 drm/amd/display: Use same max plane scaling limits for all 64 bpp formats
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Kleiner <[email protected]>
[ Upstream commit f0157ce46cf0e5e2257e19d590c9b16036ce26d4 ]
The plane scaling hw seems to have the same min/max plane scaling limits for all 16 bpc / 64 bpp interleaved pixel color formats.
Therefore add cases to amdgpu_dm_plane_get_min_max_dc_plane_scaling() for all the 16 bpc fixed-point / unorm formats to use the same .fp16 up/downscaling factor limits as used by the fp16 floating point formats.
So far, 16 bpc unorm formats were not handled, and the default: path returned max/min factors for 32 bpp argb8888 formats, which were wrong and bigger than what many DCE / DCN hw generations could handle.
The result sometimes was misscaling of framebuffers with DRM_FORMAT_XRGB16161616, DRM_FORMAT_ARGB16161616, DRM_FORMAT_XBGR16161616, DRM_FORMAT_ABGR16161616, leading to very wrong looking display, as tested on Polaris11 / DCE-11.2.
So far this went unnoticed, because only few userspace clients used such 16 bpc unorm framebuffers, and those didn't use hw plane scaling, so they did not experience this issue.
With upcoming Mesa 26 exposing 16 bpc unorm formats under both OpenGL and Vulkan under Wayland, and the upcoming GNOME 50 Mutter Wayland compositor allowing for direct scanout of these formats, the scaling hw will be used on these formats if possible for HiDPI display scaling, so it is important to use the correct hw scaling limits to avoid wrong display.
Tested on AMD Polaris 11 / DCE 11.2 with upcoming Mesa 26 and GNOME 50 on HiDPI displays with scaling enabled. The mutter Wayland compositor now correctly falls back to scaling via desktop compositing instead of direct scanout, thereby avoiding wrong image display. For unscaled mode, it correctly uses direct scanout.
--- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_plane.c +5 -0
@@ -1060,10 +1060,15 @@ static void amdgpu_dm_plane_get_min_max_dc_plane_scaling(struct drm_device *dev, *min_downscale = plane_cap->max_downscale_factor.nv12;break ; +/* All 64 bpp formats have the same fp16 scaling limits */ case DRM_FORMAT_XRGB16161616F :case DRM_FORMAT_ARGB16161616F :case DRM_FORMAT_XBGR16161616F :case DRM_FORMAT_ABGR16161616F : +case DRM_FORMAT_XRGB16161616 : +case DRM_FORMAT_ARGB16161616 : +case DRM_FORMAT_XBGR16161616 : +case DRM_FORMAT_ABGR16161616 : *max_upscale = plane_cap->max_upscale_factor.fp16; *min_downscale = plane_cap->max_downscale_factor.fp16;break ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 745/781 drm/amd/display: Dont call find_analog_engine() twice
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 613b1737abe1bd0a65b49851e777231302095e28 ]
The analog engine is already there in the link_analog_engine variable and assigned to enc_init_data.analog_engine already.
I suspect this was a rebase mistake.
--- drivers/gpu/drm/amd/display/dc/link/link_factory.c | 1 - 1 file changed, 1 deletion(-)
drivers/gpu/drm/amd/display/dc/link/link_factory.c +0 -1
@@ -648,7 +648,6 @@ static bool construct_phy(struct dc_link *link, enc_init_data.channel =get_ddc_line (link); enc_init_data.hpd_source =get_hpd_line (link); enc_init_data.transmitter = transmitter_from_encoder; - enc_init_data.analog_engine =find_analog_engine (link, &enc_init_data.analog_encoder); enc_init_data.encoder = link_encoder; enc_init_data.analog_engine = link_analog_engine;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 746/781 drm/amd/display: Turn off DAC in DCE link encoder using VBIOS
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit e021ee995056ee7e58114edd92bcd4578d8b4bb5 ]
Apparently, the VBIOS DAC1EncoderControl function is much more graceful about turning off the DAC. It writes various DAC registers in a specific sequence. Use that instead of just clearing the DAC_ENABLE register.
Do this in just the dce110_link_encoder_disable_output function and remove it from the HWSS.
--- .../drm/amd/display/dc/dce/dce_link_encoder.c | 30 +++++++++++-------- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 3 -- 2 files changed, 17 insertions(+), 16 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +17 -13
@@ -131,6 +131,21 @@ static enum bp_result link_transmitter_control(return result; } +static enum bp_result link_dac_encoder_control ( +struct dce110_link_encoder *link_enc, +enum bp_encoder_control_action action, +uint32_t pix_clk_100hz) +{ +struct dc_bios *bios = link_enc->base.ctx->dc_bios; +struct bp_encoder_control encoder_control = {0 }; + + encoder_control.action = action; + encoder_control.engine_id = link_enc->base.analog_engine; + encoder_control.pixel_clock = pix_clk_100hz /10 ; + +return bios->funcs->encoder_control (bios, &encoder_control); +} +static void enable_phy_bypass_mode (struct dce110_link_encoder *enc110,bool enable)
@@ -1337,19 +1352,8 @@ void dce110_link_encoder_disable_output(struct bp_transmitter_control cntl = {0 };enum bp_result result; -switch (enc->analog_engine) { -case ENGINE_ID_DACA : -REG_UPDATE (DAC_ENABLE ,DAC_ENABLE ,0 ); -break ; -case ENGINE_ID_DACB : -/* DACB doesn't seem to be present on DCE6+, -* although there are references to it in the register file. -*/ -DC_LOG_ERROR ("%s DACB is unsupported\n" , __func__); -break ; -default : -break ; - } +if (enc->analog_engine !=ENGINE_ID_UNKNOWN ) +link_dac_encoder_control (enc110,ENCODER_CONTROL_DISABLE ,0 );/* The code below only applies to connectors that support digital signals. */ if (enc->transmitter ==TRANSMITTER_UNKNOWN )
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +0 -3
@@ -1218,9 +1218,6 @@ void dce110_disable_stream(struct pipe_ctx *pipe_ctx) dccg->funcs->disable_symclk_se (dccg, stream_enc->stream_enc_inst, link_enc->transmitter -TRANSMITTER_UNIPHY_A ); } - -if (dc_is_rgb_signal (pipe_ctx->stream->signal)) -dce110_dac_encoder_control (pipe_ctx, false); } void dce110_unblank_stream(struct pipe_ctx *pipe_ctx,
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 747/781 drm/amd/display: Initialize DAC in DCE link encoder using VBIOS
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit e2a024345bce78a8e1ed7d9e84c859b05979e41e ]
The VBIOS DAC1EncoderControl() function can initialize the DAC, by writing board-specific values to certain registers. Call this at link encoder hardware initialization time similarly to how the equivalent UNIPHYTransmitterControl initialization is done.
This fixes DAC output on the Radeon HD 7790.
Also remove the ENCODER_CONTROL_SETUP enum from the dac_encoder_control_prepare_params function which is actually not a supported operation for DAC encoders.
--- drivers/gpu/drm/amd/display/dc/bios/command_table.c | 3 +-- drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c | 10 ++++++++++ 2 files changed, 11 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/bios/command_table.c +1 -2
@@ -1874,8 +1874,7 @@ static void dac_encoder_control_prepare_params( uint8_t dac_standard) { params->ucDacStandard = dac_standard; -if (action ==ENCODER_CONTROL_SETUP || - action ==ENCODER_CONTROL_INIT ) +if (action ==ENCODER_CONTROL_INIT ) params->ucAction =ATOM_ENCODER_INIT ;else if (action ==ENCODER_CONTROL_ENABLE ) params->ucAction =ATOM_ENABLE ;
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +10 -0
@@ -1033,6 +1033,16 @@ void dce110_link_encoder_hw_init( cntl.coherent = false; cntl.hpd_sel = enc110->base.hpd_source; +if (enc110->base.analog_engine !=ENGINE_ID_UNKNOWN ) { + result =link_dac_encoder_control (enc110,ENCODER_CONTROL_INIT ,0 ); +if (result !=BP_RESULT_OK ) { +DC_LOG_ERROR ("%s: Failed to execute VBIOS command table for DAC!\n" , + __func__); +BREAK_TO_DEBUGGER (); +return ; + } + } +/* The code below is only applicable to encoders with a digital transmitter. */ if (enc110->base.transmitter ==TRANSMITTER_UNKNOWN )return ;
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 748/781 drm/amd/display: Set CRTC source for DAC using registers
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit cbced93894d145239c83881d7fd953b7392c23a8 ]
Apparently the VBIOS SelectCRTC_Source function overwrites a few registers (such as FMT_*) which DC writes in a different place, which can cause problems.
Instead of using the SelectCRTC_Source function from the VBIOS, use the DAC_SOURCE_SELECT register directly, similarly to how it is done for digital link encoders.
--- .../amd/display/dc/dce/dce_stream_encoder.c | 23 +++++++++++++--- .../amd/display/dc/dce/dce_stream_encoder.h | 12 +++++++-- .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 26 +------------------ .../dc/resource/dce100/dce100_resource.c | 6 +++-- .../dc/resource/dce60/dce60_resource.c | 7 +++-- .../dc/resource/dce80/dce80_resource.c | 6 +++-- 6 files changed, 43 insertions(+), 37 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.c +19 -4
@@ -1498,7 +1498,10 @@ static void dig_connect_to_otg( {struct dce110_stream_encoder *enc110 =DCE110STRENC_FROM_STRENC (enc); -REG_UPDATE (DIG_FE_CNTL ,DIG_SOURCE_SELECT , tg_inst); +if (enc->id ==ENGINE_ID_DACA || enc->id ==ENGINE_ID_DACB ) +REG_UPDATE (DAC_SOURCE_SELECT ,DAC_SOURCE_SELECT , tg_inst); +else +REG_UPDATE (DIG_FE_CNTL ,DIG_SOURCE_SELECT , tg_inst); } static unsigned int dig_source_otg(
@@ -1507,7 +1510,10 @@ static unsigned int dig_source_otg(uint32_t tg_inst =0 ;struct dce110_stream_encoder *enc110 =DCE110STRENC_FROM_STRENC (enc); -REG_GET (DIG_FE_CNTL ,DIG_SOURCE_SELECT , &tg_inst); +if (enc->id ==ENGINE_ID_DACA || enc->id ==ENGINE_ID_DACB ) +REG_GET (DAC_SOURCE_SELECT ,DAC_SOURCE_SELECT , &tg_inst); +else +REG_GET (DIG_FE_CNTL ,DIG_SOURCE_SELECT , &tg_inst);return tg_inst; }
@@ -1568,16 +1574,25 @@ void dce110_stream_encoder_construct( enc110->se_mask = se_mask; } -static const struct stream_encoder_funcs dce110_an_str_enc_funcs = {}; +static const struct stream_encoder_funcs dce110_an_str_enc_funcs = { + .dig_connect_to_otg = dig_connect_to_otg, + .dig_source_otg = dig_source_otg, +};void dce110_analog_stream_encoder_construct (struct dce110_stream_encoder *enc110,struct dc_context *ctx,struct dc_bios *bp, -enum engine_id eng_id) +enum engine_id eng_id, +const struct dce110_stream_enc_registers *regs, +const struct dce_stream_encoder_shift *se_shift, +const struct dce_stream_encoder_mask *se_mask) { enc110->base.funcs = &dce110_an_str_enc_funcs; enc110->base.ctx = ctx; enc110->base.id = eng_id; enc110->base.bp = bp; + enc110->regs = regs; + enc110->se_shift = se_shift; + enc110->se_mask = se_mask; }
drivers/gpu/drm/amd/display/dc/dce/dce_stream_encoder.h +10 -2
@@ -65,6 +65,7 @@SRI (AFMT_60958_1 ,DIG , id), \SRI (AFMT_60958_2 ,DIG , id), \SRI (DIG_FE_CNTL ,DIG , id), \ +SR (DAC_SOURCE_SELECT ), \SRI (HDMI_CONTROL ,DIG , id), \SRI (HDMI_GC ,DIG , id), \ SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
@@ -290,7 +291,8 @@#define SE_COMMON_MASK_SH_LIST_DCE80_100 (mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\ SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\ - SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh) + SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh),\ + SE_SF(DAC_SOURCE_SELECT, DAC_SOURCE_SELECT, mask_sh)#define SE_COMMON_MASK_SH_LIST_DCE110 (mask_sh)\ SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
@@ -494,6 +496,7 @@ struct dce_stream_encoder_shift {uint8_t DP_VID_N_MUL ;uint8_t DP_VID_M_DOUBLE_VALUE_EN ;uint8_t DIG_SOURCE_SELECT ; +uint8_t DAC_SOURCE_SELECT ; };struct dce_stream_encoder_mask {
@@ -626,6 +629,7 @@ struct dce_stream_encoder_mask {uint32_t DP_VID_N_MUL ;uint32_t DP_VID_M_DOUBLE_VALUE_EN ;uint32_t DIG_SOURCE_SELECT ; +uint32_t DAC_SOURCE_SELECT ; };struct dce110_stream_enc_registers {
@@ -653,6 +657,7 @@ struct dce110_stream_enc_registers {uint32_t AFMT_60958_1 ;uint32_t AFMT_60958_2 ;uint32_t DIG_FE_CNTL ; +uint32_t DAC_SOURCE_SELECT ;uint32_t DP_MSE_RATE_CNTL ;uint32_t DP_MSE_RATE_UPDATE ;uint32_t DP_PIXEL_FORMAT ;
@@ -712,7 +717,10 @@ void dce110_analog_stream_encoder_construct(struct dce110_stream_encoder *enc110, struct dc_context *ctx, struct dc_bios *bp, - enum engine_id eng_id); + enum engine_id eng_id, + const struct dce110_stream_enc_registers *regs, + const struct dce_stream_encoder_shift *se_shift, + const struct dce_stream_encoder_mask *se_mask);void dce110_se_audio_mute_control (struct stream_encoder *enc,bool mute);
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +1 -25
@@ -1600,25 +1600,6 @@ static enum dc_status dce110_enable_stream_timing(return DC_OK ; } -static void -dce110_select_crtc_source (struct pipe_ctx *pipe_ctx) -{ -struct dc_link *link = pipe_ctx->stream->link; -struct dc_bios *bios = link->ctx->dc_bios; -struct bp_crtc_source_select crtc_source_select = {0 }; -enum engine_id engine_id = link->link_enc->preferred_engine; - -if (dc_is_rgb_signal (pipe_ctx->stream->signal)) - engine_id = link->link_enc->analog_engine; - - crtc_source_select.controller_id =CONTROLLER_ID_D0 + pipe_ctx->stream_res.tg->inst; - crtc_source_select.color_depth = pipe_ctx->stream->timing.display_color_depth; - crtc_source_select.engine_id = engine_id; - crtc_source_select.sink_signal = pipe_ctx->stream->signal; - - bios->funcs->select_crtc_source (bios, &crtc_source_select); -} - enum dc_status dce110_apply_single_controller_ctx_to_hw( struct pipe_ctx *pipe_ctx, struct dc_state *context,
@@ -1638,10 +1619,6 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( hws->funcs.disable_stream_gating (dc, pipe_ctx); } -if (pipe_ctx->stream->signal ==SIGNAL_TYPE_RGB ) { -dce110_select_crtc_source (pipe_ctx); - } -if (pipe_ctx->stream_res.audio !=NULL ) {struct audio_output audio_output = {0 };
@@ -1721,8 +1698,7 @@ enum dc_status dce110_apply_single_controller_ctx_to_hw( pipe_ctx->stream_res.tg->funcs->set_static_screen_control ( pipe_ctx->stream_res.tg, event_triggers,2 ); -if (!dc_is_virtual_signal (pipe_ctx->stream->signal) && - !dc_is_rgb_signal (pipe_ctx->stream->signal)) +if (!dc_is_virtual_signal (pipe_ctx->stream->signal)) pipe_ctx->stream_res.stream_enc->funcs->dig_connect_to_otg ( pipe_ctx->stream_res.stream_enc, pipe_ctx->stream_res.tg->inst);
drivers/gpu/drm/amd/display/dc/resource/dce100/dce100_resource.c +4 -2
@@ -242,7 +242,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {stream_enc_regs (3 ),stream_enc_regs (4 ),stream_enc_regs (5 ), -stream_enc_regs (6 ) +stream_enc_regs (6 ), + {SR(DAC_SOURCE_SELECT),} /* DACA */ }; static const struct dce_stream_encoder_shift se_shift = {
@@ -491,7 +492,8 @@ static struct stream_encoder *dce100_stream_encoder_create(return NULL ;if (eng_id ==ENGINE_ID_DACA || eng_id ==ENGINE_ID_DACB ) { -dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id); +dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask);return &enc110->base; }
drivers/gpu/drm/amd/display/dc/resource/dce60/dce60_resource.c +5 -2
@@ -258,7 +258,9 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {stream_enc_regs (2 ),stream_enc_regs (3 ),stream_enc_regs (4 ), -stream_enc_regs (5 ) +stream_enc_regs (5 ), + {0}, + {SR(DAC_SOURCE_SELECT),} /* DACA */ }; static const struct dce_stream_encoder_shift se_shift = {
@@ -607,7 +609,8 @@ static struct stream_encoder *dce60_stream_encoder_create(return NULL ;if (eng_id ==ENGINE_ID_DACA || eng_id ==ENGINE_ID_DACB ) { -dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id); +dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask);return &enc110->base; }
drivers/gpu/drm/amd/display/dc/resource/dce80/dce80_resource.c +4 -2
@@ -258,7 +258,8 @@ static const struct dce110_stream_enc_registers stream_enc_regs[] = {stream_enc_regs (3 ),stream_enc_regs (4 ),stream_enc_regs (5 ), -stream_enc_regs (6 ) +stream_enc_regs (6 ), + {SR(DAC_SOURCE_SELECT),} /* DACA */ }; static const struct dce_stream_encoder_shift se_shift = {
@@ -614,7 +615,8 @@ static struct stream_encoder *dce80_stream_encoder_create(return NULL ;if (eng_id ==ENGINE_ID_DACA || eng_id ==ENGINE_ID_DACB ) { -dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id); +dce110_analog_stream_encoder_construct (enc110, ctx, ctx->dc_bios, eng_id, + &stream_enc_regs[eng_id], &se_shift, &se_mask);return &enc110->base; }
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 749/781 drm/amd/display: Enable DAC in DCE link encoder
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Kristóf <[email protected]>
[ Upstream commit 4bd8b5f8bcb57b430c35494d8a2471ce5fd7661d ]
Ensure that the DAC output is enabled at the correct time by moving it to the DCE link encoder similarly to how digital outputs are enabled.
This also removes the call to DAC1EncoderControl from the DCE HWSS, which always felt like it was a hacky solution.
--- .../drm/amd/display/dc/dce/dce_link_encoder.c | 18 +++++++++++++ .../drm/amd/display/dc/dce/dce_link_encoder.h | 5 ++++ .../amd/display/dc/hwss/dce110/dce110_hwseq.c | 26 +++++++------------ .../drm/amd/display/dc/hwss/hw_sequencer.h | 2 ++ .../drm/amd/display/dc/inc/hw/link_encoder.h | 2 ++ .../gpu/drm/amd/display/dc/link/link_dpms.c | 14 +++++++++- 6 files changed, 50 insertions(+), 17 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.c +18 -0
@@ -102,6 +102,7 @@ static const struct link_encoder_funcs dce110_lnk_enc_funcs = { .enable_dp_output = dce110_link_encoder_enable_dp_output, .enable_dp_mst_output = dce110_link_encoder_enable_dp_mst_output, .enable_lvds_output = dce110_link_encoder_enable_lvds_output, + .enable_analog_output = dce110_link_encoder_enable_analog_output, .disable_output = dce110_link_encoder_disable_output, .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, .dp_set_phy_pattern = dce110_link_encoder_dp_set_phy_pattern,
@@ -1192,6 +1193,22 @@ void dce110_link_encoder_enable_lvds_output( } } +void dce110_link_encoder_enable_analog_output ( +struct link_encoder *enc, +uint32_t pixel_clock) +{ +struct dce110_link_encoder *enc110 =TO_DCE110_LINK_ENC (enc); +enum bp_result result; + + result =link_dac_encoder_control (enc110,ENCODER_CONTROL_ENABLE , pixel_clock); + +if (result !=BP_RESULT_OK ) { +DC_LOG_ERROR ("%s: Failed to execute VBIOS command table!\n" , + __func__); +BREAK_TO_DEBUGGER (); + } +} +/* enables DP PHY output */ void dce110_link_encoder_enable_dp_output( struct link_encoder *enc,
@@ -1776,6 +1793,7 @@ static const struct link_encoder_funcs dce60_lnk_enc_funcs = { .enable_dp_output = dce60_link_encoder_enable_dp_output, .enable_dp_mst_output = dce60_link_encoder_enable_dp_mst_output, .enable_lvds_output = dce110_link_encoder_enable_lvds_output, + .enable_analog_output = dce110_link_encoder_enable_analog_output, .disable_output = dce110_link_encoder_disable_output, .dp_set_lane_settings = dce110_link_encoder_dp_set_lane_settings, .dp_set_phy_pattern = dce60_link_encoder_dp_set_phy_pattern,
drivers/gpu/drm/amd/display/dc/dce/dce_link_encoder.h +5 -0
@@ -273,6 +273,11 @@ void dce110_link_encoder_enable_lvds_output(enum clock_source_id clock_source, uint32_t pixel_clock); +/* enables analog output from the DAC */ +void dce110_link_encoder_enable_analog_output ( +struct link_encoder *enc, +uint32_t pixel_clock); +/* disable PHY output */ void dce110_link_encoder_disable_output( struct link_encoder *enc,
drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +10 -16
@@ -659,20 +659,6 @@ void dce110_update_info_frame(struct pipe_ctx *pipe_ctx) } } -static void -dce110_dac_encoder_control (struct pipe_ctx *pipe_ctx,bool enable) -{ -struct dc_link *link = pipe_ctx->stream->link; -struct dc_bios *bios = link->ctx->dc_bios; -struct bp_encoder_control encoder_control = {0 }; - - encoder_control.action = enable ?ENCODER_CONTROL_ENABLE :ENCODER_CONTROL_DISABLE ; - encoder_control.engine_id = link->link_enc->analog_engine; - encoder_control.pixel_clock = pipe_ctx->stream->timing.pix_clk_100hz /10 ; - - bios->funcs->encoder_control (bios, &encoder_control); -} -void dce110_enable_stream (struct pipe_ctx *pipe_ctx) { enum dc_lane_count lane_count =
@@ -703,8 +689,6 @@ void dce110_enable_stream(struct pipe_ctx *pipe_ctx) tg->funcs->set_early_control (tg, early_control); -if (dc_is_rgb_signal (pipe_ctx->stream->signal)) -dce110_dac_encoder_control (pipe_ctx, true); } static enum bp_result link_transmitter_control(
@@ -3285,6 +3269,15 @@ void dce110_enable_tmds_link_output(struct dc_link *link, link->phy_state.symclk_state =SYMCLK_ON_TX_ON ; } +static void dce110_enable_analog_link_output ( +struct dc_link *link, +uint32_t pix_clk_100hz) +{ + link->link_enc->funcs->enable_analog_output ( + link->link_enc, + pix_clk_100hz); +} + void dce110_enable_dp_link_output( struct dc_link *link, const struct link_resource *link_res,
@@ -3422,6 +3415,7 @@ static const struct hw_sequencer_funcs dce110_funcs = { .enable_lvds_link_output = dce110_enable_lvds_link_output, .enable_tmds_link_output = dce110_enable_tmds_link_output, .enable_dp_link_output = dce110_enable_dp_link_output, + .enable_analog_link_output = dce110_enable_analog_link_output, .disable_link_output = dce110_disable_link_output, };
drivers/gpu/drm/amd/display/dc/hwss/hw_sequencer.h +2 -0
@@ -1184,6 +1184,8 @@ struct hw_sequencer_funcs {const struct link_resource *link_res, enum clock_source_id clock_source, uint32_t pixel_clock); +void (*enable_analog_link_output)(struct dc_link *link, +uint32_t pixel_clock);void (*disable_link_output)(struct dc_link *link,const struct link_resource *link_res,enum signal_type signal);
drivers/gpu/drm/amd/display/dc/inc/hw/link_encoder.h +2 -0
@@ -130,6 +130,8 @@ struct link_encoder_funcs {void (*enable_lvds_output)(struct link_encoder *enc,enum clock_source_id clock_source,uint32_t pixel_clock); +void (*enable_analog_output)(struct link_encoder *enc, +uint32_t pixel_clock);void (*disable_output)(struct link_encoder *link_enc,enum signal_type signal); void (*dp_set_lane_settings)(struct link_encoder *enc,
drivers/gpu/drm/amd/display/dc/link/link_dpms.c +13 -1
@@ -2208,6 +2208,18 @@ static enum dc_status enable_link_dp_mst(return enable_link_dp (state, pipe_ctx); } +static enum dc_status enable_link_analog ( +struct dc_state *state, +struct pipe_ctx *pipe_ctx) +{ +struct dc_link *link = pipe_ctx->stream->link; + + link->dc->hwss.enable_analog_link_output ( + link, pipe_ctx->stream->timing.pix_clk_100hz); + +return DC_OK ; +} +static enum dc_status enable_link_virtual (struct pipe_ctx *pipe_ctx) {struct dc_link *link = pipe_ctx->stream->link;
@@ -2263,7 +2275,7 @@ static enum dc_status enable_link( status =DC_OK ;break ;case SIGNAL_TYPE_RGB : - status =DC_OK ; + status =enable_link_analog (state, pipe_ctx);break ;case SIGNAL_TYPE_VIRTUAL : status =enable_link_virtual (pipe_ctx);
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 750/781 PCI: dwc: ep: Always clear IB maps on BAR update
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
[ Upstream commit 8c746e22096579897d1f8f74dbb6b17a6862fb6d ]
dw_pcie_ep_set_bar() currently tears down existing inbound mappings only when either the previous or the new struct pci_epf_bar uses submaps (num_submap != 0). If both the old and new mappings are BAR Match Mode, reprogramming the same ATU index is sufficient, so no explicit teardown was needed.
However, some callers may reuse the same struct pci_epf_bar instance and update it in place before calling set_bar() again. In that case ep_func->epf_bar[bar] and the passed-in epf_bar can point to the same object, so we cannot reliably distinguish BAR Match Mode -> BAR Match Mode from Address Match Mode -> BAR Match Mode. As a result, the conditional teardown based on num_submap becomes unreliable and existing inbound maps may be left active.
Call dw_pcie_ep_clear_ib_maps() unconditionally before reprogramming the BAR so that in-place updates are handled correctly.
This introduces a behavioral change in a corner case: if a BAR reprogramming attempt fails (especially for the long-standing BAR Match Mode -> BAR Match Mode update case), the previously programmed inbound mapping will already have been torn down. This should be acceptable, since the caller observes the error and should not use the BAR for any real transactions in that case.
While at it, document that the existing update parameter check is best-effort for in-place updates.
--- drivers/pci/controller/dwc/pcie-designware-ep.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/pci/controller/dwc/pcie-designware-ep.c +11 -3
@@ -518,6 +518,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,/* * We can only dynamically change a BAR if the new BAR size and * BAR flags do not differ from the existing configuration. +* +* Note: this safety check only works when the caller uses +* a new struct pci_epf_bar in the second set_bar() call. +* If the same instance is updated in place and passed in, +* we cannot reliably detect invalid barno/size/flags +* changes here. */ if (ep_func->epf_bar[bar]->barno != bar || ep_func->epf_bar[bar]->size != size ||
@@ -526,10 +532,12 @@ static int dw_pcie_ep_set_bar(struct pci_epc *epc, u8 func_no, u8 vfunc_no,/* * When dynamically changing a BAR, tear down any existing -* mappings before re-programming. +* mappings before re-programming. This is redundant when +* both the old and new mappings are BAR Match Mode, but +* required to handle in-place updates and match-mode +* changes reliably. */ -if (ep_func->epf_bar[bar]->num_submap || epf_bar->num_submap) -dw_pcie_ep_clear_ib_maps (ep, func_no, bar); +dw_pcie_ep_clear_ib_maps (ep, func_no, bar);/* * When dynamically changing a BAR, skip writing the BAR reg, as
Signature · 1 line
2.51.0
Greg Kroah-Hartman
maintainerPATCH 751/781 usb: cdns3: fix role switching during resume
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Richard (TI) <[email protected]>
commit 87e4b043b98a1d269be0b812f383881abee0ca45 upstream.
If the role change while we are suspended, the cdns3 driver switches to the new mode during resume. However, switching to host mode in this context causes a NULL pointer dereference.
The host role's start() operation registers a xhci-hcd device, but its probe is deferred while we are in the resume path. The host role's resume() operation assumes the xhci-hcd device is already probed, which is not the case, leading to the dereference. Since the start() operation of the new role is already called, the resume operation can be skipped.
So skip the resume operation for the new role if a role switch occurs during resume. Once the resume sequence is complete, the xhci-hcd device can be probed in case of host mode.
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000208
Mem abort info:
...
Data abort info:
...
[0000000000000208] pgd=0000000000000000, p4d=0000000000000000
Internal error: Oops: 0000000096000004 [#1] SMP Modules linked in: CPU: 0 UID: 0 PID: 146 Comm: sh Not tainted 6.19.0-rc7-00013-g6e64f4aabfae-dirty #135 PREEMPT Hardware name: Texas Instruments J7200 EVM (DT) pstate: 20000005 (nzCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : usb_hcd_is_primary_hcd+0x0/0x1c lr : cdns_host_resume+0x24/0x5c ... Call trace: usb_hcd_is_primary_hcd+0x0/0x1c (P) cdns_resume+0x6c/0xbc cdns3_controller_resume.isra.0+0xe8/0x17c cdns3_plat_resume+0x18/0x24 platform_pm_resume+0x2c/0x68 dpm_run_callback+0x90/0x248 device_resume+0x100/0x24c dpm_resume+0x190/0x2ec dpm_resume_end+0x18/0x34 suspend_devices_and_enter+0x2b0/0xa44 pm_suspend+0x16c/0x5fc state_store+0x80/0xec kobj_attr_store+0x18/0x2c sysfs_kf_write+0x7c/0x94 kernfs_fop_write_iter+0x130/0x1dc vfs_write+0x240/0x370 ksys_write+0x70/0x108 __arm64_sys_write+0x1c/0x28 invoke_syscall+0x48/0x10c el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x34/0x108 el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c Code: 52800003 f9407ca5 d63f00a0 17ffffe4 (f9410401) ---[ end trace 0000000000000000 ]---
--- drivers/usb/cdns3/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/cdns3/core.c +1 -1
@@ -551,7 +551,7 @@ int cdns_resume(struct cdns *cdns) } } -if (cdns->roles[cdns->role]->resume) +if (!role_changed && cdns->roles[cdns->role]->resume) cdns->roles[cdns->role]->resume (cdns, power_lost);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 752/781 MIPS: Work around LLVM bug when gp is used as global register variable
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yao Zi <[email protected]>
commit 30bfc2d6a1132a89a5f1c3b96c59cf3e4d076ea3 upstream.
On MIPS, __current_thread_info is defined as global register variable locating in $gp, and is simply assigned with new address during kernel relocation.
This however is broken with LLVM, which always restores $gp if it finds $gp is clobbered in any form, including when intentionally through a global register variable. This is against GCC's documentation[1], which requires a callee-saved register used as global register variable not to be restored if it's clobbered.
As a result, $gp will continue to point to the unrelocated kernel after the epilog of relocate_kernel(), leading to an early crash in init_idle,
[ 0.000000] CPU 0 Unable to handle kernel paging request at virtual address 0000000000000000, epc == ffffffff81afada8, ra == ffffffff81afad90 [ 0.000000] Oops[#1]: [ 0.000000] CPU: 0 UID: 0 PID: 0 Comm: swapper Tainted: G W 6.19.0-rc5-00262-gd3eeb99bbc99-dirty #188 VOLUNTARY [ 0.000000] Tainted: [W]=WARN [ 0.000000] Hardware name: loongson,loongson64v-4core-virtio [ 0.000000] $ 0 : 0000000000000000 0000000000000000 0000000000000001 0000000000000000 [ 0.000000] $ 4 : ffffffff80b80ec0 ffffffff80b53d48 0000000000000000 00000000000f4240 [ 0.000000] $ 8 : 0000000000000100 ffffffff81d82f80 ffffffff81d82f80 0000000000000001 [ 0.000000] $12 : 0000000000000000 ffffffff81776f58 00000000000005da 0000000000000002 [ 0.000000] $16 : ffffffff80b80e40 0000000000000000 ffffffff80b81614 9800000005dfbe80 [ 0.000000] $20 : 00000000540000e0 ffffffff81980000 0000000000000000 ffffffff80f81c80 [ 0.000000] $24 : 0000000000000a26 ffffffff8114fb90 [ 0.000000] $28 : ffffffff80b50000 ffffffff80b53d40 0000000000000000 ffffffff81afad90 [ 0.000000] Hi : 0000000000000000 [ 0.000000] Lo : 0000000000000000 [ 0.000000] epc : ffffffff81afada8 init_idle+0x130/0x270 [ 0.000000] ra : ffffffff81afad90 init_idle+0x118/0x270 [ 0.000000] Status: 540000e2 KX SX UX KERNEL EXL [ 0.000000] Cause : 00000008 (ExcCode 02) [ 0.000000] BadVA : 0000000000000000 [ 0.000000] PrId : 00006305 (ICT Loongson-3) [ 0.000000] Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000) [ 0.000000] Stack : 9800000005dfbf00 ffffffff8178e950 0000000000000000 0000000000000000 [ 0.000000] 0000000000000000 ffffffff81970000 000000000000003f ffffffff810a6528 [ 0.000000] 0000000000000001 9800000005dfbe80 9800000005dfbf00 ffffffff81980000 [ 0.000000] ffffffff810a6450 ffffffff81afb6c0 0000000000000000 ffffffff810a2258 [ 0.000000] ffffffff81d82ec8 ffffffff8198d010 ffffffff81b67e80 ffffffff8197dd98 [ 0.000000] ffffffff81d81c80 ffffffff81930000 0000000000000040 0000000000000000 [ 0.000000] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 0.000000] 0000000000000000 000000000000009e ffffffff9fc01000 0000000000000000 [ 0.000000] 0000000000000000 0000000000000000 0000000000000000 0000000000000000 [ 0.000000] 0000000000000000 ffffffff81ae86dc ffffffff81b3c741 0000000000000002 [ 0.000000] ... [ 0.000000] Call Trace: [ 0.000000] [<ffffffff81afada8>] init_idle+0x130/0x270 [ 0.000000] [<ffffffff81afb6c0>] sched_init+0x5c8/0x6c0 [ 0.000000] [<ffffffff81ae86dc>] start_kernel+0x27c/0x7a8
This bug has been reported to LLVM[2] and affects version from (at least) 18 to 21. Let's work around this by using inline assembly to assign $gp before a fix is widely available.
--- arch/mips/kernel/relocate.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
arch/mips/kernel/relocate.c +13 -0
@@ -420,7 +420,20 @@ void *__init relocate_kernel(void) goto out;/* The current thread is now within the relocated image */ +#ifndef CONFIG_CC_IS_CLANG __current_thread_info =RELOCATED (&init_thread_union); +#else +/* +* LLVM may wrongly restore $gp ($28) in epilog even if it's +* intentionally modified. Work around this by using inline +* assembly to assign $gp. $gp couldn't be listed as output or +* clobber, or LLVM will still restore its original value. +* See also LLVM upstream issue +* https://github.com/llvm/llvm-project/issues/176546 +*/ + asmvolatile ("move $28, %0" : : +"r" (RELOCATED (&init_thread_union))); +#endif /* Return the new kernel's entry point */ kernel_entry =RELOCATED (start_kernel);
Greg Kroah-Hartman
maintainerPATCH 753/781 ksmbd: call ksmbd_vfs_kern_path_end_removing() on some error paths
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fedor Pchelkin <[email protected]>
commit a09dc10d1353f0e92c21eae2a79af1c2b1ddcde8 upstream.
There are two places where ksmbd_vfs_kern_path_end_removing() needs to be called in order to balance what the corresponding successful call to ksmbd_vfs_kern_path_start_removing() has done, i.e. drop inode locks and put the taken references. Otherwise there might be potential deadlocks and unbalanced locks which are caught like:
BUG: workqueue leaked lock or atomic: kworker/5:21/0x00000000/7596
last function: handle_ksmbd_work
2 locks held by kworker/5:21/7596:
#0: ffff8881051ae448 (sb_writers#3){.+.+}-{0:0}, at: ksmbd_vfs_kern_path_locked+0x142/0x660
#1: ffff888130e966c0 (&type->i_mutex_dir_key#3/1){+.+.}-{4:4}, at: ksmbd_vfs_kern_path_locked+0x17d/0x660
CPU: 5 PID: 7596 Comm: kworker/5:21 Not tainted 6.1.162-00456-gc29b353f383b #138
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-debian-1.17.0-1 04/01/2014
Workqueue: ksmbd-io handle_ksmbd_work
Call Trace:
<TASK>
dump_stack_lvl+0x44/0x5b
process_one_work.cold+0x57/0x5c
worker_thread+0x82/0x600
kthread+0x153/0x190
ret_from_fork+0x22/0x30
</TASK>Found by Linux Verification Center (linuxtesting.org).
--- fs/smb/server/smb2pdu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/server/smb2pdu.c +2 -2
@@ -6114,14 +6114,14 @@ static int smb2_create_link(struct ksmbd rc = -EINVAL ;ksmbd_debug (SMB ,"cannot delete %s\n" , link_name); - goto out; } }else { rc = -EEXIST ;ksmbd_debug (SMB ,"link already exists\n" ); - goto out; }ksmbd_vfs_kern_path_end_removing (&path); +if (rc) + goto out; } rc =ksmbd_vfs_link (work, target_name, link_name);if (rc)
Greg Kroah-Hartman
maintainerPATCH 754/781 ext4: subdivide EXT4_EXT_DATA_VALID1
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit 22784ca541c0f01c5ebad14e8228298dc0a390ed upstream.
When splitting an extent, if the EXT4_GET_BLOCKS_CONVERT flag is set and it is necessary to split the target extent in the middle, ext4_split_extent() first handles splitting the latter half of the extent and passes the EXT4_EXT_DATA_VALID1 flag. This flag implies that all blocks before the split point contain valid data; however, this assumption is incorrect.
Therefore, subdivid EXT4_EXT_DATA_VALID1 into EXT4_EXT_DATA_ENTIRE_VALID1 and EXT4_EXT_DATA_PARTIAL_VALID1, which indicate that the first half of the extent is either entirely valid or only partially valid, respectively. These two flags cannot be set simultaneously.
This patch does not use EXT4_EXT_DATA_PARTIAL_VALID1, it only replaces EXT4_EXT_DATA_VALID1 with EXT4_EXT_DATA_ENTIRE_VALID1 at the location where it is set, no logical changes.
Message-ID: <[email protected]>
--- fs/ext4/extents.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
fs/ext4/extents.c +12 -6
@@ -43,8 +43,13 @@#define EXT4_EXT_MARK_UNWRIT1 0x2/* mark first half unwritten */ #define EXT4_EXT_MARK_UNWRIT2 0x4/* mark second half unwritten */ -#define EXT4_EXT_DATA_VALID1 0x8/* first half contains valid data */ -#define EXT4_EXT_DATA_VALID2 0x10/* second half contains valid data */ +/* first half contains valid data */ +#define EXT4_EXT_DATA_ENTIRE_VALID1 0x8/* has entirely valid data */ +#define EXT4_EXT_DATA_PARTIAL_VALID1 0x10/* has partially valid data */ +#define EXT4_EXT_DATA_VALID1 (EXT4_EXT_DATA_ENTIRE_VALID1 | \ + EXT4_EXT_DATA_PARTIAL_VALID1) + +#define EXT4_EXT_DATA_VALID2 0x20/* second half contains valid data */ static __le32 ext4_extent_block_csum (struct inode *inode,struct ext4_extent_header *eh)
@@ -3190,8 +3195,9 @@ static struct ext4_ext_path *ext4_split_unsigned int ee_len, depth;int err =0 ; -BUG_ON ((split_flag & (EXT4_EXT_DATA_VALID1 |EXT4_EXT_DATA_VALID2 )) == - (EXT4_EXT_DATA_VALID1 |EXT4_EXT_DATA_VALID2 )); +BUG_ON ((split_flag &EXT4_EXT_DATA_VALID1 ) ==EXT4_EXT_DATA_VALID1 ); +BUG_ON ((split_flag &EXT4_EXT_DATA_VALID1 ) && + (split_flag &EXT4_EXT_DATA_VALID2 ));ext_debug (inode,"logical block %llu\n" , (unsigned long long )split);
@@ -3373,7 +3379,7 @@ static struct ext4_ext_path *ext4_split_ split_flag1 |=EXT4_EXT_MARK_UNWRIT1 |EXT4_EXT_MARK_UNWRIT2 ;if (split_flag &EXT4_EXT_DATA_VALID2 ) - split_flag1 |=EXT4_EXT_DATA_VALID1 ; + split_flag1 |=EXT4_EXT_DATA_ENTIRE_VALID1 ; path =ext4_split_extent_at (handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1);if (IS_ERR (path))
@@ -3728,7 +3734,7 @@ static struct ext4_ext_path *ext4_split_/* Convert to unwritten */ if (flags &EXT4_GET_BLOCKS_CONVERT_UNWRITTEN ) { - split_flag |=EXT4_EXT_DATA_VALID1 ; + split_flag |=EXT4_EXT_DATA_ENTIRE_VALID1 ;/* Convert to initialized */ }else if (flags &EXT4_GET_BLOCKS_CONVERT ) {/*
Greg Kroah-Hartman
maintainerPATCH 755/781 ext4: dont set EXT4_GET_BLOCKS_CONVERT when splitting before submitting I/O
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit feaf2a80e78f89ee8a3464126077ba8683b62791 upstream.
When allocating blocks during within-EOF DIO and writeback with dioread_nolock enabled, EXT4_GET_BLOCKS_PRE_IO was set to split an existing large unwritten extent. However, EXT4_GET_BLOCKS_CONVERT was set when calling ext4_split_convert_extents(), which may potentially result in stale data issues.
Assume we have an unwritten extent, and then DIO writes the second half.
[UUUUUUUUUUUUUUUU] on-disk extent U: unwritten extent
[UUUUUUUUUUUUUUUU] extent status tree
|<- ->| ----> dio write this range
First, ext4_iomap_alloc() call ext4_map_blocks() with EXT4_GET_BLOCKS_PRE_IO, EXT4_GET_BLOCKS_UNWRIT_EXT and EXT4_GET_BLOCKS_CREATE flags set. ext4_map_blocks() find this extent and call ext4_split_convert_extents() with EXT4_GET_BLOCKS_CONVERT and the above flags set.
Then, ext4_split_convert_extents() calls ext4_split_extent() with EXT4_EXT_MAY_ZEROOUT, EXT4_EXT_MARK_UNWRIT2 and EXT4_EXT_DATA_VALID2 flags set, and it calls ext4_split_extent_at() to split the second half with EXT4_EXT_DATA_VALID2, EXT4_EXT_MARK_UNWRIT1, EXT4_EXT_MAY_ZEROOUT and EXT4_EXT_MARK_UNWRIT2 flags set. However, ext4_split_extent_at() failed to insert extent since a temporary lack -ENOSPC. It zeroes out the first half but convert the entire on-disk extent to written since the EXT4_EXT_DATA_VALID2 flag set, but left the second half as unwritten in the extent status tree.
[0000000000SSSSSS] data S: stale data, 0: zeroed [WWWWWWWWWWWWWWWW] on-disk extent W: written extent [WWWWWWWWWWUUUUUU] extent status tree
Finally, if the DIO failed to write data to the disk, the stale data in the second half will be exposed once the cached extent entry is gone.
Fix this issue by not passing EXT4_GET_BLOCKS_CONVERT when splitting an unwritten extent before submitting I/O, and make ext4_split_convert_extents() to zero out the entire extent range to zero for this case, and also mark the extent in the extent status tree for consistency.
Message-ID: <[email protected]>
--- fs/ext4/extents.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/ext4/extents.c +8 -4
@@ -3735,15 +3735,19 @@ static struct ext4_ext_path *ext4_split_/* Convert to unwritten */ if (flags &EXT4_GET_BLOCKS_CONVERT_UNWRITTEN ) { split_flag |=EXT4_EXT_DATA_ENTIRE_VALID1 ; -/* Convert to initialized */ - }else if (flags &EXT4_GET_BLOCKS_CONVERT ) { +/* Split the existing unwritten extent */ + }else if (flags & (EXT4_GET_BLOCKS_UNWRIT_EXT | +EXT4_GET_BLOCKS_CONVERT )) {/* * It is safe to convert extent to initialized via explicit * zeroout only if extent is fully inside i_size or new_size. */ split_flag |= ee_block + ee_len <= eof_block ?EXT4_EXT_MAY_ZEROOUT :0 ; - split_flag |= (EXT4_EXT_MARK_UNWRIT2 |EXT4_EXT_DATA_VALID2 ); + split_flag |=EXT4_EXT_MARK_UNWRIT2 ; +/* Convert to initialized */ +if (flags &EXT4_GET_BLOCKS_CONVERT ) + split_flag |=EXT4_EXT_DATA_VALID2 ; } flags |=EXT4_GET_BLOCKS_SPLIT_NOMERGE ; return ext4_split_extent(handle, inode, path, map, split_flag, flags,
@@ -3919,7 +3923,7 @@ ext4_ext_handle_unwritten_extents(handle/* get_block() before submitting IO, split the extent */ if (flags &EXT4_GET_BLOCKS_SPLIT_NOMERGE ) { path =ext4_split_convert_extents (handle, inode, map, path, - flags |EXT4_GET_BLOCKS_CONVERT , allocated); + flags, allocated);if (IS_ERR (path))return path;/*
Greg Kroah-Hartman
maintainerPATCH 756/781 ext4: dont zero the entire extent if EXT4_EXT_DATA_PARTIAL_VALID1
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit 1bf6974822d1dba86cf11b5f05498581cf3488a2 upstream.
When allocating initialized blocks from a large unwritten extent, or when splitting an unwritten extent during end I/O and converting it to initialized, there is currently a potential issue of stale data if the extent needs to be split in the middle.
0 A B N
[UUUUUUUUUUUU] U: unwritten extent
[--DDDDDDDD--] D: valid data
|<- ->| ----> this range needs to be initialized
ext4_split_extent() first try to split this extent at B with EXT4_EXT_DATA_ENTIRE_VALID1 and EXT4_EXT_MAY_ZEROOUT flag set, but ext4_split_extent_at() failed to split this extent due to temporary lack of space. It zeroout B to N and mark the entire extent from 0 to N as written.
0 A B N
[WWWWWWWWWWWW] W: written extent
[SSDDDDDDDDZZ] Z: zeroed, S: stale data
ext4_split_extent() then try to split this extent at A with EXT4_EXT_DATA_VALID2 flag set. This time, it split successfully and left a stale written extent from 0 to A.
0 A B N
[WW|WWWWWWWWWW]
[SS|DDDDDDDDZZ]Fix this by pass EXT4_EXT_DATA_PARTIAL_VALID1 to ext4_split_extent_at() when splitting at B, don't convert the entire extent to written and left it as unwritten after zeroing out B to N. The remaining work is just like the standard two-part split. ext4_split_extent() will pass the EXT4_EXT_DATA_VALID2 flag when it calls ext4_split_extent_at() for the second time, allowing it to properly handle the split. If the split is successful, it will keep extent from 0 to A as unwritten.
Message-ID: <[email protected]>
--- fs/ext4/extents.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
fs/ext4/extents.c +12 -1
@@ -3310,6 +3310,15 @@ static struct ext4_ext_path *ext4_split_ }if (!err) { +/* +* The first half contains partially valid data, the +* splitting of this extent has not been completed, fix +* extent length and ext4_split_extent() split will the +* first half again. +*/ +if (split_flag &EXT4_EXT_DATA_PARTIAL_VALID1 ) + goto fix_extent_len; +/* update the extent length and mark as initialized */ ex->ee_len =cpu_to_le16 (ee_len);ext4_ext_try_to_merge (handle, inode, path, ex);
@@ -3379,7 +3388,9 @@ static struct ext4_ext_path *ext4_split_ split_flag1 |=EXT4_EXT_MARK_UNWRIT1 |EXT4_EXT_MARK_UNWRIT2 ;if (split_flag &EXT4_EXT_DATA_VALID2 ) - split_flag1 |=EXT4_EXT_DATA_ENTIRE_VALID1 ; + split_flag1 |= map->m_lblk > ee_block ? +EXT4_EXT_DATA_PARTIAL_VALID1 : +EXT4_EXT_DATA_ENTIRE_VALID1 ; path =ext4_split_extent_at (handle, inode, path, map->m_lblk + map->m_len, split_flag1, flags1);if (IS_ERR (path))
Greg Kroah-Hartman
maintainerPATCH 757/781 ext4: dont cache extent during splitting extent
In reply to Greg Kroah-Hartman6.19-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
commit 8b4b19a2f96348d70bfa306ef7d4a13b0bcbea79 upstream.
Caching extents during the splitting process is risky, as it may result in stale extents remaining in the status tree. Moreover, in most cases, the corresponding extent block entries are likely already cached before the split happens, making caching here not particularly useful.
Assume we have an unwritten extent, and then DIO writes the first half.
[UUUUUUUUUUUUUUUU] on-disk extent U: unwritten extent
[UUUUUUUUUUUUUUUU] extent status tree
|<- ->| ----> dio write this range
First, when ext4_split_extent_at() splits this extent, it truncates the existing extent and then inserts a new one. During this process, this extent status entry may be shrunk, and calls to ext4_find_extent() and ext4_cache_extents() may occur, which could potentially insert the truncated range as a hole into the extent status tree. After the split is completed, this hole is not replaced with the correct status.
[UUUUUUU|UUUUUUUU] on-disk extent U: unwritten extent [UUUUUUU|HHHHHHHH] extent status tree H: hole
Then, the outer calling functions will not correct this remaining hole extent either. Finally, if we perform a delayed buffer write on this latter part, it will re-insert the delayed extent and cause an error in space accounting.
In adition, if the unwritten extent cache is not shrunk during the splitting, ext4_cache_extents() also conflicts with existing extents when caching extents. In the future, we will add checks when caching extents, which will trigger a warning. Therefore, Do not cache extents that are being split.
Message-ID: <[email protected]>
--- fs/ext4/extents.c | 6 ++++++ 1 file changed, 6 insertions(+)
fs/ext4/extents.c +6 -0
@@ -3199,6 +3199,9 @@ static struct ext4_ext_path *ext4_split_BUG_ON ((split_flag &EXT4_EXT_DATA_VALID1 ) && (split_flag &EXT4_EXT_DATA_VALID2 )); +/* Do not cache extents that are in the process of being modified. */ + flags |=EXT4_EX_NOCACHE ; +ext_debug (inode,"logical block %llu\n" , (unsigned long long )split);ext4_ext_show_leaf (inode, path);
@@ -3381,6 +3384,9 @@ static struct ext4_ext_path *ext4_split_ ee_len =ext4_ext_get_actual_len (ex); unwritten =ext4_ext_is_unwritten (ex); +/* Do not cache extents that are in the process of being modified. */ + flags |=EXT4_EX_NOCACHE ; +if (map->m_lblk + map->m_len < ee_block + ee_len) { split_flag1 = split_flag &EXT4_EXT_MAY_ZEROOUT ; flags1 = flags |EXT4_GET_BLOCKS_SPLIT_NOMERGE ;