Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 43713848 authored by Haishuang Yan's avatar Haishuang Yan Committed by David S. Miller
Browse files

ipv4: Namespaceify tcp_fastopen_key knob



Different namespace application might require different tcp_fastopen_key
independently of the host.

David Miller pointed out there is a leak without releasing the context
of tcp_fastopen_key during netns teardown. So add the release action in
exit_batch path.

Tested:
1. Container namespace:
# cat /proc/sys/net/ipv4/tcp_fastopen_key:
2817fff2-f803cf97-eadfd1f3-78c0992b

cookie key in tcp syn packets:
Fast Open Cookie
    Kind: TCP Fast Open Cookie (34)
    Length: 10
    Fast Open Cookie: 1e5dd82a8c492ca9

2. Host:
# cat /proc/sys/net/ipv4/tcp_fastopen_key:
107d7c5f-68eb2ac7-02fb06e6-ed341702

cookie key in tcp syn packets:
Fast Open Cookie
    Kind: TCP Fast Open Cookie (34)
    Length: 10
    Fast Open Cookie: e213c02bf0afbc8a

Signed-off-by: default avatarHaishuang Yan <yanhaishuang@cmss.chinamobile.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent dd000598
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -36,6 +36,8 @@ struct inet_timewait_death_row {
	int			sysctl_max_tw_buckets;
};

struct tcp_fastopen_context;

struct netns_ipv4 {
#ifdef CONFIG_SYSCTL
	struct ctl_table_header	*forw_hdr;
@@ -129,6 +131,8 @@ struct netns_ipv4 {
	struct inet_timewait_death_row tcp_death_row;
	int sysctl_max_syn_backlog;
	int sysctl_tcp_fastopen;
	struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
	spinlock_t tcp_fastopen_ctx_lock;

#ifdef CONFIG_NET_L3_MASTER_DEV
	int sysctl_udp_l3mdev_accept;
+3 −3
Original line number Diff line number Diff line
@@ -1549,13 +1549,13 @@ struct tcp_fastopen_request {
};
void tcp_free_fastopen_req(struct tcp_sock *tp);

extern struct tcp_fastopen_context __rcu *tcp_fastopen_ctx;
int tcp_fastopen_reset_cipher(void *key, unsigned int len);
void tcp_fastopen_ctx_destroy(struct net *net);
int tcp_fastopen_reset_cipher(struct net *net, void *key, unsigned int len);
void tcp_fastopen_add_skb(struct sock *sk, struct sk_buff *skb);
struct sock *tcp_try_fastopen(struct sock *sk, struct sk_buff *skb,
			      struct request_sock *req,
			      struct tcp_fastopen_cookie *foc);
void tcp_fastopen_init_key_once(void);
void tcp_fastopen_init_key_once(struct net *net);
bool tcp_fastopen_cookie_check(struct sock *sk, u16 *mss,
			     struct tcp_fastopen_cookie *cookie);
bool tcp_fastopen_defer_connect(struct sock *sk, int *err);
+1 −1
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ int inet_listen(struct socket *sock, int backlog)
		    (tcp_fastopen & TFO_SERVER_ENABLE) &&
		    !inet_csk(sk)->icsk_accept_queue.fastopenq.max_qlen) {
			fastopen_queue_tune(sk, backlog);
			tcp_fastopen_init_key_once();
			tcp_fastopen_init_key_once(sock_net(sk));
		}

		err = inet_csk_listen_start(sk, backlog);
+12 −9
Original line number Diff line number Diff line
@@ -251,10 +251,12 @@ static int proc_allowed_congestion_control(struct ctl_table *ctl,
	return ret;
}

static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
static int proc_tcp_fastopen_key(struct ctl_table *table, int write,
				 void __user *buffer, size_t *lenp,
				 loff_t *ppos)
{
	struct net *net = container_of(table->data, struct net,
	    ipv4.sysctl_tcp_fastopen);
	struct ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) };
	struct tcp_fastopen_context *ctxt;
	int ret;
@@ -265,7 +267,7 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
		return -ENOMEM;

	rcu_read_lock();
	ctxt = rcu_dereference(tcp_fastopen_ctx);
	ctxt = rcu_dereference(net->ipv4.tcp_fastopen_ctx);
	if (ctxt)
		memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH);
	else
@@ -282,7 +284,7 @@ static int proc_tcp_fastopen_key(struct ctl_table *ctl, int write,
			ret = -EINVAL;
			goto bad_key;
		}
		tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH);
		tcp_fastopen_reset_cipher(net, user_key, TCP_FASTOPEN_KEY_LENGTH);
	}

bad_key:
@@ -395,12 +397,6 @@ static struct ctl_table ipv4_table[] = {
		.mode		= 0644,
		.proc_handler	= proc_dointvec
	},
	{
		.procname	= "tcp_fastopen_key",
		.mode		= 0600,
		.maxlen		= ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10),
		.proc_handler	= proc_tcp_fastopen_key,
	},
	{
		.procname	= "tcp_fastopen_blackhole_timeout_sec",
		.data		= &sysctl_tcp_fastopen_blackhole_timeout,
@@ -1080,6 +1076,13 @@ static struct ctl_table ipv4_net_table[] = {
		.mode		= 0644,
		.proc_handler	= proc_dointvec,
	},
	{
		.procname	= "tcp_fastopen_key",
		.mode		= 0600,
		.data		= &init_net.ipv4.sysctl_tcp_fastopen,
		.maxlen		= ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10),
		.proc_handler	= proc_tcp_fastopen_key,
	},
#ifdef CONFIG_IP_ROUTE_MULTIPATH
	{
		.procname	= "fib_multipath_use_neigh",
+1 −1
Original line number Diff line number Diff line
@@ -2749,7 +2749,7 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
	case TCP_FASTOPEN:
		if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE |
		    TCPF_LISTEN))) {
			tcp_fastopen_init_key_once();
			tcp_fastopen_init_key_once(net);

			fastopen_queue_tune(sk, val);
		} else {
Loading