aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/flow_dissector.c2
-rw-r--r--net/core/neighbour.c3
-rw-r--r--net/core/secure_seq.c31
-rw-r--r--net/core/sysctl_net_core.c6
4 files changed, 36 insertions, 6 deletions
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
index 5f3ae922fcd1..c9cf425303f8 100644
--- a/net/core/flow_dissector.c
+++ b/net/core/flow_dissector.c
@@ -159,7 +159,7 @@ __skb_flow_dissect_arp(const struct sk_buff *skb,
159 unsigned char ar_tip[4]; 159 unsigned char ar_tip[4];
160 } *arp_eth, _arp_eth; 160 } *arp_eth, _arp_eth;
161 const struct arphdr *arp; 161 const struct arphdr *arp;
162 struct arphdr *_arp; 162 struct arphdr _arp;
163 163
164 if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ARP)) 164 if (!dissector_uses_key(flow_dissector, FLOW_DISSECTOR_KEY_ARP))
165 return FLOW_DISSECT_RET_OUT_GOOD; 165 return FLOW_DISSECT_RET_OUT_GOOD;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 7069f5e4a361..8ae87c591c8e 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -861,7 +861,8 @@ static void neigh_probe(struct neighbour *neigh)
861 if (skb) 861 if (skb)
862 skb = skb_clone(skb, GFP_ATOMIC); 862 skb = skb_clone(skb, GFP_ATOMIC);
863 write_unlock(&neigh->lock); 863 write_unlock(&neigh->lock);
864 neigh->ops->solicit(neigh, skb); 864 if (neigh->ops->solicit)
865 neigh->ops->solicit(neigh, skb);
865 atomic_inc(&neigh->probes); 866 atomic_inc(&neigh->probes);
866 kfree_skb(skb); 867 kfree_skb(skb);
867} 868}
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c
index fb87e78a2cc7..6bd2f8fb0476 100644
--- a/net/core/secure_seq.c
+++ b/net/core/secure_seq.c
@@ -20,9 +20,11 @@
20#include <net/tcp.h> 20#include <net/tcp.h>
21 21
22static siphash_key_t net_secret __read_mostly; 22static siphash_key_t net_secret __read_mostly;
23static siphash_key_t ts_secret __read_mostly;
23 24
24static __always_inline void net_secret_init(void) 25static __always_inline void net_secret_init(void)
25{ 26{
27 net_get_random_once(&ts_secret, sizeof(ts_secret));
26 net_get_random_once(&net_secret, sizeof(net_secret)); 28 net_get_random_once(&net_secret, sizeof(net_secret));
27} 29}
28#endif 30#endif
@@ -45,6 +47,23 @@ static u32 seq_scale(u32 seq)
45#endif 47#endif
46 48
47#if IS_ENABLED(CONFIG_IPV6) 49#if IS_ENABLED(CONFIG_IPV6)
50static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
51{
52 const struct {
53 struct in6_addr saddr;
54 struct in6_addr daddr;
55 } __aligned(SIPHASH_ALIGNMENT) combined = {
56 .saddr = *(struct in6_addr *)saddr,
57 .daddr = *(struct in6_addr *)daddr,
58 };
59
60 if (sysctl_tcp_timestamps != 1)
61 return 0;
62
63 return siphash(&combined, offsetofend(typeof(combined), daddr),
64 &ts_secret);
65}
66
48u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr, 67u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
49 __be16 sport, __be16 dport, u32 *tsoff) 68 __be16 sport, __be16 dport, u32 *tsoff)
50{ 69{
@@ -63,7 +82,7 @@ u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
63 net_secret_init(); 82 net_secret_init();
64 hash = siphash(&combined, offsetofend(typeof(combined), dport), 83 hash = siphash(&combined, offsetofend(typeof(combined), dport),
65 &net_secret); 84 &net_secret);
66 *tsoff = sysctl_tcp_timestamps == 1 ? (hash >> 32) : 0; 85 *tsoff = secure_tcpv6_ts_off(saddr, daddr);
67 return seq_scale(hash); 86 return seq_scale(hash);
68} 87}
69EXPORT_SYMBOL(secure_tcpv6_seq_and_tsoff); 88EXPORT_SYMBOL(secure_tcpv6_seq_and_tsoff);
@@ -88,6 +107,14 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
88#endif 107#endif
89 108
90#ifdef CONFIG_INET 109#ifdef CONFIG_INET
110static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
111{
112 if (sysctl_tcp_timestamps != 1)
113 return 0;
114
115 return siphash_2u32((__force u32)saddr, (__force u32)daddr,
116 &ts_secret);
117}
91 118
92/* secure_tcp_seq_and_tsoff(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d), 119/* secure_tcp_seq_and_tsoff(a, b, 0, d) == secure_ipv4_port_ephemeral(a, b, d),
93 * but fortunately, `sport' cannot be 0 in any circumstances. If this changes, 120 * but fortunately, `sport' cannot be 0 in any circumstances. If this changes,
@@ -102,7 +129,7 @@ u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr,
102 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr, 129 hash = siphash_3u32((__force u32)saddr, (__force u32)daddr,
103 (__force u32)sport << 16 | (__force u32)dport, 130 (__force u32)sport << 16 | (__force u32)dport,
104 &net_secret); 131 &net_secret);
105 *tsoff = sysctl_tcp_timestamps == 1 ? (hash >> 32) : 0; 132 *tsoff = secure_tcp_ts_off(saddr, daddr);
106 return seq_scale(hash); 133 return seq_scale(hash);
107} 134}
108 135
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 4ead336e14ea..7f9cc400eca0 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -408,14 +408,16 @@ static struct ctl_table net_core_table[] = {
408 .data = &sysctl_net_busy_poll, 408 .data = &sysctl_net_busy_poll,
409 .maxlen = sizeof(unsigned int), 409 .maxlen = sizeof(unsigned int),
410 .mode = 0644, 410 .mode = 0644,
411 .proc_handler = proc_dointvec 411 .proc_handler = proc_dointvec_minmax,
412 .extra1 = &zero,
412 }, 413 },
413 { 414 {
414 .procname = "busy_read", 415 .procname = "busy_read",
415 .data = &sysctl_net_busy_read, 416 .data = &sysctl_net_busy_read,
416 .maxlen = sizeof(unsigned int), 417 .maxlen = sizeof(unsigned int),
417 .mode = 0644, 418 .mode = 0644,
418 .proc_handler = proc_dointvec 419 .proc_handler = proc_dointvec_minmax,
420 .extra1 = &zero,
419 }, 421 },
420#endif 422#endif
421#ifdef CONFIG_NET_SCHED 423#ifdef CONFIG_NET_SCHED