diff --git a/Makefile.rhelver b/Makefile.rhelver index 5ac7dd0c3814a..9cfabb9850509 100644 --- a/Makefile.rhelver +++ b/Makefile.rhelver @@ -12,7 +12,7 @@ RHEL_MINOR = 10 # # Use this spot to avoid future merge conflicts. # Do not trim this comment. -RHEL_RELEASE = 553.162.1 +RHEL_RELEASE = 553.164.1 # # ZSTREAM diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 98f5634917702..8cd67a65e16a8 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -2149,12 +2149,13 @@ static int vmload_vmsave_interception(struct kvm_vcpu *vcpu, bool vmload) ret = kvm_skip_emulated_instruction(vcpu); + /* KVM always performs VMLOAD/VMSAVE on VMCB01 (see __svm_vcpu_run()) */ if (vmload) { - svm_copy_vmloadsave_state(svm->vmcb, vmcb12); + svm_copy_vmloadsave_state(svm->vmcb01.ptr, vmcb12); svm->sysenter_eip_hi = 0; svm->sysenter_esp_hi = 0; } else { - svm_copy_vmloadsave_state(vmcb12, svm->vmcb); + svm_copy_vmloadsave_state(vmcb12, svm->vmcb01.ptr); } kvm_vcpu_unmap(vcpu, &map, true); diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 4d2b7acab2a51..c378f1eb3b4e1 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -123,18 +123,8 @@ static void blkg_free(struct blkcg_gq *blkg) static void __blkg_release(struct rcu_head *rcu) { struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head); - struct blkcg *blkcg = blkg->blkcg; - int cpu; WARN_ON(!bio_list_empty(&blkg->async_bios)); - /* - * Flush all the non-empty percpu lockless lists before releasing - * us, given these stat belongs to us. - * - * blkg_stat_lock is for serializing blkg stat update - */ - for_each_possible_cpu(cpu) - __blkcg_rstat_flush(blkcg, cpu); /* release the blkcg and parent blkg refs this blkg has been holding */ css_put(&blkg->blkcg->css); @@ -154,6 +144,17 @@ static void __blkg_release(struct rcu_head *rcu) static void blkg_release(struct percpu_ref *ref) { struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt); + struct blkcg *blkcg = blkg->blkcg; + int cpu; + + /* + * Flush all the non-empty percpu lockless lists before releasing + * us, given these stat belongs to us. + * + * blkg_stat_lock is for serializing blkg stat update + */ + for_each_possible_cpu(cpu) + __blkcg_rstat_flush(blkcg, cpu); call_rcu(&blkg->rcu_head, __blkg_release); } diff --git a/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/ebf71dd4.failed b/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/ebf71dd4.failed new file mode 100644 index 0000000000000..82496e7d839e2 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/ebf71dd4.failed @@ -0,0 +1,113 @@ +net/rds: Restrict use of RDS/IB to the initial network namespace + +jira KERNEL-1605 +cve CVE-2026-68294 +Rebuild_History Non-Buildable kernel-4.18.0-553.163.1.el8_10 +Rebuild_CHGLOG: - net: qrtr: restrict socket creation to the initial network namespace (Jose Ignacio Tornos Martinez) [RHEL-239090] {CVE-2026-68294} +Rebuild_FUZZ: 80.30% +commit-author Greg Jumper +commit ebf71dd4aff46e8e421d455db3e231ba43d2fa8a +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-4.18.0-553.163.1.el8_10/ebf71dd4.failed + +Prevent using RDS/IB in network namespaces other than the initial one. +The existing RDS/IB code will not work properly in non-initial network +namespaces. + +Fixes: d5a8ac28a7ff ("RDS-TCP: Make RDS-TCP work correctly when it is set up in a netns other than init_net") + Reported-by: syzbot+da8e060735ae02c8f3d1@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=da8e060735ae02c8f3d1 + Signed-off-by: Greg Jumper + Signed-off-by: Allison Henderson +Link: https://patch.msgid.link/20260408080420.540032-3-achender@kernel.org + Signed-off-by: Jakub Kicinski +(cherry picked from commit ebf71dd4aff46e8e421d455db3e231ba43d2fa8a) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/rds/af_rds.c +# net/rds/ib.c +diff --cc net/rds/af_rds.c +index ab751a150f70,76f625986a7f..000000000000 +--- a/net/rds/af_rds.c ++++ b/net/rds/af_rds.c +@@@ -258,8 -357,8 +258,13 @@@ static int rds_cong_monitor(struct rds_ + return ret; + } + +++<<<<<<< HEAD + +static int rds_set_transport(struct rds_sock *rs, char __user *optval, + + int optlen) +++======= ++ static int rds_set_transport(struct net *net, struct rds_sock *rs, ++ sockptr_t optval, int optlen) +++>>>>>>> ebf71dd4aff4 (net/rds: Restrict use of RDS/IB to the initial network namespace) + { + int t_type; + +@@@ -329,9 -435,10 +338,10 @@@ static int rds_recv_track_latency(struc + } + + static int rds_setsockopt(struct socket *sock, int level, int optname, + - sockptr_t optval, unsigned int optlen) + + char __user *optval, unsigned int optlen) + { + struct rds_sock *rs = rds_sk_to_rs(sock->sk); ++ struct net *net = sock_net(sock->sk); + int ret; + + if (level != SOL_RDS) { +@@@ -360,12 -467,13 +370,12 @@@ + break; + case SO_RDS_TRANSPORT: + lock_sock(sock->sk); +- ret = rds_set_transport(rs, optval, optlen); ++ ret = rds_set_transport(net, rs, optval, optlen); + release_sock(sock->sk); + break; + - case SO_TIMESTAMP_OLD: + - case SO_TIMESTAMP_NEW: + + case SO_TIMESTAMP: + lock_sock(sock->sk); + - ret = rds_enable_recvtstamp(sock->sk, optval, optlen, optname); + + ret = rds_enable_recvtstamp(sock->sk, optval, optlen); + release_sock(sock->sk); + break; + case SO_RDS_MSG_RXPATH_LATENCY: +diff --cc net/rds/ib.c +index 45ae449ff7a1,39f87272e071..000000000000 +--- a/net/rds/ib.c ++++ b/net/rds/ib.c +@@@ -373,6 -487,26 +373,29 @@@ static int rds_ib_laddr_check(struct ne + return ret; + } + +++<<<<<<< HEAD +++======= ++ static int rds_ib_laddr_check(struct net *net, const struct in6_addr *addr, ++ __u32 scope_id) ++ { ++ struct rds_ib_device *rds_ibdev = NULL; ++ ++ /* RDS/IB is restricted to the initial network namespace */ ++ if (!net_eq(net, &init_net)) ++ return -EPROTOTYPE; ++ ++ if (ipv6_addr_v4mapped(addr)) { ++ rds_ibdev = rds_ib_get_device(addr->s6_addr32[3]); ++ if (rds_ibdev) { ++ rds_ib_dev_put(rds_ibdev); ++ return 0; ++ } ++ } ++ ++ return rds_ib_laddr_check_cm(net, addr, scope_id); ++ } ++ +++>>>>>>> ebf71dd4aff4 (net/rds: Restrict use of RDS/IB to the initial network namespace) + static void rds_ib_unregister_client(void) + { + ib_unregister_client(&rds_ib_client); +* Unmerged path net/rds/af_rds.c +* Unmerged path net/rds/ib.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/rebuild.details.txt b/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/rebuild.details.txt new file mode 100644 index 0000000000000..55bba158fcdc5 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.163.1.el8_10/rebuild.details.txt @@ -0,0 +1,27 @@ +Rebuild_History BUILDABLE +Rebuilding Kernel from rpm changelog with Fuzz Limit: 87.50% +Number of commits in upstream range v4.18~1..kernel-mainline: 625874 +Number of commits in rpm: 19 +Number of commits matched with upstream: 9 (47.37%) +Number of commits in upstream but not in rpm: 625865 +Number of commits NOT found in upstream: 10 (52.63%) + +Rebuilding Kernel on Branch rocky8_10_rebuild_kernel-4.18.0-553.163.1.el8_10 for kernel-4.18.0-553.163.1.el8_10 +Clean Cherry Picks: 7 (77.78%) +Empty Cherry Picks: 1 (11.11%) +_______________________________ + +__EMPTY COMMITS__________________________ +ebf71dd4aff46e8e421d455db3e231ba43d2fa8a net/rds: Restrict use of RDS/IB to the initial network namespace + +__CHANGES NOT IN UPSTREAM________________ +Adding prod certs and changed cert date to 20210620 +Adding Rocky secure boot certs +Fixing vmlinuz removal +Fixing UEFI CA path +Porting to 8.10, debranding and Rocky branding +Fixing pesign_key_name values +scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer +dm-verity: fix buffer overflow in FEC calculation +wifi: ath9k: hif_usb: don't dereference hif_dev after re-arming firmware request +net: qrtr: fix refcount saturation and potential UAF in qrtr_port_remove diff --git a/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/1c428b03.failed b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/1c428b03.failed new file mode 100644 index 0000000000000..af7d7a8d2f158 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/1c428b03.failed @@ -0,0 +1,190 @@ +xfrm: hold dev ref until after transport_finish NF_HOOK + +jira KERNEL-1623 +cve CVE-2026-31663 +Rebuild_History Non-Buildable kernel-4.18.0-553.164.1.el8_10 +commit-author Qi Tang +commit 1c428b03840094410c5fb6a5db30640486bbbfcb +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-4.18.0-553.164.1.el8_10/1c428b03.failed + +After async crypto completes, xfrm_input_resume() calls dev_put() +immediately on re-entry before the skb reaches transport_finish. +The skb->dev pointer is then used inside NF_HOOK and its okfn, +which can race with device teardown. + +Remove the dev_put from the async resumption entry and instead +drop the reference after the NF_HOOK call in transport_finish, +using a saved device pointer since NF_HOOK may consume the skb. +This covers NF_DROP, NF_QUEUE and NF_STOLEN paths that skip +the okfn. + +For non-transport exits (decaps, gro, drop) and secondary +async return points, release the reference inline when +async is set. + + Suggested-by: Florian Westphal +Fixes: acf568ee859f ("xfrm: Reinject transport-mode packets through tasklet") + Cc: stable@vger.kernel.org + Signed-off-by: Qi Tang + Signed-off-by: Steffen Klassert +(cherry picked from commit 1c428b03840094410c5fb6a5db30640486bbbfcb) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv6/xfrm6_input.c +# net/xfrm/xfrm_input.c +diff --cc net/ipv6/xfrm6_input.c +index 086605fbec35,699a001ac166..000000000000 +--- a/net/ipv6/xfrm6_input.c ++++ b/net/ipv6/xfrm6_input.c +@@@ -46,7 -43,8 +46,12 @@@ static int xfrm6_transport_finish2(stru + int xfrm6_transport_finish(struct sk_buff *skb, int async) + { + struct xfrm_offload *xo = xfrm_offload(skb); +++<<<<<<< HEAD + + int nhlen = skb->data - skb_network_header(skb); +++======= ++ struct net_device *dev = skb->dev; ++ int nhlen = -skb_network_offset(skb); +++>>>>>>> 1c428b038400 (xfrm: hold dev ref until after transport_finish NF_HOOK) + + skb_network_header(skb)[IP6CB(skb)->nhoff] = + XFRM_MODE_SKB_CB(skb)->protocol; +diff --cc net/xfrm/xfrm_input.c +index faefb4eb4d3e,f65291eba1f6..000000000000 +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@@ -525,13 -506,11 +525,12 @@@ int xfrm_input(struct sk_buff *skb, in + /* An encap_type of -1 indicates async resumption. */ + if (encap_type == -1) { + async = 1; +- dev_put(skb->dev); + seq = XFRM_SKB_CB(skb)->seq.input.low; + - spin_lock(&x->lock); + goto resume; + } + - /* GRO call */ + + + + /* encap_type < -1 indicates a GRO call. */ + + encap_type = 0; + seq = XFRM_SPI_SKB_CB(skb)->seq; + + if (xo && (xo->flags & CRYPTO_DONE)) { +@@@ -669,13 -658,16 +668,16 @@@ lock + dev_hold(skb->dev); + + nexthdr = x->type->input(x, skb); +- if (nexthdr == -EINPROGRESS) ++ if (nexthdr == -EINPROGRESS) { ++ if (async) ++ dev_put(skb->dev); + return 0; ++ } + + dev_put(skb->dev); + - spin_lock(&x->lock); + } + resume: + + spin_lock(&x->lock); + if (nexthdr < 0) { + if (nexthdr == -EBADMSG) { + xfrm_audit_state_icvfail(x, skb, +@@@ -703,17 -696,12 +705,26 @@@ + + XFRM_MODE_SKB_CB(skb)->protocol = nexthdr; + +++<<<<<<< HEAD + + inner_mode = x->inner_mode; + + + + if (x->sel.family == AF_UNSPEC) { + + inner_mode = xfrm_ip2inner_mode(x, XFRM_MODE_SKB_CB(skb)->protocol); + + if (inner_mode == NULL) { + + XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); + + goto drop; + + } + + } + + + + if (xfrm_inner_mode_input(x, inner_mode, skb)) { +++======= ++ err = xfrm_inner_mode_input(x, skb); ++ if (err == -EINPROGRESS) { ++ if (async) ++ dev_put(skb->dev); ++ return 0; ++ } else if (err) { +++>>>>>>> 1c428b038400 (xfrm: hold dev ref until after transport_finish NF_HOOK) + XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); + goto drop; + } +@@@ -742,12 -730,16 +753,22 @@@ + if (err) + goto drop; + + - nf_reset_ct(skb); + + nf_reset(skb); + + if (decaps) { +++<<<<<<< HEAD + + if (skb->sp) + + skb->sp->olen = 0; + + skb_dst_drop(skb); +++======= ++ sp = skb_sec_path(skb); ++ if (sp) ++ sp->olen = 0; ++ if (skb_valid_dst(skb)) ++ skb_dst_drop(skb); ++ if (async) ++ dev_put(skb->dev); +++>>>>>>> 1c428b038400 (xfrm: hold dev ref until after transport_finish NF_HOOK) + gro_cells_receive(&gro_cells, skb); + return 0; + } else { +@@@ -762,9 -754,13 +783,19 @@@ + err = afinfo->transport_finish(skb, xfrm_gro || async); + rcu_read_unlock(); + if (xfrm_gro) { +++<<<<<<< HEAD + + if (skb->sp) + + skb->sp->olen = 0; + + skb_dst_drop(skb); +++======= ++ sp = skb_sec_path(skb); ++ if (sp) ++ sp->olen = 0; ++ if (skb_valid_dst(skb)) ++ skb_dst_drop(skb); ++ if (async) ++ dev_put(skb->dev); +++>>>>>>> 1c428b038400 (xfrm: hold dev ref until after transport_finish NF_HOOK) + gro_cells_receive(&gro_cells, skb); + return err; + } +diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c +index 3feda5ad2af4..39a9f7ff7e8a 100644 +--- a/net/ipv4/xfrm4_input.c ++++ b/net/ipv4/xfrm4_input.c +@@ -53,6 +53,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) + { + struct xfrm_offload *xo = xfrm_offload(skb); + struct iphdr *iph = ip_hdr(skb); ++ struct net_device *dev = skb->dev; + + iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; + +@@ -72,8 +73,10 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) + } + + NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, +- dev_net(skb->dev), NULL, skb, skb->dev, NULL, ++ dev_net(dev), NULL, skb, dev, NULL, + xfrm4_rcv_encap_finish); ++ if (async) ++ dev_put(dev); + return 0; + } + +* Unmerged path net/ipv6/xfrm6_input.c +* Unmerged path net/xfrm/xfrm_input.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/791c91dc.failed b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/791c91dc.failed new file mode 100644 index 0000000000000..f640deec60ec2 --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/791c91dc.failed @@ -0,0 +1,167 @@ +ipv6: mcast: Fix use-after-free when processing MLD queries + +jira KERNEL-1623 +cve CVE-2026-53275 +Rebuild_History Non-Buildable kernel-4.18.0-553.164.1.el8_10 +commit-author Ido Schimmel +commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 +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-4.18.0-553.164.1.el8_10/791c91dc.failed + +When processing an MLD query, a pointer to the multicast group address +is retrieved when initially parsing the packet. This pointer is later +dereferenced without being reloaded despite the fact that the skb header +might have been reallocated following the pskb_may_pull() calls, leading +to a use-after-free [1]. + +Fix by copying the multicast group address when the packet is initially +parsed. + +[1] +BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512) +Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118 + +Workqueue: mld mld_query_work +Call Trace: + +dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) +print_address_description.constprop.0 (mm/kasan/report.c:378) +print_report (mm/kasan/report.c:482) +kasan_report (mm/kasan/report.c:595) +__mld_query_work (net/ipv6/mcast.c:1512) +mld_query_work (net/ipv6/mcast.c:1563) +process_one_work (kernel/workqueue.c:3314) +worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) +kthread (kernel/kthread.c:436) +ret_from_fork (arch/x86/kernel/process.c:158) +ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + + +[...] + +Freed by task 118: +kasan_save_stack (mm/kasan/common.c:57) +kasan_save_track (mm/kasan/common.c:78) +kasan_save_free_info (mm/kasan/generic.c:584) +__kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285) +kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566) +pskb_expand_head (net/core/skbuff.c:2335) +__pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4)) +__mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1)) +mld_query_work (net/ipv6/mcast.c:1563) +process_one_work (kernel/workqueue.c:3314) +worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) +kthread (kernel/kthread.c:436) +ret_from_fork (arch/x86/kernel/process.c:158) +ret_from_fork_asm (arch/x86/entry/entry_64.S:245) + +Fixes: 97300b5fdfe2 ("[MCAST] IPv6: Check packet size when process Multicast") + Reported-by: Leo Lin + Reviewed-by: David Ahern + Signed-off-by: Ido Schimmel + Reviewed-by: Eric Dumazet + Reviewed-by: Jiayuan Chen +Link: https://patch.msgid.link/20260603101811.612594-1-idosch@nvidia.com + Signed-off-by: Jakub Kicinski +(cherry picked from commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv6/mcast.c +diff --cc net/ipv6/mcast.c +index 088006e7eb1d,d9b855d5191b..000000000000 +--- a/net/ipv6/mcast.c ++++ b/net/ipv6/mcast.c +@@@ -1337,13 -1402,32 +1337,20 @@@ static int mld_process_v2(struct inet6_ + } + + /* called with rcu_read_lock() */ + -void igmp6_event_query(struct sk_buff *skb) + -{ + - struct inet6_dev *idev = __in6_dev_get(skb->dev); + - + - if (!idev || idev->dead) + - goto out; + - + - spin_lock_bh(&idev->mc_query_lock); + - if (skb_queue_len(&idev->mc_query_queue) < MLD_MAX_SKBS) { + - __skb_queue_tail(&idev->mc_query_queue, skb); + - if (!mod_delayed_work(mld_wq, &idev->mc_query_work, 0)) + - in6_dev_hold(idev); + - skb = NULL; + - } + - spin_unlock_bh(&idev->mc_query_lock); + -out: + - kfree_skb(skb); + -} + - + -static void __mld_query_work(struct sk_buff *skb) + +int igmp6_event_query(struct sk_buff *skb) + { + struct mld2_query *mlh2 = NULL; +++<<<<<<< HEAD + + struct ifmcaddr6 *ma; + + const struct in6_addr *group; + + unsigned long max_delay; + + struct inet6_dev *idev; +++======= ++ unsigned long max_delay; ++ struct inet6_dev *idev; ++ struct in6_addr group; ++ struct ifmcaddr6 *ma; +++>>>>>>> 791c91dc7a9d (ipv6: mcast: Fix use-after-free when processing MLD queries) + struct mld_msg *mld; + int group_type; + int mark = 0; +@@@ -1367,15 -1451,15 +1374,15 @@@ + ipv6_hdr(skb)->hop_limit != 1 || + !(IP6CB(skb)->flags & IP6SKB_ROUTERALERT) || + IP6CB(skb)->ra != htons(IPV6_OPT_ROUTERALERT_MLD)) + - goto kfree_skb; + + return -EINVAL; + + - idev = in6_dev_get(skb->dev); + + idev = __in6_dev_get(skb->dev); + if (!idev) + - goto kfree_skb; + + return 0; + + mld = (struct mld_msg *)icmp6_hdr(skb); +- group = &mld->mld_mca; +- group_type = ipv6_addr_type(group); ++ group = mld->mld_mca; ++ group_type = ipv6_addr_type(&group); + + if (group_type != IPV6_ADDR_ANY && + !(group_type&IPV6_ADDR_MULTICAST)) +@@@ -1418,21 -1500,17 +1425,26 @@@ + mark = 1; + } + } else { + - goto out; + + return -EINVAL; + } + + + read_lock_bh(&idev->lock); + if (group_type == IPV6_ADDR_ANY) { + - for_each_mc_mclock(idev, ma) { + + for (ma = idev->mc_list; ma; ma = ma->next) { + + spin_lock_bh(&ma->mca_lock); + igmp6_group_queried(ma, max_delay); + + spin_unlock_bh(&ma->mca_lock); + } + } else { +++<<<<<<< HEAD + + for (ma = idev->mc_list; ma; ma = ma->next) { + + if (!ipv6_addr_equal(group, &ma->mca_addr)) +++======= ++ for_each_mc_mclock(idev, ma) { ++ if (!ipv6_addr_equal(&group, &ma->mca_addr)) +++>>>>>>> 791c91dc7a9d (ipv6: mcast: Fix use-after-free when processing MLD queries) + continue; + + spin_lock_bh(&ma->mca_lock); + if (ma->mca_flags & MAF_TIMER_RUNNING) { + /* gsquery <- gsquery && mark */ + if (!mark) +* Unmerged path net/ipv6/mcast.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c16f74dc.failed b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c16f74dc.failed new file mode 100644 index 0000000000000..74703e7a9c85f --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c16f74dc.failed @@ -0,0 +1,89 @@ +xfrm: input: hold netns during deferred transport reinjection + +jira KERNEL-1623 +cve CVE-2026-63919 +Rebuild_History Non-Buildable kernel-4.18.0-553.164.1.el8_10 +commit-author Zhengchuan Liang +commit c16f74dc1d75d0e2e7670076d5375deda110ebeb +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-4.18.0-553.164.1.el8_10/c16f74dc.failed + +Transport-mode reinjection stores a struct net pointer in skb->cb and +uses it later from xfrm_trans_reinject(). That pointer must stay valid +until the deferred callback runs. + +Take a netns reference when queueing deferred reinjection work and drop +it after the callback completes. Use maybe_get_net() so the queueing +path does not revive a namespace that is already being torn down. + +This keeps the existing workqueue design and fixes the netns lifetime +handling in one place for all users of xfrm_trans_queue_net(). + +Fixes: 7b3801927e52 ("xfrm: introduce xfrm_trans_queue_net") + Cc: stable@kernel.org + Reported-by: Yuan Tan + Reported-by: Xin Liu +Co-developed-by: Luxing Yin + Signed-off-by: Luxing Yin + Signed-off-by: Zhengchuan Liang + Signed-off-by: Ren Wei +Assisted-by: Codex:gpt-5.4 + Signed-off-by: Steffen Klassert +(cherry picked from commit c16f74dc1d75d0e2e7670076d5375deda110ebeb) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/xfrm/xfrm_input.c +diff --cc net/xfrm/xfrm_input.c +index 6ceac35d61fa,e4c2cd24936d..000000000000 +--- a/net/xfrm/xfrm_input.c ++++ b/net/xfrm/xfrm_input.c +@@@ -793,11 -792,18 +793,22 @@@ static void xfrm_trans_reinject(unsigne + struct sk_buff *skb; + + __skb_queue_head_init(&queue); + - spin_lock_bh(&trans->queue_lock); + skb_queue_splice_init(&trans->queue, &queue); + - spin_unlock_bh(&trans->queue_lock); + +++<<<<<<< HEAD + + while ((skb = __skb_dequeue(&queue))) + + XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net, + + NULL, skb); +++======= ++ local_bh_disable(); ++ while ((skb = __skb_dequeue(&queue))) { ++ struct net *net = XFRM_TRANS_SKB_CB(skb)->net; ++ ++ XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb); ++ put_net(net); ++ } ++ local_bh_enable(); +++>>>>>>> c16f74dc1d75 (xfrm: input: hold netns during deferred transport reinjection) + } + + int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, +@@@ -813,10 -820,16 +825,19 @@@ + + BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb)); + ++ hold_net = maybe_get_net(net); ++ if (!hold_net) ++ return -ENODEV; ++ + XFRM_TRANS_SKB_CB(skb)->finish = finish; +++<<<<<<< HEAD + + XFRM_TRANS_SKB_CB(skb)->net = net; +++======= ++ XFRM_TRANS_SKB_CB(skb)->net = hold_net; ++ spin_lock_bh(&trans->queue_lock); +++>>>>>>> c16f74dc1d75 (xfrm: input: hold netns during deferred transport reinjection) + __skb_queue_tail(&trans->queue, skb); + - spin_unlock_bh(&trans->queue_lock); + - schedule_work(&trans->work); + + tasklet_schedule(&trans->tasklet); + return 0; + } + EXPORT_SYMBOL(xfrm_trans_queue_net); +* Unmerged path net/xfrm/xfrm_input.c diff --git a/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c89477ad.failed b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c89477ad.failed new file mode 100644 index 0000000000000..4bbb47eb76aea --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/c89477ad.failed @@ -0,0 +1,86 @@ +inet: RAW sockets using IPPROTO_RAW MUST drop incoming ICMP + +jira KERNEL-1623 +cve CVE-2026-46266 +Rebuild_History Non-Buildable kernel-4.18.0-553.164.1.el8_10 +commit-author Eric Dumazet +commit c89477ad79446867394360b29bb801010fc3ff22 +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-4.18.0-553.164.1.el8_10/c89477ad.failed + +Yizhou Zhao reported that simply having one RAW socket on protocol +IPPROTO_RAW (255) was dangerous. + + socket(AF_INET, SOCK_RAW, 255); + +A malicious incoming ICMP packet can set the protocol field to 255 +and match this socket, leading to FNHE cache changes. + +inner = IP(src="192.168.2.1", dst="8.8.8.8", proto=255)/Raw("TEST") +pkt = IP(src="192.168.1.1", dst="192.168.2.1")/ICMP(type=3, code=4, nexthopmtu=576)/inner + +"man 7 raw" states: + + A protocol of IPPROTO_RAW implies enabled IP_HDRINCL and is able + to send any IP protocol that is specified in the passed header. + Receiving of all IP protocols via IPPROTO_RAW is not possible + using raw sockets. + +Make sure we drop these malicious packets. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") + Reported-by: Yizhou Zhao +Link: https://lore.kernel.org/netdev/20251109134600.292125-1-zhaoyz24@mails.tsinghua.edu.cn/ + Signed-off-by: Eric Dumazet + Reviewed-by: David Ahern + Reviewed-by: Ido Schimmel +Link: https://patch.msgid.link/20260203192509.682208-1-edumazet@google.com + Signed-off-by: Jakub Kicinski +(cherry picked from commit c89477ad79446867394360b29bb801010fc3ff22) + Signed-off-by: Jonathan Maple + +# Conflicts: +# net/ipv4/icmp.c +diff --cc net/ipv4/icmp.c +index c98d8f3656d3,4acbbc703e79..000000000000 +--- a/net/ipv4/icmp.c ++++ b/net/ipv4/icmp.c +@@@ -777,10 -1031,12 +777,19 @@@ static void icmp_socket_deliver(struct + /* Checkin full IP header plus 8 bytes of protocol to + * avoid additional coding at protocol handlers. + */ +++<<<<<<< HEAD + + if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { + + __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); + + return; + + } +++======= ++ if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) ++ goto out; ++ ++ /* IPPROTO_RAW sockets are not supposed to receive anything. */ ++ if (protocol == IPPROTO_RAW) ++ goto out; +++>>>>>>> c89477ad7944 (inet: RAW sockets using IPPROTO_RAW MUST drop incoming ICMP) + + raw_icmp_error(skb, protocol, info); + +* Unmerged path net/ipv4/icmp.c +diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c +index f638a9b6ecf9..19d60db29b41 100644 +--- a/net/ipv6/icmp.c ++++ b/net/ipv6/icmp.c +@@ -794,6 +794,12 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type, + if (reason != SKB_NOT_DROPPED_YET) + goto out; + ++ if (nexthdr == IPPROTO_RAW) { ++ /* Add a more specific reason later ? */ ++ reason = SKB_DROP_REASON_NOT_SPECIFIED; ++ goto out; ++ } ++ + /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. + Without this we will not able f.e. to make source routed + pmtu discovery. diff --git a/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/rebuild.details.txt b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/rebuild.details.txt new file mode 100644 index 0000000000000..9f34fc9731b8b --- /dev/null +++ b/ciq/ciq_backports/kernel-4.18.0-553.164.1.el8_10/rebuild.details.txt @@ -0,0 +1,35 @@ +Rebuild_History BUILDABLE +Rebuilding Kernel from rpm changelog with Fuzz Limit: 87.50% +Number of commits in upstream range v4.18~1..kernel-mainline: 625874 +Number of commits in rpm: 35 +Number of commits matched with upstream: 20 (57.14%) +Number of commits in upstream but not in rpm: 625854 +Number of commits NOT found in upstream: 15 (42.86%) + +Rebuilding Kernel on Branch rocky8_10_rebuild_kernel-4.18.0-553.164.1.el8_10 for kernel-4.18.0-553.164.1.el8_10 +Clean Cherry Picks: 16 (80.00%) +Empty Cherry Picks: 4 (20.00%) +_______________________________ + +__EMPTY COMMITS__________________________ +791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 ipv6: mcast: Fix use-after-free when processing MLD queries +c89477ad79446867394360b29bb801010fc3ff22 inet: RAW sockets using IPPROTO_RAW MUST drop incoming ICMP +c16f74dc1d75d0e2e7670076d5375deda110ebeb xfrm: input: hold netns during deferred transport reinjection +1c428b03840094410c5fb6a5db30640486bbbfcb xfrm: hold dev ref until after transport_finish NF_HOOK + +__CHANGES NOT IN UPSTREAM________________ +Adding prod certs and changed cert date to 20210620 +Adding Rocky secure boot certs +Fixing vmlinuz removal +Fixing UEFI CA path +Porting to 8.10, debranding and Rocky branding +Fixing pesign_key_name values +net: qrtr: fix 32-bit integer overflow in qrtr_endpoint_post() +ipv6: sit: reload inner IPv6 header after GSO offloads +xfrm: Fix dev use-after-free in xfrm async resumption +xfrm: fix stale skb->prev after async crypto steals a GSO segment +xfrm: propagate -EINPROGRESS from validate_xmit_xfrm() +xfrm: policy: fix use-after-free on inexact bin in xfrm_policy_bysel_ctx() +net: guard timestamp cmsgs to real error queue skbs +net: slip: serialize receive against buffer reallocation +ALSA: timer: Fix UAF at snd_timer_user_params() diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c index e4736eb37bfb3..0ef0489827682 100644 --- a/drivers/edac/bluefield_edac.c +++ b/drivers/edac/bluefield_edac.c @@ -180,7 +180,7 @@ static void bluefield_edac_check(struct mem_ctl_info *mci) static void bluefield_edac_init_dimms(struct mem_ctl_info *mci) { struct bluefield_edac_priv *priv = mci->pvt_info; - int mem_ctrl_idx = mci->mc_idx; + u64 mem_ctrl_idx = mci->mc_idx; struct dimm_info *dimm; u64 smc_info, smc_arg; int is_empty = 1, i; diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 090570bf7fe73..63efe03964024 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -1388,6 +1388,12 @@ isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc) ib_dma_sync_single_for_cpu(ib_dev, isert_conn->login_desc->dma_addr, ISER_RX_SIZE, DMA_FROM_DEVICE); + if (unlikely(wc->byte_len < ISER_HEADERS_LEN)) { + isert_dbg("login request length %u is too short\n", + wc->byte_len); + return; + } + isert_conn->login_req_len = wc->byte_len - ISER_HEADERS_LEN; if (isert_conn->conn) { diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 1a8a985c394e9..a3522a51a6d9a 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -259,7 +259,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, (unsigned long long)block, PTR_ERR(bbuf)); /* assume the block is corrupted */ - if (neras && *neras <= v->fec->roots) + if (neras && *neras < v->fec->roots) fio->erasures[(*neras)++] = i; continue; @@ -277,7 +277,7 @@ static int fec_read_bufs(struct dm_verity *v, struct dm_verity_io *io, * skip if we have already found the theoretical * maximum number (i.e. fec->roots) of erasures */ - if (neras && *neras <= v->fec->roots && + if (neras && *neras < v->fec->roots && fec_is_erasure(v, io, want_digest, bbuf)) fio->erasures[(*neras)++] = i; } diff --git a/drivers/net/ipvlan/ipvlan.h b/drivers/net/ipvlan/ipvlan.h index adb826f55e604..e62163e698ff1 100644 --- a/drivers/net/ipvlan/ipvlan.h +++ b/drivers/net/ipvlan/ipvlan.h @@ -74,7 +74,6 @@ struct ipvl_dev { DECLARE_BITMAP(mac_filters, IPVLAN_MAC_FILTER_SIZE); netdev_features_t sfeatures; u32 msg_enable; - spinlock_t addrs_lock; }; struct ipvl_addr { @@ -95,6 +94,7 @@ struct ipvl_port { struct net_device *dev; possible_net_t pnet; struct hlist_head hlhead[IPVLAN_HASH_SIZE]; + spinlock_t addrs_lock; /* guards hash-table and addrs */ struct list_head ipvlans; u16 mode; u16 flags; diff --git a/drivers/net/ipvlan/ipvlan_core.c b/drivers/net/ipvlan/ipvlan_core.c index d5b935ee840ce..218805c3a56ab 100644 --- a/drivers/net/ipvlan/ipvlan_core.c +++ b/drivers/net/ipvlan/ipvlan_core.c @@ -109,17 +109,15 @@ void ipvlan_ht_addr_del(struct ipvl_addr *addr) struct ipvl_addr *ipvlan_find_addr(const struct ipvl_dev *ipvlan, const void *iaddr, bool is_v6) { - struct ipvl_addr *addr, *ret = NULL; + struct ipvl_addr *addr; - rcu_read_lock(); - list_for_each_entry_rcu(addr, &ipvlan->addrs, anode) { - if (addr_equal(is_v6, addr, iaddr)) { - ret = addr; - break; - } + assert_spin_locked(&ipvlan->port->addrs_lock); + + list_for_each_entry(addr, &ipvlan->addrs, anode) { + if (addr_equal(is_v6, addr, iaddr)) + return addr; } - rcu_read_unlock(); - return ret; + return NULL; } bool ipvlan_addr_busy(struct ipvl_port *port, void *iaddr, bool is_v6) diff --git a/drivers/net/ipvlan/ipvlan_main.c b/drivers/net/ipvlan/ipvlan_main.c index 140bac044d1da..7258d502aa796 100644 --- a/drivers/net/ipvlan/ipvlan_main.c +++ b/drivers/net/ipvlan/ipvlan_main.c @@ -145,6 +145,7 @@ static int ipvlan_port_create(struct net_device *dev) for (idx = 0; idx < IPVLAN_HASH_SIZE; idx++) INIT_HLIST_HEAD(&port->hlhead[idx]); + spin_lock_init(&port->addrs_lock); skb_queue_head_init(&port->backlog); INIT_WORK(&port->wq, ipvlan_process_multicast); ida_init(&port->ida); @@ -254,6 +255,7 @@ static void ipvlan_uninit(struct net_device *dev) static int ipvlan_open(struct net_device *dev) { struct ipvl_dev *ipvlan = netdev_priv(dev); + struct ipvl_port *port = ipvlan->port; struct ipvl_addr *addr; if (ipvlan->port->mode == IPVLAN_MODE_L3 || @@ -262,10 +264,10 @@ static int ipvlan_open(struct net_device *dev) else dev->flags &= ~IFF_NOARP; - rcu_read_lock(); - list_for_each_entry_rcu(addr, &ipvlan->addrs, anode) + spin_lock_bh(&port->addrs_lock); + list_for_each_entry(addr, &ipvlan->addrs, anode) ipvlan_ht_addr_add(ipvlan, addr); - rcu_read_unlock(); + spin_unlock_bh(&port->addrs_lock); return 0; } @@ -279,10 +281,10 @@ static int ipvlan_stop(struct net_device *dev) dev_uc_unsync(phy_dev, dev); dev_mc_unsync(phy_dev, dev); - rcu_read_lock(); - list_for_each_entry_rcu(addr, &ipvlan->addrs, anode) + spin_lock_bh(&ipvlan->port->addrs_lock); + list_for_each_entry(addr, &ipvlan->addrs, anode) ipvlan_ht_addr_del(addr); - rcu_read_unlock(); + spin_unlock_bh(&ipvlan->port->addrs_lock); return 0; } @@ -643,7 +645,6 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev, if (!tb[IFLA_MTU]) ipvlan_adjust_mtu(ipvlan, phy_dev); INIT_LIST_HEAD(&ipvlan->addrs); - spin_lock_init(&ipvlan->addrs_lock); /* TODO Probably put random address here to be presented to the * world but keep using the physical-dev address for the outgoing @@ -721,13 +722,13 @@ void ipvlan_link_delete(struct net_device *dev, struct list_head *head) struct ipvl_dev *ipvlan = netdev_priv(dev); struct ipvl_addr *addr, *next; - spin_lock_bh(&ipvlan->addrs_lock); + spin_lock_bh(&ipvlan->port->addrs_lock); list_for_each_entry_safe(addr, next, &ipvlan->addrs, anode) { ipvlan_ht_addr_del(addr); list_del_rcu(&addr->anode); kfree_rcu(addr, rcu); } - spin_unlock_bh(&ipvlan->addrs_lock); + spin_unlock_bh(&ipvlan->port->addrs_lock); ida_simple_remove(&ipvlan->port->ida, dev->dev_id); list_del_rcu(&ipvlan->pnode); @@ -873,6 +874,8 @@ static int ipvlan_add_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) { struct ipvl_addr *addr; + assert_spin_locked(&ipvlan->port->addrs_lock); + addr = kzalloc(sizeof(struct ipvl_addr), GFP_ATOMIC); if (!addr) return -ENOMEM; @@ -903,16 +906,16 @@ static void ipvlan_del_addr(struct ipvl_dev *ipvlan, void *iaddr, bool is_v6) { struct ipvl_addr *addr; - spin_lock_bh(&ipvlan->addrs_lock); + spin_lock_bh(&ipvlan->port->addrs_lock); addr = ipvlan_find_addr(ipvlan, iaddr, is_v6); if (!addr) { - spin_unlock_bh(&ipvlan->addrs_lock); + spin_unlock_bh(&ipvlan->port->addrs_lock); return; } ipvlan_ht_addr_del(addr); list_del_rcu(&addr->anode); - spin_unlock_bh(&ipvlan->addrs_lock); + spin_unlock_bh(&ipvlan->port->addrs_lock); kfree_rcu(addr, rcu); } @@ -934,14 +937,14 @@ static int ipvlan_add_addr6(struct ipvl_dev *ipvlan, struct in6_addr *ip6_addr) { int ret = -EINVAL; - spin_lock_bh(&ipvlan->addrs_lock); + spin_lock_bh(&ipvlan->port->addrs_lock); if (ipvlan_addr_busy(ipvlan->port, ip6_addr, true)) netif_err(ipvlan, ifup, ipvlan->dev, "Failed to add IPv6=%pI6c addr for %s intf\n", ip6_addr, ipvlan->dev->name); else ret = ipvlan_add_addr(ipvlan, ip6_addr, true); - spin_unlock_bh(&ipvlan->addrs_lock); + spin_unlock_bh(&ipvlan->port->addrs_lock); return ret; } @@ -980,21 +983,24 @@ static int ipvlan_addr6_validator_event(struct notifier_block *unused, struct in6_validator_info *i6vi = (struct in6_validator_info *)ptr; struct net_device *dev = (struct net_device *)i6vi->i6vi_dev->dev; struct ipvl_dev *ipvlan = netdev_priv(dev); + int ret = NOTIFY_OK; if (!ipvlan_is_valid_dev(dev)) return NOTIFY_DONE; switch (event) { case NETDEV_UP: + spin_lock_bh(&ipvlan->port->addrs_lock); if (ipvlan_addr_busy(ipvlan->port, &i6vi->i6vi_addr, true)) { NL_SET_ERR_MSG(i6vi->extack, "Address already assigned to an ipvlan device"); - return notifier_from_errno(-EADDRINUSE); + ret = notifier_from_errno(-EADDRINUSE); } + spin_unlock_bh(&ipvlan->port->addrs_lock); break; } - return NOTIFY_OK; + return ret; } #endif @@ -1002,14 +1008,14 @@ static int ipvlan_add_addr4(struct ipvl_dev *ipvlan, struct in_addr *ip4_addr) { int ret = -EINVAL; - spin_lock_bh(&ipvlan->addrs_lock); + spin_lock_bh(&ipvlan->port->addrs_lock); if (ipvlan_addr_busy(ipvlan->port, ip4_addr, false)) netif_err(ipvlan, ifup, ipvlan->dev, "Failed to add IPv4=%pI4 on %s intf.\n", ip4_addr, ipvlan->dev->name); else ret = ipvlan_add_addr(ipvlan, ip4_addr, false); - spin_unlock_bh(&ipvlan->addrs_lock); + spin_unlock_bh(&ipvlan->port->addrs_lock); return ret; } @@ -1051,21 +1057,24 @@ static int ipvlan_addr4_validator_event(struct notifier_block *unused, struct in_validator_info *ivi = (struct in_validator_info *)ptr; struct net_device *dev = (struct net_device *)ivi->ivi_dev->dev; struct ipvl_dev *ipvlan = netdev_priv(dev); + int ret = NOTIFY_OK; if (!ipvlan_is_valid_dev(dev)) return NOTIFY_DONE; switch (event) { case NETDEV_UP: + spin_lock_bh(&ipvlan->port->addrs_lock); if (ipvlan_addr_busy(ipvlan->port, &ivi->ivi_addr, false)) { NL_SET_ERR_MSG(ivi->extack, "Address already assigned to an ipvlan device"); - return notifier_from_errno(-EADDRINUSE); + ret = notifier_from_errno(-EADDRINUSE); } + spin_unlock_bh(&ipvlan->port->addrs_lock); break; } - return NOTIFY_OK; + return ret; } static struct notifier_block ipvlan_addr4_notifier_block __read_mostly = { diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index c9ceb2e21ec24..18a2ea5603f95 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -860,6 +860,9 @@ static int ppp_unattached_ioctl(struct net *net, struct ppp_file *pf, struct ppp_net *pn; int __user *p = (int __user *)arg; + if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) + return -EPERM; + switch (cmd) { case PPPIOCNEWUNIT: /* Create a new ppp unit */ diff --git a/drivers/net/slip/slip.c b/drivers/net/slip/slip.c index 539abf880c802..35a05287b2348 100644 --- a/drivers/net/slip/slip.c +++ b/drivers/net/slip/slip.c @@ -695,6 +695,8 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, if (!sl || sl->magic != SLIP_MAGIC || !netif_running(sl->dev)) return; + spin_lock_bh(&sl->lock); + /* Read the characters out of the buffer */ while (count--) { if (fp && *fp++) { @@ -710,6 +712,8 @@ static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, #endif slip_unesc(sl, *cp++); } + + spin_unlock_bh(&sl->lock); } /************************************ @@ -862,6 +866,11 @@ static int slip_open(struct tty_struct *tty) sl->tty = NULL; tty->disc_data = NULL; clear_bit(SLF_INUSE, &sl->flags); + sl_free_netdev(sl->dev); + /* do not call free_netdev before rtnl_unlock */ + rtnl_unlock(); + free_netdev(sl->dev); + return err; err_exit: rtnl_unlock(); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index e0130beb304df..31771d176b7f3 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -1229,15 +1229,10 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev, ret = request_firmware_nowait(THIS_MODULE, true, hif_dev->fw_name, &hif_dev->udev->dev, GFP_KERNEL, hif_dev, ath9k_hif_usb_firmware_cb); - if (ret) { + if (ret) dev_err(&hif_dev->udev->dev, "ath9k_htc: Async request for firmware %s failed\n", hif_dev->fw_name); - return ret; - } - - dev_info(&hif_dev->udev->dev, "ath9k_htc: Firmware %s requested\n", - hif_dev->fw_name); return ret; } diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c index 538c5d51c9fb1..b11a8064cfa6c 100644 --- a/drivers/scsi/libiscsi_tcp.c +++ b/drivers/scsi/libiscsi_tcp.c @@ -759,13 +759,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) rc = __iscsi_complete_pdu(conn, hdr, NULL, 0); spin_unlock(&conn->session->back_lock); break; - case ISCSI_OP_SCSI_CMD_RSP: - if (tcp_conn->in.datalen) { - iscsi_tcp_data_recv_prep(tcp_conn); - return 0; - } - rc = iscsi_complete_pdu(conn, hdr, NULL, 0); - break; case ISCSI_OP_R2T: if (ahslen) { rc = ISCSI_ERR_AHSLEN; @@ -773,6 +766,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) } rc = iscsi_tcp_r2t_rsp(conn, hdr); break; + case ISCSI_OP_SCSI_CMD_RSP: case ISCSI_OP_LOGIN_RSP: case ISCSI_OP_TEXT_RSP: case ISCSI_OP_REJECT: diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index fb0a599b83182..cc6943df601ef 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -746,6 +746,37 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats) } } +static void +fc_fpin_pname_stats_update(struct Scsi_Host *shost, + struct fc_rport *attach_rport, u16 event_type, + u32 desc_len, u32 fixed_len, u32 pname_count, + __be64 *pname_list, + void (*stats_update)(u16 event_type, + struct fc_fpin_stats *stats)) +{ + u32 i; + struct fc_rport *rport; + u64 wwpn; + + if (desc_len < fixed_len) + pname_count = 0; + else + pname_count = min(pname_count, (desc_len - fixed_len) / + sizeof(pname_list[0])); + + for (i = 0; i < pname_count; i++) { + wwpn = be64_to_cpu(pname_list[i]); + rport = fc_find_rport_by_wwpn(shost, wwpn); + if (rport && + (rport->roles & FC_PORT_ROLE_FCP_TARGET || + rport->roles & FC_PORT_ROLE_NVME_TARGET)) { + if (rport == attach_rport) + continue; + stats_update(event_type, &rport->fpin_stats); + } + } +} + /* * fc_fpin_li_stats_update - routine to update Link Integrity * event statistics. @@ -756,13 +787,11 @@ fc_cn_stats_update(u16 event_type, struct fc_fpin_stats *stats) static void fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv) { - u8 i; struct fc_rport *rport = NULL; struct fc_rport *attach_rport = NULL; struct fc_host_attrs *fc_host = shost_to_fc_host(shost); struct fc_fn_li_desc *li_desc = (struct fc_fn_li_desc *)tlv; u16 event_type = be16_to_cpu(li_desc->event_type); - u64 wwpn; rport = fc_find_rport_by_wwpn(shost, be64_to_cpu(li_desc->attached_wwpn)); @@ -773,22 +802,11 @@ fc_fpin_li_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv) fc_li_stats_update(event_type, &attach_rport->fpin_stats); } - if (be32_to_cpu(li_desc->pname_count) > 0) { - for (i = 0; - i < be32_to_cpu(li_desc->pname_count); - i++) { - wwpn = be64_to_cpu(li_desc->pname_list[i]); - rport = fc_find_rport_by_wwpn(shost, wwpn); - if (rport && - (rport->roles & FC_PORT_ROLE_FCP_TARGET || - rport->roles & FC_PORT_ROLE_NVME_TARGET)) { - if (rport == attach_rport) - continue; - fc_li_stats_update(event_type, - &rport->fpin_stats); - } - } - } + fc_fpin_pname_stats_update(shost, attach_rport, event_type, + be32_to_cpu(li_desc->desc_len), + FC_TLV_DESC_LENGTH_FROM_SZ(*li_desc), + be32_to_cpu(li_desc->pname_count), + li_desc->pname_list, fc_li_stats_update); if (fc_host->port_name == be64_to_cpu(li_desc->attached_wwpn)) fc_li_stats_update(event_type, &fc_host->fpin_stats); @@ -836,13 +854,11 @@ static void fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost, struct fc_tlv_desc *tlv) { - u8 i; struct fc_rport *rport = NULL; struct fc_rport *attach_rport = NULL; struct fc_fn_peer_congn_desc *pc_desc = (struct fc_fn_peer_congn_desc *)tlv; u16 event_type = be16_to_cpu(pc_desc->event_type); - u64 wwpn; rport = fc_find_rport_by_wwpn(shost, be64_to_cpu(pc_desc->attached_wwpn)); @@ -853,22 +869,11 @@ fc_fpin_peer_congn_stats_update(struct Scsi_Host *shost, fc_cn_stats_update(event_type, &attach_rport->fpin_stats); } - if (be32_to_cpu(pc_desc->pname_count) > 0) { - for (i = 0; - i < be32_to_cpu(pc_desc->pname_count); - i++) { - wwpn = be64_to_cpu(pc_desc->pname_list[i]); - rport = fc_find_rport_by_wwpn(shost, wwpn); - if (rport && - (rport->roles & FC_PORT_ROLE_FCP_TARGET || - rport->roles & FC_PORT_ROLE_NVME_TARGET)) { - if (rport == attach_rport) - continue; - fc_cn_stats_update(event_type, - &rport->fpin_stats); - } - } - } + fc_fpin_pname_stats_update(shost, attach_rport, event_type, + be32_to_cpu(pc_desc->desc_len), + FC_TLV_DESC_LENGTH_FROM_SZ(*pc_desc), + be32_to_cpu(pc_desc->pname_count), + pc_desc->pname_list, fc_cn_stats_update); } /* diff --git a/include/net/sock.h b/include/net/sock.h index 8f4e6ac212c5c..7ff56e1db05ab 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -1753,6 +1753,7 @@ struct sk_buff *sock_omalloc(struct sock *sk, unsigned long size, gfp_t priority); void skb_orphan_partial(struct sk_buff *skb); void sock_rfree(struct sk_buff *skb); +void sock_rmem_free(struct sk_buff *skb); void sock_efree(struct sk_buff *skb); #ifdef CONFIG_INET void sock_edemux(struct sk_buff *skb); diff --git a/kernel.sbat b/kernel.sbat index fc5ec781fd725..f45a9397fce64 100644 --- a/kernel.sbat +++ b/kernel.sbat @@ -1,2 +1,2 @@ sbat,1,SBAT Version,sbat,1,https://github.com/rhboot/shim/blob/main/SBAT.md -kernel.rocky,1,RESF,kernel-core,4.18.0-553.162.1.el8_10.x86_64,mailto:security@rockylinux.org +kernel.rocky,1,RESF,kernel-core,4.18.0-553.164.1.el8_10.x86_64,mailto:security@rockylinux.org diff --git a/net/core/dev.c b/net/core/dev.c index b92f10d4a315e..e69bb6dd240ea 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -3761,6 +3761,10 @@ int skb_csum_hwoffload_help(struct sk_buff *skb, } EXPORT_SYMBOL(skb_csum_hwoffload_help); + +/* Returns the skb on success, NULL if dropped, or ERR_PTR(-EINPROGRESS) + * if stolen by async xfrm crypto (delivered via xfrm_dev_resume()). + */ static struct sk_buff *validate_xmit_skb(struct sk_buff *skb, struct net_device *dev, bool *again) { netdev_features_t features; @@ -3828,7 +3832,7 @@ struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *d skb->prev = skb; skb = validate_xmit_skb(skb, dev, again); - if (!skb) + if (IS_ERR_OR_NULL(skb)) continue; if (!head) @@ -4378,8 +4382,11 @@ static int __dev_queue_xmit(struct sk_buff *skb, struct net_device *sb_dev) goto recursion_alert; skb = validate_xmit_skb(skb, dev, &again); - if (!skb) + if (IS_ERR_OR_NULL(skb)) { + if (PTR_ERR(skb) == -EINPROGRESS) + rc = NET_XMIT_SUCCESS; goto out; + } PRANDOM_ADD_NOISE(skb, dev, txq, jiffies); HARD_TX_LOCK(dev, txq, cpu); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index f1cce36d653dc..060e340287405 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -1244,16 +1244,13 @@ bool __skb_flow_dissect(const struct net *net, break; } - /* least significant bit of the most significant octet - * indicates if protocol field was compressed + /* PFC (compressed 1-byte protocol) frames are not processed. + * A compressed protocol field has the least significant bit of + * the most significant octet set, which will fail the following + * ppp_proto_is_valid(), returning FLOW_DISSECT_RET_OUT_BAD. */ ppp_proto = ntohs(hdr->proto); - if (ppp_proto & 0x0100) { - ppp_proto = ppp_proto >> 8; - nhoff += PPPOE_SES_HLEN - 1; - } else { - nhoff += PPPOE_SES_HLEN; - } + nhoff += PPPOE_SES_HLEN; if (ppp_proto == PPP_IP) { proto = htons(ETH_P_IP); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 8d4db21c38806..7356776e1bb33 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -4899,7 +4899,7 @@ int skb_cow_data(struct sk_buff *skb, int tailbits, struct sk_buff **trailer) } EXPORT_SYMBOL_GPL(skb_cow_data); -static void sock_rmem_free(struct sk_buff *skb) +void sock_rmem_free(struct sk_buff *skb) { struct sock *sk = skb->sk; @@ -4908,8 +4908,8 @@ static void sock_rmem_free(struct sk_buff *skb) static void skb_set_err_queue(struct sk_buff *skb) { - /* pkt_type of skbs received on local sockets is never PACKET_OUTGOING. - * So, it is safe to (mis)use it to mark skbs on the error queue. + /* The error-queue test in skb_is_err_queue() matches this marker + * with the sock_rmem_free destructor installed by sock_queue_err_skb(). */ skb->pkt_type = PACKET_OUTGOING; BUILD_BUG_ON(PACKET_OUTGOING == 0); diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index c98d8f3656d3d..472639affd1c8 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -777,16 +777,22 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) /* Checkin full IP header plus 8 bytes of protocol to * avoid additional coding at protocol handlers. */ - if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { - __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); - return; - } + if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) + goto out; + + /* IPPROTO_RAW sockets are not supposed to receive anything. */ + if (protocol == IPPROTO_RAW) + goto out; raw_icmp_error(skb, protocol, info); ipprot = rcu_dereference(inet_protos[protocol]); if (ipprot && ipprot->err_handler) ipprot->err_handler(skb, info); + return; + +out: + __ICMP_INC_STATS(dev_net(skb->dev), ICMP_MIB_INERRORS); } static bool icmp_tag_validation(int proto) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 660cc2703508e..a774331f45377 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -1323,10 +1323,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net) { struct ctl_table *table; - kfree(net->ipv4.sysctl_local_reserved_ports); table = net->ipv4.ipv4_hdr->ctl_table_arg; unregister_net_sysctl_table(net->ipv4.ipv4_hdr); kfree(table); + kfree(net->ipv4.sysctl_local_reserved_ports); } static __net_initdata struct pernet_operations ipv4_sysctl_ops = { diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 3feda5ad2af44..cf186b7efb64f 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c @@ -53,6 +53,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) { struct xfrm_offload *xo = xfrm_offload(skb); struct iphdr *iph = ip_hdr(skb); + struct net_device *dev = skb->dev; iph->protocol = XFRM_MODE_SKB_CB(skb)->protocol; @@ -72,7 +73,7 @@ int xfrm4_transport_finish(struct sk_buff *skb, int async) } NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, - dev_net(skb->dev), NULL, skb, skb->dev, NULL, + dev_net(dev), NULL, skb, dev, NULL, xfrm4_rcv_encap_finish); return 0; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 458dd874c4d15..20613a0601535 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3507,12 +3507,12 @@ static void addrconf_permanent_addr(struct net *net, struct net_device *dev) if ((ifp->flags & IFA_F_PERMANENT) && fixup_permanent_addr(net, idev, ifp) < 0) { write_unlock_bh(&idev->lock); - in6_ifa_hold(ifp); - ipv6_del_addr(ifp); - write_lock_bh(&idev->lock); net_info_ratelimited("%s: Failed to add prefix route for address %pI6c; dropping\n", idev->dev->name, &ifp->addr); + in6_ifa_hold(ifp); + ipv6_del_addr(ifp); + write_lock_bh(&idev->lock); } } diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f638a9b6ecf94..19d60db29b412 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -794,6 +794,12 @@ enum skb_drop_reason icmpv6_notify(struct sk_buff *skb, u8 type, if (reason != SKB_NOT_DROPPED_YET) goto out; + if (nexthdr == IPPROTO_RAW) { + /* Add a more specific reason later ? */ + reason = SKB_DROP_REASON_NOT_SPECIFIED; + goto out; + } + /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. Without this we will not able f.e. to make source routed pmtu discovery. diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 6f476ac3ba3b5..551e117af4206 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -738,10 +738,11 @@ vti6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p, static int vti6_update(struct ip6_tnl *t, struct __ip6_tnl_parm *p, bool keep_mtu) { - struct net *net = dev_net(t->dev); - struct vti6_net *ip6n = net_generic(net, vti6_net_id); + struct net *net = t->net; + struct vti6_net *ip6n; int err; + ip6n = net_generic(net, vti6_net_id); vti6_tnl_unlink(ip6n, t); synchronize_net(); err = vti6_tnl_change(t, p, keep_mtu); @@ -849,17 +850,24 @@ vti6_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if (p.proto != IPPROTO_IPV6 && p.proto != 0) break; vti6_parm_from_user(&p1, &p); - t = vti6_locate(net, &p1, cmd == SIOCADDTUNNEL); if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) { + struct ip6_tnl *self = netdev_priv(dev); + + err = -EPERM; + if (!ns_capable(self->net->user_ns, CAP_NET_ADMIN)) + break; + t = vti6_locate(self->net, &p1, false); if (t) { if (t->dev != dev) { err = -EEXIST; break; } } else - t = netdev_priv(dev); + t = self; err = vti6_update(t, &p1, false); + } else { + t = vti6_locate(net, &p1, cmd == SIOCADDTUNNEL); } if (t) { err = 0; @@ -1045,11 +1053,12 @@ static int vti6_changelink(struct net_device *dev, struct nlattr *tb[], struct nlattr *data[], struct netlink_ext_ack *extack) { - struct ip6_tnl *t; + struct ip6_tnl *t = netdev_priv(dev); + struct net *net = t->net; struct __ip6_tnl_parm p; - struct net *net = dev_net(dev); - struct vti6_net *ip6n = net_generic(net, vti6_net_id); + struct vti6_net *ip6n; + ip6n = net_generic(net, vti6_net_id); if (dev == ip6n->fb_tnl_dev) return -EINVAL; diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 088006e7eb1df..1a86f44082538 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1341,9 +1341,9 @@ int igmp6_event_query(struct sk_buff *skb) { struct mld2_query *mlh2 = NULL; struct ifmcaddr6 *ma; - const struct in6_addr *group; unsigned long max_delay; struct inet6_dev *idev; + struct in6_addr group; struct mld_msg *mld; int group_type; int mark = 0; @@ -1374,8 +1374,8 @@ int igmp6_event_query(struct sk_buff *skb) return 0; mld = (struct mld_msg *)icmp6_hdr(skb); - group = &mld->mld_mca; - group_type = ipv6_addr_type(group); + group = mld->mld_mca; + group_type = ipv6_addr_type(&group); if (group_type != IPV6_ADDR_ANY && !(group_type&IPV6_ADDR_MULTICAST)) @@ -1430,7 +1430,7 @@ int igmp6_event_query(struct sk_buff *skb) } } else { for (ma = idev->mc_list; ma; ma = ma->next) { - if (!ipv6_addr_equal(group, &ma->mca_addr)) + if (!ipv6_addr_equal(&group, &ma->mca_addr)) continue; spin_lock_bh(&ma->mca_lock); if (ma->mca_flags & MAF_TIMER_RUNNING) { diff --git a/net/ipv6/netfilter/ip6t_eui64.c b/net/ipv6/netfilter/ip6t_eui64.c index cda3d43e527d5..96273dcdc54cc 100644 --- a/net/ipv6/netfilter/ip6t_eui64.c +++ b/net/ipv6/netfilter/ip6t_eui64.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -24,8 +25,10 @@ eui64_mt6(const struct sk_buff *skb, struct xt_action_param *par) { unsigned char eui64[8]; - if (!(skb_mac_header(skb) >= skb->head && - skb_mac_header(skb) + ETH_HLEN <= skb->data)) { + if (!skb->dev || skb->dev->type != ARPHRD_ETHER) + return false; + + if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) { par->hotdrop = true; return false; } diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 3188e30d79f25..5f22ef7d3b5cb 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -929,6 +929,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, ip_rt_put(rt); goto tx_error; } + iph6 = ipv6_hdr(skb); if (df) { mtu = dst_mtu(&rt->dst) - t_hlen; diff --git a/net/ipv6/xfrm6_input.c b/net/ipv6/xfrm6_input.c index 086605fbec353..b5127f2da4d35 100644 --- a/net/ipv6/xfrm6_input.c +++ b/net/ipv6/xfrm6_input.c @@ -46,6 +46,7 @@ static int xfrm6_transport_finish2(struct net *net, struct sock *sk, int xfrm6_transport_finish(struct sk_buff *skb, int async) { struct xfrm_offload *xo = xfrm_offload(skb); + struct net_device *dev = skb->dev; int nhlen = skb->data - skb_network_header(skb); skb_network_header(skb)[IP6CB(skb)->nhoff] = @@ -67,7 +68,7 @@ int xfrm6_transport_finish(struct sk_buff *skb, int async) } NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, - dev_net(skb->dev), NULL, skb, skb->dev, NULL, + dev_net(dev), NULL, skb, dev, NULL, xfrm6_transport_finish2); return 0; } diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 5bbf2e1509e1b..863c83c73dac7 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3356,6 +3356,11 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) if (!ieee80211_is_mgmt(mgmt->frame_control)) return RX_DROP_MONITOR; + /* Drop non-broadcast Beacon frames */ + if (ieee80211_is_beacon(mgmt->frame_control) && + !is_broadcast_ether_addr(mgmt->da)) + return RX_DROP_MONITOR; + if (rx->sdata->vif.type == NL80211_IFTYPE_AP && ieee80211_is_beacon(mgmt->frame_control) && !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { @@ -4787,6 +4792,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, u8 sa[ETH_ALEN]; } addrs __aligned(2); struct ieee80211_sta_rx_stats *stats; + u32 encoded_rate; /* for parallel-rx, we need to have DUP_VALIDATED, otherwise we write * to a common data structure; drivers can implement that per queue @@ -4858,6 +4864,11 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, /* after this point, don't punt to the slowpath! */ + if (fast_rx->uses_rss) + stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats); + else + stats = &rx->link_sta->rx_stats; + if (rx->key && !(status->flag & RX_FLAG_MIC_STRIPPED) && pskb_trim(skb, skb->len - fast_rx->icv_len)) goto drop; @@ -4889,9 +4900,14 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, /* push the addresses in front */ memcpy(skb_push(skb, sizeof(addrs)), &addrs, sizeof(addrs)); + /* capture before mesh forward may memset or free skb->cb */ + encoded_rate = sta_stats_encode_rate(status); + res = ieee80211_rx_mesh_data(rx->sdata, rx->sta, rx->skb); switch (res) { case RX_QUEUED: + stats->last_rx = jiffies; + stats->last_rate = encoded_rate; return true; case RX_CONTINUE: break; @@ -4905,11 +4921,6 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx, drop: dev_kfree_skb(skb); - if (fast_rx->uses_rss) - stats = this_cpu_ptr(rx->link_sta->pcpu_rx_stats); - else - stats = &rx->link_sta->rx_stats; - stats->dropped++; return true; } diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index f0806e54c31a9..9e8e678d29688 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -224,8 +225,8 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, return -IPSET_ERR_BITMAP_RANGE; /* Backward compatibility: we don't check the second flag */ - if (skb_mac_header(skb) < skb->head || - (skb_mac_header(skb) + ETH_HLEN) > skb->data) + if (!skb->dev || skb->dev->type != ARPHRD_ETHER || + !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) return -EINVAL; e.id = ip_to_id(map, ip); diff --git a/net/netfilter/ipset/ip_set_hash_ipmac.c b/net/netfilter/ipset/ip_set_hash_ipmac.c index f2c2f72e2fffc..b7b98b1293158 100644 --- a/net/netfilter/ipset/ip_set_hash_ipmac.c +++ b/net/netfilter/ipset/ip_set_hash_ipmac.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -92,8 +93,8 @@ hash_ipmac4_kadt(struct ip_set *set, const struct sk_buff *skb, struct hash_ipmac4_elem e = { .ip = 0, { .foo[0] = 0, .foo[1] = 0 } }; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); - if (skb_mac_header(skb) < skb->head || - (skb_mac_header(skb) + ETH_HLEN) > skb->data) + if (!skb->dev || skb->dev->type != ARPHRD_ETHER || + !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) return -EINVAL; if (opt->flags & IPSET_DIM_TWO_SRC) @@ -208,8 +209,8 @@ hash_ipmac6_kadt(struct ip_set *set, const struct sk_buff *skb, }; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); - if (skb_mac_header(skb) < skb->head || - (skb_mac_header(skb) + ETH_HLEN) > skb->data) + if (!skb->dev || skb->dev->type != ARPHRD_ETHER || + !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) return -EINVAL; if (opt->flags & IPSET_DIM_TWO_SRC) diff --git a/net/netfilter/ipset/ip_set_hash_mac.c b/net/netfilter/ipset/ip_set_hash_mac.c index 4fe5f243d0a32..ccb925f82fa7c 100644 --- a/net/netfilter/ipset/ip_set_hash_mac.c +++ b/net/netfilter/ipset/ip_set_hash_mac.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -81,8 +82,8 @@ hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb, struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } }; struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); - if (skb_mac_header(skb) < skb->head || - (skb_mac_header(skb) + ETH_HLEN) > skb->data) + if (!skb->dev || skb->dev->type != ARPHRD_ETHER || + !skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) return -EINVAL; if (opt->flags & IPSET_DIM_ONE_SRC) diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c index 8ab3284828bc7..c46357538aa37 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c @@ -799,7 +799,7 @@ static int decode_choice(struct bitstr *bs, const struct field_t *f, if (ext || (son->attr & OPEN)) { BYTE_ALIGN(bs); - if (nf_h323_error_boundary(bs, len, 0)) + if (nf_h323_error_boundary(bs, 2, 0)) return H323_ERROR_BOUND; len = get_len(bs); if (nf_h323_error_boundary(bs, len, 0)) diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index ea003ef7ad1b3..5eccd29d5689b 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c @@ -206,7 +206,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, if (parse_dcc(data, data_limit, &dcc_ip, &dcc_port, &addr_beg_p, &addr_end_p)) { pr_debug("unable to parse dcc command\n"); - continue; + goto out; } pr_debug("DCC bound ip/port: %pI4:%u\n", @@ -220,7 +220,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, net_warn_ratelimited("Forged DCC command from %pI4: %pI4:%u\n", &tuple->src.u3.ip, &dcc_ip, dcc_port); - continue; + goto out; } exp = nf_ct_expect_alloc(ct); diff --git a/net/netfilter/nf_log_syslog.c b/net/netfilter/nf_log_syslog.c index d78a85c45ac6c..53bd25200d2fe 100644 --- a/net/netfilter/nf_log_syslog.c +++ b/net/netfilter/nf_log_syslog.c @@ -81,7 +81,10 @@ dump_arp_packet(struct nf_log_buf *m, else logflags = NF_LOG_DEFAULT_MASK; - if (logflags & NF_LOG_MACDECODE) { + if ((logflags & NF_LOG_MACDECODE) && + skb->dev && skb->dev->type == ARPHRD_ETHER && + skb_mac_header_was_set(skb) && + skb_mac_header_len(skb) >= ETH_HLEN) { nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest); nf_log_dump_vlan(m, skb); @@ -790,6 +793,9 @@ static void dump_mac_header(struct nf_log_buf *m, switch (dev->type) { case ARPHRD_ETHER: + if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) + return; + nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM ", eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest); nf_log_dump_vlan(m, skb); diff --git a/net/netfilter/xt_mac.c b/net/netfilter/xt_mac.c index d5b4fd4f91ed6..df42d0233d732 100644 --- a/net/netfilter/xt_mac.c +++ b/net/netfilter/xt_mac.c @@ -32,9 +32,7 @@ static bool mac_mt(const struct sk_buff *skb, struct xt_action_param *par) if (skb->dev == NULL || skb->dev->type != ARPHRD_ETHER) return false; - if (skb_mac_header(skb) < skb->head) - return false; - if (skb_mac_header(skb) + ETH_HLEN > skb->data) + if (!skb_mac_header_was_set(skb) || skb_mac_header_len(skb) < ETH_HLEN) return false; ret = ether_addr_equal(eth_hdr(skb)->h_source, info->srcaddr); ret ^= info->invert; diff --git a/net/netfilter/xt_policy.c b/net/netfilter/xt_policy.c index 13f8ccf946d62..e8ebaf5f264cc 100644 --- a/net/netfilter/xt_policy.c +++ b/net/netfilter/xt_policy.c @@ -66,7 +66,7 @@ match_policy_in(const struct sk_buff *skb, const struct xt_policy_info *info, return 0; for (i = sp->len - 1; i >= 0; i--) { - pos = strict ? i - sp->len + 1 : 0; + pos = strict ? sp->len - i - 1 : 0; if (pos >= info->len) return 0; e = &info->pol[pos]; diff --git a/net/qrtr/af_qrtr.c b/net/qrtr/af_qrtr.c index 48b22caf451e5..f58e38b493eb9 100644 --- a/net/qrtr/af_qrtr.c +++ b/net/qrtr/af_qrtr.c @@ -495,7 +495,7 @@ int qrtr_endpoint_post(struct qrtr_endpoint *ep, const void *data, size_t len) goto err; } - if (!size || len != ALIGN(size, 4) + hdrlen) + if (!size || size > len || len != ALIGN(size, 4) + hdrlen) goto err; if ((cb->type == QRTR_TYPE_NEW_SERVER || @@ -707,13 +707,13 @@ static void qrtr_port_remove(struct qrtr_sock *ipc) if (port == QRTR_PORT_CTRL) port = 0; - __sock_put(&ipc->sk); - xa_erase(&qrtr_ports, port); /* Ensure that if qrtr_port_lookup() did enter the RCU read section we * wait for it to up increment the refcount */ synchronize_rcu(); + + __sock_put(&ipc->sk); } /* Assign port number to socket. @@ -1266,6 +1266,14 @@ static int qrtr_create(struct net *net, struct socket *sock, if (sock->type != SOCK_DGRAM) return -EPROTOTYPE; + /* QRTR keeps its port and node state in module-global variables that + * are not partitioned per network namespace, and the in-kernel name + * service only operates in init_net. Confine the family to init_net so + * a socket in another namespace cannot reach the global control plane. + */ + if (!net_eq(net, &init_net)) + return -EAFNOSUPPORT; + sk = sk_alloc(net, AF_QIPCRTR, GFP_KERNEL, &qrtr_proto, kern); if (!sk) return -ENOMEM; diff --git a/net/socket.c b/net/socket.c index 3172a677efbc9..ebc8f536d7310 100644 --- a/net/socket.c +++ b/net/socket.c @@ -747,12 +747,13 @@ EXPORT_SYMBOL(kernel_sendmsg_locked); static bool skb_is_err_queue(const struct sk_buff *skb) { - /* pkt_type of skbs enqueued on the error queue are set to - * PACKET_OUTGOING in skb_set_err_queue(). This is only safe to do - * in recvmsg, since skbs received on a local socket will never - * have a pkt_type of PACKET_OUTGOING. + /* Error-queue skbs are marked as PACKET_OUTGOING in + * skb_set_err_queue() and use the destructor installed by + * sock_queue_err_skb(). PACKET_OUTGOING alone is not unique: + * AF_PACKET outgoing taps use the same pkt_type. */ - return skb->pkt_type == PACKET_OUTGOING; + return skb->pkt_type == PACKET_OUTGOING && + skb->destructor == sock_rmem_free; } /* On transmit, software and hardware timestamps are returned independently. diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 2aacbb75d0202..dbac3e1ac7eb7 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5464,6 +5464,9 @@ nl80211_parse_rnr_elems(struct wiphy *wiphy, struct nlattr *attrs, if (ret) return ERR_PTR(ret); + if (num_elems >= 255) + return ERR_PTR(-EINVAL); + num_elems++; } diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index 1ea03ebadaa69..e74c5fe45dba2 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -162,7 +162,7 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur err = x->type_offload->xmit(x, skb, esp_features); if (err) { if (err == -EINPROGRESS) - return NULL; + return ERR_PTR(-EINPROGRESS); XFRM_INC_STATS(xs_net(x), LINUX_MIB_XFRMOUTSTATEPROTOERROR); kfree_skb(skb); @@ -211,7 +211,15 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur skb2 = nskb; } while (skb2); - return skb; + /* skb_gso_segment() set skb->prev to the last segment, but async + * crypto may have stolen it above without updating ->prev. Repoint + * it at the last retained segment so validate_xmit_skb_list() does + * not chain onto a segment now owned by the crypto engine. + */ + if (skb) + skb->prev = pskb; + + return skb ? skb : ERR_PTR(-EINPROGRESS); } EXPORT_SYMBOL_GPL(validate_xmit_xfrm); diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 6ceac35d61fa1..7dc6896bec10f 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -492,6 +492,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) const struct xfrm_state_afinfo *afinfo; struct net *net = dev_net(skb->dev); const struct xfrm_mode *inner_mode; + struct net_device *dev = skb->dev; int err; __be32 seq; __be32 seq_hi; @@ -516,7 +517,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) LINUX_MIB_XFRMINSTATEINVALID); if (encap_type == -1) - dev_put(skb->dev); + dev_put(dev); goto drop; } @@ -662,18 +663,21 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) XFRM_SKB_CB(skb)->seq.input.low = seq; XFRM_SKB_CB(skb)->seq.input.hi = seq_hi; - dev_hold(skb->dev); - - if (crypto_done) + if (crypto_done) { nexthdr = x->type_offload->input_tail(x, skb); - else + } else { + dev_hold(dev); + nexthdr = x->type->input(x, skb); + if (nexthdr == -EINPROGRESS) { + if (async) + dev_put(dev); + return 0; + } - if (nexthdr == -EINPROGRESS) - return 0; + dev_put(dev); + } resume: - dev_put(skb->dev); - spin_lock(&x->lock); if (nexthdr < 0) { if (nexthdr == -EBADMSG) { @@ -737,9 +741,12 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) crypto_done = false; } while (!err); + rcu_read_lock(); err = xfrm_rcv_cb(skb, family, x->type->proto, 0); - if (err) + if (err) { + rcu_read_unlock(); goto drop; + } nf_reset(skb); @@ -747,7 +754,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) if (skb->sp) skb->sp->olen = 0; skb_dst_drop(skb); + if (async) + dev_put(dev); gro_cells_receive(&gro_cells, skb); + rcu_read_unlock(); return 0; } else { xo = xfrm_offload(skb); @@ -755,25 +765,27 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) xfrm_gro = xo->flags & XFRM_GRO; err = -EAFNOSUPPORT; - rcu_read_lock(); afinfo = xfrm_state_afinfo_get_rcu(x->inner_mode->family); if (likely(afinfo)) err = afinfo->transport_finish(skb, xfrm_gro || async); - rcu_read_unlock(); if (xfrm_gro) { if (skb->sp) skb->sp->olen = 0; skb_dst_drop(skb); gro_cells_receive(&gro_cells, skb); - return err; } + if (async) + dev_put(dev); + rcu_read_unlock(); return err; } drop_unlock: spin_unlock(&x->lock); drop: + if (async) + dev_put(dev); xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1); kfree_skb(skb); return 0; @@ -795,9 +807,12 @@ static void xfrm_trans_reinject(unsigned long data) __skb_queue_head_init(&queue); skb_queue_splice_init(&trans->queue, &queue); - while ((skb = __skb_dequeue(&queue))) - XFRM_TRANS_SKB_CB(skb)->finish(XFRM_TRANS_SKB_CB(skb)->net, - NULL, skb); + while ((skb = __skb_dequeue(&queue))) { + struct net *net = XFRM_TRANS_SKB_CB(skb)->net; + + XFRM_TRANS_SKB_CB(skb)->finish(net, NULL, skb); + put_net(net); + } } int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, @@ -805,6 +820,7 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, struct sk_buff *)) { struct xfrm_trans_tasklet *trans; + struct net *hold_net; trans = this_cpu_ptr(&xfrm_trans_tasklet); @@ -813,8 +829,12 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, BUILD_BUG_ON(sizeof(struct xfrm_trans_cb) > sizeof(skb->cb)); + hold_net = maybe_get_net(net); + if (!hold_net) + return -ENODEV; + XFRM_TRANS_SKB_CB(skb)->finish = finish; - XFRM_TRANS_SKB_CB(skb)->net = net; + XFRM_TRANS_SKB_CB(skb)->net = hold_net; __skb_queue_tail(&trans->queue, skb); tasklet_schedule(&trans->tasklet); return 0; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 6df211f2d530c..00c0f7a741290 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -1096,15 +1096,6 @@ static void __xfrm_policy_inexact_prune_bin(struct xfrm_pol_inexact_bin *b, bool } } -static void xfrm_policy_inexact_prune_bin(struct xfrm_pol_inexact_bin *b) -{ - struct net *net = read_pnet(&b->k.net); - - spin_lock_bh(&net->xfrm.xfrm_policy_lock); - __xfrm_policy_inexact_prune_bin(b, false); - spin_unlock_bh(&net->xfrm.xfrm_policy_lock); -} - static void __xfrm_policy_inexact_flush(struct net *net) { struct xfrm_pol_inexact_bin *bin, *t; @@ -1694,12 +1685,12 @@ xfrm_policy_bysel_ctx(struct net *net, const struct xfrm_mark *mark, u32 if_id, } ret = pol; } + if (bin && delete) + __xfrm_policy_inexact_prune_bin(bin, false); spin_unlock_bh(&net->xfrm.xfrm_policy_lock); if (ret && delete) xfrm_policy_kill(ret); - if (bin && delete) - xfrm_policy_inexact_prune_bin(bin); return ret; } EXPORT_SYMBOL(xfrm_policy_bysel_ctx); diff --git a/sound/core/timer.c b/sound/core/timer.c index e3661402d28ef..92e145296e59b 100644 --- a/sound/core/timer.c +++ b/sound/core/timer.c @@ -1841,14 +1841,21 @@ static int snd_timer_user_params(struct file *file, struct snd_timer *t; int err; + mutex_lock(®ister_mutex); tu = file->private_data; - if (!tu->timeri) + if (!tu->timeri) { + mutex_unlock(®ister_mutex); return -EBADFD; + } t = tu->timeri->timer; - if (!t) + if (!t) { + mutex_unlock(®ister_mutex); return -EBADFD; - if (copy_from_user(¶ms, _params, sizeof(params))) + } + if (copy_from_user(¶ms, _params, sizeof(params))) { + mutex_unlock(®ister_mutex); return -EFAULT; + } if (!(t->hw.flags & SNDRV_TIMER_HW_SLAVE)) { u64 resolution; @@ -1929,6 +1936,7 @@ static int snd_timer_user_params(struct file *file, spin_unlock_irq(&tu->qlock); err = 0; _end: + mutex_unlock(®ister_mutex); if (copy_to_user(_params, ¶ms, sizeof(params))) return -EFAULT; return err;