ANDROID: ABI fixup for abi break in struct dst_ops

In commit 92f1655aa2b2 ("net: fix __dst_negative_advice() race") the
struct dst_ops callback negative_advice is callback changes function
parameters.  But as this pointer is part of a structure that is tracked
in the ABI checker, the tool triggers when this is changed.

However, the callback pointer is internal to the networking stack, so
changing the function type is safe, so needing to preserve this is not
required.  To do so, switch the function pointer type back to the old
one so that the checking tools pass, AND then do a hard cast of the
function pointer to the new type when assigning and calling the
function.

[6.1.y backport note, work around --Werror=cast-function-type issue by
 abusing void * for function pointer types, despite its best effort, C
 still let's us shoot our foot off if we really want to!]

Bug: 343727534
Bug: 344532797
Fixes: 92f1655aa2b2 ("net: fix __dst_negative_advice() race")
Change-Id: I48d4ab4bbd29f8edc8fbd7923828b7f78a23e12e
Signed-off-by: Greg Kroah-Hartman <[email protected]>
(cherry picked from commit a7462d7032e5ed971980180c6a5aadc8ad700331)
diff --git a/include/net/dst_ops.h b/include/net/dst_ops.h
index dd7c0b3..382af5f 100644
--- a/include/net/dst_ops.h
+++ b/include/net/dst_ops.h
@@ -12,6 +12,16 @@ struct sk_buff;
 struct sock;
 struct net;
 
+/* *** ANDROID FIXUP ***
+ * These typedefs are used to help fixup the ABI break caused by commit
+ * 92f1655aa2b2 ("net: fix __dst_negative_advice() race") where the
+ * negative_advice callback changed function signatures.
+ * See b/343727534 for more details.
+ * *** ANDROID FIXUP ***
+ */
+typedef void (*android_dst_ops_negative_advice_new_t)(struct sock *sk, struct dst_entry *);
+typedef struct dst_entry * (*android_dst_ops_negative_advice_old_t)(struct dst_entry *);
+
 struct dst_ops {
 	unsigned short		family;
 	unsigned int		gc_thresh;
@@ -24,7 +34,7 @@ struct dst_ops {
 	void			(*destroy)(struct dst_entry *);
 	void			(*ifdown)(struct dst_entry *,
 					  struct net_device *dev, int how);
-	void			(*negative_advice)(struct sock *sk, struct dst_entry *);
+	struct dst_entry *	(*negative_advice)(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,
diff --git a/include/net/sock.h b/include/net/sock.h
index 6c69688..8bc5f19 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2215,10 +2215,20 @@ sk_dst_get(struct sock *sk)
 
 static inline void __dst_negative_advice(struct sock *sk)
 {
+	/* *** ANDROID FIXUP ***
+	 * See b/343727534 for more details why this typedef is needed here.
+	 * *** ANDROID FIXUP ***
+	 */
+	android_dst_ops_negative_advice_new_t negative_advice;
+	void *c_is_fun;		/* Work around --Werror=cast-function-type */
+
 	struct dst_entry *dst = __sk_dst_get(sk);
 
-	if (dst && dst->ops->negative_advice)
-		dst->ops->negative_advice(sk, dst);
+	if (dst && dst->ops->negative_advice) {
+		c_is_fun = dst->ops->negative_advice;
+		negative_advice = c_is_fun;
+		negative_advice(sk, dst);
+	}
 }
 
 static inline void dst_negative_advice(struct sock *sk)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index abd8661..82a2c4d 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -160,7 +160,7 @@ static struct dst_ops ipv4_dst_ops = {
 	.mtu =			ipv4_mtu,
 	.cow_metrics =		ipv4_cow_metrics,
 	.destroy =		ipv4_dst_destroy,
-	.negative_advice =	ipv4_negative_advice,
+	.negative_advice =	(void *)ipv4_negative_advice,
 	.link_failure =		ipv4_link_failure,
 	.update_pmtu =		ip_rt_update_pmtu,
 	.redirect =		ip_do_redirect,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8d88b46..1c00695a 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -258,7 +258,7 @@ static struct dst_ops ip6_dst_ops_template = {
 	.cow_metrics		=	dst_cow_metrics_generic,
 	.destroy		=	ip6_dst_destroy,
 	.ifdown			=	ip6_dst_ifdown,
-	.negative_advice	=	ip6_negative_advice,
+	.negative_advice	=	(void *)ip6_negative_advice,
 	.link_failure		=	ip6_link_failure,
 	.update_pmtu		=	ip6_rt_update_pmtu,
 	.redirect		=	rt6_do_redirect,
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index e0ac396..3c42dd4 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -3945,7 +3945,7 @@ int xfrm_policy_register_afinfo(const struct xfrm_policy_afinfo *afinfo, int fam
 		if (likely(dst_ops->mtu == NULL))
 			dst_ops->mtu = xfrm_mtu;
 		if (likely(dst_ops->negative_advice == NULL))
-			dst_ops->negative_advice = xfrm_negative_advice;
+			dst_ops->negative_advice = (void *)xfrm_negative_advice;
 		if (likely(dst_ops->link_failure == NULL))
 			dst_ops->link_failure = xfrm_link_failure;
 		if (likely(dst_ops->neigh_lookup == NULL))