aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2015-01-30 13:29:32 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-02 21:46:51 -0500
commitb245be1f4db1a0394e4b6eb66059814b46670ac3 (patch)
treee9e4e746bcb24db72ae5a947c7001bab21211a8e
parent49ca0d8bfaf3bc46d5eef60ce67b00eb195bd392 (diff)
net-timestamp: no-payload only sysctl
Tx timestamps are looped onto the error queue on top of an skb. This mechanism leaks packet headers to processes unless the no-payload options SOF_TIMESTAMPING_OPT_TSONLY is set. Add a sysctl that optionally drops looped timestamp with data. This only affects processes without CAP_NET_RAW. The policy is checked when timestamps are generated in the stack. It is possible for timestamps with data to be reported after the sysctl is set, if these were queued internally earlier. No vulnerability is immediately known that exploits knowledge gleaned from packet headers, but it may still be preferable to allow administrators to lock down this path at the cost of possible breakage of legacy applications. Signed-off-by: Willem de Bruijn <willemb@google.com> ---- Changes (v1 -> v2) - test socket CAP_NET_RAW instead of capable(CAP_NET_RAW) (rfc -> v1) - document the sysctl in Documentation/sysctl/net.txt - fix access control race: read .._OPT_TSONLY only once, use same value for permission check and skb generation. Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--Documentation/sysctl/net.txt8
-rw-r--r--include/net/sock.h1
-rw-r--r--net/core/skbuff.c21
-rw-r--r--net/core/sock.c3
-rw-r--r--net/core/sysctl_net_core.c9
5 files changed, 41 insertions, 1 deletions
diff --git a/Documentation/sysctl/net.txt b/Documentation/sysctl/net.txt
index 666594b43cff..6294b5186ae5 100644
--- a/Documentation/sysctl/net.txt
+++ b/Documentation/sysctl/net.txt
@@ -97,6 +97,14 @@ rmem_max
97 97
98The maximum receive socket buffer size in bytes. 98The maximum receive socket buffer size in bytes.
99 99
100tstamp_allow_data
101-----------------
102Allow processes to receive tx timestamps looped together with the original
103packet contents. If disabled, transmit timestamp requests from unprivileged
104processes are dropped unless socket option SOF_TIMESTAMPING_OPT_TSONLY is set.
105Default: 1 (on)
106
107
100wmem_default 108wmem_default
101------------ 109------------
102 110
diff --git a/include/net/sock.h b/include/net/sock.h
index 15341499786c..511ef7c8889b 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -2239,6 +2239,7 @@ bool sk_net_capable(const struct sock *sk, int cap);
2239extern __u32 sysctl_wmem_max; 2239extern __u32 sysctl_wmem_max;
2240extern __u32 sysctl_rmem_max; 2240extern __u32 sysctl_rmem_max;
2241 2241
2242extern int sysctl_tstamp_allow_data;
2242extern int sysctl_optmem_max; 2243extern int sysctl_optmem_max;
2243 2244
2244extern __u32 sysctl_wmem_default; 2245extern __u32 sysctl_wmem_default;
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 65a3798f43e6..a5bff2767f15 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -74,6 +74,8 @@
74#include <asm/uaccess.h> 74#include <asm/uaccess.h>
75#include <trace/events/skb.h> 75#include <trace/events/skb.h>
76#include <linux/highmem.h> 76#include <linux/highmem.h>
77#include <linux/capability.h>
78#include <linux/user_namespace.h>
77 79
78struct kmem_cache *skbuff_head_cache __read_mostly; 80struct kmem_cache *skbuff_head_cache __read_mostly;
79static struct kmem_cache *skbuff_fclone_cache __read_mostly; 81static struct kmem_cache *skbuff_fclone_cache __read_mostly;
@@ -3690,11 +3692,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
3690 kfree_skb(skb); 3692 kfree_skb(skb);
3691} 3693}
3692 3694
3695static bool skb_may_tx_timestamp(struct sock *sk, bool tsonly)
3696{
3697 bool ret;
3698
3699 if (likely(sysctl_tstamp_allow_data || tsonly))
3700 return true;
3701
3702 read_lock_bh(&sk->sk_callback_lock);
3703 ret = sk->sk_socket && sk->sk_socket->file &&
3704 file_ns_capable(sk->sk_socket->file, &init_user_ns, CAP_NET_RAW);
3705 read_unlock_bh(&sk->sk_callback_lock);
3706 return ret;
3707}
3708
3693void skb_complete_tx_timestamp(struct sk_buff *skb, 3709void skb_complete_tx_timestamp(struct sk_buff *skb,
3694 struct skb_shared_hwtstamps *hwtstamps) 3710 struct skb_shared_hwtstamps *hwtstamps)
3695{ 3711{
3696 struct sock *sk = skb->sk; 3712 struct sock *sk = skb->sk;
3697 3713
3714 if (!skb_may_tx_timestamp(sk, false))
3715 return;
3716
3698 /* take a reference to prevent skb_orphan() from freeing the socket */ 3717 /* take a reference to prevent skb_orphan() from freeing the socket */
3699 sock_hold(sk); 3718 sock_hold(sk);
3700 3719
@@ -3712,7 +3731,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
3712 struct sk_buff *skb; 3731 struct sk_buff *skb;
3713 bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY; 3732 bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
3714 3733
3715 if (!sk) 3734 if (!sk || !skb_may_tx_timestamp(sk, tsonly))
3716 return; 3735 return;
3717 3736
3718 if (tsonly) 3737 if (tsonly)
diff --git a/net/core/sock.c b/net/core/sock.c
index 1c7a33db1314..93c8b20c91e4 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -325,6 +325,8 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
325int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); 325int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
326EXPORT_SYMBOL(sysctl_optmem_max); 326EXPORT_SYMBOL(sysctl_optmem_max);
327 327
328int sysctl_tstamp_allow_data __read_mostly = 1;
329
328struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE; 330struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE;
329EXPORT_SYMBOL_GPL(memalloc_socks); 331EXPORT_SYMBOL_GPL(memalloc_socks);
330 332
@@ -840,6 +842,7 @@ set_rcvbuf:
840 ret = -EINVAL; 842 ret = -EINVAL;
841 break; 843 break;
842 } 844 }
845
843 if (val & SOF_TIMESTAMPING_OPT_ID && 846 if (val & SOF_TIMESTAMPING_OPT_ID &&
844 !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { 847 !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) {
845 if (sk->sk_protocol == IPPROTO_TCP) { 848 if (sk->sk_protocol == IPPROTO_TCP) {
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 31baba2a71ce..fde21d19e61b 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -321,6 +321,15 @@ static struct ctl_table net_core_table[] = {
321 .mode = 0644, 321 .mode = 0644,
322 .proc_handler = proc_dointvec 322 .proc_handler = proc_dointvec
323 }, 323 },
324 {
325 .procname = "tstamp_allow_data",
326 .data = &sysctl_tstamp_allow_data,
327 .maxlen = sizeof(int),
328 .mode = 0644,
329 .proc_handler = proc_dointvec_minmax,
330 .extra1 = &zero,
331 .extra2 = &one
332 },
324#ifdef CONFIG_RPS 333#ifdef CONFIG_RPS
325 { 334 {
326 .procname = "rps_sock_flow_entries", 335 .procname = "rps_sock_flow_entries",