diff options
author | Florian Westphal <fw@strlen.de> | 2020-01-25 01:04:02 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2020-01-25 08:14:39 +0100 |
commit | e42f1ac626e7f799717d006e0f8393b6d6f9fc8c (patch) | |
tree | 0cba402eedefff40444f145c5209ee62e6008560 | |
parent | Merge branch 'mptcp-part-two' (diff) | |
download | linux-e42f1ac626e7f799717d006e0f8393b6d6f9fc8c.tar.xz linux-e42f1ac626e7f799717d006e0f8393b6d6f9fc8c.zip |
mptcp: do not inherit inet proto ops
We need to initialise the struct ourselves, else we expose tcp-specific
callbacks such as tcp_splice_read which will then trigger splat because
the socket is an mptcp one:
BUG: KASAN: slab-out-of-bounds in tcp_mstamp_refresh+0x80/0xa0 net/ipv4/tcp_output.c:57
Write of size 8 at addr ffff888116aa21d0 by task syz-executor.0/5478
CPU: 1 PID: 5478 Comm: syz-executor.0 Not tainted 5.5.0-rc6 #3
Call Trace:
tcp_mstamp_refresh+0x80/0xa0 net/ipv4/tcp_output.c:57
tcp_rcv_space_adjust+0x72/0x7f0 net/ipv4/tcp_input.c:612
tcp_read_sock+0x622/0x990 net/ipv4/tcp.c:1674
tcp_splice_read+0x20b/0xb40 net/ipv4/tcp.c:791
do_splice+0x1259/0x1560 fs/splice.c:1205
To prevent build error with ipv6, add the recv/sendmsg function
declaration to ipv6.h. The functions are already accessible "thanks"
to retpoline related work, but they are currently only made visible
by socket.c specific INDIRECT_CALLABLE macros.
Reported-by: Christoph Paasch <cpaasch@apple.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/ipv6.h | 3 | ||||
-rw-r--r-- | net/mptcp/protocol.c | 70 |
2 files changed, 54 insertions, 19 deletions
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 4e95f6df508c..cec1a54401f2 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -1113,6 +1113,9 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int inet6_hash_connect(struct inet_timewait_death_row *death_row, struct sock *sk); +int inet6_sendmsg(struct socket *sock, struct msghdr *msg, size_t size); +int inet6_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, + int flags); /* * reassembly.c diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index ee916b3686fe..41d49126d29a 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -1163,7 +1163,31 @@ out_unlock: return ret; } -static struct proto_ops mptcp_stream_ops; +static const struct proto_ops mptcp_stream_ops = { + .family = PF_INET, + .owner = THIS_MODULE, + .release = inet_release, + .bind = mptcp_bind, + .connect = mptcp_stream_connect, + .socketpair = sock_no_socketpair, + .accept = mptcp_stream_accept, + .getname = mptcp_v4_getname, + .poll = mptcp_poll, + .ioctl = inet_ioctl, + .gettstamp = sock_gettstamp, + .listen = mptcp_listen, + .shutdown = mptcp_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet_sendmsg, + .recvmsg = inet_recvmsg, + .mmap = sock_no_mmap, + .sendpage = inet_sendpage, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif +}; static struct inet_protosw mptcp_protosw = { .type = SOCK_STREAM, @@ -1176,14 +1200,6 @@ static struct inet_protosw mptcp_protosw = { void mptcp_proto_init(void) { mptcp_prot.h.hashinfo = tcp_prot.h.hashinfo; - mptcp_stream_ops = inet_stream_ops; - mptcp_stream_ops.bind = mptcp_bind; - mptcp_stream_ops.connect = mptcp_stream_connect; - mptcp_stream_ops.poll = mptcp_poll; - mptcp_stream_ops.accept = mptcp_stream_accept; - mptcp_stream_ops.getname = mptcp_v4_getname; - mptcp_stream_ops.listen = mptcp_listen; - mptcp_stream_ops.shutdown = mptcp_shutdown; mptcp_subflow_init(); @@ -1194,7 +1210,32 @@ void mptcp_proto_init(void) } #if IS_ENABLED(CONFIG_MPTCP_IPV6) -static struct proto_ops mptcp_v6_stream_ops; +static const struct proto_ops mptcp_v6_stream_ops = { + .family = PF_INET6, + .owner = THIS_MODULE, + .release = inet6_release, + .bind = mptcp_bind, + .connect = mptcp_stream_connect, + .socketpair = sock_no_socketpair, + .accept = mptcp_stream_accept, + .getname = mptcp_v6_getname, + .poll = mptcp_poll, + .ioctl = inet6_ioctl, + .gettstamp = sock_gettstamp, + .listen = mptcp_listen, + .shutdown = mptcp_shutdown, + .setsockopt = sock_common_setsockopt, + .getsockopt = sock_common_getsockopt, + .sendmsg = inet6_sendmsg, + .recvmsg = inet6_recvmsg, + .mmap = sock_no_mmap, + .sendpage = inet_sendpage, +#ifdef CONFIG_COMPAT + .compat_setsockopt = compat_sock_common_setsockopt, + .compat_getsockopt = compat_sock_common_getsockopt, +#endif +}; + static struct proto mptcp_v6_prot; static void mptcp_v6_destroy(struct sock *sk) @@ -1226,15 +1267,6 @@ int mptcp_proto_v6_init(void) if (err) return err; - mptcp_v6_stream_ops = inet6_stream_ops; - mptcp_v6_stream_ops.bind = mptcp_bind; - mptcp_v6_stream_ops.connect = mptcp_stream_connect; - mptcp_v6_stream_ops.poll = mptcp_poll; - mptcp_v6_stream_ops.accept = mptcp_stream_accept; - mptcp_v6_stream_ops.getname = mptcp_v6_getname; - mptcp_v6_stream_ops.listen = mptcp_listen; - mptcp_v6_stream_ops.shutdown = mptcp_shutdown; - err = inet6_register_protosw(&mptcp_v6_protosw); if (err) proto_unregister(&mptcp_v6_prot); |