Skip to content

Commit 784325e

Browse files
matttbedavem330
authored andcommitted
mptcp: new sysctl to control the activation per NS
New MPTCP sockets will return -ENOPROTOOPT if MPTCP support is disabled for the current net namespace. We are providing here a way to control access to the feature for those that need to turn it on or off. The value of this new sysctl can be different per namespace. We can then restrict the usage of MPTCP to the selected NS. In case of serious issues with MPTCP, administrators can now easily turn MPTCP off. Co-developed-by: Peter Krystad <[email protected]> Signed-off-by: Peter Krystad <[email protected]> Signed-off-by: Matthieu Baerts <[email protected]> Signed-off-by: Christoph Paasch <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5704075 commit 784325e

File tree

4 files changed

+146
-5
lines changed

4 files changed

+146
-5
lines changed

net/mptcp/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-License-Identifier: GPL-2.0
22
obj-$(CONFIG_MPTCP) += mptcp.o
33

4-
mptcp-y := protocol.o subflow.o options.o token.o crypto.o
4+
mptcp-y := protocol.o subflow.o options.o token.o crypto.o ctrl.o

net/mptcp/ctrl.c

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Multipath TCP
3+
*
4+
* Copyright (c) 2019, Tessares SA.
5+
*/
6+
7+
#include <linux/sysctl.h>
8+
9+
#include <net/net_namespace.h>
10+
#include <net/netns/generic.h>
11+
12+
#include "protocol.h"
13+
14+
#define MPTCP_SYSCTL_PATH "net/mptcp"
15+
16+
static int mptcp_pernet_id;
17+
struct mptcp_pernet {
18+
struct ctl_table_header *ctl_table_hdr;
19+
20+
int mptcp_enabled;
21+
};
22+
23+
static struct mptcp_pernet *mptcp_get_pernet(struct net *net)
24+
{
25+
return net_generic(net, mptcp_pernet_id);
26+
}
27+
28+
int mptcp_is_enabled(struct net *net)
29+
{
30+
return mptcp_get_pernet(net)->mptcp_enabled;
31+
}
32+
33+
static struct ctl_table mptcp_sysctl_table[] = {
34+
{
35+
.procname = "enabled",
36+
.maxlen = sizeof(int),
37+
.mode = 0644,
38+
/* users with CAP_NET_ADMIN or root (not and) can change this
39+
* value, same as other sysctl or the 'net' tree.
40+
*/
41+
.proc_handler = proc_dointvec,
42+
},
43+
{}
44+
};
45+
46+
static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
47+
{
48+
pernet->mptcp_enabled = 1;
49+
}
50+
51+
static int mptcp_pernet_new_table(struct net *net, struct mptcp_pernet *pernet)
52+
{
53+
struct ctl_table_header *hdr;
54+
struct ctl_table *table;
55+
56+
table = mptcp_sysctl_table;
57+
if (!net_eq(net, &init_net)) {
58+
table = kmemdup(table, sizeof(mptcp_sysctl_table), GFP_KERNEL);
59+
if (!table)
60+
goto err_alloc;
61+
}
62+
63+
table[0].data = &pernet->mptcp_enabled;
64+
65+
hdr = register_net_sysctl(net, MPTCP_SYSCTL_PATH, table);
66+
if (!hdr)
67+
goto err_reg;
68+
69+
pernet->ctl_table_hdr = hdr;
70+
71+
return 0;
72+
73+
err_reg:
74+
if (!net_eq(net, &init_net))
75+
kfree(table);
76+
err_alloc:
77+
return -ENOMEM;
78+
}
79+
80+
static void mptcp_pernet_del_table(struct mptcp_pernet *pernet)
81+
{
82+
struct ctl_table *table = pernet->ctl_table_hdr->ctl_table_arg;
83+
84+
unregister_net_sysctl_table(pernet->ctl_table_hdr);
85+
86+
kfree(table);
87+
}
88+
89+
static int __net_init mptcp_net_init(struct net *net)
90+
{
91+
struct mptcp_pernet *pernet = mptcp_get_pernet(net);
92+
93+
mptcp_pernet_set_defaults(pernet);
94+
95+
return mptcp_pernet_new_table(net, pernet);
96+
}
97+
98+
/* Note: the callback will only be called per extra netns */
99+
static void __net_exit mptcp_net_exit(struct net *net)
100+
{
101+
struct mptcp_pernet *pernet = mptcp_get_pernet(net);
102+
103+
mptcp_pernet_del_table(pernet);
104+
}
105+
106+
static struct pernet_operations mptcp_pernet_ops = {
107+
.init = mptcp_net_init,
108+
.exit = mptcp_net_exit,
109+
.id = &mptcp_pernet_id,
110+
.size = sizeof(struct mptcp_pernet),
111+
};
112+
113+
void __init mptcp_init(void)
114+
{
115+
mptcp_proto_init();
116+
117+
if (register_pernet_subsys(&mptcp_pernet_ops) < 0)
118+
panic("Failed to register MPTCP pernet subsystem.\n");
119+
}
120+
121+
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
122+
int __init mptcpv6_init(void)
123+
{
124+
int err;
125+
126+
err = mptcp_proto_v6_init();
127+
128+
return err;
129+
}
130+
#endif

net/mptcp/protocol.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk,
522522
}
523523
}
524524

525-
static int mptcp_init_sock(struct sock *sk)
525+
static int __mptcp_init_sock(struct sock *sk)
526526
{
527527
struct mptcp_sock *msk = mptcp_sk(sk);
528528

@@ -532,6 +532,14 @@ static int mptcp_init_sock(struct sock *sk)
532532
return 0;
533533
}
534534

535+
static int mptcp_init_sock(struct sock *sk)
536+
{
537+
if (!mptcp_is_enabled(sock_net(sk)))
538+
return -ENOPROTOOPT;
539+
540+
return __mptcp_init_sock(sk);
541+
}
542+
535543
static void mptcp_subflow_shutdown(struct sock *ssk, int how)
536544
{
537545
lock_sock(ssk);
@@ -640,7 +648,7 @@ static struct sock *mptcp_accept(struct sock *sk, int flags, int *err,
640648
return NULL;
641649
}
642650

643-
mptcp_init_sock(new_mptcp_sock);
651+
__mptcp_init_sock(new_mptcp_sock);
644652

645653
msk = mptcp_sk(new_mptcp_sock);
646654
msk->remote_key = subflow->remote_key;
@@ -1078,7 +1086,7 @@ static struct inet_protosw mptcp_protosw = {
10781086
.flags = INET_PROTOSW_ICSK,
10791087
};
10801088

1081-
void __init mptcp_init(void)
1089+
void mptcp_proto_init(void)
10821090
{
10831091
mptcp_prot.h.hashinfo = tcp_prot.h.hashinfo;
10841092
mptcp_stream_ops = inet_stream_ops;
@@ -1116,7 +1124,7 @@ static struct inet_protosw mptcp_v6_protosw = {
11161124
.flags = INET_PROTOSW_ICSK,
11171125
};
11181126

1119-
int mptcpv6_init(void)
1127+
int mptcp_proto_v6_init(void)
11201128
{
11211129
int err;
11221130

net/mptcp/protocol.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ extern const struct inet_connection_sock_af_ops ipv6_specific;
179179
#endif
180180

181181
void mptcp_proto_init(void);
182+
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
183+
int mptcp_proto_v6_init(void);
184+
#endif
182185

183186
struct mptcp_read_arg {
184187
struct msghdr *msg;

0 commit comments

Comments
 (0)