Skip to content

Commit b245be1

Browse files
wdebruijdavem330
authored andcommitted
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 <[email protected]> ---- 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 <[email protected]>
1 parent 49ca0d8 commit b245be1

File tree

5 files changed

+41
-1
lines changed

5 files changed

+41
-1
lines changed

Documentation/sysctl/net.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ rmem_max
9797

9898
The maximum receive socket buffer size in bytes.
9999

100+
tstamp_allow_data
101+
-----------------
102+
Allow processes to receive tx timestamps looped together with the original
103+
packet contents. If disabled, transmit timestamp requests from unprivileged
104+
processes are dropped unless socket option SOF_TIMESTAMPING_OPT_TSONLY is set.
105+
Default: 1 (on)
106+
107+
100108
wmem_default
101109
------------
102110

include/net/sock.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,6 +2239,7 @@ bool sk_net_capable(const struct sock *sk, int cap);
22392239
extern __u32 sysctl_wmem_max;
22402240
extern __u32 sysctl_rmem_max;
22412241

2242+
extern int sysctl_tstamp_allow_data;
22422243
extern int sysctl_optmem_max;
22432244

22442245
extern __u32 sysctl_wmem_default;

net/core/skbuff.c

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@
7474
#include <asm/uaccess.h>
7575
#include <trace/events/skb.h>
7676
#include <linux/highmem.h>
77+
#include <linux/capability.h>
78+
#include <linux/user_namespace.h>
7779

7880
struct kmem_cache *skbuff_head_cache __read_mostly;
7981
static struct kmem_cache *skbuff_fclone_cache __read_mostly;
@@ -3690,11 +3692,28 @@ static void __skb_complete_tx_timestamp(struct sk_buff *skb,
36903692
kfree_skb(skb);
36913693
}
36923694

3695+
static 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+
36933709
void skb_complete_tx_timestamp(struct sk_buff *skb,
36943710
struct skb_shared_hwtstamps *hwtstamps)
36953711
{
36963712
struct sock *sk = skb->sk;
36973713

3714+
if (!skb_may_tx_timestamp(sk, false))
3715+
return;
3716+
36983717
/* take a reference to prevent skb_orphan() from freeing the socket */
36993718
sock_hold(sk);
37003719

@@ -3712,7 +3731,7 @@ void __skb_tstamp_tx(struct sk_buff *orig_skb,
37123731
struct sk_buff *skb;
37133732
bool tsonly = sk->sk_tsflags & SOF_TIMESTAMPING_OPT_TSONLY;
37143733

3715-
if (!sk)
3734+
if (!sk || !skb_may_tx_timestamp(sk, tsonly))
37163735
return;
37173736

37183737
if (tsonly)

net/core/sock.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX;
325325
int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512);
326326
EXPORT_SYMBOL(sysctl_optmem_max);
327327

328+
int sysctl_tstamp_allow_data __read_mostly = 1;
329+
328330
struct static_key memalloc_socks = STATIC_KEY_INIT_FALSE;
329331
EXPORT_SYMBOL_GPL(memalloc_socks);
330332

@@ -840,6 +842,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
840842
ret = -EINVAL;
841843
break;
842844
}
845+
843846
if (val & SOF_TIMESTAMPING_OPT_ID &&
844847
!(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) {
845848
if (sk->sk_protocol == IPPROTO_TCP) {

net/core/sysctl_net_core.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,15 @@ static struct ctl_table net_core_table[] = {
321321
.mode = 0644,
322322
.proc_handler = proc_dointvec
323323
},
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+
},
324333
#ifdef CONFIG_RPS
325334
{
326335
.procname = "rps_sock_flow_entries",

0 commit comments

Comments
 (0)