From c2ad6ebaaa21f1ddfef98aadc6f8a9857e481ce8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 12 Nov 2022 14:05:44 +0000 Subject: [PATCH] Revert "tcp/udp: Make early_demux back namespacified." This reverts commit 7162f05f1f0f2b9554ea207842a1389c067cc1db which is commit 11052589cf5c0bab3b4884d423d5f60c38fcf25d upstream. It is breaks the abi and is not needed in Android systems, so revert it. Bug: 161946584 Change-Id: I357d52cd6a635050f305127246f95cb2302633be Signed-off-by: Greg Kroah-Hartman --- include/net/protocol.h | 4 +++ include/net/tcp.h | 2 -- include/net/udp.h | 1 - net/ipv4/af_inet.c | 14 +++++++-- net/ipv4/ip_input.c | 32 +++++++-------------- net/ipv4/sysctl_net_ipv4.c | 59 ++++++++++++++++++++++++++++++++++++-- net/ipv6/ip6_input.c | 23 ++++++--------- net/ipv6/tcp_ipv6.c | 9 ++++-- net/ipv6/udp.c | 9 ++++-- 9 files changed, 106 insertions(+), 47 deletions(-) diff --git a/include/net/protocol.h b/include/net/protocol.h index 312a27393e0b..4fc75f7ae23b 100644 --- a/include/net/protocol.h +++ b/include/net/protocol.h @@ -39,6 +39,8 @@ /* This is used to register protocols. */ struct net_protocol { + int (*early_demux)(struct sk_buff *skb); + int (*early_demux_handler)(struct sk_buff *skb); int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, u32 info); unsigned int no_policy:1, @@ -52,6 +54,8 @@ struct net_protocol { #if IS_ENABLED(CONFIG_IPV6) struct inet6_protocol { + void (*early_demux)(struct sk_buff *skb); + void (*early_demux_handler)(struct sk_buff *skb); int (*handler)(struct sk_buff *skb); void (*err_handler)(struct sk_buff *skb, diff --git a/include/net/tcp.h b/include/net/tcp.h index 9a154fe06c60..487b6c5f53f4 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -901,8 +901,6 @@ static inline int tcp_v6_sdif(const struct sk_buff *skb) #endif return 0; } - -void tcp_v6_early_demux(struct sk_buff *skb); #endif static inline bool inet_exact_dif_match(struct net *net, struct sk_buff *skb) diff --git a/include/net/udp.h b/include/net/udp.h index 618c83bea50d..8482a990b0bb 100644 --- a/include/net/udp.h +++ b/include/net/udp.h @@ -173,7 +173,6 @@ typedef struct sock *(*udp_lookup_t)(struct sk_buff *skb, __be16 sport, struct sk_buff *udp_gro_receive(struct list_head *head, struct sk_buff *skb, struct udphdr *uh, udp_lookup_t lookup); int udp_gro_complete(struct sk_buff *skb, int nhoff, udp_lookup_t lookup); -void udp_v6_early_demux(struct sk_buff *skb); struct sk_buff *__udp_gso_segment(struct sk_buff *gso_skb, netdev_features_t features); diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 4b26ae525d6d..3cf9cd180898 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1678,7 +1678,12 @@ static const struct net_protocol igmp_protocol = { }; #endif -static const struct net_protocol tcp_protocol = { +/* thinking of making this const? Don't. + * early_demux can change based on sysctl. + */ +static struct net_protocol tcp_protocol = { + .early_demux = tcp_v4_early_demux, + .early_demux_handler = tcp_v4_early_demux, .handler = tcp_v4_rcv, .err_handler = tcp_v4_err, .no_policy = 1, @@ -1686,7 +1691,12 @@ static const struct net_protocol tcp_protocol = { .icmp_strict_tag_validation = 1, }; -static const struct net_protocol udp_protocol = { +/* thinking of making this const? Don't. + * early_demux can change based on sysctl. + */ +static struct net_protocol udp_protocol = { + .early_demux = udp_v4_early_demux, + .early_demux_handler = udp_v4_early_demux, .handler = udp_rcv, .err_handler = udp_err, .no_policy = 1, diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 7ead5192b2a9..c3a0683e83df 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -306,38 +306,28 @@ drop: return true; } -int udp_v4_early_demux(struct sk_buff *); -int tcp_v4_early_demux(struct sk_buff *); static int ip_rcv_finish_core(struct net *net, struct sock *sk, struct sk_buff *skb, struct net_device *dev) { const struct iphdr *iph = ip_hdr(skb); + int (*edemux)(struct sk_buff *skb); struct rtable *rt; int err; - if (READ_ONCE(net->ipv4.sysctl_ip_early_demux) && + if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && !skb->sk && !ip_is_fragment(iph)) { - switch (iph->protocol) { - case IPPROTO_TCP: - if (READ_ONCE(net->ipv4.sysctl_tcp_early_demux)) { - tcp_v4_early_demux(skb); + const struct net_protocol *ipprot; + int protocol = iph->protocol; - /* must reload iph, skb->head might have changed */ - iph = ip_hdr(skb); - } - break; - case IPPROTO_UDP: - if (READ_ONCE(net->ipv4.sysctl_udp_early_demux)) { - err = udp_v4_early_demux(skb); - if (unlikely(err)) - goto drop_error; - - /* must reload iph, skb->head might have changed */ - iph = ip_hdr(skb); - } - break; + ipprot = rcu_dereference(inet_protos[protocol]); + if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) { + err = edemux(skb); + if (unlikely(err)) + goto drop_error; + /* must reload iph, skb->head might have changed */ + iph = ip_hdr(skb); } } diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index c97ba2a44b8b..ad132b6e8cfa 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -332,6 +332,61 @@ bad_key: return ret; } +static void proc_configure_early_demux(int enabled, int protocol) +{ + struct net_protocol *ipprot; +#if IS_ENABLED(CONFIG_IPV6) + struct inet6_protocol *ip6prot; +#endif + + rcu_read_lock(); + + ipprot = rcu_dereference(inet_protos[protocol]); + if (ipprot) + ipprot->early_demux = enabled ? ipprot->early_demux_handler : + NULL; + +#if IS_ENABLED(CONFIG_IPV6) + ip6prot = rcu_dereference(inet6_protos[protocol]); + if (ip6prot) + ip6prot->early_demux = enabled ? ip6prot->early_demux_handler : + NULL; +#endif + rcu_read_unlock(); +} + +static int proc_tcp_early_demux(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int ret = 0; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write && !ret) { + int enabled = init_net.ipv4.sysctl_tcp_early_demux; + + proc_configure_early_demux(enabled, IPPROTO_TCP); + } + + return ret; +} + +static int proc_udp_early_demux(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) +{ + int ret = 0; + + ret = proc_dointvec(table, write, buffer, lenp, ppos); + + if (write && !ret) { + int enabled = init_net.ipv4.sysctl_udp_early_demux; + + proc_configure_early_demux(enabled, IPPROTO_UDP); + } + + return ret; +} + static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table, int write, void __user *buffer, @@ -583,14 +638,14 @@ static struct ctl_table ipv4_net_table[] = { .data = &init_net.ipv4.sysctl_udp_early_demux, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_douintvec_minmax, + .proc_handler = proc_udp_early_demux }, { .procname = "tcp_early_demux", .data = &init_net.ipv4.sysctl_tcp_early_demux, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_douintvec_minmax, + .proc_handler = proc_tcp_early_demux }, { .procname = "ip_default_ttl", diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 2bdb03a45baf..57d84accbf1e 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c @@ -47,25 +47,18 @@ #include #include -void udp_v6_early_demux(struct sk_buff *); -void tcp_v6_early_demux(struct sk_buff *); static void ip6_rcv_finish_core(struct net *net, struct sock *sk, struct sk_buff *skb) { - if (READ_ONCE(net->ipv4.sysctl_ip_early_demux) && - !skb_dst(skb) && !skb->sk) { - switch (ipv6_hdr(skb)->nexthdr) { - case IPPROTO_TCP: - if (READ_ONCE(net->ipv4.sysctl_tcp_early_demux)) - tcp_v6_early_demux(skb); - break; - case IPPROTO_UDP: - if (READ_ONCE(net->ipv4.sysctl_udp_early_demux)) - udp_v6_early_demux(skb); - break; - } - } + void (*edemux)(struct sk_buff *skb); + if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) { + const struct inet6_protocol *ipprot; + + ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]); + if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) + edemux(skb); + } if (!skb_valid_dst(skb)) ip6_route_input(skb); } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7a5a7a4265cf..549ea5211bfa 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -1673,7 +1673,7 @@ do_time_wait: goto discard_it; } -void tcp_v6_early_demux(struct sk_buff *skb) +static void tcp_v6_early_demux(struct sk_buff *skb) { const struct ipv6hdr *hdr; const struct tcphdr *th; @@ -2028,7 +2028,12 @@ struct proto tcpv6_prot = { .diag_destroy = tcp_abort, }; -static const struct inet6_protocol tcpv6_protocol = { +/* thinking of making this const? Don't. + * early_demux can change based on sysctl. + */ +static struct inet6_protocol tcpv6_protocol = { + .early_demux = tcp_v6_early_demux, + .early_demux_handler = tcp_v6_early_demux, .handler = tcp_v6_rcv, .err_handler = tcp_v6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 9b0cae403027..fb71da6c6c74 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -912,7 +912,7 @@ static struct sock *__udp6_lib_demux_lookup(struct net *net, return NULL; } -void udp_v6_early_demux(struct sk_buff *skb) +static void udp_v6_early_demux(struct sk_buff *skb) { struct net *net = dev_net(skb->dev); const struct udphdr *uh; @@ -1533,7 +1533,12 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, } #endif -static const struct inet6_protocol udpv6_protocol = { +/* thinking of making this const? Don't. + * early_demux can change based on sysctl. + */ +static struct inet6_protocol udpv6_protocol = { + .early_demux = udp_v6_early_demux, + .early_demux_handler = udp_v6_early_demux, .handler = udpv6_rcv, .err_handler = udpv6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,