Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix for CVE-2024-36971 #8

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion include/net/dst_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ struct dst_ops {
void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *,
struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*negative_advice)(struct sock *sk, struct dst_entry *);
void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu,
Expand Down
13 changes: 3 additions & 10 deletions include/net/sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -1802,19 +1802,12 @@ sk_dst_get(struct sock *sk)

static inline void dst_negative_advice(struct sock *sk)
{
struct dst_entry *ndst, *dst = __sk_dst_get(sk);
struct dst_entry *dst = __sk_dst_get(sk);

sk_rethink_txhash(sk);

if (dst && dst->ops->negative_advice) {
ndst = dst->ops->negative_advice(dst);

if (ndst != dst) {
rcu_assign_pointer(sk->sk_dst_cache, ndst);
sk_tx_queue_clear(sk);
WRITE_ONCE(sk->sk_dst_pending_confirm, 0);
}
}
if (dst && dst->ops->negative_advice)
dst->ops->negative_advice(sk, dst);
}

static inline void
Expand Down
22 changes: 8 additions & 14 deletions net/ipv4/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,8 @@ static int ip_rt_gc_timeout __read_mostly = RT_GC_TIMEOUT;
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ipv4_default_advmss(const struct dst_entry *dst);
static unsigned int ipv4_mtu(const struct dst_entry *dst);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_negative_advice(struct sock *sk,
struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu,
Expand Down Expand Up @@ -863,22 +864,15 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buf
__ip_do_redirect(rt, skb, &fl4, true);
}

static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst)
static void ipv4_negative_advice(struct sock *sk,
struct dst_entry *dst)
{
struct rtable *rt = (struct rtable *)dst;
struct dst_entry *ret = dst;

if (rt) {
if (dst->obsolete > 0) {
ip_rt_put(rt);
ret = NULL;
} else if ((rt->rt_flags & RTCF_REDIRECTED) ||
rt->dst.expires) {
ip_rt_put(rt);
ret = NULL;
}
}
return ret;
if ((dst->obsolete > 0) ||
(rt->rt_flags & RTCF_REDIRECTED) ||
rt->dst.expires)
sk_dst_reset(sk);
}

/*
Expand Down
25 changes: 13 additions & 12 deletions net/ipv6/route.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ static void ip6_rt_copy_init(struct rt6_info *rt, struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static unsigned int ip6_default_advmss(const struct dst_entry *dst);
static unsigned int ip6_mtu(const struct dst_entry *dst);
static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_negative_advice(struct sock *sk,
struct dst_entry *dst);
static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *,
struct net_device *dev, int how);
Expand Down Expand Up @@ -1415,22 +1416,22 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
return rt6_check(rt, cookie);
}

static struct dst_entry *ip6_negative_advice(struct dst_entry *dst)
static void ip6_negative_advice(struct sock *sk,
struct dst_entry *dst)
{
struct rt6_info *rt = (struct rt6_info *) dst;

if (rt) {
if (rt->rt6i_flags & RTF_CACHE) {
if (rt6_check_expired(rt)) {
ip6_del_rt(rt);
dst = NULL;
}
} else {
dst_release(dst);
dst = NULL;
if (rt->rt6i_flags & RTF_CACHE) {
if (rt6_check_expired(rt)) {
/* counteract the dst_release() in sk_dst_reset() */
dst_hold(dst);
sk_dst_reset(sk);

ip6_del_rt(rt);
}
return;
}
return dst;
sk_dst_reset(sk);
}

static void ip6_link_failure(struct sk_buff *skb)
Expand Down
11 changes: 3 additions & 8 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2484,15 +2484,10 @@ static void xfrm_link_failure(struct sk_buff *skb)
/* Impossible. Such dst must be popped before reaches point of failure. */
}

static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst)
static void xfrm_negative_advice(struct sock *sk, struct dst_entry *dst)
{
if (dst) {
if (dst->obsolete) {
dst_release(dst);
dst = NULL;
}
}
return dst;
if (dst->obsolete)
sk_dst_reset(sk);
}

static void xfrm_init_pmtu(struct dst_entry *dst)
Expand Down