mirror of
https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9.git
synced 2026-09-09 00:08:12 +08:00
Merge: Merge tag 'kernel-5.14.0-741.1.1.el9_9' into centos-stream-9/main
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8708 Merge kernel MRs from RHEL-9.9's kernel-5.14.0-741.1.1.el9_9 into the centos-stream-9/main repo for 9.10 inclusion. MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8664 MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8234 MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/8535 MR: https://gitlab.com/redhat/rhel/src/kernel/rhel-9/-/merge_requests/7141 MR: https://gitlab.com/redhat/rhel/src/kernel/rhel-9/-/merge_requests/7139 Signed-off-by: Jarod Wilson <jarod@redhat.com> Approved-by: Shivani Chandanshive <schandan@redhat.com> Approved-by: Julio Faracco <jfaracco@redhat.com> Merged-by: CKI GitLab Kmaint Pipeline Bot <26919896-cki-kmaint-pipeline-bot@users.noreply.gitlab.com>
This commit is contained in:
@@ -914,6 +914,12 @@ static void privcmd_close(struct vm_area_struct *vma)
|
||||
kfree(pages);
|
||||
}
|
||||
|
||||
static int privcmd_may_split(struct vm_area_struct *area, unsigned long addr)
|
||||
{
|
||||
/* Forbid splitting, avoids double free via privcmd_close(). */
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static vm_fault_t privcmd_fault(struct vm_fault *vmf)
|
||||
{
|
||||
printk(KERN_DEBUG "privcmd_fault: vma=%p %lx-%lx, pgoff=%lx, uv=%p\n",
|
||||
@@ -925,6 +931,7 @@ static vm_fault_t privcmd_fault(struct vm_fault *vmf)
|
||||
|
||||
static const struct vm_operations_struct privcmd_vm_ops = {
|
||||
.close = privcmd_close,
|
||||
.may_split = privcmd_may_split,
|
||||
.fault = privcmd_fault
|
||||
};
|
||||
|
||||
|
||||
@@ -364,6 +364,8 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
|
||||
ret = sprintf(buffer, "<denied>");
|
||||
return ret;
|
||||
}
|
||||
if (ret > PAGE_SIZE)
|
||||
return -ENOSPC;
|
||||
|
||||
buildid = kmalloc(sizeof(*buildid) + ret, GFP_KERNEL);
|
||||
if (!buildid)
|
||||
@@ -371,8 +373,10 @@ static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer)
|
||||
|
||||
buildid->len = ret;
|
||||
ret = HYPERVISOR_xen_version(XENVER_build_id, buildid);
|
||||
if (ret > 0)
|
||||
ret = sprintf(buffer, "%s", buildid->buf);
|
||||
if (ret > 0) {
|
||||
/* Build id is binary, not a string. */
|
||||
memcpy(buffer, buildid->buf, ret);
|
||||
}
|
||||
kfree(buildid);
|
||||
|
||||
return ret;
|
||||
|
||||
@@ -114,7 +114,7 @@ static inline bool inet6_match(struct net *net, const struct sock *sk,
|
||||
|
||||
if (!net_eq(sock_net(sk), net) ||
|
||||
sk->sk_family != AF_INET6 ||
|
||||
sk->sk_portpair != ports ||
|
||||
READ_ONCE(sk->sk_portpair) != ports ||
|
||||
!ipv6_addr_equal(&sk->sk_v6_daddr, saddr) ||
|
||||
!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
|
||||
return false;
|
||||
|
||||
@@ -274,7 +274,7 @@ static inline bool inet_match(struct net *net, const struct sock *sk,
|
||||
int bound_dev_if;
|
||||
|
||||
if (!net_eq(sock_net(sk), net) ||
|
||||
sk->sk_portpair != ports ||
|
||||
READ_ONCE(sk->sk_portpair) != ports ||
|
||||
sk->sk_addrpair != cookie)
|
||||
return false;
|
||||
|
||||
|
||||
+1
-1
@@ -96,7 +96,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
|
||||
ipcm->sockc.tsflags = inet->sk.sk_tsflags;
|
||||
ipcm->oif = READ_ONCE(inet->sk.sk_bound_dev_if);
|
||||
ipcm->addr = inet->inet_saddr;
|
||||
ipcm->protocol = inet->inet_num;
|
||||
ipcm->protocol = READ_ONCE(inet->inet_num);
|
||||
}
|
||||
|
||||
#define IPCB(skb) ((struct inet_skb_parm*)((skb)->cb))
|
||||
|
||||
+7
-4
@@ -1273,12 +1273,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
|
||||
|
||||
static inline int ip6_sock_set_v6only(struct sock *sk)
|
||||
{
|
||||
if (inet_sk(sk)->inet_num)
|
||||
return -EINVAL;
|
||||
int ret = 0;
|
||||
|
||||
lock_sock(sk);
|
||||
sk->sk_ipv6only = true;
|
||||
if (inet_sk(sk)->inet_num)
|
||||
ret = -EINVAL;
|
||||
else
|
||||
sk->sk_ipv6only = true;
|
||||
release_sock(sk);
|
||||
return 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void ip6_sock_set_recverr(struct sock *sk)
|
||||
|
||||
@@ -319,7 +319,8 @@ struct sctp_cookie {
|
||||
|
||||
__u8 auth_random[sizeof(struct sctp_paramhdr) +
|
||||
SCTP_AUTH_RANDOM_LENGTH];
|
||||
__u8 auth_hmacs[SCTP_AUTH_NUM_HMACS * sizeof(__u16) + 2];
|
||||
__u8 auth_hmacs[sizeof(struct sctp_paramhdr) +
|
||||
SCTP_AUTH_NUM_HMACS * sizeof(__u16)];
|
||||
__u8 auth_chunks[sizeof(struct sctp_paramhdr) + SCTP_AUTH_MAX_CHUNKS];
|
||||
|
||||
/* This is a shim for my peer's INIT packet, followed by
|
||||
|
||||
@@ -1197,7 +1197,7 @@ next_chunk:
|
||||
if (r->sdiag_family != AF_UNSPEC &&
|
||||
sk->sk_family != r->sdiag_family)
|
||||
goto next_normal;
|
||||
if (r->id.idiag_sport != htons(sk->sk_num) &&
|
||||
if (r->id.idiag_sport != htons(READ_ONCE(sk->sk_num)) &&
|
||||
r->id.idiag_sport)
|
||||
goto next_normal;
|
||||
if (r->id.idiag_dport != sk->sk_dport &&
|
||||
|
||||
@@ -95,7 +95,7 @@ void inet_bind_bucket_destroy(struct kmem_cache *cachep, struct inet_bind_bucket
|
||||
void inet_bind_hash(struct sock *sk, struct inet_bind_bucket *tb,
|
||||
const unsigned short snum)
|
||||
{
|
||||
inet_sk(sk)->inet_num = snum;
|
||||
WRITE_ONCE(inet_sk(sk)->inet_num, snum);
|
||||
sk_add_bind_node(sk, &tb->owners);
|
||||
inet_csk(sk)->icsk_bind_hash = tb;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ static void __inet_put_port(struct sock *sk)
|
||||
tb = inet_csk(sk)->icsk_bind_hash;
|
||||
__sk_del_bind_node(sk);
|
||||
inet_csk(sk)->icsk_bind_hash = NULL;
|
||||
inet_sk(sk)->inet_num = 0;
|
||||
WRITE_ONCE(inet_sk(sk)->inet_num, 0);
|
||||
inet_bind_bucket_destroy(hashinfo->bind_bucket_cachep, tb);
|
||||
spin_unlock(&head->lock);
|
||||
}
|
||||
@@ -199,7 +199,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
|
||||
{
|
||||
int score = -1;
|
||||
|
||||
if (net_eq(sock_net(sk), net) && sk->sk_num == hnum &&
|
||||
if (net_eq(sock_net(sk), net) && READ_ONCE(sk->sk_num) == hnum &&
|
||||
!ipv6_only_sock(sk)) {
|
||||
if (sk->sk_rcv_saddr != daddr)
|
||||
return -1;
|
||||
|
||||
+13
-6
@@ -2115,16 +2115,18 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
|
||||
struct net *net = dev_net(ifp->idev->dev);
|
||||
int max_addresses;
|
||||
|
||||
if (addrconf_dad_end(ifp)) {
|
||||
spin_lock_bh(&ifp->lock);
|
||||
|
||||
if (ifp->state != INET6_IFADDR_STATE_DAD) {
|
||||
spin_unlock_bh(&ifp->lock);
|
||||
in6_ifa_put(ifp);
|
||||
return;
|
||||
}
|
||||
ifp->state = INET6_IFADDR_STATE_POSTDAD;
|
||||
|
||||
net_info_ratelimited("%s: IPv6 duplicate address %pI6c used by %pM detected!\n",
|
||||
ifp->idev->dev->name, &ifp->addr, eth_hdr(skb)->h_source);
|
||||
|
||||
spin_lock_bh(&ifp->lock);
|
||||
|
||||
if (ifp->flags & IFA_F_STABLE_PRIVACY) {
|
||||
struct in6_addr new_addr;
|
||||
struct inet6_ifaddr *ifp2;
|
||||
@@ -2172,6 +2174,11 @@ void addrconf_dad_failure(struct sk_buff *skb, struct inet6_ifaddr *ifp)
|
||||
in6_ifa_put(ifp2);
|
||||
lock_errdad:
|
||||
spin_lock_bh(&ifp->lock);
|
||||
if (ifp->state != INET6_IFADDR_STATE_POSTDAD) {
|
||||
spin_unlock_bh(&ifp->lock);
|
||||
in6_ifa_put(ifp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
errdad:
|
||||
@@ -3531,12 +3538,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+56
-8
@@ -616,6 +616,18 @@ void ip6_datagram_recv_common_ctl(struct sock *sk, struct msghdr *msg,
|
||||
}
|
||||
}
|
||||
|
||||
static u16 ipv6_get_exthdr_len(const struct sk_buff *skb, const u8 *ptr)
|
||||
{
|
||||
u16 len;
|
||||
|
||||
if (ptr + 2 > skb_tail_pointer(skb))
|
||||
return 0;
|
||||
|
||||
len = (ptr[1] + 1) << 3;
|
||||
|
||||
return (len <= skb_tail_pointer(skb) - ptr) ? len : 0;
|
||||
}
|
||||
|
||||
void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
@@ -642,7 +654,10 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
|
||||
/* HbH is allowed only once */
|
||||
if (np->rxopt.bits.hopopts && (opt->flags & IP6SKB_HOPBYHOP)) {
|
||||
u8 *ptr = nh + sizeof(struct ipv6hdr);
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr);
|
||||
u16 len = ipv6_get_exthdr_len(skb, ptr);
|
||||
|
||||
if (len)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, len, ptr);
|
||||
}
|
||||
|
||||
if (opt->lastopt &&
|
||||
@@ -663,26 +678,37 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
|
||||
unsigned int len;
|
||||
u8 *ptr = nh + off;
|
||||
|
||||
if (ptr + 2 > skb_tail_pointer(skb))
|
||||
return;
|
||||
|
||||
switch (nexthdr) {
|
||||
case IPPROTO_DSTOPTS:
|
||||
nexthdr = ptr[0];
|
||||
len = (ptr[1] + 1) << 3;
|
||||
len = ipv6_get_exthdr_len(skb, ptr);
|
||||
if (!len)
|
||||
return;
|
||||
if (np->rxopt.bits.dstopts)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, len, ptr);
|
||||
break;
|
||||
case IPPROTO_ROUTING:
|
||||
nexthdr = ptr[0];
|
||||
len = (ptr[1] + 1) << 3;
|
||||
len = ipv6_get_exthdr_len(skb, ptr);
|
||||
if (!len)
|
||||
return;
|
||||
if (np->rxopt.bits.srcrt)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, len, ptr);
|
||||
break;
|
||||
case IPPROTO_AH:
|
||||
nexthdr = ptr[0];
|
||||
len = (ptr[1] + 2) << 2;
|
||||
if (ptr + len > skb_tail_pointer(skb))
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
nexthdr = ptr[0];
|
||||
len = (ptr[1] + 1) << 3;
|
||||
len = ipv6_get_exthdr_len(skb, ptr);
|
||||
if (!len)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -704,19 +730,31 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
|
||||
}
|
||||
if (np->rxopt.bits.ohopopts && (opt->flags & IP6SKB_HOPBYHOP)) {
|
||||
u8 *ptr = nh + sizeof(struct ipv6hdr);
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr);
|
||||
u16 len = ipv6_get_exthdr_len(skb, ptr);
|
||||
|
||||
if (len)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, len, ptr);
|
||||
}
|
||||
if (np->rxopt.bits.odstopts && opt->dst0) {
|
||||
u8 *ptr = nh + opt->dst0;
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
|
||||
u16 len = ipv6_get_exthdr_len(skb, ptr);
|
||||
|
||||
if (len)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, len, ptr);
|
||||
}
|
||||
if (np->rxopt.bits.osrcrt && opt->srcrt) {
|
||||
struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(nh + opt->srcrt);
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr);
|
||||
u16 len = ipv6_get_exthdr_len(skb, (u8 *)rthdr);
|
||||
|
||||
if (len)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, len, rthdr);
|
||||
}
|
||||
if (np->rxopt.bits.odstopts && opt->dst1) {
|
||||
u8 *ptr = nh + opt->dst1;
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr);
|
||||
u16 len = ipv6_get_exthdr_len(skb, ptr);
|
||||
|
||||
if (len)
|
||||
put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, len, ptr);
|
||||
}
|
||||
if (np->rxopt.bits.rxorigdstaddr) {
|
||||
struct sockaddr_in6 sin6;
|
||||
@@ -761,6 +799,7 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
|
||||
{
|
||||
struct in6_pktinfo *src_info;
|
||||
struct cmsghdr *cmsg;
|
||||
struct ipv6_rt_hdr *orthdr;
|
||||
struct ipv6_rt_hdr *rthdr;
|
||||
struct ipv6_opt_hdr *hdr;
|
||||
struct ipv6_txoptions *opt = ipc6->opt;
|
||||
@@ -922,9 +961,13 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
|
||||
goto exit_f;
|
||||
}
|
||||
if (cmsg->cmsg_type == IPV6_DSTOPTS) {
|
||||
if (opt->dst1opt)
|
||||
opt->opt_flen -= ipv6_optlen(opt->dst1opt);
|
||||
opt->opt_flen += len;
|
||||
opt->dst1opt = hdr;
|
||||
} else {
|
||||
if (opt->dst0opt)
|
||||
opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
|
||||
opt->opt_nflen += len;
|
||||
opt->dst0opt = hdr;
|
||||
}
|
||||
@@ -967,12 +1010,17 @@ int ip6_datagram_send_ctl(struct net *net, struct sock *sk,
|
||||
goto exit_f;
|
||||
}
|
||||
|
||||
orthdr = opt->srcrt;
|
||||
if (orthdr)
|
||||
opt->opt_nflen -= ((orthdr->hdrlen + 1) << 3);
|
||||
opt->opt_nflen += len;
|
||||
opt->srcrt = rthdr;
|
||||
|
||||
if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) {
|
||||
int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3);
|
||||
|
||||
if (opt->dst0opt)
|
||||
opt->opt_nflen -= ipv6_optlen(opt->dst0opt);
|
||||
opt->opt_nflen += dsthdrlen;
|
||||
opt->dst0opt = opt->dst1opt;
|
||||
opt->dst1opt = NULL;
|
||||
|
||||
+13
-1
@@ -181,6 +181,18 @@ static bool ip6_parse_tlv(const struct tlvtype_proc *procs,
|
||||
func(). */
|
||||
if (curr->func(skb, off) == false)
|
||||
return false;
|
||||
|
||||
/* RHEL-only: allow per-option special
|
||||
* handling after the above call, due to
|
||||
* missing upstream commit 51b8f812e5b3.
|
||||
*/
|
||||
switch (curr->type) {
|
||||
case IPV6_TLV_HAO:
|
||||
case IPV6_TLV_JUMBO:
|
||||
nh = skb_network_header(skb);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -548,7 +560,7 @@ looped_back:
|
||||
* unsigned char which is segments_left field. Should not be
|
||||
* higher than that.
|
||||
*/
|
||||
if (r || (n + 1) > 255) {
|
||||
if (r || (n + 1) > 127) {
|
||||
kfree_skb(skb);
|
||||
return -1;
|
||||
}
|
||||
|
||||
+4
-6
@@ -911,7 +911,6 @@ static int icmpv6_rcv(struct sk_buff *skb)
|
||||
struct net *net = dev_net(skb->dev);
|
||||
struct net_device *dev = icmp6_dev(skb);
|
||||
struct inet6_dev *idev = __in6_dev_get(dev);
|
||||
const struct in6_addr *saddr, *daddr;
|
||||
struct icmp6hdr *hdr;
|
||||
u8 type;
|
||||
|
||||
@@ -942,12 +941,10 @@ static int icmpv6_rcv(struct sk_buff *skb)
|
||||
|
||||
__ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INMSGS);
|
||||
|
||||
saddr = &ipv6_hdr(skb)->saddr;
|
||||
daddr = &ipv6_hdr(skb)->daddr;
|
||||
|
||||
if (skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo)) {
|
||||
net_dbg_ratelimited("ICMPv6 checksum failed [%pI6c > %pI6c]\n",
|
||||
saddr, daddr);
|
||||
&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr);
|
||||
goto csum_error;
|
||||
}
|
||||
|
||||
@@ -1030,7 +1027,8 @@ static int icmpv6_rcv(struct sk_buff *skb)
|
||||
break;
|
||||
|
||||
net_dbg_ratelimited("icmpv6: msg of unknown type [%pI6c > %pI6c]\n",
|
||||
saddr, daddr);
|
||||
&ipv6_hdr(skb)->saddr,
|
||||
&ipv6_hdr(skb)->daddr);
|
||||
|
||||
/*
|
||||
* error of unknown type.
|
||||
|
||||
@@ -96,7 +96,8 @@ static inline int compute_score(struct sock *sk, struct net *net,
|
||||
{
|
||||
int score = -1;
|
||||
|
||||
if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum &&
|
||||
if (net_eq(sock_net(sk), net) &&
|
||||
READ_ONCE(inet_sk(sk)->inet_num) == hnum &&
|
||||
sk->sk_family == PF_INET6) {
|
||||
if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, daddr))
|
||||
return -1;
|
||||
|
||||
+11
-3
@@ -719,20 +719,28 @@ out:
|
||||
|
||||
void fib6_metric_set(struct fib6_info *f6i, int metric, u32 val)
|
||||
{
|
||||
struct dst_metrics *m;
|
||||
|
||||
if (!f6i)
|
||||
return;
|
||||
|
||||
if (f6i->fib6_metrics == &dst_default_metrics) {
|
||||
if (READ_ONCE(f6i->fib6_metrics) == &dst_default_metrics) {
|
||||
struct dst_metrics *dflt = (struct dst_metrics *)&dst_default_metrics;
|
||||
struct dst_metrics *p = kzalloc(sizeof(*p), GFP_ATOMIC);
|
||||
|
||||
if (!p)
|
||||
return;
|
||||
|
||||
p->metrics[metric - 1] = val;
|
||||
refcount_set(&p->refcnt, 1);
|
||||
f6i->fib6_metrics = p;
|
||||
if (cmpxchg(&f6i->fib6_metrics, dflt, p) != dflt)
|
||||
kfree(p);
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
f6i->fib6_metrics->metrics[metric - 1] = val;
|
||||
m = READ_ONCE(f6i->fib6_metrics);
|
||||
WRITE_ONCE(m->metrics[metric - 1], val);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -133,11 +133,6 @@ static void fl_release(struct ip6_flowlabel *fl)
|
||||
if (time_after(ttd, fl->expires))
|
||||
fl->expires = ttd;
|
||||
ttd = fl->expires;
|
||||
if (fl->opt && fl->share == IPV6_FL_S_EXCL) {
|
||||
struct ipv6_txoptions *opt = fl->opt;
|
||||
fl->opt = NULL;
|
||||
kfree(opt);
|
||||
}
|
||||
if (!timer_pending(&ip6_fl_gc_timer) ||
|
||||
time_after(ip6_fl_gc_timer.expires, ttd))
|
||||
mod_timer(&ip6_fl_gc_timer, ttd);
|
||||
|
||||
@@ -454,6 +454,7 @@ static int ip6_forward_proxy_check(struct sk_buff *skb)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
hdr = ipv6_hdr(skb);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -570,6 +571,8 @@ int ip6_forward(struct sk_buff *skb)
|
||||
if (READ_ONCE(net->ipv6.devconf_all->proxy_ndp) &&
|
||||
pneigh_lookup(&nd_tbl, net, &hdr->daddr, skb->dev, 0)) {
|
||||
int proxied = ip6_forward_proxy_check(skb);
|
||||
|
||||
hdr = ipv6_hdr(skb);
|
||||
if (proxied > 0) {
|
||||
/* It's tempting to decrease the hop limit
|
||||
* here by 1, as we do at the end of the
|
||||
|
||||
+2
-1
@@ -2006,6 +2006,7 @@ static inline int ip6mr_forward2_finish(struct net *net, struct sock *sk, struct
|
||||
static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
|
||||
struct sk_buff *skb, int vifi)
|
||||
{
|
||||
struct net_device *indev = skb->dev;
|
||||
struct ipv6hdr *ipv6h;
|
||||
struct vif_device *vif = &mrt->vif_table[vifi];
|
||||
struct net_device *dev;
|
||||
@@ -2069,7 +2070,7 @@ static int ip6mr_forward2(struct net *net, struct mr_table *mrt,
|
||||
IP6CB(skb)->flags |= IP6SKB_FORWARDED;
|
||||
|
||||
return NF_HOOK(NFPROTO_IPV6, NF_INET_FORWARD,
|
||||
net, NULL, skb, skb->dev, dev,
|
||||
net, NULL, skb, indev, skb->dev,
|
||||
ip6mr_forward2_finish);
|
||||
|
||||
out_free:
|
||||
|
||||
+4
-4
@@ -1393,9 +1393,9 @@ out:
|
||||
static void __mld_query_work(struct sk_buff *skb)
|
||||
{
|
||||
struct mld2_query *mlh2 = NULL;
|
||||
const struct in6_addr *group;
|
||||
unsigned long max_delay;
|
||||
struct inet6_dev *idev;
|
||||
struct in6_addr group;
|
||||
struct ifmcaddr6 *ma;
|
||||
struct mld_msg *mld;
|
||||
int group_type;
|
||||
@@ -1427,8 +1427,8 @@ static void __mld_query_work(struct sk_buff *skb)
|
||||
goto kfree_skb;
|
||||
|
||||
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))
|
||||
@@ -1480,7 +1480,7 @@ static void __mld_query_work(struct sk_buff *skb)
|
||||
}
|
||||
} else {
|
||||
for_each_mc_mclock(idev, ma) {
|
||||
if (!ipv6_addr_equal(group, &ma->mca_addr))
|
||||
if (!ipv6_addr_equal(&group, &ma->mca_addr))
|
||||
continue;
|
||||
if (ma->mca_flags & MAF_TIMER_RUNNING) {
|
||||
/* gsquery <- gsquery && mark */
|
||||
|
||||
+21
-7
@@ -451,6 +451,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
|
||||
const struct fib6_nh *nh = sibling->fib6_nh;
|
||||
int nh_upper_bound;
|
||||
|
||||
if (!READ_ONCE(match->fib6_nsiblings))
|
||||
break;
|
||||
|
||||
nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
|
||||
if (fl6->mp_hash > nh_upper_bound)
|
||||
continue;
|
||||
@@ -1024,7 +1027,8 @@ static struct net_device *ip6_rt_get_dev_rcu(const struct fib6_result *res)
|
||||
*/
|
||||
if (netif_is_l3_slave(dev) &&
|
||||
!rt6_need_strict(&res->f6i->fib6_dst.addr))
|
||||
dev = l3mdev_master_dev_rcu(dev);
|
||||
dev = l3mdev_master_dev_rcu(dev) ? :
|
||||
dev_net(dev)->loopback_dev;
|
||||
else if (!netif_is_l3_master(dev))
|
||||
dev = dev_net(dev)->loopback_dev;
|
||||
/* last case is netif_is_l3_master(dev) is true in which
|
||||
@@ -1604,6 +1608,10 @@ static unsigned int fib6_mtu(const struct fib6_result *res)
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(dev);
|
||||
if (!idev) {
|
||||
rcu_read_unlock();
|
||||
return 0;
|
||||
}
|
||||
mtu = READ_ONCE(idev->cnf.mtu6);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
@@ -3552,7 +3560,6 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
|
||||
netdevice_tracker *dev_tracker = &fib6_nh->fib_nh_dev_tracker;
|
||||
struct net_device *dev = NULL;
|
||||
struct inet6_dev *idev = NULL;
|
||||
int addr_type;
|
||||
int err;
|
||||
|
||||
fib6_nh->fib_nh_family = AF_INET6;
|
||||
@@ -3594,11 +3601,10 @@ int fib6_nh_init(struct net *net, struct fib6_nh *fib6_nh,
|
||||
|
||||
fib6_nh->fib_nh_weight = 1;
|
||||
|
||||
/* We cannot add true routes via loopback here,
|
||||
* they would result in kernel looping; promote them to reject routes
|
||||
/* Reset the nexthop device to the loopback device in case of reject
|
||||
* routes.
|
||||
*/
|
||||
addr_type = ipv6_addr_type(&cfg->fc_dst);
|
||||
if (fib6_is_reject(cfg->fc_flags, dev, addr_type)) {
|
||||
if (cfg->fc_flags & RTF_REJECT) {
|
||||
/* hold loopback dev/idev if we haven't done so. */
|
||||
if (dev != net->loopback_dev) {
|
||||
if (dev) {
|
||||
@@ -5795,6 +5801,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
|
||||
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (!READ_ONCE(rt->fib6_nsiblings))
|
||||
break;
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
@@ -6807,7 +6815,7 @@ int __init ip6_route_init(void)
|
||||
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
|
||||
ret = bpf_iter_register();
|
||||
if (ret)
|
||||
goto out_register_late_subsys;
|
||||
goto out_register_notifier;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -6822,6 +6830,12 @@ int __init ip6_route_init(void)
|
||||
out:
|
||||
return ret;
|
||||
|
||||
#if IS_BUILTIN(CONFIG_IPV6)
|
||||
#if defined(CONFIG_BPF_SYSCALL) && defined(CONFIG_PROC_FS)
|
||||
out_register_notifier:
|
||||
unregister_netdevice_notifier(&ip6_route_dev_notifier);
|
||||
#endif
|
||||
#endif
|
||||
out_register_late_subsys:
|
||||
rtnl_unregister_all(PF_INET6);
|
||||
unregister_pernet_subsys(&ip6_route_net_late_ops);
|
||||
|
||||
+9
-8
@@ -267,15 +267,15 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t
|
||||
|
||||
lock_sock(sk);
|
||||
|
||||
rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL);
|
||||
if (!rep) {
|
||||
release_sock(sk);
|
||||
return -ENOMEM;
|
||||
if (ep != assoc->ep || assoc->base.dead) {
|
||||
err = -ESTALE;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (ep != assoc->ep) {
|
||||
err = -EAGAIN;
|
||||
goto out;
|
||||
rep = nlmsg_new(inet_assoc_attr_size(sk, assoc), GFP_KERNEL);
|
||||
if (!rep) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
err = inet_sctp_diag_fill(sk, assoc, rep, req, sk_user_ns(NETLINK_CB(skb).sk),
|
||||
@@ -290,8 +290,9 @@ static int sctp_sock_dump_one(struct sctp_endpoint *ep, struct sctp_transport *t
|
||||
return nlmsg_unicast(sock_net(skb->sk)->diag_nlsk, rep, NETLINK_CB(skb).portid);
|
||||
|
||||
out:
|
||||
release_sock(sk);
|
||||
kfree_skb(rep);
|
||||
out_unlock:
|
||||
release_sock(sk);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,
|
||||
struct sctp_chunk auth;
|
||||
|
||||
if (!chunk->auth_chunk)
|
||||
return true;
|
||||
return !sctp_auth_recv_cid(chunk->chunk_hdr->type, asoc);
|
||||
|
||||
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
|
||||
* is supposed to be authenticated and we have to do delayed
|
||||
|
||||
@@ -9392,6 +9392,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)
|
||||
release_sock(sk);
|
||||
current_timeo = schedule_timeout(current_timeo);
|
||||
lock_sock(sk);
|
||||
if (sk != asoc->base.sk)
|
||||
goto do_error;
|
||||
|
||||
*timeo_p = current_timeo;
|
||||
}
|
||||
|
||||
+5
-1
@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
|
||||
goto out;
|
||||
|
||||
param_len += str_nums * sizeof(__u16) +
|
||||
sizeof(struct sctp_strreset_inreq);
|
||||
(out ? sizeof(struct sctp_strreset_inreq)
|
||||
: sizeof(struct sctp_strreset_outreq));
|
||||
}
|
||||
|
||||
if (param_len > SCTP_MAX_CHUNK_LEN -
|
||||
@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq(
|
||||
|
||||
nums = (ntohs(param.p->length) - sizeof(*inreq)) / sizeof(__u16);
|
||||
str_p = inreq->list_of_streams;
|
||||
if (nums * sizeof(__u16) + sizeof(struct sctp_strreset_outreq) >
|
||||
SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_reconf_chunk))
|
||||
goto out;
|
||||
for (i = 0; i < nums; i++) {
|
||||
if (ntohs(str_p[i]) >= stream->outcnt) {
|
||||
result = SCTP_STRRESET_ERR_WRONG_SSN;
|
||||
|
||||
@@ -950,12 +950,20 @@ static int tipc_aead_decrypt(struct net *net, struct tipc_aead *aead,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Get net to avoid freed tipc_crypto when delete namespace */
|
||||
if (!maybe_get_net(net)) {
|
||||
tipc_bearer_put(b);
|
||||
rc = -ENODEV;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Now, do decrypt */
|
||||
rc = crypto_aead_decrypt(req);
|
||||
if (rc == -EINPROGRESS || rc == -EBUSY)
|
||||
return rc;
|
||||
|
||||
tipc_bearer_put(b);
|
||||
put_net(net);
|
||||
|
||||
exit:
|
||||
kfree(ctx);
|
||||
@@ -993,6 +1001,7 @@ static void tipc_aead_decrypt_done(struct crypto_async_request *base, int err)
|
||||
}
|
||||
|
||||
tipc_bearer_put(b);
|
||||
put_net(net);
|
||||
}
|
||||
|
||||
static inline int tipc_ehdr_size(struct tipc_ehdr *ehdr)
|
||||
|
||||
@@ -501,6 +501,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock,
|
||||
tipc_set_sk_state(sk, TIPC_OPEN);
|
||||
if (tipc_sk_insert(tsk)) {
|
||||
sk_free(sk);
|
||||
sock->sk = NULL;
|
||||
pr_warn("Socket create failed; port number exhausted\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
* Thu Aug 27 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-741.1.1.el9_9]
|
||||
- xen/privcmd: fix double free via VMA splitting (Vitaly Kuznetsov) [RHEL-172489] {CVE-2026-31787}
|
||||
- Buffer overflow in drivers/xen/sys-hypervisor.c (Vitaly Kuznetsov) [RHEL-172511] {CVE-2026-31786}
|
||||
- ALSA: virtio: Validate control metadata from the device (CKI Backport Bot) [RHEL-230137] {CVE-2026-64490}
|
||||
- ipv6: mcast: Fix use-after-free when processing MLD queries (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix possible infinite loop in fib6_select_path() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix possible infinite loop in rt6_fill_node() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: validate extension header length before copying to cmsg (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: exthdrs: refresh nh pointer after ipv6_hop_jumbo() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: exthdrs: refresh nh after handling HAO option (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: route: Unregister netdevice notifier on BPF init failure (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: addrconf: bail out of dad_failure when state is no longer POSTDAD (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix potential UAF caused by ip6_forward_proxy_check() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: Fix null-ptr-deref in fib6_mtu(). (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix possible UAF in icmpv6_rcv() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: avoid overflows in ip6_datagram_send_ctl() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix data race in fib6_metric_set() using cmpxchg (Antoine Tenart) [RHEL-152681]
|
||||
- net: ipv6: flowlabel: defer exclusive option free until RCU teardown (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: prevent possible UaF in addrconf_permanent_addr() (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: add NULL checks for idev in SRv6 paths (Antoine Tenart) [RHEL-152681]
|
||||
- net: ipv6: fix panic when IPv4 route references loopback IPv6 nexthop (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix NULL pointer deref in ip6_rt_get_dev_rcu() (Antoine Tenart) [RHEL-152681]
|
||||
- inet: annotate data-races around isk->inet_num (Antoine Tenart) [RHEL-152681]
|
||||
- ipv6: fix a race in ip6_sock_set_v6only() (Antoine Tenart) [RHEL-152681]
|
||||
- net: ipv6: ip6mr: Fix in/out netdev to pass to the FORWARD chain (Antoine Tenart) [RHEL-152681]
|
||||
- tipc: fix slab-use-after-free Read in tipc_aead_decrypt_done (Xin Long) [RHEL-228882] {CVE-2026-63801}
|
||||
- tipc: clear sock->sk on the failed-insert path in tipc_sk_create() (Xin Long) [RHEL-238040] {CVE-2026-68117}
|
||||
- sctp: fix race between sctp_wait_for_connect and peeloff (Xin Long) [RHEL-229476] {CVE-2026-63971}
|
||||
- sctp: diag: reject stale associations in dump_one path (Xin Long) [RHEL-231576] {CVE-2026-52917}
|
||||
- sctp: validate stream count in sctp_process_strreset_inreq() (Xin Long) [RHEL-236160] {CVE-2026-68315}
|
||||
- sctp: fix auth_hmacs array size in struct sctp_cookie (Xin Long) [RHEL-237403] {CVE-2026-68376}
|
||||
- sctp: auth: verify auth requirement when auth_chunk is NULL (Xin Long) [RHEL-237090] {CVE-2026-68300}
|
||||
- redhat: update self-test data (Jarod Wilson)
|
||||
- gitlab-ci: disttag override and tree name for 9.9 (Jarod Wilson)
|
||||
- redhat: set defaults for 9.9 stabilization/zstream (Jarod Wilson)
|
||||
Resolves: RHEL-152681, RHEL-172489, RHEL-172511, RHEL-228882, RHEL-229476, RHEL-230137, RHEL-231576, RHEL-236160, RHEL-237090, RHEL-237403, RHEL-238040
|
||||
|
||||
* Fri Aug 21 2026 CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> [5.14.0-741.el9]
|
||||
- dm cache policy smq: check allocation under invalidate lock (Benjamin Marzinski) [RHEL-231826] {CVE-2026-53062}
|
||||
- sctp: validate embedded INIT chunk and address list lengths in cookie (Xin Long) [RHEL-190190]
|
||||
|
||||
@@ -18,6 +18,21 @@ static const snd_ctl_elem_type_t g_v2a_type_map[] = {
|
||||
[VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
|
||||
};
|
||||
|
||||
/* Map for converting VirtIO types to maximum value counts. */
|
||||
static const unsigned int g_v2a_count_map[] = {
|
||||
[VIRTIO_SND_CTL_TYPE_BOOLEAN] =
|
||||
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
|
||||
[VIRTIO_SND_CTL_TYPE_INTEGER] =
|
||||
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
|
||||
[VIRTIO_SND_CTL_TYPE_INTEGER64] =
|
||||
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer64),
|
||||
[VIRTIO_SND_CTL_TYPE_ENUMERATED] =
|
||||
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.enumerated),
|
||||
[VIRTIO_SND_CTL_TYPE_BYTES] =
|
||||
ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.bytes),
|
||||
[VIRTIO_SND_CTL_TYPE_IEC958] = 1
|
||||
};
|
||||
|
||||
/* Map for converting VirtIO access rights to ALSA access rights. */
|
||||
static const unsigned int g_v2a_access_map[] = {
|
||||
[VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
|
||||
@@ -36,6 +51,37 @@ static const unsigned int g_v2a_mask_map[] = {
|
||||
[VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
|
||||
};
|
||||
|
||||
static int virtsnd_kctl_validate_info(struct virtio_snd *snd, u32 cid,
|
||||
struct virtio_snd_ctl_info *kinfo)
|
||||
{
|
||||
struct virtio_device *vdev = snd->vdev;
|
||||
unsigned int type = le32_to_cpu(kinfo->type);
|
||||
unsigned int count = le32_to_cpu(kinfo->count);
|
||||
|
||||
if (type >= ARRAY_SIZE(g_v2a_type_map)) {
|
||||
dev_err(&vdev->dev, "control #%u: unknown type %u\n",
|
||||
cid, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (count > g_v2a_count_map[type] ||
|
||||
(type == VIRTIO_SND_CTL_TYPE_IEC958 && count != 1)) {
|
||||
dev_err(&vdev->dev, "control #%u: invalid count %u for type %u\n",
|
||||
cid, count, type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED &&
|
||||
!le32_to_cpu(kinfo->value.enumerated.items)) {
|
||||
dev_err(&vdev->dev,
|
||||
"control #%u: no items for enumerated control\n",
|
||||
cid);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* virtsnd_kctl_info() - Returns information about the control.
|
||||
* @kcontrol: ALSA control element.
|
||||
@@ -385,6 +431,10 @@ int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
|
||||
struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
|
||||
unsigned int type = le32_to_cpu(kinfo->type);
|
||||
|
||||
rc = virtsnd_kctl_validate_info(snd, i, kinfo);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
|
||||
rc = virtsnd_kctl_get_enum_items(snd, i);
|
||||
if (rc)
|
||||
|
||||
Reference in New Issue
Block a user