diff --git a/COPYING-5.14.0-611.35.1.el9_7 b/COPYING-5.14.0-611.36.1.el9_7 similarity index 100% rename from COPYING-5.14.0-611.35.1.el9_7 rename to COPYING-5.14.0-611.36.1.el9_7 diff --git a/Documentation/netlink/specs/dpll.yaml b/Documentation/netlink/specs/dpll.yaml index 50188eb74e04f..ed5866238682e 100644 --- a/Documentation/netlink/specs/dpll.yaml +++ b/Documentation/netlink/specs/dpll.yaml @@ -446,6 +446,16 @@ attribute-sets: doc: | Granularity of phase adjustment, in picoseconds. The value of phase adjustment must be a multiple of this granularity. + - + name: fractional-frequency-offset-ppt + type: sint + doc: | + The FFO (Fractional Frequency Offset) of the pin with respect to + the nominal frequency. + Value = (frequency_measured - frequency_nominal) / frequency_nominal + Value is in PPT (parts per trillion, 10^-12). + Note: This attribute provides higher resolution than the standard + fractional-frequency-offset (which is in PPM). - name: pin-parent-device @@ -550,6 +560,7 @@ operations: request: attributes: - id + - mode - phase-offset-monitor - phase-offset-avg-factor - @@ -627,6 +638,7 @@ operations: - phase-adjust-max - phase-adjust - fractional-frequency-offset + - fractional-frequency-offset-ppt - esync-frequency - esync-frequency-supported - esync-pulse diff --git a/Documentation/netlink/specs/fou.yaml b/Documentation/netlink/specs/fou.yaml index 0af5ab842c04d..79f8dc5055642 100644 --- a/Documentation/netlink/specs/fou.yaml +++ b/Documentation/netlink/specs/fou.yaml @@ -15,7 +15,7 @@ kernel-policy: global definitions: - type: enum - name: encap_type + name: encap-type name-prefix: fou-encap- enum-name: entries: [ unspec, direct, gue ] @@ -39,30 +39,32 @@ attribute-sets: - name: ipproto type: u8 + checks: + min: 1 - name: type type: u8 - - name: remcsum_nopartial + name: remcsum-nopartial type: flag - - name: local_v4 + name: local-v4 type: u32 - - name: local_v6 + name: local-v6 type: binary checks: min-len: 16 - - name: peer_v4 + name: peer-v4 type: u32 - - name: peer_v6 + name: peer-v6 type: binary checks: min-len: 16 - - name: peer_port + name: peer-port type: u16 byte-order: big-endian - @@ -90,12 +92,12 @@ operations: - port - ipproto - type - - remcsum_nopartial - - local_v4 - - peer_v4 - - local_v6 - - peer_v6 - - peer_port + - remcsum-nopartial + - local-v4 + - peer-v4 + - local-v6 + - peer-v6 + - peer-port - ifindex - @@ -112,11 +114,11 @@ operations: - af - ifindex - port - - peer_port - - local_v4 - - peer_v4 - - local_v6 - - peer_v6 + - peer-port + - local-v4 + - peer-v4 + - local-v6 + - peer-v6 - name: get diff --git a/Makefile.rhelver b/Makefile.rhelver index 6ea0bba4c136d..b118f9faf53a1 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 7 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 611.35.1 +RHEL_RELEASE = 611.36.1 # # ZSTREAM diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h index 0a696d0fbf737..e5d44e575a7ed 100644 --- a/arch/s390/include/asm/pgtable.h +++ b/arch/s390/include/asm/pgtable.h @@ -1103,17 +1103,15 @@ static inline pte_t pte_mkhuge(pte_t pte) #define IPTE_NODAT 0x400 #define IPTE_GUEST_ASCE 0x800 -static __always_inline void __ptep_rdp(unsigned long addr, pte_t *ptep, - unsigned long opt, unsigned long asce, - int local) +static __always_inline void __ptep_rdp(unsigned long addr, pte_t *ptep, int local) { unsigned long pto; pto = __pa(ptep) & ~(PTRS_PER_PTE * sizeof(pte_t) - 1); - asm volatile(".insn rrf,0xb98b0000,%[r1],%[r2],%[asce],%[m4]" + asm volatile(".insn rrf,0xb98b0000,%[r1],%[r2],%%r0,%[m4]" : "+m" (*ptep) - : [r1] "a" (pto), [r2] "a" ((addr & PAGE_MASK) | opt), - [asce] "a" (asce), [m4] "i" (local)); + : [r1] "a" (pto), [r2] "a" (addr & PAGE_MASK), + [m4] "i" (local)); } static __always_inline void __ptep_ipte(unsigned long address, pte_t *ptep, @@ -1297,7 +1295,7 @@ static inline void flush_tlb_fix_spurious_fault(struct vm_area_struct *vma, * A local RDP can be used to do the flush. */ if (MACHINE_HAS_RDP && !(pte_val(*ptep) & _PAGE_PROTECT)) - __ptep_rdp(address, ptep, 0, 0, 1); + __ptep_rdp(address, ptep, 1); } #define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index c670195c01077..61c6ae698199b 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -303,9 +303,9 @@ void ptep_reset_dat_prot(struct mm_struct *mm, unsigned long addr, pte_t *ptep, preempt_disable(); atomic_inc(&mm->context.flush_count); if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) - __ptep_rdp(addr, ptep, 0, 0, 1); + __ptep_rdp(addr, ptep, 1); else - __ptep_rdp(addr, ptep, 0, 0, 0); + __ptep_rdp(addr, ptep, 0); /* * PTE is not invalidated by RDP, only _PAGE_PROTECT is cleared. That * means it is still valid and active, and must not be changed according diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/31475b88.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/31475b88.failed new file mode 100644 index 0000000000000..ce16eec93a6c8 --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/31475b88.failed @@ -0,0 +1,68 @@ +s390/mm: Fix __ptep_rdp() inline assembly + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Heiko Carstens +commit 31475b88110c4725b4f9a79c3a0d9bbf97e69e1c +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/31475b88.failed + +When a zero ASCE is passed to the __ptep_rdp() inline assembly, the +generated instruction should have the R3 field of the instruction set to +zero. However the inline assembly is written incorrectly: for such cases a +zero is loaded into a register allocated by the compiler and this register +is then used by the instruction. + +This means that selected TLB entries may not be flushed since the specified +ASCE does not match the one which was used when the selected TLB entries +were created. + +Fix this by removing the asce and opt parameters of __ptep_rdp(), since +all callers always pass zero, and use a hard-coded register zero for +the R3 field. + +Fixes: 0807b856521f ("s390/mm: add support for RDP (Reset DAT-Protection)") + Cc: stable@vger.kernel.org + Reviewed-by: Gerald Schaefer + Signed-off-by: Heiko Carstens +(cherry picked from commit 31475b88110c4725b4f9a79c3a0d9bbf97e69e1c) + Signed-off-by: Jonathan Maple + +# Conflicts: +# arch/s390/include/asm/pgtable.h +diff --cc arch/s390/include/asm/pgtable.h +index 0a696d0fbf73,6663f1619abb..000000000000 +--- a/arch/s390/include/asm/pgtable.h ++++ b/arch/s390/include/asm/pgtable.h +@@@ -1296,8 -1345,8 +1294,13 @@@ static inline void flush_tlb_fix_spurio + * PTE does not have _PAGE_PROTECT set, to avoid unnecessary overhead. + * A local RDP can be used to do the flush. + */ +++<<<<<<< HEAD + + if (MACHINE_HAS_RDP && !(pte_val(*ptep) & _PAGE_PROTECT)) + + __ptep_rdp(address, ptep, 0, 0, 1); +++======= ++ if (cpu_has_rdp() && !(pte_val(*ptep) & _PAGE_PROTECT)) ++ __ptep_rdp(address, ptep, 1); +++>>>>>>> 31475b88110c (s390/mm: Fix __ptep_rdp() inline assembly) + } + #define flush_tlb_fix_spurious_fault flush_tlb_fix_spurious_fault + +* Unmerged path arch/s390/include/asm/pgtable.h +diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c +index c670195c0107..61c6ae698199 100644 +--- a/arch/s390/mm/pgtable.c ++++ b/arch/s390/mm/pgtable.c +@@ -303,9 +303,9 @@ void ptep_reset_dat_prot(struct mm_struct *mm, unsigned long addr, pte_t *ptep, + preempt_disable(); + atomic_inc(&mm->context.flush_count); + if (cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) +- __ptep_rdp(addr, ptep, 0, 0, 1); ++ __ptep_rdp(addr, ptep, 1); + else +- __ptep_rdp(addr, ptep, 0, 0, 0); ++ __ptep_rdp(addr, ptep, 0); + /* + * PTE is not invalidated by RDP, only _PAGE_PROTECT is cleared. That + * means it is still valid and active, and must not be changed according diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/41387874.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/41387874.failed new file mode 100644 index 0000000000000..a955bd4266202 --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/41387874.failed @@ -0,0 +1,99 @@ +tick/sched: Limit non-timekeeper CPUs calling jiffies update + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Steve Wahl +commit 4138787408aa47e9e107f28876cb59b42d78bb99 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/41387874.failed + +On large NUMA systems, while running a test program that saturates the +inter-processor and inter-NUMA links, acquiring the jiffies_lock can be +very expensive. + +If the cpu designated to do jiffies updates (tick_do_timer_cpu) gets +delayed and other cpus decide to do the jiffies update themselves, a large +number of them decide to do so at the same time. + +The inexpensive check against tick_next_period is far quicker than actually +acquiring the lock, so most of these get in line to obtain the lock. If +obtaining the lock is slow enough, this spirals into the vast majority of +CPUs continuously being stuck waiting for this lock, just to obtain it and +find out that time has already been updated by another cpu. For example, on +one random entry to kdb by manually-injected NMI, 2912 of 3840 CPUs were +observed to be stuck there. + +To avoid this, allow only one non-timekeeper CPU to call +tick_do_update_jiffies64() at any given time, resetting ts->stalled jiffies +only if the jiffies update function is actually called. + +With this change, manually interrupting the test at most two CPUs are +observed to invoke tick_do_update_jiffies64() - the timekeeper and one +other. + + Signed-off-by: Steve Wahl + Signed-off-by: Thomas Gleixner + Acked-by: Shrikanth Hegde +Link: https://patch.msgid.link/20251027183456.343407-1-steve.wahl@hpe.com +(cherry picked from commit 4138787408aa47e9e107f28876cb59b42d78bb99) + Signed-off-by: Jonathan Maple + +# Conflicts: +# kernel/time/tick-sched.c +diff --cc kernel/time/tick-sched.c +index 5205373652e9,3ff3eb1f90d0..000000000000 +--- a/kernel/time/tick-sched.c ++++ b/kernel/time/tick-sched.c +@@@ -181,6 -181,47 +181,50 @@@ static ktime_t tick_init_jiffy_update(v + return period; + } + +++<<<<<<< HEAD +++======= ++ static inline int tick_sched_flag_test(struct tick_sched *ts, ++ unsigned long flag) ++ { ++ return !!(ts->flags & flag); ++ } ++ ++ static inline void tick_sched_flag_set(struct tick_sched *ts, ++ unsigned long flag) ++ { ++ lockdep_assert_irqs_disabled(); ++ ts->flags |= flag; ++ } ++ ++ static inline void tick_sched_flag_clear(struct tick_sched *ts, ++ unsigned long flag) ++ { ++ lockdep_assert_irqs_disabled(); ++ ts->flags &= ~flag; ++ } ++ ++ /* ++ * Allow only one non-timekeeper CPU at a time update jiffies from ++ * the timer tick. ++ * ++ * Returns true if update was run. ++ */ ++ static bool tick_limited_update_jiffies64(struct tick_sched *ts, ktime_t now) ++ { ++ static atomic_t in_progress; ++ int inp; ++ ++ inp = atomic_read(&in_progress); ++ if (inp || !atomic_try_cmpxchg(&in_progress, &inp, 1)) ++ return false; ++ ++ if (ts->last_tick_jiffies == jiffies) ++ tick_do_update_jiffies64(now); ++ atomic_set(&in_progress, 0); ++ return true; ++ } ++ +++>>>>>>> 4138787408aa (tick/sched: Limit non-timekeeper CPUs calling jiffies update) + #define MAX_STALLED_JIFFIES 5 + + static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now) +* Unmerged path kernel/time/tick-sched.c diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/4c800227.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/4c800227.failed new file mode 100644 index 0000000000000..39ac3e0c1e235 --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/4c800227.failed @@ -0,0 +1,42 @@ +fou: fix initialization of grc + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Muhammad Usama Anjum +commit 4c8002277167125078e6b9b90137bdf443ebaa08 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/4c800227.failed + +The grc must be initialize first. There can be a condition where if +fou is NULL, goto out will be executed and grc would be used +uninitialized. + +Fixes: 7e4196935069 ("fou: Fix null-ptr-deref in GRO.") + Signed-off-by: Muhammad Usama Anjum + Reviewed-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20240906102839.202798-1-usama.anjum@collabora.com + Signed-off-by: Jakub Kicinski +(cherry picked from commit 4c8002277167125078e6b9b90137bdf443ebaa08) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv4/fou_core.c +diff --cc net/ipv4/fou_core.c +index b7b887f83b65,3e30745e2c09..000000000000 +--- a/net/ipv4/fou_core.c ++++ b/net/ipv4/fou_core.c +@@@ -328,6 -338,9 +328,12 @@@ static struct sk_buff *gue_gro_receive( + + skb_gro_remcsum_init(&grc); + +++<<<<<<< HEAD +++======= ++ if (!fou) ++ goto out; ++ +++>>>>>>> 4c8002277167 (fou: fix initialization of grc) + off = skb_gro_offset(skb); + len = off + sizeof(*guehdr); + +* Unmerged path net/ipv4/fou_core.c diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/7e419693.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/7e419693.failed new file mode 100644 index 0000000000000..25542097589f0 --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/7e419693.failed @@ -0,0 +1,140 @@ +fou: Fix null-ptr-deref in GRO. + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Kuniyuki Iwashima +commit 7e4196935069947d8b70b09c1660b67b067e75cb +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/7e419693.failed + +We observed a null-ptr-deref in fou_gro_receive() while shutting down +a host. [0] + +The NULL pointer is sk->sk_user_data, and the offset 8 is of protocol +in struct fou. + +When fou_release() is called due to netns dismantle or explicit tunnel +teardown, udp_tunnel_sock_release() sets NULL to sk->sk_user_data. +Then, the tunnel socket is destroyed after a single RCU grace period. + +So, in-flight udp4_gro_receive() could find the socket and execute the +FOU GRO handler, where sk->sk_user_data could be NULL. + +Let's use rcu_dereference_sk_user_data() in fou_from_sock() and add NULL +checks in FOU GRO handlers. + +[0]: +BUG: kernel NULL pointer dereference, address: 0000000000000008 + PF: supervisor read access in kernel mode + PF: error_code(0x0000) - not-present page +PGD 80000001032f4067 P4D 80000001032f4067 PUD 103240067 PMD 0 +SMP PTI +CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.10.216-204.855.amzn2.x86_64 #1 +Hardware name: Amazon EC2 c5.large/, BIOS 1.0 10/16/2017 +RIP: 0010:fou_gro_receive (net/ipv4/fou.c:233) [fou] +Code: 41 5f c3 cc cc cc cc e8 e7 2e 69 f4 0f 1f 80 00 00 00 00 0f 1f 44 00 00 49 89 f8 41 54 48 89 f7 48 89 d6 49 8b 80 88 02 00 00 <0f> b6 48 08 0f b7 42 4a 66 25 fd fd 80 cc 02 66 89 42 4a 0f b6 42 +RSP: 0018:ffffa330c0003d08 EFLAGS: 00010297 +RAX: 0000000000000000 RBX: ffff93d9e3a6b900 RCX: 0000000000000010 +RDX: ffff93d9e3a6b900 RSI: ffff93d9e3a6b900 RDI: ffff93dac2e24d08 +RBP: ffff93d9e3a6b900 R08: ffff93dacbce6400 R09: 0000000000000002 +R10: 0000000000000000 R11: ffffffffb5f369b0 R12: ffff93dacbce6400 +R13: ffff93dac2e24d08 R14: 0000000000000000 R15: ffffffffb4edd1c0 +FS: 0000000000000000(0000) GS:ffff93daee800000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000000008 CR3: 0000000102140001 CR4: 00000000007706f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +PKRU: 55555554 +Call Trace: + + ? show_trace_log_lvl (arch/x86/kernel/dumpstack.c:259) + ? __die_body.cold (arch/x86/kernel/dumpstack.c:478 arch/x86/kernel/dumpstack.c:420) + ? no_context (arch/x86/mm/fault.c:752) + ? exc_page_fault (arch/x86/include/asm/irqflags.h:49 arch/x86/include/asm/irqflags.h:89 arch/x86/mm/fault.c:1435 arch/x86/mm/fault.c:1483) + ? asm_exc_page_fault (arch/x86/include/asm/idtentry.h:571) + ? fou_gro_receive (net/ipv4/fou.c:233) [fou] + udp_gro_receive (include/linux/netdevice.h:2552 net/ipv4/udp_offload.c:559) + udp4_gro_receive (net/ipv4/udp_offload.c:604) + inet_gro_receive (net/ipv4/af_inet.c:1549 (discriminator 7)) + dev_gro_receive (net/core/dev.c:6035 (discriminator 4)) + napi_gro_receive (net/core/dev.c:6170) + ena_clean_rx_irq (drivers/amazon/net/ena/ena_netdev.c:1558) [ena] + ena_io_poll (drivers/amazon/net/ena/ena_netdev.c:1742) [ena] + napi_poll (net/core/dev.c:6847) + net_rx_action (net/core/dev.c:6917) + __do_softirq (arch/x86/include/asm/jump_label.h:25 include/linux/jump_label.h:200 include/trace/events/irq.h:142 kernel/softirq.c:299) + asm_call_irq_on_stack (arch/x86/entry/entry_64.S:809) + + do_softirq_own_stack (arch/x86/include/asm/irq_stack.h:27 arch/x86/include/asm/irq_stack.h:77 arch/x86/kernel/irq_64.c:77) + irq_exit_rcu (kernel/softirq.c:393 kernel/softirq.c:423 kernel/softirq.c:435) + common_interrupt (arch/x86/kernel/irq.c:239) + asm_common_interrupt (arch/x86/include/asm/idtentry.h:626) +RIP: 0010:acpi_idle_do_entry (arch/x86/include/asm/irqflags.h:49 arch/x86/include/asm/irqflags.h:89 drivers/acpi/processor_idle.c:114 drivers/acpi/processor_idle.c:575) +Code: 8b 15 d1 3c c4 02 ed c3 cc cc cc cc 65 48 8b 04 25 40 ef 01 00 48 8b 00 a8 08 75 eb 0f 1f 44 00 00 0f 00 2d d5 09 55 00 fb f4 c3 cc cc cc cc e9 be fc ff ff 66 66 2e 0f 1f 84 00 00 00 00 00 +RSP: 0018:ffffffffb5603e58 EFLAGS: 00000246 +RAX: 0000000000004000 RBX: ffff93dac0929c00 RCX: ffff93daee833900 +RDX: ffff93daee800000 RSI: ffff93daee87dc00 RDI: ffff93daee87dc64 +RBP: 0000000000000001 R08: ffffffffb5e7b6c0 R09: 0000000000000044 +R10: ffff93daee831b04 R11: 00000000000001cd R12: 0000000000000001 +R13: ffffffffb5e7b740 R14: 0000000000000001 R15: 0000000000000000 + ? sched_clock_cpu (kernel/sched/clock.c:371) + acpi_idle_enter (drivers/acpi/processor_idle.c:712 (discriminator 3)) + cpuidle_enter_state (drivers/cpuidle/cpuidle.c:237) + cpuidle_enter (drivers/cpuidle/cpuidle.c:353) + cpuidle_idle_call (kernel/sched/idle.c:158 kernel/sched/idle.c:239) + do_idle (kernel/sched/idle.c:302) + cpu_startup_entry (kernel/sched/idle.c:395 (discriminator 1)) + start_kernel (init/main.c:1048) + secondary_startup_64_no_verify (arch/x86/kernel/head_64.S:310) +Modules linked in: udp_diag tcp_diag inet_diag nft_nat ipip tunnel4 dummy fou ip_tunnel nft_masq nft_chain_nat nf_nat wireguard nft_ct curve25519_x86_64 libcurve25519_generic nf_conntrack libchacha20poly1305 nf_defrag_ipv6 nf_defrag_ipv4 nft_objref chacha_x86_64 nft_counter nf_tables nfnetlink poly1305_x86_64 ip6_udp_tunnel udp_tunnel libchacha crc32_pclmul ghash_clmulni_intel aesni_intel crypto_simd cryptd glue_helper mousedev psmouse button ena ptp pps_core crc32c_intel +CR2: 0000000000000008 + +Fixes: d92283e338f6 ("fou: change to use UDP socket GRO") + Reported-by: Alphonse Kurian + Signed-off-by: Kuniyuki Iwashima +Link: https://patch.msgid.link/20240902173927.62706-1-kuniyu@amazon.com + Signed-off-by: Jakub Kicinski +(cherry picked from commit 7e4196935069947d8b70b09c1660b67b067e75cb) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv4/fou_core.c +diff --cc net/ipv4/fou_core.c +index b7b887f83b65,78b869b31492..000000000000 +--- a/net/ipv4/fou_core.c ++++ b/net/ipv4/fou_core.c +@@@ -266,15 -269,24 +272,30 @@@ static int fou_gro_complete(struct soc + int nhoff) + { + const struct net_offload __rcu **offloads; +- u8 proto = fou_from_sock(sk)->protocol; ++ struct fou *fou = fou_from_sock(sk); + const struct net_offload *ops; +- int err = -ENOSYS; ++ u8 proto; ++ int err; ++ ++ if (!fou) { ++ err = -ENOENT; ++ goto out; ++ } ++ ++ proto = fou->protocol; + + + rcu_read_lock(); + offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; + ops = rcu_dereference(offloads[proto]); +++<<<<<<< HEAD + + if (WARN_ON(!ops || !ops->callbacks.gro_complete)) + + goto out_unlock; +++======= ++ if (WARN_ON(!ops || !ops->callbacks.gro_complete)) { ++ err = -ENOSYS; ++ goto out; ++ } +++>>>>>>> 7e4196935069 (fou: Fix null-ptr-deref in GRO.) + + err = ops->callbacks.gro_complete(skb, nhoff); + +* Unmerged path net/ipv4/fou_core.c diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/922a6f34.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/922a6f34.failed new file mode 100644 index 0000000000000..c40e5acd9449f --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/922a6f34.failed @@ -0,0 +1,1117 @@ +autofs: dont trigger mount if it cant succeed + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Ian Kent +commit 922a6f34c1756d2b0c35d9b2d915b8af19e85965 +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/922a6f34.failed + +If a mount namespace contains autofs mounts, and they are propagation +private, and there is no namespace specific automount daemon to handle +possible automounting then attempted path resolution will loop until +MAXSYMLINKS is reached before failing causing quite a bit of noise in +the log. + +Add a check for this in autofs ->d_automount() so that the VFS can +immediately return an error in this case. Since the mount is propagation +private an EPERM return seems most appropriate. + +Suggested by: Christian Brauner + + Signed-off-by: Ian Kent +Link: https://patch.msgid.link/20251118024631.10854-2-raven@themaw.net + Signed-off-by: Christian Brauner +(cherry picked from commit 922a6f34c1756d2b0c35d9b2d915b8af19e85965) + Signed-off-by: Jonathan Maple + +# Conflicts: +# fs/autofs/autofs_i.h +# fs/autofs/inode.c +# fs/namespace.c +diff --cc fs/autofs/autofs_i.h +index 8026f44a107e,4fd555528c5d..000000000000 +--- a/fs/autofs/autofs_i.h ++++ b/fs/autofs/autofs_i.h +@@@ -25,6 -26,11 +26,14 @@@ + #include + #include + #include +++<<<<<<< HEAD +++======= ++ #include ++ #include ++ #include "../mount.h" ++ #include ++ +++>>>>>>> 922a6f34c175 (autofs: dont trigger mount if it cant succeed) + + /* This is the range of ioctl() numbers we claim as ours */ + #define AUTOFS_IOC_FIRST AUTOFS_IOC_READY +diff --cc fs/autofs/inode.c +index 49b34730e7b9,732aee76a24c..000000000000 +--- a/fs/autofs/inode.c ++++ b/fs/autofs/inode.c +@@@ -233,22 -244,16 +233,27 @@@ int autofs_fill_super(struct super_bloc + + sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); + if (!sbi) + - return NULL; + + return -ENOMEM; + + pr_debug("starting up, sbi = %p\n", sbi); + + + s->s_fs_info = sbi; + sbi->magic = AUTOFS_SBI_MAGIC; + - sbi->flags = AUTOFS_SBI_CATATONIC; + - sbi->min_proto = AUTOFS_MIN_PROTO_VERSION; + - sbi->max_proto = AUTOFS_MAX_PROTO_VERSION; + sbi->pipefd = -1; +++<<<<<<< HEAD + + sbi->pipe = NULL; + + sbi->exp_timeout = 0; + + sbi->oz_pgrp = NULL; + + sbi->sb = s; + + sbi->version = 0; + + sbi->sub_version = 0; + + sbi->flags = AUTOFS_SBI_CATATONIC; +++======= ++ sbi->mnt_ns_id = to_ns_common(current->nsproxy->mnt_ns)->ns_id; ++ +++>>>>>>> 922a6f34c175 (autofs: dont trigger mount if it cant succeed) + set_autofs_type_indirect(&sbi->type); + + sbi->min_proto = 0; + + sbi->max_proto = 0; + mutex_init(&sbi->wq_mutex); + mutex_init(&sbi->pipe_mutex); + spin_lock_init(&sbi->fs_lock); +diff --cc fs/namespace.c +index faa8e1bff7c9,27bb12693cba..000000000000 +--- a/fs/namespace.c ++++ b/fs/namespace.c +@@@ -4278,6 -5031,976 +4278,979 @@@ SYSCALL_DEFINE5(mount_setattr, int, dfd + return err; + } + +++<<<<<<< HEAD +++======= ++ SYSCALL_DEFINE5(open_tree_attr, int, dfd, const char __user *, filename, ++ unsigned, flags, struct mount_attr __user *, uattr, ++ size_t, usize) ++ { ++ struct file __free(fput) *file = NULL; ++ int fd; ++ ++ if (!uattr && usize) ++ return -EINVAL; ++ ++ file = vfs_open_tree(dfd, filename, flags); ++ if (IS_ERR(file)) ++ return PTR_ERR(file); ++ ++ if (uattr) { ++ int ret; ++ struct mount_kattr kattr = {}; ++ ++ if (flags & OPEN_TREE_CLONE) ++ kattr.kflags = MOUNT_KATTR_IDMAP_REPLACE; ++ if (flags & AT_RECURSIVE) ++ kattr.kflags |= MOUNT_KATTR_RECURSE; ++ ++ ret = wants_mount_setattr(uattr, usize, &kattr); ++ if (ret > 0) { ++ ret = do_mount_setattr(&file->f_path, &kattr); ++ finish_mount_kattr(&kattr); ++ } ++ if (ret) ++ return ret; ++ } ++ ++ fd = get_unused_fd_flags(flags & O_CLOEXEC); ++ if (fd < 0) ++ return fd; ++ ++ fd_install(fd, no_free_ptr(file)); ++ return fd; ++ } ++ ++ int show_path(struct seq_file *m, struct dentry *root) ++ { ++ if (root->d_sb->s_op->show_path) ++ return root->d_sb->s_op->show_path(m, root); ++ ++ seq_dentry(m, root, " \t\n\\"); ++ return 0; ++ } ++ ++ static struct vfsmount *lookup_mnt_in_ns(u64 id, struct mnt_namespace *ns) ++ { ++ struct mount *mnt = mnt_find_id_at(ns, id); ++ ++ if (!mnt || mnt->mnt_id_unique != id) ++ return NULL; ++ ++ return &mnt->mnt; ++ } ++ ++ struct kstatmount { ++ struct statmount __user *buf; ++ size_t bufsize; ++ struct vfsmount *mnt; ++ struct mnt_idmap *idmap; ++ u64 mask; ++ struct path root; ++ struct seq_file seq; ++ ++ /* Must be last --ends in a flexible-array member. */ ++ struct statmount sm; ++ }; ++ ++ static u64 mnt_to_attr_flags(struct vfsmount *mnt) ++ { ++ unsigned int mnt_flags = READ_ONCE(mnt->mnt_flags); ++ u64 attr_flags = 0; ++ ++ if (mnt_flags & MNT_READONLY) ++ attr_flags |= MOUNT_ATTR_RDONLY; ++ if (mnt_flags & MNT_NOSUID) ++ attr_flags |= MOUNT_ATTR_NOSUID; ++ if (mnt_flags & MNT_NODEV) ++ attr_flags |= MOUNT_ATTR_NODEV; ++ if (mnt_flags & MNT_NOEXEC) ++ attr_flags |= MOUNT_ATTR_NOEXEC; ++ if (mnt_flags & MNT_NODIRATIME) ++ attr_flags |= MOUNT_ATTR_NODIRATIME; ++ if (mnt_flags & MNT_NOSYMFOLLOW) ++ attr_flags |= MOUNT_ATTR_NOSYMFOLLOW; ++ ++ if (mnt_flags & MNT_NOATIME) ++ attr_flags |= MOUNT_ATTR_NOATIME; ++ else if (mnt_flags & MNT_RELATIME) ++ attr_flags |= MOUNT_ATTR_RELATIME; ++ else ++ attr_flags |= MOUNT_ATTR_STRICTATIME; ++ ++ if (is_idmapped_mnt(mnt)) ++ attr_flags |= MOUNT_ATTR_IDMAP; ++ ++ return attr_flags; ++ } ++ ++ static u64 mnt_to_propagation_flags(struct mount *m) ++ { ++ u64 propagation = 0; ++ ++ if (IS_MNT_SHARED(m)) ++ propagation |= MS_SHARED; ++ if (IS_MNT_SLAVE(m)) ++ propagation |= MS_SLAVE; ++ if (IS_MNT_UNBINDABLE(m)) ++ propagation |= MS_UNBINDABLE; ++ if (!propagation) ++ propagation |= MS_PRIVATE; ++ ++ return propagation; ++ } ++ ++ u64 vfsmount_to_propagation_flags(struct vfsmount *mnt) ++ { ++ return mnt_to_propagation_flags(real_mount(mnt)); ++ } ++ EXPORT_SYMBOL_GPL(vfsmount_to_propagation_flags); ++ ++ static void statmount_sb_basic(struct kstatmount *s) ++ { ++ struct super_block *sb = s->mnt->mnt_sb; ++ ++ s->sm.mask |= STATMOUNT_SB_BASIC; ++ s->sm.sb_dev_major = MAJOR(sb->s_dev); ++ s->sm.sb_dev_minor = MINOR(sb->s_dev); ++ s->sm.sb_magic = sb->s_magic; ++ s->sm.sb_flags = sb->s_flags & (SB_RDONLY|SB_SYNCHRONOUS|SB_DIRSYNC|SB_LAZYTIME); ++ } ++ ++ static void statmount_mnt_basic(struct kstatmount *s) ++ { ++ struct mount *m = real_mount(s->mnt); ++ ++ s->sm.mask |= STATMOUNT_MNT_BASIC; ++ s->sm.mnt_id = m->mnt_id_unique; ++ s->sm.mnt_parent_id = m->mnt_parent->mnt_id_unique; ++ s->sm.mnt_id_old = m->mnt_id; ++ s->sm.mnt_parent_id_old = m->mnt_parent->mnt_id; ++ s->sm.mnt_attr = mnt_to_attr_flags(&m->mnt); ++ s->sm.mnt_propagation = mnt_to_propagation_flags(m); ++ s->sm.mnt_peer_group = m->mnt_group_id; ++ s->sm.mnt_master = IS_MNT_SLAVE(m) ? m->mnt_master->mnt_group_id : 0; ++ } ++ ++ static void statmount_propagate_from(struct kstatmount *s) ++ { ++ struct mount *m = real_mount(s->mnt); ++ ++ s->sm.mask |= STATMOUNT_PROPAGATE_FROM; ++ if (IS_MNT_SLAVE(m)) ++ s->sm.propagate_from = get_dominating_id(m, ¤t->fs->root); ++ } ++ ++ static int statmount_mnt_root(struct kstatmount *s, struct seq_file *seq) ++ { ++ int ret; ++ size_t start = seq->count; ++ ++ ret = show_path(seq, s->mnt->mnt_root); ++ if (ret) ++ return ret; ++ ++ if (unlikely(seq_has_overflowed(seq))) ++ return -EAGAIN; ++ ++ /* ++ * Unescape the result. It would be better if supplied string was not ++ * escaped in the first place, but that's a pretty invasive change. ++ */ ++ seq->buf[seq->count] = '\0'; ++ seq->count = start; ++ seq_commit(seq, string_unescape_inplace(seq->buf + start, UNESCAPE_OCTAL)); ++ return 0; ++ } ++ ++ static int statmount_mnt_point(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct vfsmount *mnt = s->mnt; ++ struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; ++ int err; ++ ++ err = seq_path_root(seq, &mnt_path, &s->root, ""); ++ return err == SEQ_SKIP ? 0 : err; ++ } ++ ++ static int statmount_fs_type(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct super_block *sb = s->mnt->mnt_sb; ++ ++ seq_puts(seq, sb->s_type->name); ++ return 0; ++ } ++ ++ static void statmount_fs_subtype(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct super_block *sb = s->mnt->mnt_sb; ++ ++ if (sb->s_subtype) ++ seq_puts(seq, sb->s_subtype); ++ } ++ ++ static int statmount_sb_source(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct super_block *sb = s->mnt->mnt_sb; ++ struct mount *r = real_mount(s->mnt); ++ ++ if (sb->s_op->show_devname) { ++ size_t start = seq->count; ++ int ret; ++ ++ ret = sb->s_op->show_devname(seq, s->mnt->mnt_root); ++ if (ret) ++ return ret; ++ ++ if (unlikely(seq_has_overflowed(seq))) ++ return -EAGAIN; ++ ++ /* Unescape the result */ ++ seq->buf[seq->count] = '\0'; ++ seq->count = start; ++ seq_commit(seq, string_unescape_inplace(seq->buf + start, UNESCAPE_OCTAL)); ++ } else { ++ seq_puts(seq, r->mnt_devname); ++ } ++ return 0; ++ } ++ ++ static void statmount_mnt_ns_id(struct kstatmount *s, struct mnt_namespace *ns) ++ { ++ s->sm.mask |= STATMOUNT_MNT_NS_ID; ++ s->sm.mnt_ns_id = ns->ns.ns_id; ++ } ++ ++ static int statmount_mnt_opts(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct vfsmount *mnt = s->mnt; ++ struct super_block *sb = mnt->mnt_sb; ++ size_t start = seq->count; ++ int err; ++ ++ err = security_sb_show_options(seq, sb); ++ if (err) ++ return err; ++ ++ if (sb->s_op->show_options) { ++ err = sb->s_op->show_options(seq, mnt->mnt_root); ++ if (err) ++ return err; ++ } ++ ++ if (unlikely(seq_has_overflowed(seq))) ++ return -EAGAIN; ++ ++ if (seq->count == start) ++ return 0; ++ ++ /* skip leading comma */ ++ memmove(seq->buf + start, seq->buf + start + 1, ++ seq->count - start - 1); ++ seq->count--; ++ ++ return 0; ++ } ++ ++ static inline int statmount_opt_process(struct seq_file *seq, size_t start) ++ { ++ char *buf_end, *opt_end, *src, *dst; ++ int count = 0; ++ ++ if (unlikely(seq_has_overflowed(seq))) ++ return -EAGAIN; ++ ++ buf_end = seq->buf + seq->count; ++ dst = seq->buf + start; ++ src = dst + 1; /* skip initial comma */ ++ ++ if (src >= buf_end) { ++ seq->count = start; ++ return 0; ++ } ++ ++ *buf_end = '\0'; ++ for (; src < buf_end; src = opt_end + 1) { ++ opt_end = strchrnul(src, ','); ++ *opt_end = '\0'; ++ dst += string_unescape(src, dst, 0, UNESCAPE_OCTAL) + 1; ++ if (WARN_ON_ONCE(++count == INT_MAX)) ++ return -EOVERFLOW; ++ } ++ seq->count = dst - 1 - seq->buf; ++ return count; ++ } ++ ++ static int statmount_opt_array(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct vfsmount *mnt = s->mnt; ++ struct super_block *sb = mnt->mnt_sb; ++ size_t start = seq->count; ++ int err; ++ ++ if (!sb->s_op->show_options) ++ return 0; ++ ++ err = sb->s_op->show_options(seq, mnt->mnt_root); ++ if (err) ++ return err; ++ ++ err = statmount_opt_process(seq, start); ++ if (err < 0) ++ return err; ++ ++ s->sm.opt_num = err; ++ return 0; ++ } ++ ++ static int statmount_opt_sec_array(struct kstatmount *s, struct seq_file *seq) ++ { ++ struct vfsmount *mnt = s->mnt; ++ struct super_block *sb = mnt->mnt_sb; ++ size_t start = seq->count; ++ int err; ++ ++ err = security_sb_show_options(seq, sb); ++ if (err) ++ return err; ++ ++ err = statmount_opt_process(seq, start); ++ if (err < 0) ++ return err; ++ ++ s->sm.opt_sec_num = err; ++ return 0; ++ } ++ ++ static inline int statmount_mnt_uidmap(struct kstatmount *s, struct seq_file *seq) ++ { ++ int ret; ++ ++ ret = statmount_mnt_idmap(s->idmap, seq, true); ++ if (ret < 0) ++ return ret; ++ ++ s->sm.mnt_uidmap_num = ret; ++ /* ++ * Always raise STATMOUNT_MNT_UIDMAP even if there are no valid ++ * mappings. This allows userspace to distinguish between a ++ * non-idmapped mount and an idmapped mount where none of the ++ * individual mappings are valid in the caller's idmapping. ++ */ ++ if (is_valid_mnt_idmap(s->idmap)) ++ s->sm.mask |= STATMOUNT_MNT_UIDMAP; ++ return 0; ++ } ++ ++ static inline int statmount_mnt_gidmap(struct kstatmount *s, struct seq_file *seq) ++ { ++ int ret; ++ ++ ret = statmount_mnt_idmap(s->idmap, seq, false); ++ if (ret < 0) ++ return ret; ++ ++ s->sm.mnt_gidmap_num = ret; ++ /* ++ * Always raise STATMOUNT_MNT_GIDMAP even if there are no valid ++ * mappings. This allows userspace to distinguish between a ++ * non-idmapped mount and an idmapped mount where none of the ++ * individual mappings are valid in the caller's idmapping. ++ */ ++ if (is_valid_mnt_idmap(s->idmap)) ++ s->sm.mask |= STATMOUNT_MNT_GIDMAP; ++ return 0; ++ } ++ ++ static int statmount_string(struct kstatmount *s, u64 flag) ++ { ++ int ret = 0; ++ size_t kbufsize; ++ struct seq_file *seq = &s->seq; ++ struct statmount *sm = &s->sm; ++ u32 start, *offp; ++ ++ /* Reserve an empty string at the beginning for any unset offsets */ ++ if (!seq->count) ++ seq_putc(seq, 0); ++ ++ start = seq->count; ++ ++ switch (flag) { ++ case STATMOUNT_FS_TYPE: ++ offp = &sm->fs_type; ++ ret = statmount_fs_type(s, seq); ++ break; ++ case STATMOUNT_MNT_ROOT: ++ offp = &sm->mnt_root; ++ ret = statmount_mnt_root(s, seq); ++ break; ++ case STATMOUNT_MNT_POINT: ++ offp = &sm->mnt_point; ++ ret = statmount_mnt_point(s, seq); ++ break; ++ case STATMOUNT_MNT_OPTS: ++ offp = &sm->mnt_opts; ++ ret = statmount_mnt_opts(s, seq); ++ break; ++ case STATMOUNT_OPT_ARRAY: ++ offp = &sm->opt_array; ++ ret = statmount_opt_array(s, seq); ++ break; ++ case STATMOUNT_OPT_SEC_ARRAY: ++ offp = &sm->opt_sec_array; ++ ret = statmount_opt_sec_array(s, seq); ++ break; ++ case STATMOUNT_FS_SUBTYPE: ++ offp = &sm->fs_subtype; ++ statmount_fs_subtype(s, seq); ++ break; ++ case STATMOUNT_SB_SOURCE: ++ offp = &sm->sb_source; ++ ret = statmount_sb_source(s, seq); ++ break; ++ case STATMOUNT_MNT_UIDMAP: ++ sm->mnt_uidmap = start; ++ ret = statmount_mnt_uidmap(s, seq); ++ break; ++ case STATMOUNT_MNT_GIDMAP: ++ sm->mnt_gidmap = start; ++ ret = statmount_mnt_gidmap(s, seq); ++ break; ++ default: ++ WARN_ON_ONCE(true); ++ return -EINVAL; ++ } ++ ++ /* ++ * If nothing was emitted, return to avoid setting the flag ++ * and terminating the buffer. ++ */ ++ if (seq->count == start) ++ return ret; ++ if (unlikely(check_add_overflow(sizeof(*sm), seq->count, &kbufsize))) ++ return -EOVERFLOW; ++ if (kbufsize >= s->bufsize) ++ return -EOVERFLOW; ++ ++ /* signal a retry */ ++ if (unlikely(seq_has_overflowed(seq))) ++ return -EAGAIN; ++ ++ if (ret) ++ return ret; ++ ++ seq->buf[seq->count++] = '\0'; ++ sm->mask |= flag; ++ *offp = start; ++ return 0; ++ } ++ ++ static int copy_statmount_to_user(struct kstatmount *s) ++ { ++ struct statmount *sm = &s->sm; ++ struct seq_file *seq = &s->seq; ++ char __user *str = ((char __user *)s->buf) + sizeof(*sm); ++ size_t copysize = min_t(size_t, s->bufsize, sizeof(*sm)); ++ ++ if (seq->count && copy_to_user(str, seq->buf, seq->count)) ++ return -EFAULT; ++ ++ /* Return the number of bytes copied to the buffer */ ++ sm->size = copysize + seq->count; ++ if (copy_to_user(s->buf, sm, copysize)) ++ return -EFAULT; ++ ++ return 0; ++ } ++ ++ static struct mount *listmnt_next(struct mount *curr, bool reverse) ++ { ++ struct rb_node *node; ++ ++ if (reverse) ++ node = rb_prev(&curr->mnt_node); ++ else ++ node = rb_next(&curr->mnt_node); ++ ++ return node_to_mount(node); ++ } ++ ++ static int grab_requested_root(struct mnt_namespace *ns, struct path *root) ++ { ++ struct mount *first, *child; ++ ++ rwsem_assert_held(&namespace_sem); ++ ++ /* We're looking at our own ns, just use get_fs_root. */ ++ if (ns == current->nsproxy->mnt_ns) { ++ get_fs_root(current->fs, root); ++ return 0; ++ } ++ ++ /* ++ * We have to find the first mount in our ns and use that, however it ++ * may not exist, so handle that properly. ++ */ ++ if (mnt_ns_empty(ns)) ++ return -ENOENT; ++ ++ first = child = ns->root; ++ for (;;) { ++ child = listmnt_next(child, false); ++ if (!child) ++ return -ENOENT; ++ if (child->mnt_parent == first) ++ break; ++ } ++ ++ root->mnt = mntget(&child->mnt); ++ root->dentry = dget(root->mnt->mnt_root); ++ return 0; ++ } ++ ++ /* This must be updated whenever a new flag is added */ ++ #define STATMOUNT_SUPPORTED (STATMOUNT_SB_BASIC | \ ++ STATMOUNT_MNT_BASIC | \ ++ STATMOUNT_PROPAGATE_FROM | \ ++ STATMOUNT_MNT_ROOT | \ ++ STATMOUNT_MNT_POINT | \ ++ STATMOUNT_FS_TYPE | \ ++ STATMOUNT_MNT_NS_ID | \ ++ STATMOUNT_MNT_OPTS | \ ++ STATMOUNT_FS_SUBTYPE | \ ++ STATMOUNT_SB_SOURCE | \ ++ STATMOUNT_OPT_ARRAY | \ ++ STATMOUNT_OPT_SEC_ARRAY | \ ++ STATMOUNT_SUPPORTED_MASK | \ ++ STATMOUNT_MNT_UIDMAP | \ ++ STATMOUNT_MNT_GIDMAP) ++ ++ /* locks: namespace_shared */ ++ static int do_statmount(struct kstatmount *s, u64 mnt_id, u64 mnt_ns_id, ++ struct mnt_namespace *ns) ++ { ++ struct mount *m; ++ int err; ++ ++ /* Has the namespace already been emptied? */ ++ if (mnt_ns_id && mnt_ns_empty(ns)) ++ return -ENOENT; ++ ++ s->mnt = lookup_mnt_in_ns(mnt_id, ns); ++ if (!s->mnt) ++ return -ENOENT; ++ ++ err = grab_requested_root(ns, &s->root); ++ if (err) ++ return err; ++ ++ /* ++ * Don't trigger audit denials. We just want to determine what ++ * mounts to show users. ++ */ ++ m = real_mount(s->mnt); ++ if (!is_path_reachable(m, m->mnt.mnt_root, &s->root) && ++ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ err = security_sb_statfs(s->mnt->mnt_root); ++ if (err) ++ return err; ++ ++ /* ++ * Note that mount properties in mnt->mnt_flags, mnt->mnt_idmap ++ * can change concurrently as we only hold the read-side of the ++ * namespace semaphore and mount properties may change with only ++ * the mount lock held. ++ * ++ * We could sample the mount lock sequence counter to detect ++ * those changes and retry. But it's not worth it. Worst that ++ * happens is that the mnt->mnt_idmap pointer is already changed ++ * while mnt->mnt_flags isn't or vica versa. So what. ++ * ++ * Both mnt->mnt_flags and mnt->mnt_idmap are set and retrieved ++ * via READ_ONCE()/WRITE_ONCE() and guard against theoretical ++ * torn read/write. That's all we care about right now. ++ */ ++ s->idmap = mnt_idmap(s->mnt); ++ if (s->mask & STATMOUNT_MNT_BASIC) ++ statmount_mnt_basic(s); ++ ++ if (s->mask & STATMOUNT_SB_BASIC) ++ statmount_sb_basic(s); ++ ++ if (s->mask & STATMOUNT_PROPAGATE_FROM) ++ statmount_propagate_from(s); ++ ++ if (s->mask & STATMOUNT_FS_TYPE) ++ err = statmount_string(s, STATMOUNT_FS_TYPE); ++ ++ if (!err && s->mask & STATMOUNT_MNT_ROOT) ++ err = statmount_string(s, STATMOUNT_MNT_ROOT); ++ ++ if (!err && s->mask & STATMOUNT_MNT_POINT) ++ err = statmount_string(s, STATMOUNT_MNT_POINT); ++ ++ if (!err && s->mask & STATMOUNT_MNT_OPTS) ++ err = statmount_string(s, STATMOUNT_MNT_OPTS); ++ ++ if (!err && s->mask & STATMOUNT_OPT_ARRAY) ++ err = statmount_string(s, STATMOUNT_OPT_ARRAY); ++ ++ if (!err && s->mask & STATMOUNT_OPT_SEC_ARRAY) ++ err = statmount_string(s, STATMOUNT_OPT_SEC_ARRAY); ++ ++ if (!err && s->mask & STATMOUNT_FS_SUBTYPE) ++ err = statmount_string(s, STATMOUNT_FS_SUBTYPE); ++ ++ if (!err && s->mask & STATMOUNT_SB_SOURCE) ++ err = statmount_string(s, STATMOUNT_SB_SOURCE); ++ ++ if (!err && s->mask & STATMOUNT_MNT_UIDMAP) ++ err = statmount_string(s, STATMOUNT_MNT_UIDMAP); ++ ++ if (!err && s->mask & STATMOUNT_MNT_GIDMAP) ++ err = statmount_string(s, STATMOUNT_MNT_GIDMAP); ++ ++ if (!err && s->mask & STATMOUNT_MNT_NS_ID) ++ statmount_mnt_ns_id(s, ns); ++ ++ if (!err && s->mask & STATMOUNT_SUPPORTED_MASK) { ++ s->sm.mask |= STATMOUNT_SUPPORTED_MASK; ++ s->sm.supported_mask = STATMOUNT_SUPPORTED; ++ } ++ ++ if (err) ++ return err; ++ ++ /* Are there bits in the return mask not present in STATMOUNT_SUPPORTED? */ ++ WARN_ON_ONCE(~STATMOUNT_SUPPORTED & s->sm.mask); ++ ++ return 0; ++ } ++ ++ static inline bool retry_statmount(const long ret, size_t *seq_size) ++ { ++ if (likely(ret != -EAGAIN)) ++ return false; ++ if (unlikely(check_mul_overflow(*seq_size, 2, seq_size))) ++ return false; ++ if (unlikely(*seq_size > MAX_RW_COUNT)) ++ return false; ++ return true; ++ } ++ ++ #define STATMOUNT_STRING_REQ (STATMOUNT_MNT_ROOT | STATMOUNT_MNT_POINT | \ ++ STATMOUNT_FS_TYPE | STATMOUNT_MNT_OPTS | \ ++ STATMOUNT_FS_SUBTYPE | STATMOUNT_SB_SOURCE | \ ++ STATMOUNT_OPT_ARRAY | STATMOUNT_OPT_SEC_ARRAY | \ ++ STATMOUNT_MNT_UIDMAP | STATMOUNT_MNT_GIDMAP) ++ ++ static int prepare_kstatmount(struct kstatmount *ks, struct mnt_id_req *kreq, ++ struct statmount __user *buf, size_t bufsize, ++ size_t seq_size) ++ { ++ if (!access_ok(buf, bufsize)) ++ return -EFAULT; ++ ++ memset(ks, 0, sizeof(*ks)); ++ ks->mask = kreq->param; ++ ks->buf = buf; ++ ks->bufsize = bufsize; ++ ++ if (ks->mask & STATMOUNT_STRING_REQ) { ++ if (bufsize == sizeof(ks->sm)) ++ return -EOVERFLOW; ++ ++ ks->seq.buf = kvmalloc(seq_size, GFP_KERNEL_ACCOUNT); ++ if (!ks->seq.buf) ++ return -ENOMEM; ++ ++ ks->seq.size = seq_size; ++ } ++ ++ return 0; ++ } ++ ++ static int copy_mnt_id_req(const struct mnt_id_req __user *req, ++ struct mnt_id_req *kreq) ++ { ++ int ret; ++ size_t usize; ++ ++ BUILD_BUG_ON(sizeof(struct mnt_id_req) != MNT_ID_REQ_SIZE_VER1); ++ ++ ret = get_user(usize, &req->size); ++ if (ret) ++ return -EFAULT; ++ if (unlikely(usize > PAGE_SIZE)) ++ return -E2BIG; ++ if (unlikely(usize < MNT_ID_REQ_SIZE_VER0)) ++ return -EINVAL; ++ memset(kreq, 0, sizeof(*kreq)); ++ ret = copy_struct_from_user(kreq, sizeof(*kreq), req, usize); ++ if (ret) ++ return ret; ++ if (kreq->spare != 0) ++ return -EINVAL; ++ /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */ ++ if (kreq->mnt_id <= MNT_UNIQUE_ID_OFFSET) ++ return -EINVAL; ++ return 0; ++ } ++ ++ /* ++ * If the user requested a specific mount namespace id, look that up and return ++ * that, or if not simply grab a passive reference on our mount namespace and ++ * return that. ++ */ ++ static struct mnt_namespace *grab_requested_mnt_ns(const struct mnt_id_req *kreq) ++ { ++ struct mnt_namespace *mnt_ns; ++ ++ if (kreq->mnt_ns_id && kreq->spare) ++ return ERR_PTR(-EINVAL); ++ ++ if (kreq->mnt_ns_id) ++ return lookup_mnt_ns(kreq->mnt_ns_id); ++ ++ if (kreq->spare) { ++ struct ns_common *ns; ++ ++ CLASS(fd, f)(kreq->spare); ++ if (fd_empty(f)) ++ return ERR_PTR(-EBADF); ++ ++ if (!proc_ns_file(fd_file(f))) ++ return ERR_PTR(-EINVAL); ++ ++ ns = get_proc_ns(file_inode(fd_file(f))); ++ if (ns->ns_type != CLONE_NEWNS) ++ return ERR_PTR(-EINVAL); ++ ++ mnt_ns = to_mnt_ns(ns); ++ } else { ++ mnt_ns = current->nsproxy->mnt_ns; ++ } ++ ++ refcount_inc(&mnt_ns->passive); ++ return mnt_ns; ++ } ++ ++ SYSCALL_DEFINE4(statmount, const struct mnt_id_req __user *, req, ++ struct statmount __user *, buf, size_t, bufsize, ++ unsigned int, flags) ++ { ++ struct mnt_namespace *ns __free(mnt_ns_release) = NULL; ++ struct kstatmount *ks __free(kfree) = NULL; ++ struct mnt_id_req kreq; ++ /* We currently support retrieval of 3 strings. */ ++ size_t seq_size = 3 * PATH_MAX; ++ int ret; ++ ++ if (flags) ++ return -EINVAL; ++ ++ ret = copy_mnt_id_req(req, &kreq); ++ if (ret) ++ return ret; ++ ++ ns = grab_requested_mnt_ns(&kreq); ++ if (!ns) ++ return -ENOENT; ++ ++ if (kreq.mnt_ns_id && (ns != current->nsproxy->mnt_ns) && ++ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) ++ return -ENOENT; ++ ++ ks = kmalloc(sizeof(*ks), GFP_KERNEL_ACCOUNT); ++ if (!ks) ++ return -ENOMEM; ++ ++ retry: ++ ret = prepare_kstatmount(ks, &kreq, buf, bufsize, seq_size); ++ if (ret) ++ return ret; ++ ++ scoped_guard(namespace_shared) ++ ret = do_statmount(ks, kreq.mnt_id, kreq.mnt_ns_id, ns); ++ ++ if (!ret) ++ ret = copy_statmount_to_user(ks); ++ kvfree(ks->seq.buf); ++ path_put(&ks->root); ++ if (retry_statmount(ret, &seq_size)) ++ goto retry; ++ return ret; ++ } ++ ++ struct klistmount { ++ u64 last_mnt_id; ++ u64 mnt_parent_id; ++ u64 *kmnt_ids; ++ u32 nr_mnt_ids; ++ struct mnt_namespace *ns; ++ struct path root; ++ }; ++ ++ /* locks: namespace_shared */ ++ static ssize_t do_listmount(struct klistmount *kls, bool reverse) ++ { ++ struct mnt_namespace *ns = kls->ns; ++ u64 mnt_parent_id = kls->mnt_parent_id; ++ u64 last_mnt_id = kls->last_mnt_id; ++ u64 *mnt_ids = kls->kmnt_ids; ++ size_t nr_mnt_ids = kls->nr_mnt_ids; ++ struct path orig; ++ struct mount *r, *first; ++ ssize_t ret; ++ ++ rwsem_assert_held(&namespace_sem); ++ ++ ret = grab_requested_root(ns, &kls->root); ++ if (ret) ++ return ret; ++ ++ if (mnt_parent_id == LSMT_ROOT) { ++ orig = kls->root; ++ } else { ++ orig.mnt = lookup_mnt_in_ns(mnt_parent_id, ns); ++ if (!orig.mnt) ++ return -ENOENT; ++ orig.dentry = orig.mnt->mnt_root; ++ } ++ ++ /* ++ * Don't trigger audit denials. We just want to determine what ++ * mounts to show users. ++ */ ++ if (!is_path_reachable(real_mount(orig.mnt), orig.dentry, &kls->root) && ++ !ns_capable_noaudit(ns->user_ns, CAP_SYS_ADMIN)) ++ return -EPERM; ++ ++ ret = security_sb_statfs(orig.dentry); ++ if (ret) ++ return ret; ++ ++ if (!last_mnt_id) { ++ if (reverse) ++ first = node_to_mount(ns->mnt_last_node); ++ else ++ first = node_to_mount(ns->mnt_first_node); ++ } else { ++ if (reverse) ++ first = mnt_find_id_at_reverse(ns, last_mnt_id - 1); ++ else ++ first = mnt_find_id_at(ns, last_mnt_id + 1); ++ } ++ ++ for (ret = 0, r = first; r && nr_mnt_ids; r = listmnt_next(r, reverse)) { ++ if (r->mnt_id_unique == mnt_parent_id) ++ continue; ++ if (!is_path_reachable(r, r->mnt.mnt_root, &orig)) ++ continue; ++ *mnt_ids = r->mnt_id_unique; ++ mnt_ids++; ++ nr_mnt_ids--; ++ ret++; ++ } ++ return ret; ++ } ++ ++ static void __free_klistmount_free(const struct klistmount *kls) ++ { ++ path_put(&kls->root); ++ kvfree(kls->kmnt_ids); ++ mnt_ns_release(kls->ns); ++ } ++ ++ static inline int prepare_klistmount(struct klistmount *kls, struct mnt_id_req *kreq, ++ size_t nr_mnt_ids) ++ { ++ ++ u64 last_mnt_id = kreq->param; ++ ++ /* The first valid unique mount id is MNT_UNIQUE_ID_OFFSET + 1. */ ++ if (last_mnt_id != 0 && last_mnt_id <= MNT_UNIQUE_ID_OFFSET) ++ return -EINVAL; ++ ++ kls->last_mnt_id = last_mnt_id; ++ ++ kls->nr_mnt_ids = nr_mnt_ids; ++ kls->kmnt_ids = kvmalloc_array(nr_mnt_ids, sizeof(*kls->kmnt_ids), ++ GFP_KERNEL_ACCOUNT); ++ if (!kls->kmnt_ids) ++ return -ENOMEM; ++ ++ kls->ns = grab_requested_mnt_ns(kreq); ++ if (!kls->ns) ++ return -ENOENT; ++ ++ kls->mnt_parent_id = kreq->mnt_id; ++ return 0; ++ } ++ ++ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req, ++ u64 __user *, mnt_ids, size_t, nr_mnt_ids, unsigned int, flags) ++ { ++ struct klistmount kls __free(klistmount_free) = {}; ++ const size_t maxcount = 1000000; ++ struct mnt_id_req kreq; ++ ssize_t ret; ++ ++ if (flags & ~LISTMOUNT_REVERSE) ++ return -EINVAL; ++ ++ /* ++ * If the mount namespace really has more than 1 million mounts the ++ * caller must iterate over the mount namespace (and reconsider their ++ * system design...). ++ */ ++ if (unlikely(nr_mnt_ids > maxcount)) ++ return -EOVERFLOW; ++ ++ if (!access_ok(mnt_ids, nr_mnt_ids * sizeof(*mnt_ids))) ++ return -EFAULT; ++ ++ ret = copy_mnt_id_req(req, &kreq); ++ if (ret) ++ return ret; ++ ++ ret = prepare_klistmount(&kls, &kreq, nr_mnt_ids); ++ if (ret) ++ return ret; ++ ++ if (kreq.mnt_ns_id && (kls.ns != current->nsproxy->mnt_ns) && ++ !ns_capable_noaudit(kls.ns->user_ns, CAP_SYS_ADMIN)) ++ return -ENOENT; ++ ++ /* ++ * We only need to guard against mount topology changes as ++ * listmount() doesn't care about any mount properties. ++ */ ++ scoped_guard(namespace_shared) ++ ret = do_listmount(&kls, (flags & LISTMOUNT_REVERSE)); ++ if (ret <= 0) ++ return ret; ++ ++ if (copy_to_user(mnt_ids, kls.kmnt_ids, ret * sizeof(*mnt_ids))) ++ return -EFAULT; ++ ++ return ret; ++ } ++ ++ struct mnt_namespace init_mnt_ns = { ++ .ns.inum = ns_init_inum(&init_mnt_ns), ++ .ns.ops = &mntns_operations, ++ .user_ns = &init_user_ns, ++ .ns.__ns_ref = REFCOUNT_INIT(1), ++ .ns.ns_type = ns_common_type(&init_mnt_ns), ++ .passive = REFCOUNT_INIT(1), ++ .mounts = RB_ROOT, ++ .poll = __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll), ++ }; ++ +++>>>>>>> 922a6f34c175 (autofs: dont trigger mount if it cant succeed) + static void __init init_mount_tree(void) + { + struct vfsmount *mnt; +* Unmerged path fs/autofs/autofs_i.h +diff --git a/fs/autofs/dev-ioctl.c b/fs/autofs/dev-ioctl.c +index 6d57efbb8110..67c76e6590f9 100644 +--- a/fs/autofs/dev-ioctl.c ++++ b/fs/autofs/dev-ioctl.c +@@ -381,6 +381,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, + swap(sbi->oz_pgrp, new_pid); + sbi->pipefd = pipefd; + sbi->pipe = pipe; ++ sbi->mnt_ns_id = to_ns_common(current->nsproxy->mnt_ns)->ns_id; + sbi->flags &= ~AUTOFS_SBI_CATATONIC; + } + out: +* Unmerged path fs/autofs/inode.c +diff --git a/fs/autofs/root.c b/fs/autofs/root.c +index 6baf90b08e0e..05b908c965a9 100644 +--- a/fs/autofs/root.c ++++ b/fs/autofs/root.c +@@ -341,6 +341,14 @@ static struct vfsmount *autofs_d_automount(struct path *path) + if (autofs_oz_mode(sbi)) + return NULL; + ++ /* Refuse to trigger mount if current namespace is not the owner ++ * and the mount is propagation private. ++ */ ++ if (sbi->mnt_ns_id != to_ns_common(current->nsproxy->mnt_ns)->ns_id) { ++ if (vfsmount_to_propagation_flags(path->mnt) & MS_PRIVATE) ++ return ERR_PTR(-EPERM); ++ } ++ + /* + * If an expire request is pending everyone must wait. + * If the expire fails we're still mounted so continue +* Unmerged path fs/namespace.c +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 53cf26162c5d..d02f204c7eb9 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -2808,6 +2808,7 @@ extern struct file * open_exec(const char *); + /* fs/dcache.c -- generic fs support functions */ + extern bool is_subdir(struct dentry *, struct dentry *); + extern bool path_is_under(const struct path *, const struct path *); ++u64 vfsmount_to_propagation_flags(struct vfsmount *mnt); + + extern char *file_path(struct file *, char *, int); + diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/dd89a81d.failed b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/dd89a81d.failed new file mode 100644 index 0000000000000..25a8fd0cc719c --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/dd89a81d.failed @@ -0,0 +1,53 @@ +fou: remove warn in gue_gro_receive on unsupported protocol + +jira KERNEL-703 +Rebuild_History Non-Buildable kernel-5.14.0-611.36.1.el9_7 +commit-author Willem de Bruijn +commit dd89a81d850fa9a65f67b4527c0e420d15bf836c +Empty-Commit: Cherry-Pick Conflicts during history rebuild. +Will be included in final tarball splat. Ref for failed cherry-pick at: +ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/dd89a81d.failed + +Drop the WARN_ON_ONCE inn gue_gro_receive if the encapsulated type is +not known or does not have a GRO handler. + +Such a packet is easily constructed. Syzbot generates them and sets +off this warning. + +Remove the warning as it is expected and not actionable. + +The warning was previously reduced from WARN_ON to WARN_ON_ONCE in +commit 270136613bf7 ("fou: Do WARN_ON_ONCE in gue_gro_receive for bad +proto callbacks"). + + Signed-off-by: Willem de Bruijn + Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240614122552.1649044-1-willemdebruijn.kernel@gmail.com + Signed-off-by: Jakub Kicinski +(cherry picked from commit dd89a81d850fa9a65f67b4527c0e420d15bf836c) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv4/fou_core.c +diff --cc net/ipv4/fou_core.c +index b7b887f83b65,0abbc413e0fe..000000000000 +--- a/net/ipv4/fou_core.c ++++ b/net/ipv4/fou_core.c +@@@ -437,11 -431,10 +437,16 @@@ next_proto + /* Flag this frame as already having an outer encap header */ + NAPI_GRO_CB(skb)->is_fou = 1; + + + rcu_read_lock(); + offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; + ops = rcu_dereference(offloads[proto]); +++<<<<<<< HEAD + + if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) + + goto out_unlock; +++======= ++ if (!ops || !ops->callbacks.gro_receive) ++ goto out; +++>>>>>>> dd89a81d850f (fou: remove warn in gue_gro_receive on unsupported protocol) + + pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); + flush = 0; +* Unmerged path net/ipv4/fou_core.c diff --git a/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/rebuild.details.txt b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/rebuild.details.txt new file mode 100644 index 0000000000000..e24e9e736c7ba --- /dev/null +++ b/ciq/ciq_backports/kernel-5.14.0-611.36.1.el9_7/rebuild.details.txt @@ -0,0 +1,38 @@ +Rebuild_History BUILDABLE +Rebuilding Kernel from rpm changelog with Fuzz Limit: 87.50% +Number of commits in upstream range v5.14~1..kernel-mainline: 351590 +Number of commits in rpm: 28 +Number of commits matched with upstream: 12 (42.86%) +Number of commits in upstream but not in rpm: 351578 +Number of commits NOT found in upstream: 16 (57.14%) + +Rebuilding Kernel on Branch rocky9_7_rebuild_kernel-5.14.0-611.36.1.el9_7 for kernel-5.14.0-611.36.1.el9_7 +Clean Cherry Picks: 6 (50.00%) +Empty Cherry Picks: 6 (50.00%) +_______________________________ + +__EMPTY COMMITS__________________________ +4138787408aa47e9e107f28876cb59b42d78bb99 tick/sched: Limit non-timekeeper CPUs calling jiffies update +31475b88110c4725b4f9a79c3a0d9bbf97e69e1c s390/mm: Fix __ptep_rdp() inline assembly +dd89a81d850fa9a65f67b4527c0e420d15bf836c fou: remove warn in gue_gro_receive on unsupported protocol +7e4196935069947d8b70b09c1660b67b067e75cb fou: Fix null-ptr-deref in GRO. +4c8002277167125078e6b9b90137bdf443ebaa08 fou: fix initialization of grc +922a6f34c1756d2b0c35d9b2d915b8af19e85965 autofs: dont trigger mount if it cant succeed + +__CHANGES NOT IN UPSTREAM________________ +Replace sbat with Rocky Linux sbat +Change bug tracker URL +Ensure appended release in sbat is removed' +migrate: correct lock ordering for hugetlb file folios +ice: PTP: fix missing timestamps on E825 hardware +fou: Don't allow 0 for FOU_ATTR_IPPROTO. +tools: ynl: Specify --no-line-number in ynl-regen.sh. +gue: Fix skb memleak with inner IP protocol 0. +redhat: enable FOU modules in kernel-modules-extra +dpll: expose fractional frequency offset in ppt +dpll: zl3073x: Implement device mode setting support +dpll: add dpll_device op to set working mode +dpll: add dpll_device op to get supported modes +i40e: add rh_phys_port_name mod option to behave like upstream +ice: add rh_phys_port_name mod option to behave like upstream +scsi: qla2xxx: Fix bsg_done() causing double free diff --git a/configs/kernel-5.14.0-aarch64-64k-debug.config b/configs/kernel-5.14.0-aarch64-64k-debug.config index 04233b7333bd2..5369541016e1f 100644 --- a/configs/kernel-5.14.0-aarch64-64k-debug.config +++ b/configs/kernel-5.14.0-aarch64-64k-debug.config @@ -1200,8 +1200,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1254,6 +1254,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-64k.config b/configs/kernel-5.14.0-aarch64-64k.config index 0058678b6ea43..a9b7c905758b8 100644 --- a/configs/kernel-5.14.0-aarch64-64k.config +++ b/configs/kernel-5.14.0-aarch64-64k.config @@ -1196,8 +1196,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1250,6 +1250,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-debug.config b/configs/kernel-5.14.0-aarch64-debug.config index c737657c77114..e5f52f699a616 100644 --- a/configs/kernel-5.14.0-aarch64-debug.config +++ b/configs/kernel-5.14.0-aarch64-debug.config @@ -1203,8 +1203,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1257,6 +1257,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-rt-64k-debug.config b/configs/kernel-5.14.0-aarch64-rt-64k-debug.config index 79725480470d1..31611cd217db9 100644 --- a/configs/kernel-5.14.0-aarch64-rt-64k-debug.config +++ b/configs/kernel-5.14.0-aarch64-rt-64k-debug.config @@ -1197,8 +1197,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1251,6 +1251,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-rt-64k.config b/configs/kernel-5.14.0-aarch64-rt-64k.config index 7c723e71f914a..bb13fa62ef1a4 100644 --- a/configs/kernel-5.14.0-aarch64-rt-64k.config +++ b/configs/kernel-5.14.0-aarch64-rt-64k.config @@ -1194,8 +1194,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1248,6 +1248,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-rt-debug.config b/configs/kernel-5.14.0-aarch64-rt-debug.config index 695cfeed66113..40eaa51751799 100644 --- a/configs/kernel-5.14.0-aarch64-rt-debug.config +++ b/configs/kernel-5.14.0-aarch64-rt-debug.config @@ -1198,8 +1198,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1252,6 +1252,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64-rt.config b/configs/kernel-5.14.0-aarch64-rt.config index e09ce0fdc7564..cd833762598d6 100644 --- a/configs/kernel-5.14.0-aarch64-rt.config +++ b/configs/kernel-5.14.0-aarch64-rt.config @@ -1195,8 +1195,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1249,6 +1249,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-aarch64.config b/configs/kernel-5.14.0-aarch64.config index ffa8960cd4807..572b21cc9493b 100644 --- a/configs/kernel-5.14.0-aarch64.config +++ b/configs/kernel-5.14.0-aarch64.config @@ -1199,8 +1199,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1253,6 +1253,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-ppc64le-debug.config b/configs/kernel-5.14.0-ppc64le-debug.config index f0ae4d0e99095..d198f247bdebf 100644 --- a/configs/kernel-5.14.0-ppc64le-debug.config +++ b/configs/kernel-5.14.0-ppc64le-debug.config @@ -966,8 +966,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1020,6 +1020,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-ppc64le.config b/configs/kernel-5.14.0-ppc64le.config index 531b9025abbbe..25c9d6cca4efb 100644 --- a/configs/kernel-5.14.0-ppc64le.config +++ b/configs/kernel-5.14.0-ppc64le.config @@ -969,8 +969,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1023,6 +1023,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-s390x-debug.config b/configs/kernel-5.14.0-s390x-debug.config index 8da129157e89a..b0b6bdf9b9b1b 100644 --- a/configs/kernel-5.14.0-s390x-debug.config +++ b/configs/kernel-5.14.0-s390x-debug.config @@ -832,8 +832,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -886,6 +886,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-s390x.config b/configs/kernel-5.14.0-s390x.config index 44541bd3e0f48..092da14fef0e1 100644 --- a/configs/kernel-5.14.0-s390x.config +++ b/configs/kernel-5.14.0-s390x.config @@ -855,8 +855,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -909,6 +909,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-x86_64-debug.config b/configs/kernel-5.14.0-x86_64-debug.config index e74a390505da8..c554d7f09753a 100644 --- a/configs/kernel-5.14.0-x86_64-debug.config +++ b/configs/kernel-5.14.0-x86_64-debug.config @@ -1282,8 +1282,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1336,6 +1336,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-x86_64-rt-debug.config b/configs/kernel-5.14.0-x86_64-rt-debug.config index 537a6df1ace9d..f9ad603f4dab8 100644 --- a/configs/kernel-5.14.0-x86_64-rt-debug.config +++ b/configs/kernel-5.14.0-x86_64-rt-debug.config @@ -1282,8 +1282,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1336,6 +1336,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-x86_64-rt.config b/configs/kernel-5.14.0-x86_64-rt.config index 5a8eaaa847058..6f00bdbf8322a 100644 --- a/configs/kernel-5.14.0-x86_64-rt.config +++ b/configs/kernel-5.14.0-x86_64-rt.config @@ -1279,8 +1279,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1333,6 +1333,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-5.14.0-x86_64.config b/configs/kernel-5.14.0-x86_64.config index 24116f549bc30..bd11b1b23a6a7 100644 --- a/configs/kernel-5.14.0-x86_64.config +++ b/configs/kernel-5.14.0-x86_64.config @@ -1278,8 +1278,8 @@ CONFIG_IP_PIMSM_V2=y CONFIG_SYN_COOKIES=y CONFIG_NET_IPVTI=m CONFIG_NET_UDP_TUNNEL=m -# CONFIG_NET_FOU is not set -# CONFIG_NET_FOU_IP_TUNNELS is not set +CONFIG_NET_FOU=m +CONFIG_NET_FOU_IP_TUNNELS=y CONFIG_INET_AH=m CONFIG_INET_ESP=m CONFIG_INET_ESP_OFFLOAD=m @@ -1332,6 +1332,8 @@ CONFIG_IPV6_SIT_6RD=y CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m CONFIG_IPV6_GRE=m +CONFIG_IPV6_FOU=m +CONFIG_IPV6_FOU_TUNNEL=m CONFIG_IPV6_MULTIPLE_TABLES=y # CONFIG_IPV6_SUBTREES is not set CONFIG_IPV6_MROUTE=y diff --git a/configs/kernel-aarch64-64k-debug-rhel.config b/configs/kernel-aarch64-64k-debug-rhel.config index 2a996aed8966a..7d4db19474dda 100644 --- a/configs/kernel-aarch64-64k-debug-rhel.config +++ b/configs/kernel-aarch64-64k-debug-rhel.config @@ -3934,8 +3934,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-64k-rhel.config b/configs/kernel-aarch64-64k-rhel.config index 2bf130311bbfc..1283e67ee3f7b 100644 --- a/configs/kernel-aarch64-64k-rhel.config +++ b/configs/kernel-aarch64-64k-rhel.config @@ -3913,8 +3913,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-debug-rhel.config b/configs/kernel-aarch64-debug-rhel.config index da59c4daefce4..e9f0d381f9a7a 100644 --- a/configs/kernel-aarch64-debug-rhel.config +++ b/configs/kernel-aarch64-debug-rhel.config @@ -3932,8 +3932,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-rhel.config b/configs/kernel-aarch64-rhel.config index 299d893226bee..b26a83fe659b7 100644 --- a/configs/kernel-aarch64-rhel.config +++ b/configs/kernel-aarch64-rhel.config @@ -3911,8 +3911,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-rt-64k-debug-rhel.config b/configs/kernel-aarch64-rt-64k-debug-rhel.config index 4cc140e73e725..f1d5eda47da98 100644 --- a/configs/kernel-aarch64-rt-64k-debug-rhel.config +++ b/configs/kernel-aarch64-rt-64k-debug-rhel.config @@ -4007,8 +4007,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-rt-64k-rhel.config b/configs/kernel-aarch64-rt-64k-rhel.config index 75303a482086b..129cd2164f578 100644 --- a/configs/kernel-aarch64-rt-64k-rhel.config +++ b/configs/kernel-aarch64-rt-64k-rhel.config @@ -3986,8 +3986,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-rt-debug-rhel.config b/configs/kernel-aarch64-rt-debug-rhel.config index 9d3d42e4d6912..f4070ab441df7 100644 --- a/configs/kernel-aarch64-rt-debug-rhel.config +++ b/configs/kernel-aarch64-rt-debug-rhel.config @@ -4005,8 +4005,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-aarch64-rt-rhel.config b/configs/kernel-aarch64-rt-rhel.config index 273e126722712..2793f45b558a4 100644 --- a/configs/kernel-aarch64-rt-rhel.config +++ b/configs/kernel-aarch64-rt-rhel.config @@ -3984,8 +3984,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-ppc64le-debug-rhel.config b/configs/kernel-ppc64le-debug-rhel.config index 1e8d5fb1efe27..a02846413886d 100644 --- a/configs/kernel-ppc64le-debug-rhel.config +++ b/configs/kernel-ppc64le-debug-rhel.config @@ -3559,8 +3559,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-ppc64le-rhel.config b/configs/kernel-ppc64le-rhel.config index ffb3ad34923f1..60e25de180301 100644 --- a/configs/kernel-ppc64le-rhel.config +++ b/configs/kernel-ppc64le-rhel.config @@ -3539,8 +3539,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-s390x-debug-rhel.config b/configs/kernel-s390x-debug-rhel.config index f4afec11a246f..f8c7a4247122f 100644 --- a/configs/kernel-s390x-debug-rhel.config +++ b/configs/kernel-s390x-debug-rhel.config @@ -3550,8 +3550,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-s390x-rhel.config b/configs/kernel-s390x-rhel.config index f74c811e652ae..b2e9d27c8b481 100644 --- a/configs/kernel-s390x-rhel.config +++ b/configs/kernel-s390x-rhel.config @@ -3530,8 +3530,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-s390x-zfcpdump-rhel.config b/configs/kernel-s390x-zfcpdump-rhel.config index 41f013b88959e..7e1f33a503dfb 100644 --- a/configs/kernel-s390x-zfcpdump-rhel.config +++ b/configs/kernel-s390x-zfcpdump-rhel.config @@ -3542,8 +3542,8 @@ CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y # CONFIG_NETFS_SUPPORT is not set CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-x86_64-debug-rhel.config b/configs/kernel-x86_64-debug-rhel.config index 77b391b9d43f3..bcff13948f384 100644 --- a/configs/kernel-x86_64-debug-rhel.config +++ b/configs/kernel-x86_64-debug-rhel.config @@ -3790,8 +3790,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-x86_64-rhel.config b/configs/kernel-x86_64-rhel.config index d15a210df8fbe..81d63c0cc4f1c 100644 --- a/configs/kernel-x86_64-rhel.config +++ b/configs/kernel-x86_64-rhel.config @@ -3770,8 +3770,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-x86_64-rt-debug-rhel.config b/configs/kernel-x86_64-rt-debug-rhel.config index b522df4754adc..f895e1c9b78c7 100644 --- a/configs/kernel-x86_64-rt-debug-rhel.config +++ b/configs/kernel-x86_64-rt-debug-rhel.config @@ -3861,8 +3861,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/kernel-x86_64-rt-rhel.config b/configs/kernel-x86_64-rt-rhel.config index 407374b0fd2b1..41141176f9aa1 100644 --- a/configs/kernel-x86_64-rt-rhel.config +++ b/configs/kernel-x86_64-rt-rhel.config @@ -3841,8 +3841,8 @@ CONFIG_NETFILTER_XT_TARGET_TEE=m CONFIG_NETFILTER_XT_TARGET_TPROXY=m CONFIG_NETFILTER_XT_TARGET_TRACE=m CONFIG_NETFILTER=y -# CONFIG_NET_FOU_IP_TUNNELS is not set -# CONFIG_NET_FOU is not set +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_NET_FOU=m CONFIG_NETFS_STATS=y CONFIG_NETFS_SUPPORT=m CONFIG_NET_HANDSHAKE_KUNIT_TEST=m diff --git a/configs/mod-extra.list b/configs/mod-extra.list index f9ec7eb96e42a..c63247ed3a599 100644 --- a/configs/mod-extra.list +++ b/configs/mod-extra.list @@ -47,6 +47,8 @@ ems_pci.ko ems_usb.ko esd_usb2.ko esi-sir.ko +fou.ko +fou6.ko gamecon.ko gf2k.ko gigaset.ko diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 64944f601ee5a..904199ddd1781 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -128,18 +128,29 @@ dpll_msg_add_mode_supported(struct sk_buff *msg, struct dpll_device *dpll, struct netlink_ext_ack *extack) { const struct dpll_device_ops *ops = dpll_device_ops(dpll); + DECLARE_BITMAP(modes, DPLL_MODE_MAX + 1) = { 0 }; enum dpll_mode mode; int ret; - /* No mode change is supported now, so the only supported mode is the - * one obtained by mode_get(). - */ + if (ops->supported_modes_get) { + ret = ops->supported_modes_get(dpll, dpll_priv(dpll), modes, + extack); + if (ret) + return ret; + } else { + /* If the supported modes are not reported by the driver, the + * only supported mode is the one obtained by mode_get(). + */ + ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack); + if (ret) + return ret; - ret = ops->mode_get(dpll, dpll_priv(dpll), &mode, extack); - if (ret) - return ret; - if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode)) - return -EMSGSIZE; + __set_bit(mode, modes); + } + + for_each_set_bit(mode, modes, DPLL_MODE_MAX + 1) + if (nla_put_u32(msg, DPLL_A_MODE_SUPPORTED, mode)) + return -EMSGSIZE; return 0; } @@ -378,7 +389,15 @@ static int dpll_msg_add_ffo(struct sk_buff *msg, struct dpll_pin *pin, return 0; return ret; } - return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, ffo); + /* Put the FFO value in PPM to preserve compatibility with older + * programs. + */ + ret = nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET, + div_s64(ffo, 1000000)); + if (ret) + return -EMSGSIZE; + return nla_put_sint(msg, DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, + ffo); } static int @@ -842,6 +861,45 @@ int dpll_pin_change_ntf(struct dpll_pin *pin) } EXPORT_SYMBOL_GPL(dpll_pin_change_ntf); +static int +dpll_mode_set(struct dpll_device *dpll, struct nlattr *a, + struct netlink_ext_ack *extack) +{ + const struct dpll_device_ops *ops = dpll_device_ops(dpll); + DECLARE_BITMAP(modes, DPLL_MODE_MAX + 1) = { 0 }; + enum dpll_mode mode = nla_get_u32(a), old_mode; + int ret; + + if (!(ops->mode_set && ops->supported_modes_get)) { + NL_SET_ERR_MSG_ATTR(extack, a, + "dpll device does not support mode switch"); + return -EOPNOTSUPP; + } + + ret = ops->mode_get(dpll, dpll_priv(dpll), &old_mode, extack); + if (ret) { + NL_SET_ERR_MSG(extack, "unable to get current mode"); + return ret; + } + + if (mode == old_mode) + return 0; + + ret = ops->supported_modes_get(dpll, dpll_priv(dpll), modes, extack); + if (ret) { + NL_SET_ERR_MSG(extack, "unable to get supported modes"); + return ret; + } + + if (!test_bit(mode, modes)) { + NL_SET_ERR_MSG(extack, + "dpll device does not support requested mode"); + return -EINVAL; + } + + return ops->mode_set(dpll, dpll_priv(dpll), mode, extack); +} + static int dpll_phase_offset_monitor_set(struct dpll_device *dpll, struct nlattr *a, struct netlink_ext_ack *extack) @@ -1797,6 +1855,11 @@ dpll_set_from_nlattr(struct dpll_device *dpll, struct genl_info *info) nla_for_each_attr(a, genlmsg_data(info->genlhdr), genlmsg_len(info->genlhdr), rem) { switch (nla_type(a)) { + case DPLL_A_MODE: + ret = dpll_mode_set(dpll, a, info->extack); + if (ret) + return ret; + break; case DPLL_A_PHASE_OFFSET_MONITOR: ret = dpll_phase_offset_monitor_set(dpll, a, info->extack); diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c index 3c6d570babf89..3fb64aab18fa3 100644 --- a/drivers/dpll/dpll_nl.c +++ b/drivers/dpll/dpll_nl.c @@ -44,6 +44,7 @@ static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_ID + 1] = { /* DPLL_CMD_DEVICE_SET - do */ static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_PHASE_OFFSET_AVG_FACTOR + 1] = { [DPLL_A_ID] = { .type = NLA_U32, }, + [DPLL_A_MODE] = NLA_POLICY_RANGE(NLA_U32, 1, 2), [DPLL_A_PHASE_OFFSET_MONITOR] = NLA_POLICY_MAX(NLA_U32, 1), [DPLL_A_PHASE_OFFSET_AVG_FACTOR] = { .type = NLA_U32, }, }; diff --git a/drivers/dpll/zl3073x/core.c b/drivers/dpll/zl3073x/core.c index 986fb2eada843..60bf70f3c2826 100644 --- a/drivers/dpll/zl3073x/core.c +++ b/drivers/dpll/zl3073x/core.c @@ -710,8 +710,11 @@ zl3073x_ref_ffo_update(struct zl3073x_dev *zldev) if (rc) return rc; - /* Convert to ppm -> ffo = (10^6 * value) / 2^32 */ - zldev->ref[i].ffo = mul_s64_u64_shr(value, 1000000, 32); + /* Convert to ppt + * ffo = (10^12 * value) / 2^32 + * ffo = ( 5^12 * value) / 2^20 + */ + zldev->ref[i].ffo = mul_s64_u64_shr(value, 244140625, 20); } return 0; diff --git a/drivers/dpll/zl3073x/dpll.c b/drivers/dpll/zl3073x/dpll.c index 9879d85d29af0..7d8ed948b9706 100644 --- a/drivers/dpll/zl3073x/dpll.c +++ b/drivers/dpll/zl3073x/dpll.c @@ -100,6 +100,20 @@ zl3073x_dpll_pin_direction_get(const struct dpll_pin *dpll_pin, void *pin_priv, return 0; } +static struct zl3073x_dpll_pin * +zl3073x_dpll_pin_get_by_ref(struct zl3073x_dpll *zldpll, u8 ref_id) +{ + struct zl3073x_dpll_pin *pin; + + list_for_each_entry(pin, &zldpll->pins, list) { + if (zl3073x_dpll_is_input_pin(pin) && + zl3073x_input_pin_ref_get(pin->id) == ref_id) + return pin; + } + + return NULL; +} + static int zl3073x_dpll_input_pin_esync_get(const struct dpll_pin *dpll_pin, void *pin_priv, @@ -1137,6 +1151,26 @@ zl3073x_dpll_lock_status_get(const struct dpll_device *dpll, void *dpll_priv, return 0; } +static int +zl3073x_dpll_supported_modes_get(const struct dpll_device *dpll, + void *dpll_priv, unsigned long *modes, + struct netlink_ext_ack *extack) +{ + struct zl3073x_dpll *zldpll = dpll_priv; + + /* We support switching between automatic and manual mode, except in + * a case where the DPLL channel is configured to run in NCO mode. + * In this case, report only the manual mode to which the NCO is mapped + * as the only supported one. + */ + if (zldpll->refsel_mode != ZL_DPLL_MODE_REFSEL_MODE_NCO) + __set_bit(DPLL_MODE_AUTOMATIC, modes); + + __set_bit(DPLL_MODE_MANUAL, modes); + + return 0; +} + static int zl3073x_dpll_mode_get(const struct dpll_device *dpll, void *dpll_priv, enum dpll_mode *mode, struct netlink_ext_ack *extack) @@ -1217,6 +1251,82 @@ zl3073x_dpll_phase_offset_avg_factor_set(const struct dpll_device *dpll, return 0; } +static int +zl3073x_dpll_mode_set(const struct dpll_device *dpll, void *dpll_priv, + enum dpll_mode mode, struct netlink_ext_ack *extack) +{ + struct zl3073x_dpll *zldpll = dpll_priv; + u8 hw_mode, mode_refsel, ref; + int rc; + + rc = zl3073x_dpll_selected_ref_get(zldpll, &ref); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, "failed to get selected reference"); + return rc; + } + + if (mode == DPLL_MODE_MANUAL) { + /* We are switching from automatic to manual mode: + * - if we have a valid reference selected during auto mode then + * we will switch to forced reference lock mode and use this + * reference for selection + * - if NO valid reference is selected, we will switch to forced + * holdover mode or freerun mode, depending on the current + * lock status + */ + if (ZL3073X_DPLL_REF_IS_VALID(ref)) + hw_mode = ZL_DPLL_MODE_REFSEL_MODE_REFLOCK; + else if (zldpll->lock_status == DPLL_LOCK_STATUS_UNLOCKED) + hw_mode = ZL_DPLL_MODE_REFSEL_MODE_FREERUN; + else + hw_mode = ZL_DPLL_MODE_REFSEL_MODE_HOLDOVER; + } else { + /* We are switching from manual to automatic mode: + * - if there is a valid reference selected then ensure that + * it is selectable after switch to automatic mode + * - switch to automatic mode + */ + struct zl3073x_dpll_pin *pin; + + pin = zl3073x_dpll_pin_get_by_ref(zldpll, ref); + if (pin && !pin->selectable) { + /* Restore pin priority in HW */ + rc = zl3073x_dpll_ref_prio_set(pin, pin->prio); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, + "failed to restore pin priority"); + return rc; + } + + pin->selectable = true; + } + + hw_mode = ZL_DPLL_MODE_REFSEL_MODE_AUTO; + } + + /* Build mode_refsel value */ + mode_refsel = FIELD_PREP(ZL_DPLL_MODE_REFSEL_MODE, hw_mode); + + if (ZL3073X_DPLL_REF_IS_VALID(ref)) + mode_refsel |= FIELD_PREP(ZL_DPLL_MODE_REFSEL_REF, ref); + + /* Update dpll_mode_refsel register */ + rc = zl3073x_write_u8(zldpll->dev, ZL_REG_DPLL_MODE_REFSEL(zldpll->id), + mode_refsel); + if (rc) { + NL_SET_ERR_MSG_MOD(extack, + "failed to set reference selection mode"); + return rc; + } + + zldpll->refsel_mode = hw_mode; + + if (ZL3073X_DPLL_REF_IS_VALID(ref)) + zldpll->forced_ref = ref; + + return 0; +} + static int zl3073x_dpll_phase_offset_monitor_get(const struct dpll_device *dpll, void *dpll_priv, @@ -1276,10 +1386,12 @@ static const struct dpll_pin_ops zl3073x_dpll_output_pin_ops = { static const struct dpll_device_ops zl3073x_dpll_device_ops = { .lock_status_get = zl3073x_dpll_lock_status_get, .mode_get = zl3073x_dpll_mode_get, + .mode_set = zl3073x_dpll_mode_set, .phase_offset_avg_factor_get = zl3073x_dpll_phase_offset_avg_factor_get, .phase_offset_avg_factor_set = zl3073x_dpll_phase_offset_avg_factor_set, .phase_offset_monitor_get = zl3073x_dpll_phase_offset_monitor_get, .phase_offset_monitor_set = zl3073x_dpll_phase_offset_monitor_set, + .supported_modes_get = zl3073x_dpll_supported_modes_get, }; /** diff --git a/drivers/net/ethernet/intel/i40e/i40e_devlink.c b/drivers/net/ethernet/intel/i40e/i40e_devlink.c index 342b35e124cb0..ca82ad166390f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_devlink.c +++ b/drivers/net/ethernet/intel/i40e/i40e_devlink.c @@ -5,6 +5,10 @@ #include "i40e.h" #include "i40e_devlink.h" +/* RHEL-specific opt-in to expose "phys_port_name" in sysfs to match upstream behavior. */ +static int rh_phys_port_name; +module_param(rh_phys_port_name, int, 0644); + static void i40e_info_get_dsn(struct i40e_pf *pf, char *buf, size_t len) { u8 dsn[8]; @@ -229,7 +233,7 @@ int i40e_devlink_create_port(struct i40e_pf *pf) **/ struct devlink_port *i40e_get_devlink_port(struct net_device *netdev) { - return NULL; + return rh_phys_port_name ? netdev->devlink_port : NULL; } /** diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index f81c5dcbe9d39..27fdbc2bbb821 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -49,6 +49,10 @@ MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all), hw debug_mask (0x8XXXX MODULE_PARM_DESC(debug, "netif level (0=none,...,16=all)"); #endif /* !CONFIG_DYNAMIC_DEBUG */ +/* RHEL-only opt-in to expose "phys_port_name" in sysfs */ +static int rh_phys_port_name; +module_param(rh_phys_port_name, int, 0644); + DEFINE_STATIC_KEY_FALSE(ice_xdp_locking_key); EXPORT_SYMBOL(ice_xdp_locking_key); @@ -321,6 +325,9 @@ static struct devlink_port *ice_get_devlink_port(struct net_device *netdev) { struct ice_pf *pf = ice_netdev_to_pf(netdev); + if (rh_phys_port_name) + return netdev->devlink_port; + if (!ice_is_switchdev_running(pf)) return NULL; @@ -3401,18 +3408,20 @@ static irqreturn_t ice_misc_intr_thread_fn(int __always_unused irq, void *data) if (ice_is_reset_in_progress(pf->state)) goto skip_irq; - if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) { - /* Process outstanding Tx timestamps. If there is more work, - * re-arm the interrupt to trigger again. - */ - if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) { - wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); - ice_flush(hw); - } - } + if (test_and_clear_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread)) + ice_ptp_process_ts(pf); skip_irq: ice_irq_dynamic_ena(hw, NULL, NULL); + ice_flush(hw); + + if (ice_ptp_tx_tstamps_pending(pf)) { + /* If any new Tx timestamps happened while in interrupt, + * re-arm the interrupt to trigger it again. + */ + wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M); + ice_flush(hw); + } return IRQ_HANDLED; } diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c index 0f94dd4dec8e6..9b247304f1416 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.c +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c @@ -666,6 +666,9 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) pf = ptp_port_to_pf(ptp_port); hw = &pf->hw; + if (!tx->init) + return; + /* Read the Tx ready status first */ if (tx->has_ready_bitmap) { err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready); @@ -762,14 +765,9 @@ static void ice_ptp_process_tx_tstamp(struct ice_ptp_tx *tx) } } -/** - * ice_ptp_tx_tstamp_owner - Process Tx timestamps for all ports on the device - * @pf: Board private structure - */ -static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) +static void ice_ptp_tx_tstamp_owner(struct ice_pf *pf) { struct ice_ptp_port *port; - unsigned int i; mutex_lock(&pf->adapter->ports.lock); list_for_each_entry(port, &pf->adapter->ports.ports, list_node) { @@ -781,49 +779,6 @@ static enum ice_tx_tstamp_work ice_ptp_tx_tstamp_owner(struct ice_pf *pf) ice_ptp_process_tx_tstamp(tx); } mutex_unlock(&pf->adapter->ports.lock); - - for (i = 0; i < ICE_GET_QUAD_NUM(pf->hw.ptp.num_lports); i++) { - u64 tstamp_ready; - int err; - - /* Read the Tx ready status first */ - err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); - if (err) - break; - else if (tstamp_ready) - return ICE_TX_TSTAMP_WORK_PENDING; - } - - return ICE_TX_TSTAMP_WORK_DONE; -} - -/** - * ice_ptp_tx_tstamp - Process Tx timestamps for this function. - * @tx: Tx tracking structure to initialize - * - * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding incomplete - * Tx timestamps, or ICE_TX_TSTAMP_WORK_DONE otherwise. - */ -static enum ice_tx_tstamp_work ice_ptp_tx_tstamp(struct ice_ptp_tx *tx) -{ - bool more_timestamps; - unsigned long flags; - - if (!tx->init) - return ICE_TX_TSTAMP_WORK_DONE; - - /* Process the Tx timestamp tracker */ - ice_ptp_process_tx_tstamp(tx); - - /* Check if there are outstanding Tx timestamps */ - spin_lock_irqsave(&tx->lock, flags); - more_timestamps = tx->init && !bitmap_empty(tx->in_use, tx->len); - spin_unlock_irqrestore(&tx->lock, flags); - - if (more_timestamps) - return ICE_TX_TSTAMP_WORK_PENDING; - - return ICE_TX_TSTAMP_WORK_DONE; } /** @@ -2837,30 +2792,92 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb) return idx + tx->offset; } -/** - * ice_ptp_process_ts - Process the PTP Tx timestamps - * @pf: Board private structure - * - * Returns: ICE_TX_TSTAMP_WORK_PENDING if there are any outstanding Tx - * timestamps that need processing, and ICE_TX_TSTAMP_WORK_DONE otherwise. - */ -enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf) +void ice_ptp_process_ts(struct ice_pf *pf) { switch (pf->ptp.tx_interrupt_mode) { case ICE_PTP_TX_INTERRUPT_NONE: /* This device has the clock owner handle timestamps for it */ - return ICE_TX_TSTAMP_WORK_DONE; + return; case ICE_PTP_TX_INTERRUPT_SELF: /* This device handles its own timestamps */ - return ice_ptp_tx_tstamp(&pf->ptp.port.tx); + ice_ptp_process_tx_tstamp(&pf->ptp.port.tx); + return; case ICE_PTP_TX_INTERRUPT_ALL: /* This device handles timestamps for all ports */ - return ice_ptp_tx_tstamp_owner(pf); + ice_ptp_tx_tstamp_owner(pf); + return; + default: + WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n", + pf->ptp.tx_interrupt_mode); + return; + } +} + +static bool ice_port_has_timestamps(struct ice_ptp_tx *tx) +{ + bool more_timestamps; + + scoped_guard(spinlock_irqsave, &tx->lock) { + if (!tx->init) + return false; + + more_timestamps = !bitmap_empty(tx->in_use, tx->len); + } + + return more_timestamps; +} + +static bool ice_any_port_has_timestamps(struct ice_pf *pf) +{ + struct ice_ptp_port *port; + + scoped_guard(mutex, &pf->adapter->ports.lock) { + list_for_each_entry(port, &pf->adapter->ports.ports, + list_node) { + struct ice_ptp_tx *tx = &port->tx; + + if (ice_port_has_timestamps(tx)) + return true; + } + } + + return false; +} + +bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf) +{ + struct ice_hw *hw = &pf->hw; + unsigned int i; + + /* Check software indicator */ + switch (pf->ptp.tx_interrupt_mode) { + case ICE_PTP_TX_INTERRUPT_NONE: + return false; + case ICE_PTP_TX_INTERRUPT_SELF: + if (ice_port_has_timestamps(&pf->ptp.port.tx)) + return true; + break; + case ICE_PTP_TX_INTERRUPT_ALL: + if (ice_any_port_has_timestamps(pf)) + return true; + break; default: WARN_ONCE(1, "Unexpected Tx timestamp interrupt mode %u\n", pf->ptp.tx_interrupt_mode); - return ICE_TX_TSTAMP_WORK_DONE; + break; + } + + /* Check hardware indicator */ + for (i = 0; i < ICE_GET_QUAD_NUM(hw->ptp.num_lports); i++) { + u64 tstamp_ready = 0; + int err; + + err = ice_get_phy_tx_tstamp_ready(&pf->hw, i, &tstamp_ready); + if (err || tstamp_ready) + return true; } + + return false; } /** @@ -2912,7 +2929,9 @@ irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf) return IRQ_WAKE_THREAD; case ICE_MAC_E830: /* E830 can read timestamps in the top half using rd32() */ - if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) { + ice_ptp_process_ts(pf); + + if (ice_ptp_tx_tstamps_pending(pf)) { /* Process outstanding Tx timestamps. If there * is more work, re-arm the interrupt to trigger again. */ @@ -3365,8 +3384,9 @@ static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf) { switch (pf->hw.mac_type) { case ICE_MAC_GENERIC: - /* E822 based PHY has the clock owner process the interrupt - * for all ports. + case ICE_MAC_GENERIC_3K_E825: + /* E82x hardware has the clock owner process timestamps for + * all ports. */ if (ice_pf_src_tmr_owned(pf)) pf->ptp.tx_interrupt_mode = ICE_PTP_TX_INTERRUPT_ALL; diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h index 3b769a0cad00d..ef281509ae70b 100644 --- a/drivers/net/ethernet/intel/ice/ice_ptp.h +++ b/drivers/net/ethernet/intel/ice/ice_ptp.h @@ -302,8 +302,9 @@ void ice_ptp_extts_event(struct ice_pf *pf); s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb); void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx); void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx); -enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf); +void ice_ptp_process_ts(struct ice_pf *pf); irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf); +bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf); u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts); @@ -339,16 +340,18 @@ static inline void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx) static inline void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx) { } -static inline bool ice_ptp_process_ts(struct ice_pf *pf) -{ - return true; -} +static inline void ice_ptp_process_ts(struct ice_pf *pf) { } static inline irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf) { return IRQ_HANDLED; } +static inline bool ice_ptp_tx_tstamps_pending(struct ice_pf *pf) +{ + return false; +} + static inline u64 ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c index 1e5522a194839..3ea8a1766ae28 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dpll.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dpll.c @@ -136,7 +136,7 @@ mlx5_dpll_pin_ffo_get(struct mlx5_dpll_synce_status *synce_status, { if (!synce_status->oper_freq_measure) return -ENODATA; - *ffo = synce_status->frequency_diff; + *ffo = 1000000LL * synce_status->frequency_diff; return 0; } diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c index 10431a67d202b..f43969ed87bf9 100644 --- a/drivers/scsi/qla2xxx/qla_bsg.c +++ b/drivers/scsi/qla2xxx/qla_bsg.c @@ -1546,8 +1546,9 @@ qla2x00_update_optrom(struct bsg_job *bsg_job) ha->optrom_buffer = NULL; ha->optrom_state = QLA_SWAITING; mutex_unlock(&ha->optrom_mutex); - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!rval) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return rval; } @@ -2612,8 +2613,9 @@ qla2x00_manage_host_stats(struct bsg_job *bsg_job) sizeof(struct ql_vnd_mng_host_stats_resp)); bsg_reply->result = DID_OK; - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!ret) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return ret; } @@ -2702,8 +2704,9 @@ qla2x00_get_host_stats(struct bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, data, response_len); bsg_reply->result = DID_OK; - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!ret) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); kfree(data); host_stat_out: @@ -2802,8 +2805,9 @@ qla2x00_get_tgt_stats(struct bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, data, response_len); bsg_reply->result = DID_OK; - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!ret) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); tgt_stat_out: kfree(data); @@ -2864,8 +2868,9 @@ qla2x00_manage_host_port(struct bsg_job *bsg_job) bsg_job->reply_payload.sg_cnt, &rsp_data, sizeof(struct ql_vnd_mng_host_port_resp)); bsg_reply->result = DID_OK; - bsg_job_done(bsg_job, bsg_reply->result, - bsg_reply->reply_payload_rcv_len); + if (!ret) + bsg_job_done(bsg_job, bsg_reply->result, + bsg_reply->reply_payload_rcv_len); return ret; } @@ -3240,7 +3245,8 @@ int qla2x00_mailbox_passthru(struct bsg_job *bsg_job) bsg_job->reply_len = sizeof(*bsg_job->reply); bsg_reply->result = DID_OK << 16; - bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); + if (!ret) + bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len); kfree(req_data); diff --git a/fs/autofs/autofs_i.h b/fs/autofs/autofs_i.h index 8026f44a107e0..e8bd2b6283aa5 100644 --- a/fs/autofs/autofs_i.h +++ b/fs/autofs/autofs_i.h @@ -16,6 +16,8 @@ #include #include #include +#include +#include #include #include #include @@ -25,6 +27,8 @@ #include #include #include +#include "../mount.h" +#include /* This is the range of ioctl() numbers we claim as ours */ #define AUTOFS_IOC_FIRST AUTOFS_IOC_READY @@ -112,6 +116,7 @@ struct autofs_sb_info { int pipefd; struct file *pipe; struct pid *oz_pgrp; + u64 mnt_ns_id; int version; int sub_version; int min_proto; diff --git a/fs/autofs/dev-ioctl.c b/fs/autofs/dev-ioctl.c index 6d57efbb81102..91a206353e6f2 100644 --- a/fs/autofs/dev-ioctl.c +++ b/fs/autofs/dev-ioctl.c @@ -381,6 +381,7 @@ static int autofs_dev_ioctl_setpipefd(struct file *fp, swap(sbi->oz_pgrp, new_pid); sbi->pipefd = pipefd; sbi->pipe = pipe; + sbi->mnt_ns_id = current->nsproxy->mnt_ns->seq; sbi->flags &= ~AUTOFS_SBI_CATATONIC; } out: diff --git a/fs/autofs/inode.c b/fs/autofs/inode.c index 49b34730e7b99..76b974503d2ce 100644 --- a/fs/autofs/inode.c +++ b/fs/autofs/inode.c @@ -239,6 +239,7 @@ int autofs_fill_super(struct super_block *s, void *data, int silent) s->s_fs_info = sbi; sbi->magic = AUTOFS_SBI_MAGIC; sbi->pipefd = -1; + sbi->mnt_ns_id = current->nsproxy->mnt_ns->seq; sbi->pipe = NULL; sbi->exp_timeout = 0; sbi->oz_pgrp = NULL; diff --git a/fs/autofs/root.c b/fs/autofs/root.c index 6baf90b08e0ef..ad294a98e6d09 100644 --- a/fs/autofs/root.c +++ b/fs/autofs/root.c @@ -341,6 +341,14 @@ static struct vfsmount *autofs_d_automount(struct path *path) if (autofs_oz_mode(sbi)) return NULL; + /* Refuse to trigger mount if current namespace is not the owner + * and the mount is propagation private. + */ + if (sbi->mnt_ns_id != current->nsproxy->mnt_ns->seq) { + if (vfsmount_to_propagation_flags(path->mnt) & MS_PRIVATE) + return ERR_PTR(-EPERM); + } + /* * If an expire request is pending everyone must wait. * If the expire fails we're still mounted so continue diff --git a/fs/namespace.c b/fs/namespace.c index faa8e1bff7c91..1169a95300ddf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -4278,6 +4278,27 @@ SYSCALL_DEFINE5(mount_setattr, int, dfd, const char __user *, path, return err; } +static u64 mnt_to_propagation_flags(struct mount *m) +{ + u64 propagation = 0; + + if (IS_MNT_SHARED(m)) + propagation |= MS_SHARED; + if (IS_MNT_SLAVE(m)) + propagation |= MS_SLAVE; + if (IS_MNT_UNBINDABLE(m)) + propagation |= MS_UNBINDABLE; + if (!propagation) + propagation |= MS_PRIVATE; + + return propagation; +} + +u64 vfsmount_to_propagation_flags(struct vfsmount *mnt) +{ + return mnt_to_propagation_flags(real_mount(mnt)); +} + static void __init init_mount_tree(void) { struct vfsmount *mnt; diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 9ad2d62e16ba4..b2c2bf0b2506b 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -47,8 +47,11 @@ struct dpll_device_ops { RH_KABI_USE(2, int (*phase_offset_avg_factor_get)(const struct dpll_device *dpll, void *dpll_priv, u32 *factor, struct netlink_ext_ack *extack)) - RH_KABI_RESERVE(3) - RH_KABI_RESERVE(4) + RH_KABI_USE(3, int (*supported_modes_get)(const struct dpll_device *dpll, + void *dpll_priv, unsigned long *modes, + struct netlink_ext_ack *extack)) + RH_KABI_USE(4, int (*mode_set)(const struct dpll_device *dpll, void *dpll_priv, + enum dpll_mode mode, struct netlink_ext_ack *extack)) RH_KABI_RESERVE(5) RH_KABI_RESERVE(6) RH_KABI_RESERVE(7) diff --git a/include/linux/fs.h b/include/linux/fs.h index 53cf26162c5de..d02f204c7eb91 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2808,6 +2808,7 @@ extern struct file * open_exec(const char *); /* fs/dcache.c -- generic fs support functions */ extern bool is_subdir(struct dentry *, struct dentry *); extern bool path_is_under(const struct path *, const struct path *); +u64 vfsmount_to_propagation_flags(struct vfsmount *mnt); extern char *file_path(struct file *, char *, int); diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index 69d35570ac4f1..603a88cb665f9 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -252,6 +252,7 @@ enum dpll_a_pin { DPLL_A_PIN_ESYNC_PULSE, DPLL_A_PIN_REFERENCE_SYNC, DPLL_A_PIN_PHASE_ADJUST_GRAN, + DPLL_A_PIN_FRACTIONAL_FREQUENCY_OFFSET_PPT, __DPLL_A_PIN_MAX, DPLL_A_PIN_MAX = (__DPLL_A_PIN_MAX - 1) diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index 5205373652e98..94d964a8b952b 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -181,6 +181,27 @@ static ktime_t tick_init_jiffy_update(void) return period; } +/* + * Allow only one non-timekeeper CPU at a time update jiffies from + * the timer tick. + * + * Returns true if update was run. + */ +static bool tick_limited_update_jiffies64(struct tick_sched *ts, ktime_t now) +{ + static atomic_t in_progress; + int inp; + + inp = atomic_read(&in_progress); + if (inp || !atomic_try_cmpxchg(&in_progress, &inp, 1)) + return false; + + if (ts->last_tick_jiffies == jiffies) + tick_do_update_jiffies64(now); + atomic_set(&in_progress, 0); + return true; +} + #define MAX_STALLED_JIFFIES 5 static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now) @@ -218,10 +239,11 @@ static void tick_sched_do_timer(struct tick_sched *ts, ktime_t now) ts->stalled_jiffies = 0; ts->last_tick_jiffies = READ_ONCE(jiffies); } else { - if (++ts->stalled_jiffies == MAX_STALLED_JIFFIES) { - tick_do_update_jiffies64(now); - ts->stalled_jiffies = 0; - ts->last_tick_jiffies = READ_ONCE(jiffies); + if (++ts->stalled_jiffies >= MAX_STALLED_JIFFIES) { + if (tick_limited_update_jiffies64(ts, now)) { + ts->stalled_jiffies = 0; + ts->last_tick_jiffies = READ_ONCE(jiffies); + } } } diff --git a/mm/migrate.c b/mm/migrate.c index 41df98b69c80f..1da730c8222f8 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -1383,6 +1383,7 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, int page_was_mapped = 0; struct anon_vma *anon_vma = NULL; struct address_space *mapping = NULL; + enum ttu_flags ttu = 0; if (folio_ref_count(src) == 1) { /* page was freed from under us. So we are done. */ @@ -1424,8 +1425,6 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, goto put_anon; if (folio_mapped(src)) { - enum ttu_flags ttu = 0; - if (!folio_test_anon(src)) { /* * In shared mappings, try_to_unmap could potentially @@ -1442,9 +1441,6 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, try_to_migrate(src, ttu); page_was_mapped = 1; - - if (ttu & TTU_RMAP_LOCKED) - i_mmap_unlock_write(mapping); } if (!folio_mapped(src)) @@ -1452,7 +1448,11 @@ static int unmap_and_move_huge_page(new_folio_t get_new_folio, if (page_was_mapped) remove_migration_ptes(src, - rc == MIGRATEPAGE_SUCCESS ? dst : src, false); + rc == MIGRATEPAGE_SUCCESS ? dst : src, + ttu ? true : false); + + if (ttu & TTU_RMAP_LOCKED) + i_mmap_unlock_write(mapping); unlock_put_anon: folio_unlock(dst); diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 87983e70f03f3..e983bb0c50127 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig @@ -321,7 +321,6 @@ config NET_UDP_TUNNEL config NET_FOU tristate "IP: Foo (IP protocols) over UDP" - select XFRM select NET_UDP_TUNNEL help Foo over UDP allows any IP protocol to be directly encapsulated diff --git a/net/ipv4/fou_core.c b/net/ipv4/fou_core.c index 9e94970e07418..7b5b898cf4c94 100644 --- a/net/ipv4/fou_core.c +++ b/net/ipv4/fou_core.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include @@ -51,7 +50,7 @@ struct fou_net { static inline struct fou *fou_from_sock(struct sock *sk) { - return sk->sk_user_data; + return rcu_dereference_sk_user_data(sk); } static int fou_recv_pull(struct sk_buff *skb, struct fou *fou, size_t len) @@ -216,6 +215,9 @@ static int gue_udp_recv(struct sock *sk, struct sk_buff *skb) return gue_control_message(skb, guehdr); proto_ctype = guehdr->proto_ctype; + if (unlikely(!proto_ctype)) + goto drop; + __skb_pull(skb, sizeof(struct udphdr) + hdrlen); skb_reset_transport_header(skb); @@ -233,10 +235,16 @@ static struct sk_buff *fou_gro_receive(struct sock *sk, struct list_head *head, struct sk_buff *skb) { - u8 proto = fou_from_sock(sk)->protocol; - const struct net_offload **offloads; + const struct net_offload __rcu **offloads; + struct fou *fou = fou_from_sock(sk); const struct net_offload *ops; struct sk_buff *pp = NULL; + u8 proto; + + if (!fou) + return NULL; + + proto = fou->protocol; /* We can clear the encap_mark for FOU as we are essentially doing * one of two possible things. We are either adding an L4 tunnel @@ -266,16 +274,24 @@ static struct sk_buff *fou_gro_receive(struct sock *sk, static int fou_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { + const struct net_offload __rcu **offloads; + struct fou *fou = fou_from_sock(sk); const struct net_offload *ops; - u8 proto = fou_from_sock(sk)->protocol; - int err = -ENOSYS; - const struct net_offload **offloads; + u8 proto; + int err; + + if (!fou) + return -ENOENT; + + proto = fou->protocol; rcu_read_lock(); offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; ops = rcu_dereference(offloads[proto]); - if (WARN_ON(!ops || !ops->callbacks.gro_complete)) + if (WARN_ON(!ops || !ops->callbacks.gro_complete)) { + err = -ENOSYS; goto out_unlock; + } err = ops->callbacks.gro_complete(skb, nhoff); @@ -314,7 +330,7 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, struct list_head *head, struct sk_buff *skb) { - const struct net_offload **offloads; + const struct net_offload __rcu **offloads; const struct net_offload *ops; struct sk_buff *pp = NULL; struct sk_buff *p; @@ -329,6 +345,9 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, skb_gro_remcsum_init(&grc); + if (!fou) + goto out; + off = skb_gro_offset(skb); len = off + sizeof(*guehdr); @@ -441,7 +460,7 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, rcu_read_lock(); offloads = NAPI_GRO_CB(skb)->is_ipv6 ? inet6_offloads : inet_offloads; ops = rcu_dereference(offloads[proto]); - if (WARN_ON_ONCE(!ops || !ops->callbacks.gro_receive)) + if (!ops || !ops->callbacks.gro_receive) goto out_unlock; pp = call_gro_receive(ops->callbacks.gro_receive, head, skb); @@ -457,8 +476,8 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, static int gue_gro_complete(struct sock *sk, struct sk_buff *skb, int nhoff) { - const struct net_offload **offloads; struct guehdr *guehdr = (struct guehdr *)(skb->data + nhoff); + const struct net_offload __rcu **offloads; const struct net_offload *ops; unsigned int guehlen = 0; u8 proto; diff --git a/net/ipv4/fou_nl.c b/net/ipv4/fou_nl.c index 98b90107b5abc..bbd955f4c9d19 100644 --- a/net/ipv4/fou_nl.c +++ b/net/ipv4/fou_nl.c @@ -14,7 +14,7 @@ const struct nla_policy fou_nl_policy[FOU_ATTR_IFINDEX + 1] = { [FOU_ATTR_PORT] = { .type = NLA_U16, }, [FOU_ATTR_AF] = { .type = NLA_U8, }, - [FOU_ATTR_IPPROTO] = { .type = NLA_U8, }, + [FOU_ATTR_IPPROTO] = NLA_POLICY_MIN(NLA_U8, 1), [FOU_ATTR_TYPE] = { .type = NLA_U8, }, [FOU_ATTR_REMCSUM_NOPARTIAL] = { .type = NLA_FLAG, }, [FOU_ATTR_LOCAL_V4] = { .type = NLA_U32, }, diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index da7a3f7d5ea60..911e475e8e4d0 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c @@ -154,8 +154,8 @@ struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, netdev_features_t features, bool is_ipv6) { + const struct net_offload __rcu **offloads; __be16 protocol = skb->protocol; - const struct net_offload **offloads; const struct net_offload *ops; struct sk_buff *segs = ERR_PTR(-EINVAL); struct sk_buff *(*gso_inner_segment)(struct sk_buff *skb, diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c index 1578ed9e97d89..201f455653639 100644 --- a/net/ipv6/calipso.c +++ b/net/ipv6/calipso.c @@ -1322,7 +1322,8 @@ static int calipso_skbuff_setattr(struct sk_buff *skb, /* At this point new_end aligns to 4n, so (new_end & 4) pads to 8n */ pad = ((new_end & 4) + (end & 7)) & 7; len_delta = new_end - (int)end + pad; - ret_val = skb_cow(skb, skb_headroom(skb) + len_delta); + ret_val = skb_cow(skb, + skb_headroom(skb) + (len_delta > 0 ? len_delta : 0)); if (ret_val < 0) return ret_val; diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c index 7afc53f1ec74e..f86161201e065 100644 --- a/net/smc/smc_clc.c +++ b/net/smc/smc_clc.c @@ -426,8 +426,6 @@ smc_clc_msg_decl_valid(struct smc_clc_msg_decline *dclc) { struct smc_clc_msg_hdr *hdr = &dclc->hdr; - if (hdr->typev1 != SMC_TYPE_R && hdr->typev1 != SMC_TYPE_D) - return false; if (hdr->version == SMC_V1) { if (ntohs(hdr->length) != sizeof(struct smc_clc_msg_decline)) return false; @@ -656,26 +654,26 @@ static int smc_clc_prfx_match6_rcu(struct net_device *dev, int smc_clc_prfx_match(struct socket *clcsock, struct smc_clc_msg_proposal_prefix *prop) { - struct dst_entry *dst = sk_dst_get(clcsock->sk); + struct net_device *dev; + struct dst_entry *dst; int rc; - if (!dst) { - rc = -ENOTCONN; - goto out; - } - if (!dst->dev) { + rcu_read_lock(); + + dst = __sk_dst_get(clcsock->sk); + dev = dst ? dst_dev_rcu(dst) : NULL; + if (!dev) { rc = -ENODEV; - goto out_rel; + goto out; } - rcu_read_lock(); + if (!prop->ipv6_prefixes_cnt) - rc = smc_clc_prfx_match4_rcu(dst->dev, prop); + rc = smc_clc_prfx_match4_rcu(dev, prop); else - rc = smc_clc_prfx_match6_rcu(dst->dev, prop); - rcu_read_unlock(); -out_rel: - dst_release(dst); + rc = smc_clc_prfx_match6_rcu(dev, prop); out: + rcu_read_unlock(); + return rc; } diff --git a/redhat/configs/common/generic/CONFIG_NET_FOU b/redhat/configs/common/generic/CONFIG_NET_FOU new file mode 100644 index 0000000000000..f78ee6d878821 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_NET_FOU @@ -0,0 +1 @@ +CONFIG_NET_FOU=m diff --git a/redhat/configs/common/generic/CONFIG_NET_FOU_IP_TUNNELS b/redhat/configs/common/generic/CONFIG_NET_FOU_IP_TUNNELS new file mode 100644 index 0000000000000..7d89b7659e6d9 --- /dev/null +++ b/redhat/configs/common/generic/CONFIG_NET_FOU_IP_TUNNELS @@ -0,0 +1 @@ +CONFIG_NET_FOU_IP_TUNNELS=y diff --git a/redhat/configs/rhel/generic/CONFIG_NET_FOU b/redhat/configs/rhel/generic/CONFIG_NET_FOU deleted file mode 100644 index 12f5c083633ab..0000000000000 --- a/redhat/configs/rhel/generic/CONFIG_NET_FOU +++ /dev/null @@ -1 +0,0 @@ -# CONFIG_NET_FOU is not set diff --git a/redhat/configs/rhel/generic/CONFIG_NET_FOU_IP_TUNNELS b/redhat/configs/rhel/generic/CONFIG_NET_FOU_IP_TUNNELS deleted file mode 100644 index b2cb0a55c7637..0000000000000 --- a/redhat/configs/rhel/generic/CONFIG_NET_FOU_IP_TUNNELS +++ /dev/null @@ -1 +0,0 @@ -# CONFIG_NET_FOU_IP_TUNNELS is not set diff --git a/redhat/kernel.changelog-9.7 b/redhat/kernel.changelog-9.7 index f431471a80aee..c7aee9685e383 100644 --- a/redhat/kernel.changelog-9.7 +++ b/redhat/kernel.changelog-9.7 @@ -1,3 +1,31 @@ +* Tue Feb 24 2026 CKI KWF Bot [5.14.0-611.36.1.el9_7] +- net/smc: Remove validation of reserved bits in CLC Decline message (Mete Durlu) [RHEL-143718] +- autofs: dont trigger mount if it cant succeed (Ian Kent) [RHEL-149495] +- migrate: correct lock ordering for hugetlb file folios (Luiz Capitulino) [RHEL-147266] {CVE-2026-23097} +- ice: PTP: fix missing timestamps on E825 hardware (CKI Backport Bot) [RHEL-148166] +- fou: Don't allow 0 for FOU_ATTR_IPPROTO. (Xin Long) [RHEL-144987] +- tools: ynl: Specify --no-line-number in ynl-regen.sh. (Xin Long) [RHEL-144987] +- gue: Fix skb memleak with inner IP protocol 0. (Xin Long) [RHEL-144987] +- netlink: specs: fou: replace underscores with dashes in names (Xin Long) [RHEL-144987] +- fou: fix initialization of grc (Xin Long) [RHEL-144987] +- fou: Fix null-ptr-deref in GRO. (Xin Long) [RHEL-144987] +- fou: remove warn in gue_gro_receive on unsupported protocol (Xin Long) [RHEL-144987] +- fou: Remove XRFM from NET_FOU Kconfig (Xin Long) [RHEL-144987] +- fou: remove sparse errors (Xin Long) [RHEL-144987] +- redhat: enable FOU modules in kernel-modules-extra (Xin Long) [RHEL-144987] +- s390/mm: Fix __ptep_rdp() inline assembly (Mete Durlu) [RHEL-143713] +- dpll: expose fractional frequency offset in ppt (Ivan Vecera) [RHEL-146357] +- dpll: zl3073x: Implement device mode setting support (Ivan Vecera) [RHEL-147459] +- dpll: add dpll_device op to set working mode (Ivan Vecera) [RHEL-147459] +- dpll: add dpll_device op to get supported modes (Ivan Vecera) [RHEL-147459] +- i40e: add rh_phys_port_name mod option to behave like upstream (CKI Backport Bot) [RHEL-128237] +- ice: add rh_phys_port_name mod option to behave like upstream (CKI Backport Bot) [RHEL-128237] +- scsi: qla2xxx: Fix bsg_done() causing double free (Ewan D. Milne) [RHEL-146049] +- ipv6: BUG() in pskb_expand_head() as part of calipso_skbuff_setattr() (CKI Backport Bot) [RHEL-143545] {CVE-2025-71085} +- tick/sched: Limit non-timekeeper CPUs calling jiffies update (Phil Auld) [RHEL-141462] +- smc: Use __sk_dst_get() and dst_dev_rcu() in smc_clc_prfx_match(). (Mete Durlu) [RHEL-130017] {CVE-2025-40168} +Resolves: RHEL-128237, RHEL-130017, RHEL-141462, RHEL-143545, RHEL-143713, RHEL-143718, RHEL-144987, RHEL-146049, RHEL-146357, RHEL-147266, RHEL-147459, RHEL-148166, RHEL-149495 + * Tue Feb 17 2026 CKI KWF Bot [5.14.0-611.35.1.el9_7] - page_pool: Fix use-after-free in page_pool_recycle_in_ring (Paolo Abeni) [RHEL-137841] {CVE-2025-38129} - exfat: fix double free in delayed_free (CKI Backport Bot) [RHEL-146403] {CVE-2025-38206} diff --git a/redhat/rhel_files/mod-extra.list.rhel b/redhat/rhel_files/mod-extra.list.rhel index f9ec7eb96e42a..c63247ed3a599 100644 --- a/redhat/rhel_files/mod-extra.list.rhel +++ b/redhat/rhel_files/mod-extra.list.rhel @@ -47,6 +47,8 @@ ems_pci.ko ems_usb.ko esd_usb2.ko esi-sir.ko +fou.ko +fou6.ko gamecon.ko gf2k.ko gigaset.ko diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh index a37304dcc88e1..7bfe773dce1bf 100755 --- a/tools/net/ynl/ynl-regen.sh +++ b/tools/net/ynl/ynl-regen.sh @@ -21,7 +21,7 @@ files=$(git grep --files-with-matches '^/\* YNL-GEN \(kernel\|uapi\|user\)') for f in $files; do # params: 0 1 2 3 # $YAML YNL-GEN kernel $mode - params=( $(git grep -B1 -h '/\* YNL-GEN' $f | sed 's@/\*\(.*\)\*/@\1@') ) + params=( $(git grep --no-line-number -B1 -h '/\* YNL-GEN' $f | sed 's@/\*\(.*\)\*/@\1@') ) args=$(sed -n 's@/\* YNL-ARG \(.*\) \*/@\1@p' $f) if [ $f -nt ${params[0]} -a -z "$force" ]; then