2020-01-22 00:56:17 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* Multipath TCP
|
|
|
|
*
|
|
|
|
* Copyright (c) 2017 - 2019, Intel Corporation.
|
|
|
|
*/
|
|
|
|
|
2020-01-22 00:56:20 +00:00
|
|
|
#define pr_fmt(fmt) "MPTCP: " fmt
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <linux/module.h>
|
|
|
|
#include <linux/netdevice.h>
|
2020-11-13 05:20:21 +00:00
|
|
|
#include <crypto/sha2.h>
|
2023-08-22 09:34:10 +00:00
|
|
|
#include <crypto/utils.h>
|
2020-01-22 00:56:17 +00:00
|
|
|
#include <net/sock.h>
|
|
|
|
#include <net/inet_common.h>
|
|
|
|
#include <net/inet_hashtables.h>
|
|
|
|
#include <net/protocol.h>
|
2020-01-22 00:56:18 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
#include <net/ip6_route.h>
|
2021-01-20 14:39:14 +00:00
|
|
|
#include <net/transp_v6.h>
|
2020-01-22 00:56:18 +00:00
|
|
|
#endif
|
2020-01-22 00:56:17 +00:00
|
|
|
#include <net/mptcp.h>
|
2024-04-25 03:13:35 +00:00
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
#include "protocol.h"
|
2020-03-27 21:48:50 +00:00
|
|
|
#include "mib.h"
|
|
|
|
|
2021-04-16 22:38:05 +00:00
|
|
|
#include <trace/events/mptcp.h>
|
2023-01-20 00:45:16 +00:00
|
|
|
#include <trace/events/sock.h>
|
2021-04-16 22:38:05 +00:00
|
|
|
|
2021-01-20 14:39:14 +00:00
|
|
|
static void mptcp_subflow_ops_undo_override(struct sock *ssk);
|
|
|
|
|
2020-03-27 21:48:50 +00:00
|
|
|
static void SUBFLOW_REQ_INC_STATS(struct request_sock *req,
|
|
|
|
enum linux_mptcp_mib_field field)
|
|
|
|
{
|
|
|
|
MPTCP_INC_STATS(sock_net(req_to_sk(req)), field);
|
|
|
|
}
|
2020-01-22 00:56:17 +00:00
|
|
|
|
2020-01-22 00:56:20 +00:00
|
|
|
static void subflow_req_destructor(struct request_sock *req)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow_req=%p\n", subflow_req);
|
2020-01-22 00:56:20 +00:00
|
|
|
|
2020-06-17 10:08:56 +00:00
|
|
|
if (subflow_req->msk)
|
|
|
|
sock_put((struct sock *)subflow_req->msk);
|
|
|
|
|
2020-06-26 17:30:00 +00:00
|
|
|
mptcp_token_destroy_request(req);
|
2020-01-22 00:56:20 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
static void subflow_generate_hmac(u64 key1, u64 key2, u32 nonce1, u32 nonce2,
|
|
|
|
void *hmac)
|
|
|
|
{
|
|
|
|
u8 msg[8];
|
|
|
|
|
|
|
|
put_unaligned_be32(nonce1, &msg[0]);
|
|
|
|
put_unaligned_be32(nonce2, &msg[4]);
|
|
|
|
|
|
|
|
mptcp_crypto_hmac_sha(key1, key2, msg, 8, hmac);
|
|
|
|
}
|
|
|
|
|
2020-07-23 11:02:36 +00:00
|
|
|
static bool mptcp_can_accept_new_subflow(const struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
return mptcp_is_fully_established((void *)msk) &&
|
2022-05-02 20:52:31 +00:00
|
|
|
((mptcp_pm_is_userspace(msk) &&
|
|
|
|
mptcp_userspace_pm_active(msk)) ||
|
|
|
|
READ_ONCE(msk->pm.accept_subflow));
|
2020-07-23 11:02:36 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
/* validate received token and create truncated hmac and nonce for SYN-ACK */
|
2021-02-01 23:09:14 +00:00
|
|
|
static void subflow_req_create_thmac(struct mptcp_subflow_request_sock *subflow_req)
|
|
|
|
{
|
|
|
|
struct mptcp_sock *msk = subflow_req->msk;
|
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
|
|
|
|
|
|
|
get_random_bytes(&subflow_req->local_nonce, sizeof(u32));
|
|
|
|
|
2024-02-02 11:40:07 +00:00
|
|
|
subflow_generate_hmac(READ_ONCE(msk->local_key),
|
|
|
|
READ_ONCE(msk->remote_key),
|
2021-02-01 23:09:14 +00:00
|
|
|
subflow_req->local_nonce,
|
|
|
|
subflow_req->remote_nonce, hmac);
|
|
|
|
|
|
|
|
subflow_req->thmac = get_unaligned_be64(hmac);
|
|
|
|
}
|
|
|
|
|
2021-02-01 23:09:13 +00:00
|
|
|
static struct mptcp_sock *subflow_token_join_request(struct request_sock *req)
|
2020-03-27 21:48:39 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
int local_id;
|
|
|
|
|
2021-09-24 00:04:11 +00:00
|
|
|
msk = mptcp_token_get_sock(sock_net(req_to_sk(req)), subflow_req->token);
|
2020-03-27 21:48:39 +00:00
|
|
|
if (!msk) {
|
2020-03-27 21:48:50 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINNOTOKEN);
|
2020-06-17 10:08:56 +00:00
|
|
|
return NULL;
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
local_id = mptcp_pm_get_local_id(msk, (struct sock_common *)req);
|
|
|
|
if (local_id < 0) {
|
|
|
|
sock_put((struct sock *)msk);
|
2020-06-17 10:08:56 +00:00
|
|
|
return NULL;
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
|
|
|
subflow_req->local_id = local_id;
|
2024-07-27 10:01:28 +00:00
|
|
|
subflow_req->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)req);
|
2020-03-27 21:48:39 +00:00
|
|
|
|
2020-06-17 10:08:56 +00:00
|
|
|
return msk;
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
|
|
|
|
2021-02-11 23:30:40 +00:00
|
|
|
static void subflow_init_req(struct request_sock *req, const struct sock *sk_listener)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
|
|
|
|
subflow_req->mp_capable = 0;
|
2020-03-27 21:48:39 +00:00
|
|
|
subflow_req->mp_join = 0;
|
2021-06-17 23:46:09 +00:00
|
|
|
subflow_req->csum_reqd = mptcp_is_checksum_enabled(sock_net(sk_listener));
|
2021-06-22 19:25:19 +00:00
|
|
|
subflow_req->allow_join_id0 = mptcp_allow_join_id0(sock_net(sk_listener));
|
2020-06-17 10:08:56 +00:00
|
|
|
subflow_req->msk = NULL;
|
2020-06-26 17:30:00 +00:00
|
|
|
mptcp_token_init_request(req);
|
2020-07-30 19:25:52 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 23:09:15 +00:00
|
|
|
static bool subflow_use_different_sport(struct mptcp_sock *msk, const struct sock *sk)
|
|
|
|
{
|
|
|
|
return inet_sk(sk)->inet_sport != inet_sk((struct sock *)msk)->inet_sport;
|
|
|
|
}
|
|
|
|
|
2021-04-01 23:19:44 +00:00
|
|
|
static void subflow_add_reset_reason(struct sk_buff *skb, u8 reason)
|
|
|
|
{
|
|
|
|
struct mptcp_ext *mpext = skb_ext_add(skb, SKB_EXT_MPTCP);
|
|
|
|
|
|
|
|
if (mpext) {
|
|
|
|
memset(mpext, 0, sizeof(*mpext));
|
|
|
|
mpext->reset_reason = reason;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
mptcp: prevent MPC handshake on port-based signal endpoints
Syzkaller reported a lockdep splat:
============================================
WARNING: possible recursive locking detected
6.11.0-rc6-syzkaller-00019-g67784a74e258 #0 Not tainted
--------------------------------------------
syz-executor364/5113 is trying to acquire lock:
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
but task is already holding lock:
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(k-slock-AF_INET);
lock(k-slock-AF_INET);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by syz-executor364/5113:
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg+0x153/0x1b10 net/mptcp/protocol.c:1806
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg_fastopen+0x11f/0x530 net/mptcp/protocol.c:1727
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x5f/0x1b80 net/ipv4/ip_output.c:470
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x45f/0x1390 net/ipv4/ip_output.c:228
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: local_lock_acquire include/linux/local_lock_internal.h:29 [inline]
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: process_backlog+0x33b/0x15b0 net/core/dev.c:6104
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_local_deliver_finish+0x230/0x5f0 net/ipv4/ip_input.c:232
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
stack backtrace:
CPU: 0 UID: 0 PID: 5113 Comm: syz-executor364 Not tainted 6.11.0-rc6-syzkaller-00019-g67784a74e258 #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:93 [inline]
dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119
check_deadlock kernel/locking/lockdep.c:3061 [inline]
validate_chain+0x15d3/0x5900 kernel/locking/lockdep.c:3855
__lock_acquire+0x137a/0x2040 kernel/locking/lockdep.c:5142
lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5759
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
mptcp_sk_clone_init+0x32/0x13c0 net/mptcp/protocol.c:3279
subflow_syn_recv_sock+0x931/0x1920 net/mptcp/subflow.c:874
tcp_check_req+0xfe4/0x1a20 net/ipv4/tcp_minisocks.c:853
tcp_v4_rcv+0x1c3e/0x37f0 net/ipv4/tcp_ipv4.c:2267
ip_protocol_deliver_rcu+0x22e/0x440 net/ipv4/ip_input.c:205
ip_local_deliver_finish+0x341/0x5f0 net/ipv4/ip_input.c:233
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
__netif_receive_skb_one_core net/core/dev.c:5661 [inline]
__netif_receive_skb+0x2bf/0x650 net/core/dev.c:5775
process_backlog+0x662/0x15b0 net/core/dev.c:6108
__napi_poll+0xcb/0x490 net/core/dev.c:6772
napi_poll net/core/dev.c:6841 [inline]
net_rx_action+0x89b/0x1240 net/core/dev.c:6963
handle_softirqs+0x2c4/0x970 kernel/softirq.c:554
do_softirq+0x11b/0x1e0 kernel/softirq.c:455
</IRQ>
<TASK>
__local_bh_enable_ip+0x1bb/0x200 kernel/softirq.c:382
local_bh_enable include/linux/bottom_half.h:33 [inline]
rcu_read_unlock_bh include/linux/rcupdate.h:908 [inline]
__dev_queue_xmit+0x1763/0x3e90 net/core/dev.c:4450
dev_queue_xmit include/linux/netdevice.h:3105 [inline]
neigh_hh_output include/net/neighbour.h:526 [inline]
neigh_output include/net/neighbour.h:540 [inline]
ip_finish_output2+0xd41/0x1390 net/ipv4/ip_output.c:235
ip_local_out net/ipv4/ip_output.c:129 [inline]
__ip_queue_xmit+0x118c/0x1b80 net/ipv4/ip_output.c:535
__tcp_transmit_skb+0x2544/0x3b30 net/ipv4/tcp_output.c:1466
tcp_rcv_synsent_state_process net/ipv4/tcp_input.c:6542 [inline]
tcp_rcv_state_process+0x2c32/0x4570 net/ipv4/tcp_input.c:6729
tcp_v4_do_rcv+0x77d/0xc70 net/ipv4/tcp_ipv4.c:1934
sk_backlog_rcv include/net/sock.h:1111 [inline]
__release_sock+0x214/0x350 net/core/sock.c:3004
release_sock+0x61/0x1f0 net/core/sock.c:3558
mptcp_sendmsg_fastopen+0x1ad/0x530 net/mptcp/protocol.c:1733
mptcp_sendmsg+0x1884/0x1b10 net/mptcp/protocol.c:1812
sock_sendmsg_nosec net/socket.c:730 [inline]
__sock_sendmsg+0x1a6/0x270 net/socket.c:745
____sys_sendmsg+0x525/0x7d0 net/socket.c:2597
___sys_sendmsg net/socket.c:2651 [inline]
__sys_sendmmsg+0x3b2/0x740 net/socket.c:2737
__do_sys_sendmmsg net/socket.c:2766 [inline]
__se_sys_sendmmsg net/socket.c:2763 [inline]
__x64_sys_sendmmsg+0xa0/0xb0 net/socket.c:2763
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f04fb13a6b9
Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 01 1a 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd651f42d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000133
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f04fb13a6b9
RDX: 0000000000000001 RSI: 0000000020000d00 RDI: 0000000000000004
RBP: 00007ffd651f4310 R08: 0000000000000001 R09: 0000000000000001
R10: 0000000020000080 R11: 0000000000000246 R12: 00000000000f4240
R13: 00007f04fb187449 R14: 00007ffd651f42f4 R15: 00007ffd651f4300
</TASK>
As noted by Cong Wang, the splat is false positive, but the code
path leading to the report is an unexpected one: a client is
attempting an MPC handshake towards the in-kernel listener created
by the in-kernel PM for a port based signal endpoint.
Such connection will be never accepted; many of them can make the
listener queue full and preventing the creation of MPJ subflow via
such listener - its intended role.
Explicitly detect this scenario at initial-syn time and drop the
incoming MPC request.
Fixes: 1729cf186d8a ("mptcp: create the listening socket for new port")
Cc: stable@vger.kernel.org
Reported-by: syzbot+f4aacdfef2c6a6529c3e@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f4aacdfef2c6a6529c3e
Cc: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20241014-net-mptcp-mpc-port-endp-v2-1-7faea8e6b6ae@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-10-14 14:06:00 +00:00
|
|
|
static int subflow_reset_req_endp(struct request_sock *req, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEENDPATTEMPT);
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
|
|
|
return -EPERM;
|
|
|
|
}
|
|
|
|
|
2020-11-30 15:36:31 +00:00
|
|
|
/* Init mptcp request socket.
|
|
|
|
*
|
|
|
|
* Returns an error code if a JOIN has failed and a TCP reset
|
|
|
|
* should be sent.
|
|
|
|
*/
|
2021-02-11 23:30:40 +00:00
|
|
|
static int subflow_check_req(struct request_sock *req,
|
|
|
|
const struct sock *sk_listener,
|
|
|
|
struct sk_buff *skb)
|
2020-07-30 19:25:52 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
struct mptcp_options_received mp_opt;
|
2021-08-27 00:44:52 +00:00
|
|
|
bool opt_mp_capable, opt_mp_join;
|
2020-07-30 19:25:52 +00:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow_req=%p, listener=%p\n", subflow_req, listener);
|
2020-07-30 19:25:52 +00:00
|
|
|
|
2021-02-11 23:30:40 +00:00
|
|
|
#ifdef CONFIG_TCP_MD5SIG
|
|
|
|
/* no MPTCP if MD5SIG is enabled on this socket or we may run out of
|
|
|
|
* TCP option space.
|
|
|
|
*/
|
2024-04-06 01:48:48 +00:00
|
|
|
if (rcu_access_pointer(tcp_sk(sk_listener)->md5sig_info)) {
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
|
2021-02-11 23:30:40 +00:00
|
|
|
return -EINVAL;
|
2024-04-06 01:48:48 +00:00
|
|
|
}
|
2021-02-11 23:30:40 +00:00
|
|
|
#endif
|
2020-07-30 19:25:52 +00:00
|
|
|
|
2022-02-16 02:11:25 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
2020-07-30 19:25:52 +00:00
|
|
|
|
2024-01-11 19:49:17 +00:00
|
|
|
opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYN);
|
2024-01-11 19:49:16 +00:00
|
|
|
opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYN);
|
2021-08-27 00:44:52 +00:00
|
|
|
if (opt_mp_capable) {
|
2020-03-27 21:48:50 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
|
|
|
|
|
mptcp: prevent MPC handshake on port-based signal endpoints
Syzkaller reported a lockdep splat:
============================================
WARNING: possible recursive locking detected
6.11.0-rc6-syzkaller-00019-g67784a74e258 #0 Not tainted
--------------------------------------------
syz-executor364/5113 is trying to acquire lock:
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
but task is already holding lock:
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(k-slock-AF_INET);
lock(k-slock-AF_INET);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by syz-executor364/5113:
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg+0x153/0x1b10 net/mptcp/protocol.c:1806
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg_fastopen+0x11f/0x530 net/mptcp/protocol.c:1727
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x5f/0x1b80 net/ipv4/ip_output.c:470
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x45f/0x1390 net/ipv4/ip_output.c:228
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: local_lock_acquire include/linux/local_lock_internal.h:29 [inline]
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: process_backlog+0x33b/0x15b0 net/core/dev.c:6104
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_local_deliver_finish+0x230/0x5f0 net/ipv4/ip_input.c:232
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
stack backtrace:
CPU: 0 UID: 0 PID: 5113 Comm: syz-executor364 Not tainted 6.11.0-rc6-syzkaller-00019-g67784a74e258 #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:93 [inline]
dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119
check_deadlock kernel/locking/lockdep.c:3061 [inline]
validate_chain+0x15d3/0x5900 kernel/locking/lockdep.c:3855
__lock_acquire+0x137a/0x2040 kernel/locking/lockdep.c:5142
lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5759
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
mptcp_sk_clone_init+0x32/0x13c0 net/mptcp/protocol.c:3279
subflow_syn_recv_sock+0x931/0x1920 net/mptcp/subflow.c:874
tcp_check_req+0xfe4/0x1a20 net/ipv4/tcp_minisocks.c:853
tcp_v4_rcv+0x1c3e/0x37f0 net/ipv4/tcp_ipv4.c:2267
ip_protocol_deliver_rcu+0x22e/0x440 net/ipv4/ip_input.c:205
ip_local_deliver_finish+0x341/0x5f0 net/ipv4/ip_input.c:233
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
__netif_receive_skb_one_core net/core/dev.c:5661 [inline]
__netif_receive_skb+0x2bf/0x650 net/core/dev.c:5775
process_backlog+0x662/0x15b0 net/core/dev.c:6108
__napi_poll+0xcb/0x490 net/core/dev.c:6772
napi_poll net/core/dev.c:6841 [inline]
net_rx_action+0x89b/0x1240 net/core/dev.c:6963
handle_softirqs+0x2c4/0x970 kernel/softirq.c:554
do_softirq+0x11b/0x1e0 kernel/softirq.c:455
</IRQ>
<TASK>
__local_bh_enable_ip+0x1bb/0x200 kernel/softirq.c:382
local_bh_enable include/linux/bottom_half.h:33 [inline]
rcu_read_unlock_bh include/linux/rcupdate.h:908 [inline]
__dev_queue_xmit+0x1763/0x3e90 net/core/dev.c:4450
dev_queue_xmit include/linux/netdevice.h:3105 [inline]
neigh_hh_output include/net/neighbour.h:526 [inline]
neigh_output include/net/neighbour.h:540 [inline]
ip_finish_output2+0xd41/0x1390 net/ipv4/ip_output.c:235
ip_local_out net/ipv4/ip_output.c:129 [inline]
__ip_queue_xmit+0x118c/0x1b80 net/ipv4/ip_output.c:535
__tcp_transmit_skb+0x2544/0x3b30 net/ipv4/tcp_output.c:1466
tcp_rcv_synsent_state_process net/ipv4/tcp_input.c:6542 [inline]
tcp_rcv_state_process+0x2c32/0x4570 net/ipv4/tcp_input.c:6729
tcp_v4_do_rcv+0x77d/0xc70 net/ipv4/tcp_ipv4.c:1934
sk_backlog_rcv include/net/sock.h:1111 [inline]
__release_sock+0x214/0x350 net/core/sock.c:3004
release_sock+0x61/0x1f0 net/core/sock.c:3558
mptcp_sendmsg_fastopen+0x1ad/0x530 net/mptcp/protocol.c:1733
mptcp_sendmsg+0x1884/0x1b10 net/mptcp/protocol.c:1812
sock_sendmsg_nosec net/socket.c:730 [inline]
__sock_sendmsg+0x1a6/0x270 net/socket.c:745
____sys_sendmsg+0x525/0x7d0 net/socket.c:2597
___sys_sendmsg net/socket.c:2651 [inline]
__sys_sendmmsg+0x3b2/0x740 net/socket.c:2737
__do_sys_sendmmsg net/socket.c:2766 [inline]
__se_sys_sendmmsg net/socket.c:2763 [inline]
__x64_sys_sendmmsg+0xa0/0xb0 net/socket.c:2763
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f04fb13a6b9
Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 01 1a 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd651f42d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000133
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f04fb13a6b9
RDX: 0000000000000001 RSI: 0000000020000d00 RDI: 0000000000000004
RBP: 00007ffd651f4310 R08: 0000000000000001 R09: 0000000000000001
R10: 0000000020000080 R11: 0000000000000246 R12: 00000000000f4240
R13: 00007f04fb187449 R14: 00007ffd651f42f4 R15: 00007ffd651f4300
</TASK>
As noted by Cong Wang, the splat is false positive, but the code
path leading to the report is an unexpected one: a client is
attempting an MPC handshake towards the in-kernel listener created
by the in-kernel PM for a port based signal endpoint.
Such connection will be never accepted; many of them can make the
listener queue full and preventing the creation of MPJ subflow via
such listener - its intended role.
Explicitly detect this scenario at initial-syn time and drop the
incoming MPC request.
Fixes: 1729cf186d8a ("mptcp: create the listening socket for new port")
Cc: stable@vger.kernel.org
Reported-by: syzbot+f4aacdfef2c6a6529c3e@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f4aacdfef2c6a6529c3e
Cc: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20241014-net-mptcp-mpc-port-endp-v2-1-7faea8e6b6ae@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-10-14 14:06:00 +00:00
|
|
|
if (unlikely(listener->pm_listener))
|
|
|
|
return subflow_reset_req_endp(req, skb);
|
2021-08-27 00:44:52 +00:00
|
|
|
if (opt_mp_join)
|
2020-11-30 15:36:31 +00:00
|
|
|
return 0;
|
2021-08-27 00:44:52 +00:00
|
|
|
} else if (opt_mp_join) {
|
2020-03-27 21:48:50 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX);
|
mptcp: mib: count MPJ with backup flag
Without such counters, it is difficult to easily debug issues with MPJ
not having the backup flags on production servers.
This is not strictly a fix, but it eases to validate the following
patches without requiring to take packet traces, to query ongoing
connections with Netlink with admin permissions, or to guess by looking
at the behaviour of the packet scheduler. Also, the modification is self
contained, isolated, well controlled, and the increments are done just
after others, there from the beginning. It looks then safe, and helpful
to backport this.
Fixes: 4596a2c1b7f5 ("mptcp: allow creating non-backup subflows")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2024-07-27 10:01:26 +00:00
|
|
|
|
|
|
|
if (mp_opt.backup)
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNBACKUPRX);
|
mptcp: prevent MPC handshake on port-based signal endpoints
Syzkaller reported a lockdep splat:
============================================
WARNING: possible recursive locking detected
6.11.0-rc6-syzkaller-00019-g67784a74e258 #0 Not tainted
--------------------------------------------
syz-executor364/5113 is trying to acquire lock:
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff8880449f1958 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
but task is already holding lock:
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(k-slock-AF_INET);
lock(k-slock-AF_INET);
*** DEADLOCK ***
May be due to missing lock nesting notation
7 locks held by syz-executor364/5113:
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#0: ffff8880449f0e18 (sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg+0x153/0x1b10 net/mptcp/protocol.c:1806
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1607 [inline]
#1: ffff88803fe39ad8 (k-sk_lock-AF_INET){+.+.}-{0:0}, at: mptcp_sendmsg_fastopen+0x11f/0x530 net/mptcp/protocol.c:1727
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#2: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: __ip_queue_xmit+0x5f/0x1b80 net/ipv4/ip_output.c:470
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#3: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_finish_output2+0x45f/0x1390 net/ipv4/ip_output.c:228
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: local_lock_acquire include/linux/local_lock_internal.h:29 [inline]
#4: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: process_backlog+0x33b/0x15b0 net/core/dev.c:6104
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_lock_acquire include/linux/rcupdate.h:326 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: rcu_read_lock include/linux/rcupdate.h:838 [inline]
#5: ffffffff8e938320 (rcu_read_lock){....}-{1:2}, at: ip_local_deliver_finish+0x230/0x5f0 net/ipv4/ip_input.c:232
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: spin_lock include/linux/spinlock.h:351 [inline]
#6: ffff88803fe3cb58 (k-slock-AF_INET){+.-.}-{2:2}, at: sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
stack backtrace:
CPU: 0 UID: 0 PID: 5113 Comm: syz-executor364 Not tainted 6.11.0-rc6-syzkaller-00019-g67784a74e258 #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Call Trace:
<IRQ>
__dump_stack lib/dump_stack.c:93 [inline]
dump_stack_lvl+0x241/0x360 lib/dump_stack.c:119
check_deadlock kernel/locking/lockdep.c:3061 [inline]
validate_chain+0x15d3/0x5900 kernel/locking/lockdep.c:3855
__lock_acquire+0x137a/0x2040 kernel/locking/lockdep.c:5142
lock_acquire+0x1ed/0x550 kernel/locking/lockdep.c:5759
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
sk_clone_lock+0x2cd/0xf40 net/core/sock.c:2328
mptcp_sk_clone_init+0x32/0x13c0 net/mptcp/protocol.c:3279
subflow_syn_recv_sock+0x931/0x1920 net/mptcp/subflow.c:874
tcp_check_req+0xfe4/0x1a20 net/ipv4/tcp_minisocks.c:853
tcp_v4_rcv+0x1c3e/0x37f0 net/ipv4/tcp_ipv4.c:2267
ip_protocol_deliver_rcu+0x22e/0x440 net/ipv4/ip_input.c:205
ip_local_deliver_finish+0x341/0x5f0 net/ipv4/ip_input.c:233
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
NF_HOOK+0x3a4/0x450 include/linux/netfilter.h:314
__netif_receive_skb_one_core net/core/dev.c:5661 [inline]
__netif_receive_skb+0x2bf/0x650 net/core/dev.c:5775
process_backlog+0x662/0x15b0 net/core/dev.c:6108
__napi_poll+0xcb/0x490 net/core/dev.c:6772
napi_poll net/core/dev.c:6841 [inline]
net_rx_action+0x89b/0x1240 net/core/dev.c:6963
handle_softirqs+0x2c4/0x970 kernel/softirq.c:554
do_softirq+0x11b/0x1e0 kernel/softirq.c:455
</IRQ>
<TASK>
__local_bh_enable_ip+0x1bb/0x200 kernel/softirq.c:382
local_bh_enable include/linux/bottom_half.h:33 [inline]
rcu_read_unlock_bh include/linux/rcupdate.h:908 [inline]
__dev_queue_xmit+0x1763/0x3e90 net/core/dev.c:4450
dev_queue_xmit include/linux/netdevice.h:3105 [inline]
neigh_hh_output include/net/neighbour.h:526 [inline]
neigh_output include/net/neighbour.h:540 [inline]
ip_finish_output2+0xd41/0x1390 net/ipv4/ip_output.c:235
ip_local_out net/ipv4/ip_output.c:129 [inline]
__ip_queue_xmit+0x118c/0x1b80 net/ipv4/ip_output.c:535
__tcp_transmit_skb+0x2544/0x3b30 net/ipv4/tcp_output.c:1466
tcp_rcv_synsent_state_process net/ipv4/tcp_input.c:6542 [inline]
tcp_rcv_state_process+0x2c32/0x4570 net/ipv4/tcp_input.c:6729
tcp_v4_do_rcv+0x77d/0xc70 net/ipv4/tcp_ipv4.c:1934
sk_backlog_rcv include/net/sock.h:1111 [inline]
__release_sock+0x214/0x350 net/core/sock.c:3004
release_sock+0x61/0x1f0 net/core/sock.c:3558
mptcp_sendmsg_fastopen+0x1ad/0x530 net/mptcp/protocol.c:1733
mptcp_sendmsg+0x1884/0x1b10 net/mptcp/protocol.c:1812
sock_sendmsg_nosec net/socket.c:730 [inline]
__sock_sendmsg+0x1a6/0x270 net/socket.c:745
____sys_sendmsg+0x525/0x7d0 net/socket.c:2597
___sys_sendmsg net/socket.c:2651 [inline]
__sys_sendmmsg+0x3b2/0x740 net/socket.c:2737
__do_sys_sendmmsg net/socket.c:2766 [inline]
__se_sys_sendmmsg net/socket.c:2763 [inline]
__x64_sys_sendmmsg+0xa0/0xb0 net/socket.c:2763
do_syscall_x64 arch/x86/entry/common.c:52 [inline]
do_syscall_64+0xf3/0x230 arch/x86/entry/common.c:83
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f04fb13a6b9
Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 01 1a 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007ffd651f42d8 EFLAGS: 00000246 ORIG_RAX: 0000000000000133
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007f04fb13a6b9
RDX: 0000000000000001 RSI: 0000000020000d00 RDI: 0000000000000004
RBP: 00007ffd651f4310 R08: 0000000000000001 R09: 0000000000000001
R10: 0000000020000080 R11: 0000000000000246 R12: 00000000000f4240
R13: 00007f04fb187449 R14: 00007ffd651f42f4 R15: 00007ffd651f4300
</TASK>
As noted by Cong Wang, the splat is false positive, but the code
path leading to the report is an unexpected one: a client is
attempting an MPC handshake towards the in-kernel listener created
by the in-kernel PM for a port based signal endpoint.
Such connection will be never accepted; many of them can make the
listener queue full and preventing the creation of MPJ subflow via
such listener - its intended role.
Explicitly detect this scenario at initial-syn time and drop the
incoming MPC request.
Fixes: 1729cf186d8a ("mptcp: create the listening socket for new port")
Cc: stable@vger.kernel.org
Reported-by: syzbot+f4aacdfef2c6a6529c3e@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f4aacdfef2c6a6529c3e
Cc: Cong Wang <cong.wang@bytedance.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20241014-net-mptcp-mpc-port-endp-v2-1-7faea8e6b6ae@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-10-14 14:06:00 +00:00
|
|
|
} else if (unlikely(listener->pm_listener)) {
|
|
|
|
return subflow_reset_req_endp(req, skb);
|
2020-03-27 21:48:50 +00:00
|
|
|
}
|
2020-03-27 21:48:39 +00:00
|
|
|
|
2021-08-27 00:44:52 +00:00
|
|
|
if (opt_mp_capable && listener->request_mptcp) {
|
2021-05-27 23:54:25 +00:00
|
|
|
int err, retries = MPTCP_TOKEN_MAX_RETRIES;
|
2020-07-30 19:25:51 +00:00
|
|
|
|
2020-07-30 19:25:54 +00:00
|
|
|
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
|
2020-07-30 19:25:51 +00:00
|
|
|
again:
|
|
|
|
do {
|
|
|
|
get_random_bytes(&subflow_req->local_key, sizeof(subflow_req->local_key));
|
|
|
|
} while (subflow_req->local_key == 0);
|
2020-01-22 00:56:20 +00:00
|
|
|
|
2020-07-30 19:25:54 +00:00
|
|
|
if (unlikely(req->syncookie)) {
|
|
|
|
mptcp_crypto_key_sha(subflow_req->local_key,
|
|
|
|
&subflow_req->token,
|
|
|
|
&subflow_req->idsn);
|
|
|
|
if (mptcp_token_exists(subflow_req->token)) {
|
|
|
|
if (retries-- > 0)
|
|
|
|
goto again;
|
2021-04-01 23:19:41 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_TOKENFALLBACKINIT);
|
2020-07-30 19:25:54 +00:00
|
|
|
} else {
|
|
|
|
subflow_req->mp_capable = 1;
|
|
|
|
}
|
2020-11-30 15:36:31 +00:00
|
|
|
return 0;
|
2020-07-30 19:25:54 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:20 +00:00
|
|
|
err = mptcp_token_new_request(req);
|
|
|
|
if (err == 0)
|
|
|
|
subflow_req->mp_capable = 1;
|
2020-07-30 19:25:51 +00:00
|
|
|
else if (retries-- > 0)
|
|
|
|
goto again;
|
2021-04-01 23:19:41 +00:00
|
|
|
else
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_TOKENFALLBACKINIT);
|
2020-01-22 00:56:20 +00:00
|
|
|
|
2021-08-27 00:44:52 +00:00
|
|
|
} else if (opt_mp_join && listener->request_mptcp) {
|
2020-03-27 21:48:40 +00:00
|
|
|
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq;
|
2020-03-27 21:48:39 +00:00
|
|
|
subflow_req->mp_join = 1;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
subflow_req->backup = mp_opt.backup;
|
|
|
|
subflow_req->remote_id = mp_opt.join_id;
|
|
|
|
subflow_req->token = mp_opt.token;
|
|
|
|
subflow_req->remote_nonce = mp_opt.nonce;
|
2021-02-01 23:09:13 +00:00
|
|
|
subflow_req->msk = subflow_token_join_request(req);
|
2020-07-30 19:25:56 +00:00
|
|
|
|
2020-11-30 15:36:31 +00:00
|
|
|
/* Can't fall back to TCP in this case. */
|
2021-04-01 23:19:44 +00:00
|
|
|
if (!subflow_req->msk) {
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
|
2020-11-30 15:36:31 +00:00
|
|
|
return -EPERM;
|
2021-04-01 23:19:44 +00:00
|
|
|
}
|
2020-11-30 15:36:31 +00:00
|
|
|
|
2021-02-01 23:09:15 +00:00
|
|
|
if (subflow_use_different_sport(subflow_req->msk, sk_listener)) {
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("syn inet_sport=%d %d\n",
|
2021-02-01 23:09:15 +00:00
|
|
|
ntohs(inet_sk(sk_listener)->inet_sport),
|
|
|
|
ntohs(inet_sk((struct sock *)subflow_req->msk)->inet_sport));
|
|
|
|
if (!mptcp_pm_sport_in_anno_list(subflow_req->msk, sk_listener)) {
|
2021-02-01 23:09:19 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTSYNRX);
|
2024-04-06 01:48:48 +00:00
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
2021-02-01 23:09:15 +00:00
|
|
|
return -EPERM;
|
|
|
|
}
|
2021-02-01 23:09:19 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINPORTSYNRX);
|
2021-02-01 23:09:15 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 23:09:14 +00:00
|
|
|
subflow_req_create_thmac(subflow_req);
|
|
|
|
|
2020-11-30 15:36:31 +00:00
|
|
|
if (unlikely(req->syncookie)) {
|
2024-04-06 01:48:48 +00:00
|
|
|
if (!mptcp_can_accept_new_subflow(subflow_req->msk)) {
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
mptcp: fix syncookie process if mptcp can not_accept new subflow
Lots of "TCP: tcp_fin: Impossible, sk->sk_state=7" in client side
when doing stress testing using wrk and webfsd.
There are at least two cases may trigger this warning:
1.mptcp is in syncookie, and server recv MP_JOIN SYN request,
in subflow_check_req(), the mptcp_can_accept_new_subflow()
return false, so subflow_init_req_cookie_join_save() isn't
called, i.e. not store the data present in the MP_JOIN syn
request and the random nonce in hash table - join_entries[],
but still send synack. When recv 3rd-ack,
mptcp_token_join_cookie_init_state() will return false, and
3rd-ack is dropped, then if mptcp conn is closed by client,
client will send a DATA_FIN and a MPTCP FIN, the DATA_FIN
doesn't have MP_CAPABLE or MP_JOIN,
so mptcp_subflow_init_cookie_req() will return 0, and pass
the cookie check, MP_JOIN request is fallback to normal TCP.
Server will send a TCP FIN if closed, in client side,
when process TCP FIN, it will do reset, the code path is:
tcp_data_queue()->mptcp_incoming_options()
->check_fully_established()->mptcp_subflow_reset().
mptcp_subflow_reset() will set sock state to TCP_CLOSE,
so tcp_fin will hit TCP_CLOSE, and print the warning.
2.mptcp is in syncookie, and server recv 3rd-ack, in
mptcp_subflow_init_cookie_req(), mptcp_can_accept_new_subflow()
return false, and subflow_req->mp_join is not set to 1,
so in subflow_syn_recv_sock() will not reset the MP_JOIN
subflow, but fallback to normal TCP, and then the same thing
happens when server will send a TCP FIN if closed.
For case1, subflow_check_req() return -EPERM,
then tcp_conn_request() will drop MP_JOIN SYN.
For case2, let subflow_syn_recv_sock() call
mptcp_can_accept_new_subflow(), and do fatal fallback, send reset.
Fixes: 9466a1ccebbe ("mptcp: enable JOIN requests even if cookies are in use")
Signed-off-by: Jianguo Wu <wujianguo@chinatelecom.cn>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-10 00:20:48 +00:00
|
|
|
return -EPERM;
|
2024-04-06 01:48:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
subflow_init_req_cookie_join_save(subflow_req, skb);
|
2020-07-30 19:25:56 +00:00
|
|
|
}
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("token=%u, remote_nonce=%u msk=%p\n", subflow_req->token,
|
2020-06-17 10:08:56 +00:00
|
|
|
subflow_req->remote_nonce, subflow_req->msk);
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
2020-11-30 15:36:31 +00:00
|
|
|
|
|
|
|
return 0;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2020-07-30 19:25:54 +00:00
|
|
|
int mptcp_subflow_init_cookie_req(struct request_sock *req,
|
|
|
|
const struct sock *sk_listener,
|
|
|
|
struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk_listener);
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
struct mptcp_options_received mp_opt;
|
2021-08-27 00:44:52 +00:00
|
|
|
bool opt_mp_capable, opt_mp_join;
|
2020-07-30 19:25:54 +00:00
|
|
|
int err;
|
|
|
|
|
2021-02-11 23:30:40 +00:00
|
|
|
subflow_init_req(req, sk_listener);
|
2022-02-16 02:11:25 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
2020-07-30 19:25:54 +00:00
|
|
|
|
2024-01-11 19:49:17 +00:00
|
|
|
opt_mp_capable = !!(mp_opt.suboptions & OPTION_MPTCP_MPC_ACK);
|
2024-01-11 19:49:16 +00:00
|
|
|
opt_mp_join = !!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK);
|
2021-08-27 00:44:52 +00:00
|
|
|
if (opt_mp_capable && opt_mp_join)
|
2020-07-30 19:25:54 +00:00
|
|
|
return -EINVAL;
|
|
|
|
|
2021-08-27 00:44:52 +00:00
|
|
|
if (opt_mp_capable && listener->request_mptcp) {
|
2020-07-30 19:25:54 +00:00
|
|
|
if (mp_opt.sndr_key == 0)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
subflow_req->local_key = mp_opt.rcvr_key;
|
|
|
|
err = mptcp_token_new_request(req);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
subflow_req->mp_capable = 1;
|
|
|
|
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq - 1;
|
2021-08-27 00:44:52 +00:00
|
|
|
} else if (opt_mp_join && listener->request_mptcp) {
|
2020-07-30 19:25:56 +00:00
|
|
|
if (!mptcp_token_join_cookie_init_state(subflow_req, skb))
|
|
|
|
return -EINVAL;
|
|
|
|
|
mptcp: fix syncookie process if mptcp can not_accept new subflow
Lots of "TCP: tcp_fin: Impossible, sk->sk_state=7" in client side
when doing stress testing using wrk and webfsd.
There are at least two cases may trigger this warning:
1.mptcp is in syncookie, and server recv MP_JOIN SYN request,
in subflow_check_req(), the mptcp_can_accept_new_subflow()
return false, so subflow_init_req_cookie_join_save() isn't
called, i.e. not store the data present in the MP_JOIN syn
request and the random nonce in hash table - join_entries[],
but still send synack. When recv 3rd-ack,
mptcp_token_join_cookie_init_state() will return false, and
3rd-ack is dropped, then if mptcp conn is closed by client,
client will send a DATA_FIN and a MPTCP FIN, the DATA_FIN
doesn't have MP_CAPABLE or MP_JOIN,
so mptcp_subflow_init_cookie_req() will return 0, and pass
the cookie check, MP_JOIN request is fallback to normal TCP.
Server will send a TCP FIN if closed, in client side,
when process TCP FIN, it will do reset, the code path is:
tcp_data_queue()->mptcp_incoming_options()
->check_fully_established()->mptcp_subflow_reset().
mptcp_subflow_reset() will set sock state to TCP_CLOSE,
so tcp_fin will hit TCP_CLOSE, and print the warning.
2.mptcp is in syncookie, and server recv 3rd-ack, in
mptcp_subflow_init_cookie_req(), mptcp_can_accept_new_subflow()
return false, and subflow_req->mp_join is not set to 1,
so in subflow_syn_recv_sock() will not reset the MP_JOIN
subflow, but fallback to normal TCP, and then the same thing
happens when server will send a TCP FIN if closed.
For case1, subflow_check_req() return -EPERM,
then tcp_conn_request() will drop MP_JOIN SYN.
For case2, let subflow_syn_recv_sock() call
mptcp_can_accept_new_subflow(), and do fatal fallback, send reset.
Fixes: 9466a1ccebbe ("mptcp: enable JOIN requests even if cookies are in use")
Signed-off-by: Jianguo Wu <wujianguo@chinatelecom.cn>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-07-10 00:20:48 +00:00
|
|
|
subflow_req->mp_join = 1;
|
2020-07-30 19:25:56 +00:00
|
|
|
subflow_req->ssn_offset = TCP_SKB_CB(skb)->seq - 1;
|
2020-07-30 19:25:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(mptcp_subflow_init_cookie_req);
|
|
|
|
|
2024-05-06 12:30:32 +00:00
|
|
|
static enum sk_rst_reason mptcp_get_rst_reason(const struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
const struct mptcp_ext *mpext = mptcp_get_ext(skb);
|
|
|
|
|
|
|
|
if (!mpext)
|
|
|
|
return SK_RST_REASON_NOT_SPECIFIED;
|
|
|
|
|
|
|
|
return sk_rst_convert_mptcp_reason(mpext->reset_reason);
|
|
|
|
}
|
|
|
|
|
2020-11-30 15:36:30 +00:00
|
|
|
static struct dst_entry *subflow_v4_route_req(const struct sock *sk,
|
|
|
|
struct sk_buff *skb,
|
|
|
|
struct flowi *fl,
|
2024-04-07 09:33:21 +00:00
|
|
|
struct request_sock *req,
|
|
|
|
u32 tw_isn)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
2020-11-30 15:36:30 +00:00
|
|
|
struct dst_entry *dst;
|
2020-11-30 15:36:31 +00:00
|
|
|
int err;
|
2020-11-30 15:36:30 +00:00
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
tcp_rsk(req)->is_mptcp = 1;
|
2021-02-11 23:30:40 +00:00
|
|
|
subflow_init_req(req, sk);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2024-04-07 09:33:21 +00:00
|
|
|
dst = tcp_request_sock_ipv4_ops.route_req(sk, skb, fl, req, tw_isn);
|
2020-11-30 15:36:30 +00:00
|
|
|
if (!dst)
|
|
|
|
return NULL;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2021-02-11 23:30:40 +00:00
|
|
|
err = subflow_check_req(req, sk, skb);
|
2020-11-30 15:36:31 +00:00
|
|
|
if (err == 0)
|
|
|
|
return dst;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2020-11-30 15:36:31 +00:00
|
|
|
dst_release(dst);
|
2024-05-06 12:30:32 +00:00
|
|
|
if (!req->syncookie)
|
|
|
|
tcp_request_sock_ops.send_reset(sk, skb,
|
|
|
|
mptcp_get_rst_reason(skb));
|
2020-11-30 15:36:31 +00:00
|
|
|
return NULL;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2022-11-25 22:29:51 +00:00
|
|
|
static void subflow_prep_synack(const struct sock *sk, struct request_sock *req,
|
|
|
|
struct tcp_fastopen_cookie *foc,
|
|
|
|
enum tcp_synack_type synack_type)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
struct inet_request_sock *ireq = inet_rsk(req);
|
|
|
|
|
|
|
|
/* clear tstamp_ok, as needed depending on cookie */
|
|
|
|
if (foc && foc->len > -1)
|
|
|
|
ireq->tstamp_ok = 0;
|
|
|
|
|
|
|
|
if (synack_type == TCP_SYNACK_FASTOPEN)
|
|
|
|
mptcp_fastopen_subflow_synack_set_params(subflow, req);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int subflow_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
|
|
|
|
struct flowi *fl,
|
|
|
|
struct request_sock *req,
|
|
|
|
struct tcp_fastopen_cookie *foc,
|
|
|
|
enum tcp_synack_type synack_type,
|
|
|
|
struct sk_buff *syn_skb)
|
|
|
|
{
|
|
|
|
subflow_prep_synack(sk, req, foc, synack_type);
|
|
|
|
|
|
|
|
return tcp_request_sock_ipv4_ops.send_synack(sk, dst, fl, req, foc,
|
|
|
|
synack_type, syn_skb);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2022-11-25 22:29:51 +00:00
|
|
|
static int subflow_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
|
|
|
|
struct flowi *fl,
|
|
|
|
struct request_sock *req,
|
|
|
|
struct tcp_fastopen_cookie *foc,
|
|
|
|
enum tcp_synack_type synack_type,
|
|
|
|
struct sk_buff *syn_skb)
|
|
|
|
{
|
|
|
|
subflow_prep_synack(sk, req, foc, synack_type);
|
|
|
|
|
|
|
|
return tcp_request_sock_ipv6_ops.send_synack(sk, dst, fl, req, foc,
|
|
|
|
synack_type, syn_skb);
|
|
|
|
}
|
|
|
|
|
2020-11-30 15:36:30 +00:00
|
|
|
static struct dst_entry *subflow_v6_route_req(const struct sock *sk,
|
|
|
|
struct sk_buff *skb,
|
|
|
|
struct flowi *fl,
|
2024-04-07 09:33:21 +00:00
|
|
|
struct request_sock *req,
|
|
|
|
u32 tw_isn)
|
2020-01-22 00:56:18 +00:00
|
|
|
{
|
2020-11-30 15:36:30 +00:00
|
|
|
struct dst_entry *dst;
|
2020-11-30 15:36:31 +00:00
|
|
|
int err;
|
2020-11-30 15:36:30 +00:00
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
tcp_rsk(req)->is_mptcp = 1;
|
2021-02-11 23:30:40 +00:00
|
|
|
subflow_init_req(req, sk);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2024-04-07 09:33:21 +00:00
|
|
|
dst = tcp_request_sock_ipv6_ops.route_req(sk, skb, fl, req, tw_isn);
|
2020-11-30 15:36:30 +00:00
|
|
|
if (!dst)
|
|
|
|
return NULL;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2021-02-11 23:30:40 +00:00
|
|
|
err = subflow_check_req(req, sk, skb);
|
2020-11-30 15:36:31 +00:00
|
|
|
if (err == 0)
|
|
|
|
return dst;
|
|
|
|
|
|
|
|
dst_release(dst);
|
2024-05-06 12:30:32 +00:00
|
|
|
if (!req->syncookie)
|
|
|
|
tcp6_request_sock_ops.send_reset(sk, skb,
|
|
|
|
mptcp_get_rst_reason(skb));
|
2020-11-30 15:36:31 +00:00
|
|
|
return NULL;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
/* validate received truncated hmac and create hmac for third ACK */
|
|
|
|
static bool subflow_thmac_valid(struct mptcp_subflow_context *subflow)
|
|
|
|
{
|
2020-05-22 02:10:49 +00:00
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
2020-03-27 21:48:40 +00:00
|
|
|
u64 thmac;
|
|
|
|
|
|
|
|
subflow_generate_hmac(subflow->remote_key, subflow->local_key,
|
|
|
|
subflow->remote_nonce, subflow->local_nonce,
|
|
|
|
hmac);
|
|
|
|
|
|
|
|
thmac = get_unaligned_be64(hmac);
|
|
|
|
pr_debug("subflow=%p, token=%u, thmac=%llu, subflow->thmac=%llu\n",
|
2022-02-16 02:11:26 +00:00
|
|
|
subflow, subflow->token, thmac, subflow->thmac);
|
2020-03-27 21:48:40 +00:00
|
|
|
|
|
|
|
return thmac == subflow->thmac;
|
|
|
|
}
|
|
|
|
|
2020-10-09 17:00:00 +00:00
|
|
|
void mptcp_subflow_reset(struct sock *ssk)
|
|
|
|
{
|
2020-10-09 17:00:01 +00:00
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
struct sock *sk = subflow->conn;
|
|
|
|
|
2023-03-09 14:49:58 +00:00
|
|
|
/* mptcp_mp_fail_no_response() can reach here on an already closed
|
|
|
|
* socket
|
|
|
|
*/
|
|
|
|
if (ssk->sk_state == TCP_CLOSE)
|
|
|
|
return;
|
|
|
|
|
2020-12-10 22:25:02 +00:00
|
|
|
/* must hold: tcp_done() could drop last reference on parent */
|
|
|
|
sock_hold(sk);
|
|
|
|
|
2024-04-25 03:13:39 +00:00
|
|
|
mptcp_send_active_reset_reason(ssk);
|
2020-10-09 17:00:00 +00:00
|
|
|
tcp_done(ssk);
|
2023-04-11 20:42:09 +00:00
|
|
|
if (!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &mptcp_sk(sk)->flags))
|
|
|
|
mptcp_schedule_work(sk);
|
2020-12-10 22:25:02 +00:00
|
|
|
|
|
|
|
sock_put(sk);
|
2020-10-09 17:00:00 +00:00
|
|
|
}
|
|
|
|
|
2021-02-01 23:09:15 +00:00
|
|
|
static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct sock *sk)
|
|
|
|
{
|
|
|
|
return inet_sk(sk)->inet_dport != inet_sk((struct sock *)msk)->inet_dport;
|
|
|
|
}
|
|
|
|
|
2023-12-15 16:04:25 +00:00
|
|
|
void __mptcp_sync_state(struct sock *sk, int state)
|
2021-06-22 00:33:08 +00:00
|
|
|
{
|
2024-02-08 18:03:51 +00:00
|
|
|
struct mptcp_subflow_context *subflow;
|
2023-12-15 16:04:25 +00:00
|
|
|
struct mptcp_sock *msk = mptcp_sk(sk);
|
2024-02-08 18:03:51 +00:00
|
|
|
struct sock *ssk = msk->first;
|
2023-12-15 16:04:25 +00:00
|
|
|
|
2024-02-08 18:03:51 +00:00
|
|
|
subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
__mptcp_propagate_sndbuf(sk, ssk);
|
2024-02-08 18:03:50 +00:00
|
|
|
if (!msk->rcvspace_init)
|
2024-02-08 18:03:51 +00:00
|
|
|
mptcp_rcv_space_init(msk, ssk);
|
2023-12-15 16:04:25 +00:00
|
|
|
|
2021-06-22 00:33:08 +00:00
|
|
|
if (sk->sk_state == TCP_SYN_SENT) {
|
2024-02-08 18:03:51 +00:00
|
|
|
/* subflow->idsn is always available is TCP_SYN_SENT state,
|
|
|
|
* even for the FASTOPEN scenarios
|
|
|
|
*/
|
|
|
|
WRITE_ONCE(msk->write_seq, subflow->idsn + 1);
|
|
|
|
WRITE_ONCE(msk->snd_nxt, msk->write_seq);
|
2023-12-22 12:47:23 +00:00
|
|
|
mptcp_set_state(sk, state);
|
2021-06-22 00:33:08 +00:00
|
|
|
sk->sk_state_change(sk);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-25 22:29:49 +00:00
|
|
|
static void subflow_set_remote_key(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_subflow_context *subflow,
|
|
|
|
const struct mptcp_options_received *mp_opt)
|
|
|
|
{
|
|
|
|
/* active MPC subflow will reach here multiple times:
|
|
|
|
* at subflow_finish_connect() time and at 4th ack time
|
|
|
|
*/
|
|
|
|
if (subflow->remote_key_valid)
|
|
|
|
return;
|
|
|
|
|
|
|
|
subflow->remote_key_valid = 1;
|
|
|
|
subflow->remote_key = mp_opt->sndr_key;
|
|
|
|
mptcp_crypto_key_sha(subflow->remote_key, NULL, &subflow->iasn);
|
|
|
|
subflow->iasn++;
|
|
|
|
|
|
|
|
WRITE_ONCE(msk->remote_key, subflow->remote_key);
|
|
|
|
WRITE_ONCE(msk->ack_seq, subflow->iasn);
|
|
|
|
WRITE_ONCE(msk->can_ack, true);
|
|
|
|
atomic64_set(&msk->rcv_wnd_sent, subflow->iasn);
|
|
|
|
}
|
|
|
|
|
2024-02-08 18:03:52 +00:00
|
|
|
static void mptcp_propagate_state(struct sock *sk, struct sock *ssk,
|
|
|
|
struct mptcp_subflow_context *subflow,
|
|
|
|
const struct mptcp_options_received *mp_opt)
|
|
|
|
{
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(sk);
|
|
|
|
|
|
|
|
mptcp_data_lock(sk);
|
|
|
|
if (mp_opt) {
|
|
|
|
/* Options are available only in the non fallback cases
|
|
|
|
* avoid updating rx path fields otherwise
|
|
|
|
*/
|
|
|
|
WRITE_ONCE(msk->snd_una, subflow->idsn + 1);
|
|
|
|
WRITE_ONCE(msk->wnd_end, subflow->idsn + 1 + tcp_sk(ssk)->snd_wnd);
|
|
|
|
subflow_set_remote_key(msk, subflow, mp_opt);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!sock_owned_by_user(sk)) {
|
|
|
|
__mptcp_sync_state(sk, ssk->sk_state);
|
|
|
|
} else {
|
|
|
|
msk->pending_state = ssk->sk_state;
|
|
|
|
__set_bit(MPTCP_SYNC_STATE, &msk->cb_flags);
|
|
|
|
}
|
|
|
|
mptcp_data_unlock(sk);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
struct mptcp_options_received mp_opt;
|
2020-03-19 21:45:37 +00:00
|
|
|
struct sock *parent = subflow->conn;
|
2022-11-25 22:29:49 +00:00
|
|
|
struct mptcp_sock *msk;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
subflow->icsk_af_ops->sk_rx_dst_set(sk, skb);
|
|
|
|
|
2020-04-30 13:01:51 +00:00
|
|
|
/* be sure no special action on any packet other than syn-ack */
|
|
|
|
if (subflow->conn_finished)
|
|
|
|
return;
|
|
|
|
|
2022-11-25 22:29:49 +00:00
|
|
|
msk = mptcp_sk(parent);
|
2020-07-23 11:02:29 +00:00
|
|
|
subflow->rel_write_seq = 1;
|
2020-04-30 13:01:51 +00:00
|
|
|
subflow->conn_finished = 1;
|
2020-06-29 20:26:20 +00:00
|
|
|
subflow->ssn_offset = TCP_SKB_CB(skb)->seq;
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p synack seq=%x\n", subflow, subflow->ssn_offset);
|
2020-04-30 13:01:51 +00:00
|
|
|
|
2022-02-16 02:11:25 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
2020-07-23 11:02:33 +00:00
|
|
|
if (subflow->request_mptcp) {
|
2024-01-11 19:49:17 +00:00
|
|
|
if (!(mp_opt.suboptions & OPTION_MPTCP_MPC_SYNACK)) {
|
2020-07-23 11:02:33 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk),
|
|
|
|
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK);
|
|
|
|
mptcp_do_fallback(sk);
|
2022-11-25 22:29:49 +00:00
|
|
|
pr_fallback(msk);
|
2020-07-23 11:02:33 +00:00
|
|
|
goto fallback;
|
|
|
|
}
|
|
|
|
|
2021-08-27 00:44:52 +00:00
|
|
|
if (mp_opt.suboptions & OPTION_MPTCP_CSUMREQD)
|
2022-11-25 22:29:49 +00:00
|
|
|
WRITE_ONCE(msk->csum_enabled, true);
|
2021-06-22 19:25:20 +00:00
|
|
|
if (mp_opt.deny_join_id0)
|
2022-11-25 22:29:49 +00:00
|
|
|
WRITE_ONCE(msk->pm.remote_deny_join_id0, true);
|
2020-04-30 13:01:51 +00:00
|
|
|
subflow->mp_capable = 1;
|
2021-04-01 23:19:42 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK);
|
2020-07-23 11:02:33 +00:00
|
|
|
mptcp_finish_connect(sk);
|
2024-09-09 20:09:23 +00:00
|
|
|
mptcp_active_enable(parent);
|
2024-02-08 18:03:52 +00:00
|
|
|
mptcp_propagate_state(parent, sk, subflow, &mp_opt);
|
2020-07-23 11:02:33 +00:00
|
|
|
} else if (subflow->request_join) {
|
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
|
|
|
|
2024-01-11 19:49:15 +00:00
|
|
|
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_SYNACK)) {
|
2021-04-01 23:19:44 +00:00
|
|
|
subflow->reset_reason = MPTCP_RST_EMPTCP;
|
2020-07-23 11:02:33 +00:00
|
|
|
goto do_reset;
|
2021-04-01 23:19:44 +00:00
|
|
|
}
|
2020-07-23 11:02:33 +00:00
|
|
|
|
2021-08-13 22:15:47 +00:00
|
|
|
subflow->backup = mp_opt.backup;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
subflow->thmac = mp_opt.thmac;
|
|
|
|
subflow->remote_nonce = mp_opt.nonce;
|
2024-02-15 18:25:32 +00:00
|
|
|
WRITE_ONCE(subflow->remote_id, mp_opt.join_id);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p, thmac=%llu, remote_nonce=%u backup=%d\n",
|
2021-08-13 22:15:47 +00:00
|
|
|
subflow, subflow->thmac, subflow->remote_nonce,
|
|
|
|
subflow->backup);
|
2020-04-30 13:01:51 +00:00
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
if (!subflow_thmac_valid(subflow)) {
|
2020-03-27 21:48:50 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINACKMAC);
|
2021-04-01 23:19:44 +00:00
|
|
|
subflow->reset_reason = MPTCP_RST_EMPTCP;
|
2020-03-27 21:48:40 +00:00
|
|
|
goto do_reset;
|
|
|
|
}
|
|
|
|
|
2021-05-27 23:54:26 +00:00
|
|
|
if (!mptcp_finish_join(sk))
|
|
|
|
goto do_reset;
|
|
|
|
|
2020-03-27 21:48:40 +00:00
|
|
|
subflow_generate_hmac(subflow->local_key, subflow->remote_key,
|
|
|
|
subflow->local_nonce,
|
|
|
|
subflow->remote_nonce,
|
2020-05-22 02:10:49 +00:00
|
|
|
hmac);
|
|
|
|
memcpy(subflow->hmac, hmac, MPTCPOPT_HMAC_LEN);
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2020-07-23 11:02:33 +00:00
|
|
|
subflow->mp_join = 1;
|
2020-03-27 21:48:50 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKRX);
|
2021-02-01 23:09:15 +00:00
|
|
|
|
mptcp: mib: count MPJ with backup flag
Without such counters, it is difficult to easily debug issues with MPJ
not having the backup flags on production servers.
This is not strictly a fix, but it eases to validate the following
patches without requiring to take packet traces, to query ongoing
connections with Netlink with admin permissions, or to guess by looking
at the behaviour of the packet scheduler. Also, the modification is self
contained, isolated, well controlled, and the increments are done just
after others, there from the beginning. It looks then safe, and helpful
to backport this.
Fixes: 4596a2c1b7f5 ("mptcp: allow creating non-backup subflows")
Cc: stable@vger.kernel.org
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
2024-07-27 10:01:26 +00:00
|
|
|
if (subflow->backup)
|
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNACKBACKUPRX);
|
|
|
|
|
2022-11-25 22:29:49 +00:00
|
|
|
if (subflow_use_different_dport(msk, sk)) {
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("synack inet_dport=%d %d\n",
|
2021-02-01 23:09:15 +00:00
|
|
|
ntohs(inet_sk(sk)->inet_dport),
|
|
|
|
ntohs(inet_sk(parent)->inet_dport));
|
2021-02-01 23:09:19 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINPORTSYNACKRX);
|
2021-02-01 23:09:15 +00:00
|
|
|
}
|
2020-07-23 11:02:33 +00:00
|
|
|
} else if (mptcp_check_fallback(sk)) {
|
2024-09-09 20:09:23 +00:00
|
|
|
/* It looks like MPTCP is blocked, while TCP is not */
|
|
|
|
if (subflow->mpc_drop)
|
|
|
|
mptcp_active_disable(parent);
|
2020-07-23 11:02:33 +00:00
|
|
|
fallback:
|
2024-02-08 18:03:52 +00:00
|
|
|
mptcp_propagate_state(parent, sk, subflow, NULL);
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
2020-07-23 11:02:33 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
do_reset:
|
2021-04-01 23:19:44 +00:00
|
|
|
subflow->reset_transient = 0;
|
2020-10-09 17:00:00 +00:00
|
|
|
mptcp_subflow_reset(sk);
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2022-03-07 20:44:37 +00:00
|
|
|
static void subflow_set_local_id(struct mptcp_subflow_context *subflow, int local_id)
|
|
|
|
{
|
2024-02-15 18:25:31 +00:00
|
|
|
WARN_ON_ONCE(local_id < 0 || local_id > 255);
|
|
|
|
WRITE_ONCE(subflow->local_id, local_id);
|
2022-03-07 20:44:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int subflow_chk_local_id(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
|
|
|
int err;
|
|
|
|
|
2024-02-15 18:25:31 +00:00
|
|
|
if (likely(subflow->local_id >= 0))
|
2022-03-07 20:44:37 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
err = mptcp_pm_get_local_id(msk, (struct sock_common *)sk);
|
|
|
|
if (err < 0)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
subflow_set_local_id(subflow, err);
|
2024-07-27 10:01:28 +00:00
|
|
|
subflow->request_bkup = mptcp_pm_is_backup(msk, (struct sock_common *)sk);
|
|
|
|
|
2022-03-07 20:44:37 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int subflow_rebuild_header(struct sock *sk)
|
|
|
|
{
|
|
|
|
int err = subflow_chk_local_id(sk);
|
|
|
|
|
|
|
|
if (unlikely(err < 0))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
return inet_sk_rebuild_header(sk);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
static int subflow_v6_rebuild_header(struct sock *sk)
|
|
|
|
{
|
|
|
|
int err = subflow_chk_local_id(sk);
|
|
|
|
|
|
|
|
if (unlikely(err < 0))
|
|
|
|
return err;
|
|
|
|
|
|
|
|
return inet6_sk_rebuild_header(sk);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2022-12-10 00:28:09 +00:00
|
|
|
static struct request_sock_ops mptcp_subflow_v4_request_sock_ops __ro_after_init;
|
2022-02-16 02:11:29 +00:00
|
|
|
static struct tcp_request_sock_ops subflow_request_sock_ipv4_ops __ro_after_init;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
static int subflow_v4_conn_request(struct sock *sk, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p\n", subflow);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
/* Never answer to SYNs sent to broadcast or multicast */
|
|
|
|
if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST))
|
|
|
|
goto drop;
|
|
|
|
|
2022-12-10 00:28:09 +00:00
|
|
|
return tcp_conn_request(&mptcp_subflow_v4_request_sock_ops,
|
2020-01-22 00:56:18 +00:00
|
|
|
&subflow_request_sock_ipv4_ops,
|
|
|
|
sk, skb);
|
|
|
|
drop:
|
|
|
|
tcp_listendrop(sk);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-12-10 00:28:10 +00:00
|
|
|
static void subflow_v4_req_destructor(struct request_sock *req)
|
|
|
|
{
|
|
|
|
subflow_req_destructor(req);
|
|
|
|
tcp_request_sock_ops.destructor(req);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2022-12-10 00:28:09 +00:00
|
|
|
static struct request_sock_ops mptcp_subflow_v6_request_sock_ops __ro_after_init;
|
2022-02-16 02:11:29 +00:00
|
|
|
static struct tcp_request_sock_ops subflow_request_sock_ipv6_ops __ro_after_init;
|
|
|
|
static struct inet_connection_sock_af_ops subflow_v6_specific __ro_after_init;
|
|
|
|
static struct inet_connection_sock_af_ops subflow_v6m_specific __ro_after_init;
|
2023-03-09 14:50:02 +00:00
|
|
|
static struct proto tcpv6_prot_override __ro_after_init;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
static int subflow_v6_conn_request(struct sock *sk, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p\n", subflow);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
if (skb->protocol == htons(ETH_P_IP))
|
|
|
|
return subflow_v4_conn_request(sk, skb);
|
|
|
|
|
|
|
|
if (!ipv6_unicast_destination(skb))
|
|
|
|
goto drop;
|
|
|
|
|
2021-03-17 16:55:15 +00:00
|
|
|
if (ipv6_addr_v4mapped(&ipv6_hdr(skb)->saddr)) {
|
|
|
|
__IP6_INC_STATS(sock_net(sk), NULL, IPSTATS_MIB_INHDRERRORS);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2022-12-10 00:28:09 +00:00
|
|
|
return tcp_conn_request(&mptcp_subflow_v6_request_sock_ops,
|
2020-01-22 00:56:18 +00:00
|
|
|
&subflow_request_sock_ipv6_ops, sk, skb);
|
|
|
|
|
|
|
|
drop:
|
|
|
|
tcp_listendrop(sk);
|
|
|
|
return 0; /* don't send reset */
|
|
|
|
}
|
2022-12-10 00:28:10 +00:00
|
|
|
|
|
|
|
static void subflow_v6_req_destructor(struct request_sock *req)
|
|
|
|
{
|
|
|
|
subflow_req_destructor(req);
|
|
|
|
tcp6_request_sock_ops.destructor(req);
|
|
|
|
}
|
2020-01-22 00:56:18 +00:00
|
|
|
#endif
|
|
|
|
|
2022-12-10 00:28:08 +00:00
|
|
|
struct request_sock *mptcp_subflow_reqsk_alloc(const struct request_sock_ops *ops,
|
|
|
|
struct sock *sk_listener,
|
|
|
|
bool attach_listener)
|
|
|
|
{
|
2022-12-10 00:28:09 +00:00
|
|
|
if (ops->family == AF_INET)
|
|
|
|
ops = &mptcp_subflow_v4_request_sock_ops;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (ops->family == AF_INET6)
|
|
|
|
ops = &mptcp_subflow_v6_request_sock_ops;
|
2020-01-22 00:56:18 +00:00
|
|
|
#endif
|
|
|
|
|
2022-12-10 00:28:08 +00:00
|
|
|
return inet_reqsk_alloc(ops, sk_listener, attach_listener);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL(mptcp_subflow_reqsk_alloc);
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
/* validate hmac received in third ACK */
|
|
|
|
static bool subflow_hmac_valid(const struct request_sock *req,
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
const struct mptcp_options_received *mp_opt)
|
2020-03-27 21:48:39 +00:00
|
|
|
{
|
|
|
|
const struct mptcp_subflow_request_sock *subflow_req;
|
2020-05-22 02:10:49 +00:00
|
|
|
u8 hmac[SHA256_DIGEST_SIZE];
|
2020-03-27 21:48:39 +00:00
|
|
|
struct mptcp_sock *msk;
|
|
|
|
|
|
|
|
subflow_req = mptcp_subflow_rsk(req);
|
2020-06-17 10:08:56 +00:00
|
|
|
msk = subflow_req->msk;
|
2020-03-27 21:48:39 +00:00
|
|
|
if (!msk)
|
|
|
|
return false;
|
|
|
|
|
2024-02-02 11:40:07 +00:00
|
|
|
subflow_generate_hmac(READ_ONCE(msk->remote_key),
|
|
|
|
READ_ONCE(msk->local_key),
|
2020-03-27 21:48:39 +00:00
|
|
|
subflow_req->remote_nonce,
|
|
|
|
subflow_req->local_nonce, hmac);
|
|
|
|
|
2020-06-17 10:08:56 +00:00
|
|
|
return !crypto_memneq(hmac, mp_opt->hmac, MPTCPOPT_HMAC_LEN);
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
|
|
|
|
2020-04-20 14:25:05 +00:00
|
|
|
static void subflow_ulp_fallback(struct sock *sk,
|
|
|
|
struct mptcp_subflow_context *old_ctx)
|
|
|
|
{
|
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
|
|
|
|
mptcp_subflow_tcp_fallback(sk, old_ctx);
|
|
|
|
icsk->icsk_ulp_ops = NULL;
|
|
|
|
rcu_assign_pointer(icsk->icsk_ulp_data, NULL);
|
|
|
|
tcp_sk(sk)->is_mptcp = 0;
|
2021-01-20 14:39:14 +00:00
|
|
|
|
|
|
|
mptcp_subflow_ops_undo_override(sk);
|
2020-04-20 14:25:05 +00:00
|
|
|
}
|
|
|
|
|
2023-03-09 14:49:59 +00:00
|
|
|
void mptcp_subflow_drop_ctx(struct sock *ssk)
|
2020-05-29 15:49:18 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(ssk);
|
|
|
|
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
|
2023-04-17 14:00:41 +00:00
|
|
|
list_del(&mptcp_subflow_ctx(ssk)->node);
|
|
|
|
if (inet_csk(ssk)->icsk_ulp_ops) {
|
|
|
|
subflow_ulp_fallback(ssk, ctx);
|
|
|
|
if (ctx->conn)
|
|
|
|
sock_put(ctx->conn);
|
|
|
|
}
|
2020-05-29 15:49:18 +00:00
|
|
|
|
|
|
|
kfree_rcu(ctx, rcu);
|
|
|
|
}
|
|
|
|
|
2024-02-08 18:03:52 +00:00
|
|
|
void __mptcp_subflow_fully_established(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_subflow_context *subflow,
|
|
|
|
const struct mptcp_options_received *mp_opt)
|
2020-07-23 11:02:32 +00:00
|
|
|
{
|
2022-11-25 22:29:49 +00:00
|
|
|
subflow_set_remote_key(msk, subflow, mp_opt);
|
2024-10-21 15:14:04 +00:00
|
|
|
WRITE_ONCE(subflow->fully_established, true);
|
2020-07-23 11:02:32 +00:00
|
|
|
WRITE_ONCE(msk->fully_established, true);
|
2022-11-25 22:29:50 +00:00
|
|
|
|
|
|
|
if (subflow->is_mptfo)
|
2024-02-08 18:03:52 +00:00
|
|
|
__mptcp_fastopen_gen_msk_ackseq(msk, subflow, mp_opt);
|
2020-07-23 11:02:32 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
static struct sock *subflow_syn_recv_sock(const struct sock *sk,
|
|
|
|
struct sk_buff *skb,
|
|
|
|
struct request_sock *req,
|
|
|
|
struct dst_entry *dst,
|
|
|
|
struct request_sock *req_unhash,
|
|
|
|
bool *own_req)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *listener = mptcp_subflow_ctx(sk);
|
2020-01-22 00:56:31 +00:00
|
|
|
struct mptcp_subflow_request_sock *subflow_req;
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
struct mptcp_options_received mp_opt;
|
2020-06-17 10:08:57 +00:00
|
|
|
bool fallback, fallback_is_fatal;
|
2024-04-25 03:13:38 +00:00
|
|
|
enum sk_rst_reason reason;
|
2023-03-09 14:49:58 +00:00
|
|
|
struct mptcp_sock *owner;
|
2020-01-22 00:56:18 +00:00
|
|
|
struct sock *child;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("listener=%p, req=%p, conn=%p\n", listener, req, listener->conn);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2021-08-27 00:44:52 +00:00
|
|
|
/* After child creation we must look for MPC even when options
|
2020-06-17 10:08:57 +00:00
|
|
|
* are not parsed
|
mptcp: move option parsing into mptcp_incoming_options()
The mptcp_options_received structure carries several per
packet flags (mp_capable, mp_join, etc.). Such fields must
be cleared on each packet, even on dropped ones or packet
not carrying any MPTCP options, but the current mptcp
code clears them only on TCP option reset.
On several races/corner cases we end-up with stray bits in
incoming options, leading to WARN_ON splats. e.g.:
[ 171.164906] Bad mapping: ssn=32714 map_seq=1 map_data_len=32713
[ 171.165006] WARNING: CPU: 1 PID: 5026 at net/mptcp/subflow.c:533 warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.167632] Modules linked in: ip6_vti ip_vti ip_gre ipip sit tunnel4 ip_tunnel geneve ip6_udp_tunnel udp_tunnel macsec macvtap tap ipvlan macvlan 8021q garp mrp xfrm_interface veth netdevsim nlmon dummy team bonding vcan bridge stp llc ip6_gre gre ip6_tunnel tunnel6 tun binfmt_misc intel_rapl_msr intel_rapl_common rfkill kvm_intel kvm irqbypass crct10dif_pclmul crc32_pclmul ghash_clmulni_intel joydev virtio_balloon pcspkr i2c_piix4 sunrpc ip_tables xfs libcrc32c crc32c_intel serio_raw virtio_console ata_generic virtio_blk virtio_net net_failover failover ata_piix libata
[ 171.199464] CPU: 1 PID: 5026 Comm: repro Not tainted 5.7.0-rc1.mptcp_f227fdf5d388+ #95
[ 171.200886] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-2.fc30 04/01/2014
[ 171.202546] RIP: 0010:warn_bad_map (linux-mptcp/net/mptcp/subflow.c:533 linux-mptcp/net/mptcp/subflow.c:531)
[ 171.206537] Code: c1 ea 03 0f b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 04 84 d2 75 1d 8b 55 3c 44 89 e6 48 c7 c7 20 51 13 95 e8 37 8b 22 fe <0f> 0b 48 83 c4 08 5b 5d 41 5c c3 89 4c 24 04 e8 db d6 94 fe 8b 4c
[ 171.220473] RSP: 0018:ffffc90000150560 EFLAGS: 00010282
[ 171.221639] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[ 171.223108] RDX: 0000000000000000 RSI: 0000000000000008 RDI: fffff5200002a09e
[ 171.224388] RBP: ffff8880aa6e3c00 R08: 0000000000000001 R09: fffffbfff2ec9955
[ 171.225706] R10: ffffffff9764caa7 R11: fffffbfff2ec9954 R12: 0000000000007fca
[ 171.227211] R13: ffff8881066f4a7f R14: ffff8880aa6e3c00 R15: 0000000000000020
[ 171.228460] FS: 00007f8623719740(0000) GS:ffff88810be00000(0000) knlGS:0000000000000000
[ 171.230065] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 171.231303] CR2: 00007ffdab190a50 CR3: 00000001038ea006 CR4: 0000000000160ee0
[ 171.232586] Call Trace:
[ 171.233109] <IRQ>
[ 171.233531] get_mapping_status (linux-mptcp/net/mptcp/subflow.c:691)
[ 171.234371] mptcp_subflow_data_available (linux-mptcp/net/mptcp/subflow.c:736 linux-mptcp/net/mptcp/subflow.c:832)
[ 171.238181] subflow_state_change (linux-mptcp/net/mptcp/subflow.c:1085 (discriminator 1))
[ 171.239066] tcp_fin (linux-mptcp/net/ipv4/tcp_input.c:4217)
[ 171.240123] tcp_data_queue (linux-mptcp/./include/linux/compiler.h:199 linux-mptcp/net/ipv4/tcp_input.c:4822)
[ 171.245083] tcp_rcv_established (linux-mptcp/./include/linux/skbuff.h:1785 linux-mptcp/./include/net/tcp.h:1774 linux-mptcp/./include/net/tcp.h:1847 linux-mptcp/net/ipv4/tcp_input.c:5238 linux-mptcp/net/ipv4/tcp_input.c:5730)
[ 171.254089] tcp_v4_rcv (linux-mptcp/./include/linux/spinlock.h:393 linux-mptcp/net/ipv4/tcp_ipv4.c:2009)
[ 171.258969] ip_protocol_deliver_rcu (linux-mptcp/net/ipv4/ip_input.c:204 (discriminator 1))
[ 171.260214] ip_local_deliver_finish (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/ipv4/ip_input.c:232)
[ 171.261389] ip_local_deliver (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:252)
[ 171.265884] ip_rcv (linux-mptcp/./include/linux/netfilter.h:307 linux-mptcp/./include/linux/netfilter.h:301 linux-mptcp/net/ipv4/ip_input.c:539)
[ 171.273666] process_backlog (linux-mptcp/./include/linux/rcupdate.h:651 linux-mptcp/net/core/dev.c:6135)
[ 171.275328] net_rx_action (linux-mptcp/net/core/dev.c:6572 linux-mptcp/net/core/dev.c:6640)
[ 171.280472] __do_softirq (linux-mptcp/./arch/x86/include/asm/jump_label.h:25 linux-mptcp/./include/linux/jump_label.h:200 linux-mptcp/./include/trace/events/irq.h:142 linux-mptcp/kernel/softirq.c:293)
[ 171.281379] do_softirq_own_stack (linux-mptcp/arch/x86/entry/entry_64.S:1083)
[ 171.282358] </IRQ>
We could address the issue clearing explicitly the relevant fields
in several places - tcp_parse_option, tcp_fast_parse_options,
possibly others.
Instead we move the MPTCP option parsing into the already existing
mptcp ingress hook, so that we need to clear the fields in a single
place.
This allows us dropping an MPTCP hook from the TCP code and
removing the quite large mptcp_options_received from the tcp_sock
struct. On the flip side, the MPTCP sockets will traverse the
option space twice (in tcp_parse_option() and in
mptcp_incoming_options(). That looks acceptable: we already
do that for syn and 3rd ack packets, plain TCP socket will
benefit from it, and even MPTCP sockets will experience better
code locality, reducing the jumps between TCP and MPTCP code.
v1 -> v2:
- rebased on current '-net' tree
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-04-30 13:01:52 +00:00
|
|
|
*/
|
2021-08-27 00:44:52 +00:00
|
|
|
mp_opt.suboptions = 0;
|
2020-06-17 10:08:57 +00:00
|
|
|
|
|
|
|
/* hopefully temporary handling for MP_JOIN+syncookie */
|
|
|
|
subflow_req = mptcp_subflow_rsk(req);
|
2020-07-23 11:02:34 +00:00
|
|
|
fallback_is_fatal = tcp_rsk(req)->is_mptcp && subflow_req->mp_join;
|
2020-06-17 10:08:57 +00:00
|
|
|
fallback = !tcp_rsk(req)->is_mptcp;
|
|
|
|
if (fallback)
|
2020-01-29 14:54:46 +00:00
|
|
|
goto create_child;
|
|
|
|
|
2020-01-22 00:56:32 +00:00
|
|
|
/* if the sk is MP_CAPABLE, we try to fetch the client key */
|
2020-01-22 00:56:31 +00:00
|
|
|
if (subflow_req->mp_capable) {
|
2021-05-27 23:31:38 +00:00
|
|
|
/* we can receive and accept an in-window, out-of-order pkt,
|
|
|
|
* which may not carry the MP_CAPABLE opt even on mptcp enabled
|
|
|
|
* paths: always try to extract the peer key, and fallback
|
|
|
|
* for packets missing it.
|
|
|
|
* Even OoO DSS packets coming legitly after dropped or
|
|
|
|
* reordered MPC will cause fallback, but we don't have other
|
|
|
|
* options.
|
|
|
|
*/
|
2022-02-16 02:11:25 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
2024-01-16 17:18:47 +00:00
|
|
|
if (!(mp_opt.suboptions &
|
|
|
|
(OPTION_MPTCP_MPC_SYN | OPTION_MPTCP_MPC_ACK)))
|
2020-04-20 14:25:05 +00:00
|
|
|
fallback = true;
|
2020-03-13 15:52:41 +00:00
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
} else if (subflow_req->mp_join) {
|
2022-02-16 02:11:25 +00:00
|
|
|
mptcp_get_options(skb, &mp_opt);
|
2024-01-11 19:49:14 +00:00
|
|
|
if (!(mp_opt.suboptions & OPTION_MPTCP_MPJ_ACK) ||
|
2021-08-27 00:44:52 +00:00
|
|
|
!subflow_hmac_valid(req, &mp_opt) ||
|
2020-11-26 14:17:53 +00:00
|
|
|
!mptcp_can_accept_new_subflow(subflow_req->msk)) {
|
2020-03-27 21:48:50 +00:00
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKMAC);
|
2020-06-17 10:08:57 +00:00
|
|
|
fallback = true;
|
2020-03-27 21:48:50 +00:00
|
|
|
}
|
2020-01-22 00:56:31 +00:00
|
|
|
}
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2020-01-22 00:56:32 +00:00
|
|
|
create_child:
|
2020-01-22 00:56:18 +00:00
|
|
|
child = listener->icsk_af_ops->syn_recv_sock(sk, skb, req, dst,
|
|
|
|
req_unhash, own_req);
|
|
|
|
|
|
|
|
if (child && *own_req) {
|
2020-01-22 00:56:20 +00:00
|
|
|
struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(child);
|
|
|
|
|
2020-05-15 17:22:15 +00:00
|
|
|
tcp_rsk(req)->drop_req = false;
|
|
|
|
|
2020-04-20 14:25:05 +00:00
|
|
|
/* we need to fallback on ctx allocation failure and on pre-reqs
|
|
|
|
* checking above. In the latter scenario we additionally need
|
|
|
|
* to reset the context to non MPTCP status.
|
2020-01-22 00:56:20 +00:00
|
|
|
*/
|
2020-04-20 14:25:05 +00:00
|
|
|
if (!ctx || fallback) {
|
2021-04-01 23:19:44 +00:00
|
|
|
if (fallback_is_fatal) {
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EMPTCP);
|
2020-05-15 17:22:17 +00:00
|
|
|
goto dispose_child;
|
2021-04-01 23:19:44 +00:00
|
|
|
}
|
2023-03-27 10:22:22 +00:00
|
|
|
goto fallback;
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
2020-01-22 00:56:20 +00:00
|
|
|
|
2021-04-15 23:44:54 +00:00
|
|
|
/* ssk inherits options of listener sk */
|
|
|
|
ctx->setsockopt_seq = listener->setsockopt_seq;
|
|
|
|
|
2020-01-22 00:56:20 +00:00
|
|
|
if (ctx->mp_capable) {
|
2023-05-31 19:37:05 +00:00
|
|
|
ctx->conn = mptcp_sk_clone_init(listener->conn, &mp_opt, child, req);
|
2023-03-27 10:22:22 +00:00
|
|
|
if (!ctx->conn)
|
|
|
|
goto fallback;
|
|
|
|
|
2023-06-20 16:30:17 +00:00
|
|
|
ctx->subflow_id = 1;
|
2023-03-27 10:22:22 +00:00
|
|
|
owner = mptcp_sk(ctx->conn);
|
2023-03-09 14:49:58 +00:00
|
|
|
mptcp_pm_new_connection(owner, child, 1);
|
2022-10-21 22:58:54 +00:00
|
|
|
|
2020-04-20 14:25:06 +00:00
|
|
|
/* with OoO packets we can reach here without ingress
|
|
|
|
* mpc option
|
|
|
|
*/
|
2023-03-09 14:49:58 +00:00
|
|
|
if (mp_opt.suboptions & OPTION_MPTCP_MPC_ACK) {
|
2023-04-14 14:08:00 +00:00
|
|
|
mptcp_pm_fully_established(owner, child);
|
2023-03-09 14:49:58 +00:00
|
|
|
ctx->pm_notified = 1;
|
|
|
|
}
|
2020-03-27 21:48:39 +00:00
|
|
|
} else if (ctx->mp_join) {
|
2020-06-17 10:08:56 +00:00
|
|
|
owner = subflow_req->msk;
|
2021-04-01 23:19:44 +00:00
|
|
|
if (!owner) {
|
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
2020-05-15 17:22:17 +00:00
|
|
|
goto dispose_child;
|
2021-04-01 23:19:44 +00:00
|
|
|
}
|
2020-03-27 21:48:39 +00:00
|
|
|
|
2020-06-17 10:08:56 +00:00
|
|
|
/* move the msk reference ownership to the subflow */
|
|
|
|
subflow_req->msk = NULL;
|
2020-03-27 21:48:39 +00:00
|
|
|
ctx->conn = (struct sock *)owner;
|
2021-02-01 23:09:15 +00:00
|
|
|
|
|
|
|
if (subflow_use_different_sport(owner, sk)) {
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("ack inet_sport=%d %d\n",
|
2021-02-01 23:09:15 +00:00
|
|
|
ntohs(inet_sk(sk)->inet_sport),
|
|
|
|
ntohs(inet_sk((struct sock *)owner)->inet_sport));
|
2021-02-01 23:09:19 +00:00
|
|
|
if (!mptcp_pm_sport_in_anno_list(owner, sk)) {
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MISMATCHPORTACKRX);
|
2024-04-06 01:48:48 +00:00
|
|
|
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
|
2021-03-04 21:32:16 +00:00
|
|
|
goto dispose_child;
|
2021-02-01 23:09:19 +00:00
|
|
|
}
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINPORTACKRX);
|
2021-02-01 23:09:15 +00:00
|
|
|
}
|
2021-03-04 21:32:16 +00:00
|
|
|
|
2024-04-06 01:48:48 +00:00
|
|
|
if (!mptcp_finish_join(child)) {
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(child);
|
|
|
|
|
|
|
|
subflow_add_reset_reason(skb, subflow->reset_reason);
|
2021-03-04 21:32:16 +00:00
|
|
|
goto dispose_child;
|
2024-04-06 01:48:48 +00:00
|
|
|
}
|
2021-03-04 21:32:16 +00:00
|
|
|
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINACKRX);
|
|
|
|
tcp_rsk(req)->drop_req = true;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-20 14:25:05 +00:00
|
|
|
/* check for expected invariant - should never trigger, just help
|
2024-05-02 15:47:40 +00:00
|
|
|
* catching earlier subtle bugs
|
2020-04-20 14:25:05 +00:00
|
|
|
*/
|
2020-04-30 13:03:22 +00:00
|
|
|
WARN_ON_ONCE(child && *own_req && tcp_sk(child)->is_mptcp &&
|
2020-04-20 14:25:05 +00:00
|
|
|
(!mptcp_subflow_ctx(child) ||
|
|
|
|
!mptcp_subflow_ctx(child)->conn));
|
2020-01-22 00:56:18 +00:00
|
|
|
return child;
|
2020-03-27 21:48:39 +00:00
|
|
|
|
2020-05-15 17:22:17 +00:00
|
|
|
dispose_child:
|
2023-03-09 14:49:59 +00:00
|
|
|
mptcp_subflow_drop_ctx(child);
|
2020-05-15 17:22:17 +00:00
|
|
|
tcp_rsk(req)->drop_req = true;
|
|
|
|
inet_csk_prepare_for_destroy_sock(child);
|
2020-03-27 21:48:39 +00:00
|
|
|
tcp_done(child);
|
2024-05-06 12:30:32 +00:00
|
|
|
reason = mptcp_get_rst_reason(skb);
|
2024-04-25 03:13:38 +00:00
|
|
|
req->rsk_ops->send_reset(sk, skb, reason);
|
2020-05-15 17:22:17 +00:00
|
|
|
|
|
|
|
/* The last child reference will be released by the caller */
|
|
|
|
return child;
|
2023-03-27 10:22:22 +00:00
|
|
|
|
|
|
|
fallback:
|
2024-03-29 12:08:52 +00:00
|
|
|
if (fallback)
|
|
|
|
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVEFALLBACK);
|
2023-03-27 10:22:22 +00:00
|
|
|
mptcp_subflow_drop_ctx(child);
|
|
|
|
return child;
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2022-02-16 02:11:29 +00:00
|
|
|
static struct inet_connection_sock_af_ops subflow_specific __ro_after_init;
|
2023-03-09 14:50:02 +00:00
|
|
|
static struct proto tcp_prot_override __ro_after_init;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
enum mapping_status {
|
|
|
|
MAPPING_OK,
|
|
|
|
MAPPING_INVALID,
|
|
|
|
MAPPING_EMPTY,
|
2020-06-29 20:26:20 +00:00
|
|
|
MAPPING_DATA_FIN,
|
2022-06-28 01:02:36 +00:00
|
|
|
MAPPING_DUMMY,
|
2024-10-21 15:14:06 +00:00
|
|
|
MAPPING_BAD_CSUM,
|
|
|
|
MAPPING_NODSS
|
2020-01-22 00:56:24 +00:00
|
|
|
};
|
|
|
|
|
2021-06-10 22:59:42 +00:00
|
|
|
static void dbg_bad_map(struct mptcp_subflow_context *subflow, u32 ssn)
|
2020-01-22 00:56:24 +00:00
|
|
|
{
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("Bad mapping: ssn=%d map_seq=%d map_data_len=%d\n",
|
2021-06-10 22:59:42 +00:00
|
|
|
ssn, subflow->map_subflow_seq, subflow->map_data_len);
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool skb_is_fully_mapped(struct sock *ssk, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
unsigned int skb_consumed;
|
|
|
|
|
|
|
|
skb_consumed = tcp_sk(ssk)->copied_seq - TCP_SKB_CB(skb)->seq;
|
2024-10-08 11:04:52 +00:00
|
|
|
if (unlikely(skb_consumed >= skb->len)) {
|
|
|
|
DEBUG_NET_WARN_ON_ONCE(1);
|
2020-01-22 00:56:24 +00:00
|
|
|
return true;
|
2024-10-08 11:04:52 +00:00
|
|
|
}
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
return skb->len - skb_consumed <= subflow->map_data_len -
|
|
|
|
mptcp_subflow_get_map_offset(subflow);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool validate_mapping(struct sock *ssk, struct sk_buff *skb)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
u32 ssn = tcp_sk(ssk)->copied_seq - subflow->ssn_offset;
|
|
|
|
|
|
|
|
if (unlikely(before(ssn, subflow->map_subflow_seq))) {
|
|
|
|
/* Mapping covers data later in the subflow stream,
|
|
|
|
* currently unsupported.
|
|
|
|
*/
|
2021-06-10 22:59:42 +00:00
|
|
|
dbg_bad_map(subflow, ssn);
|
2020-01-22 00:56:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (unlikely(!before(ssn, subflow->map_subflow_seq +
|
|
|
|
subflow->map_data_len))) {
|
|
|
|
/* Mapping does covers past subflow data, invalid */
|
2021-06-10 22:59:42 +00:00
|
|
|
dbg_bad_map(subflow, ssn);
|
2020-01-22 00:56:24 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
static enum mapping_status validate_data_csum(struct sock *ssk, struct sk_buff *skb,
|
|
|
|
bool csum_reqd)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
u32 offset, seq, delta;
|
2022-05-17 18:02:11 +00:00
|
|
|
__sum16 csum;
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
int len;
|
|
|
|
|
|
|
|
if (!csum_reqd)
|
|
|
|
return MAPPING_OK;
|
|
|
|
|
|
|
|
/* mapping already validated on previous traversal */
|
|
|
|
if (subflow->map_csum_len == subflow->map_data_len)
|
|
|
|
return MAPPING_OK;
|
|
|
|
|
|
|
|
/* traverse the receive queue, ensuring it contains a full
|
|
|
|
* DSS mapping and accumulating the related csum.
|
|
|
|
* Preserve the accoumlate csum across multiple calls, to compute
|
|
|
|
* the csum only once
|
|
|
|
*/
|
|
|
|
delta = subflow->map_data_len - subflow->map_csum_len;
|
|
|
|
for (;;) {
|
|
|
|
seq = tcp_sk(ssk)->copied_seq + subflow->map_csum_len;
|
|
|
|
offset = seq - TCP_SKB_CB(skb)->seq;
|
|
|
|
|
|
|
|
/* if the current skb has not been accounted yet, csum its contents
|
|
|
|
* up to the amount covered by the current DSS
|
|
|
|
*/
|
|
|
|
if (offset < skb->len) {
|
|
|
|
__wsum csum;
|
|
|
|
|
|
|
|
len = min(skb->len - offset, delta);
|
|
|
|
csum = skb_checksum(skb, offset, len, 0);
|
|
|
|
subflow->map_data_csum = csum_block_add(subflow->map_data_csum, csum,
|
|
|
|
subflow->map_csum_len);
|
|
|
|
|
|
|
|
delta -= len;
|
|
|
|
subflow->map_csum_len += len;
|
|
|
|
}
|
|
|
|
if (delta == 0)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (skb_queue_is_last(&ssk->sk_receive_queue, skb)) {
|
|
|
|
/* if this subflow is closed, the partial mapping
|
|
|
|
* will be never completed; flush the pending skbs, so
|
|
|
|
* that subflow_sched_work_if_closed() can kick in
|
|
|
|
*/
|
|
|
|
if (unlikely(ssk->sk_state == TCP_CLOSE))
|
|
|
|
while ((skb = skb_peek(&ssk->sk_receive_queue)))
|
|
|
|
sk_eat_skb(ssk, skb);
|
|
|
|
|
|
|
|
/* not enough data to validate the csum */
|
|
|
|
return MAPPING_EMPTY;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* the DSS mapping for next skbs will be validated later,
|
|
|
|
* when a get_mapping_status call will process such skb
|
|
|
|
*/
|
|
|
|
skb = skb->next;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* note that 'map_data_len' accounts only for the carried data, does
|
|
|
|
* not include the eventual seq increment due to the data fin,
|
|
|
|
* while the pseudo header requires the original DSS data len,
|
|
|
|
* including that
|
|
|
|
*/
|
2022-01-07 19:25:24 +00:00
|
|
|
csum = __mptcp_make_csum(subflow->map_seq,
|
|
|
|
subflow->map_subflow_seq,
|
|
|
|
subflow->map_data_len + subflow->map_data_fin,
|
|
|
|
subflow->map_data_csum);
|
|
|
|
if (unlikely(csum)) {
|
2021-06-17 23:46:18 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DATACSUMERR);
|
2022-06-28 01:02:36 +00:00
|
|
|
return MAPPING_BAD_CSUM;
|
2021-06-17 23:46:18 +00:00
|
|
|
}
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
|
mptcp: Do TCP fallback on early DSS checksum failure
RFC 8684 section 3.7 describes several opportunities for a MPTCP
connection to "fall back" to regular TCP early in the connection
process, before it has been confirmed that MPTCP options can be
successfully propagated on all SYN, SYN/ACK, and data packets. If a peer
acknowledges the first received data packet with a regular TCP header
(no MPTCP options), fallback is allowed.
If the recipient of that first data packet finds a MPTCP DSS checksum
error, this provides an opportunity to fail gracefully with a TCP
fallback rather than resetting the connection (as might happen if a
checksum failure were detected later).
This commit modifies the checksum failure code to attempt fallback on
the initial subflow of a MPTCP connection, only if it's a failure in the
first data mapping. In cases where the peer initiates the connection,
requests checksums, is the first to send data, and the peer is sending
incorrect checksums (see
https://github.com/multipath-tcp/mptcp_net-next/issues/275), this allows
the connection to proceed as TCP rather than reset.
Fixes: dd8bcd1768ff ("mptcp: validate the data checksum")
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-17 18:02:12 +00:00
|
|
|
subflow->valid_csum_seen = 1;
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
return MAPPING_OK;
|
|
|
|
}
|
|
|
|
|
2020-07-28 22:12:06 +00:00
|
|
|
static enum mapping_status get_mapping_status(struct sock *ssk,
|
|
|
|
struct mptcp_sock *msk)
|
2020-01-22 00:56:24 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
bool csum_reqd = READ_ONCE(msk->csum_enabled);
|
2020-01-22 00:56:24 +00:00
|
|
|
struct mptcp_ext *mpext;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
u16 data_len;
|
|
|
|
u64 map_seq;
|
|
|
|
|
|
|
|
skb = skb_peek(&ssk->sk_receive_queue);
|
|
|
|
if (!skb)
|
|
|
|
return MAPPING_EMPTY;
|
|
|
|
|
2020-06-29 20:26:20 +00:00
|
|
|
if (mptcp_check_fallback(ssk))
|
|
|
|
return MAPPING_DUMMY;
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
mpext = mptcp_get_ext(skb);
|
|
|
|
if (!mpext || !mpext->use_map) {
|
|
|
|
if (!subflow->map_valid && !skb->len) {
|
|
|
|
/* the TCP stack deliver 0 len FIN pkt to the receive
|
|
|
|
* queue, that is the only 0len pkts ever expected here,
|
|
|
|
* and we can admit no mapping only for 0 len pkts
|
|
|
|
*/
|
|
|
|
if (!(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN))
|
|
|
|
WARN_ONCE(1, "0len seq %d:%d flags %x",
|
|
|
|
TCP_SKB_CB(skb)->seq,
|
|
|
|
TCP_SKB_CB(skb)->end_seq,
|
|
|
|
TCP_SKB_CB(skb)->tcp_flags);
|
|
|
|
sk_eat_skb(ssk, skb);
|
|
|
|
return MAPPING_EMPTY;
|
|
|
|
}
|
|
|
|
|
2024-10-21 15:14:06 +00:00
|
|
|
/* If the required DSS has likely been dropped by a middlebox */
|
2020-01-22 00:56:24 +00:00
|
|
|
if (!subflow->map_valid)
|
2024-10-21 15:14:06 +00:00
|
|
|
return MAPPING_NODSS;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
goto validate_seq;
|
|
|
|
}
|
|
|
|
|
2021-04-16 22:38:05 +00:00
|
|
|
trace_get_mapping_status(mpext);
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
data_len = mpext->data_len;
|
|
|
|
if (data_len == 0) {
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("infinite mapping received\n");
|
2020-03-27 21:48:50 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_INFINITEMAPRX);
|
2022-04-22 21:55:40 +00:00
|
|
|
subflow->map_data_len = 0;
|
2020-01-22 00:56:24 +00:00
|
|
|
return MAPPING_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mpext->data_fin == 1) {
|
2024-05-14 01:13:30 +00:00
|
|
|
u64 data_fin_seq;
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
if (data_len == 1) {
|
2020-09-29 22:08:20 +00:00
|
|
|
bool updated = mptcp_update_rcv_data_fin(msk, mpext->data_seq,
|
|
|
|
mpext->dsn64);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("DATA_FIN with no payload seq=%llu\n", mpext->data_seq);
|
2020-01-22 00:56:24 +00:00
|
|
|
if (subflow->map_valid) {
|
|
|
|
/* A DATA_FIN might arrive in a DSS
|
|
|
|
* option before the previous mapping
|
|
|
|
* has been fully consumed. Continue
|
|
|
|
* handling the existing mapping.
|
|
|
|
*/
|
|
|
|
skb_ext_del(skb, SKB_EXT_MPTCP);
|
|
|
|
return MAPPING_OK;
|
|
|
|
}
|
2020-09-29 22:08:20 +00:00
|
|
|
|
2024-05-14 01:13:30 +00:00
|
|
|
if (updated)
|
|
|
|
mptcp_schedule_work((struct sock *)msk);
|
2020-09-29 22:08:20 +00:00
|
|
|
|
2024-05-14 01:13:30 +00:00
|
|
|
return MAPPING_DATA_FIN;
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
2024-05-14 01:13:30 +00:00
|
|
|
data_fin_seq = mpext->data_seq + data_len - 1;
|
|
|
|
|
|
|
|
/* If mpext->data_seq is a 32-bit value, data_fin_seq must also
|
|
|
|
* be limited to 32 bits.
|
|
|
|
*/
|
|
|
|
if (!mpext->dsn64)
|
|
|
|
data_fin_seq &= GENMASK_ULL(31, 0);
|
|
|
|
|
|
|
|
mptcp_update_rcv_data_fin(msk, data_fin_seq, mpext->dsn64);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("DATA_FIN with mapping seq=%llu dsn64=%d\n",
|
2024-05-14 01:13:30 +00:00
|
|
|
data_fin_seq, mpext->dsn64);
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
/* Adjust for DATA_FIN using 1 byte of sequence space */
|
|
|
|
data_len--;
|
|
|
|
}
|
|
|
|
|
2021-06-18 22:02:21 +00:00
|
|
|
map_seq = mptcp_expand_seq(READ_ONCE(msk->ack_seq), mpext->data_seq, mpext->dsn64);
|
2020-10-06 16:26:17 +00:00
|
|
|
WRITE_ONCE(mptcp_sk(subflow->conn)->use_64bit_ack, !!mpext->dsn64);
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
if (subflow->map_valid) {
|
|
|
|
/* Allow replacing only with an identical map */
|
|
|
|
if (subflow->map_seq == map_seq &&
|
|
|
|
subflow->map_subflow_seq == mpext->subflow_seq &&
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
subflow->map_data_len == data_len &&
|
|
|
|
subflow->map_csum_reqd == mpext->csum_reqd) {
|
2020-01-22 00:56:24 +00:00
|
|
|
skb_ext_del(skb, SKB_EXT_MPTCP);
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
goto validate_csum;
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* If this skb data are fully covered by the current mapping,
|
|
|
|
* the new map would need caching, which is not supported
|
|
|
|
*/
|
2020-03-27 21:48:50 +00:00
|
|
|
if (skb_is_fully_mapped(ssk, skb)) {
|
|
|
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSNOMATCH);
|
2020-01-22 00:56:24 +00:00
|
|
|
return MAPPING_INVALID;
|
2020-03-27 21:48:50 +00:00
|
|
|
}
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
/* will validate the next map after consuming the current one */
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
goto validate_csum;
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
subflow->map_seq = map_seq;
|
|
|
|
subflow->map_subflow_seq = mpext->subflow_seq;
|
|
|
|
subflow->map_data_len = data_len;
|
|
|
|
subflow->map_valid = 1;
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
subflow->map_data_fin = mpext->data_fin;
|
2020-01-22 00:56:32 +00:00
|
|
|
subflow->mpc_map = mpext->mpc_map;
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
subflow->map_csum_reqd = mpext->csum_reqd;
|
|
|
|
subflow->map_csum_len = 0;
|
|
|
|
subflow->map_data_csum = csum_unfold(mpext->csum);
|
|
|
|
|
|
|
|
/* Cfr RFC 8684 Section 3.3.0 */
|
|
|
|
if (unlikely(subflow->map_csum_reqd != csum_reqd))
|
|
|
|
return MAPPING_INVALID;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("new map seq=%llu subflow_seq=%u data_len=%u csum=%d:%u\n",
|
2020-01-22 00:56:24 +00:00
|
|
|
subflow->map_seq, subflow->map_subflow_seq,
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
subflow->map_data_len, subflow->map_csum_reqd,
|
|
|
|
subflow->map_data_csum);
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
validate_seq:
|
|
|
|
/* we revalidate valid mapping on new skb, because we must ensure
|
|
|
|
* the current skb is completely covered by the available mapping
|
|
|
|
*/
|
2021-06-21 22:54:37 +00:00
|
|
|
if (!validate_mapping(ssk, skb)) {
|
|
|
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DSSTCPMISMATCH);
|
2020-01-22 00:56:24 +00:00
|
|
|
return MAPPING_INVALID;
|
2021-06-21 22:54:37 +00:00
|
|
|
}
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
skb_ext_del(skb, SKB_EXT_MPTCP);
|
mptcp: validate the data checksum
This patch added three new members named data_csum, csum_len and
map_csum in struct mptcp_subflow_context, implemented a new function
named mptcp_validate_data_checksum().
If the current mapping is valid and csum is enabled traverse the later
pending skbs and compute csum incrementally till the whole mapping has
been covered. If not enough data is available in the rx queue, return
MAPPING_EMPTY - that is, no data.
Next subflow_data_ready invocation will trigger again csum computation.
When the full DSS is available, validate the csum and return to the
caller an appropriate error code, to trigger subflow reset of fallback
as required by the RFC.
Additionally:
- if the csum prevence in the DSS don't match the negotiated value e.g.
csum present, but not requested, return invalid mapping to trigger
subflow reset.
- keep some csum state, to avoid re-compute the csum on the same data
when multiple rx queue traversal are required.
- clean-up the uncompleted mapping from the receive queue on close, to
allow proper subflow disposal
Co-developed-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Geliang Tang <geliangtang@gmail.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-17 23:46:16 +00:00
|
|
|
|
|
|
|
validate_csum:
|
|
|
|
return validate_data_csum(ssk, skb, csum_reqd);
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
2020-09-14 08:01:13 +00:00
|
|
|
static void mptcp_subflow_discard_data(struct sock *ssk, struct sk_buff *skb,
|
2020-09-17 21:07:24 +00:00
|
|
|
u64 limit)
|
2020-09-14 08:01:09 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
2020-09-14 08:01:13 +00:00
|
|
|
bool fin = TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN;
|
2024-07-31 10:10:15 +00:00
|
|
|
struct tcp_sock *tp = tcp_sk(ssk);
|
|
|
|
u32 offset, incr, avail_len;
|
2020-09-14 08:01:13 +00:00
|
|
|
|
2024-07-31 10:10:15 +00:00
|
|
|
offset = tp->copied_seq - TCP_SKB_CB(skb)->seq;
|
|
|
|
if (WARN_ON_ONCE(offset > skb->len))
|
|
|
|
goto out;
|
2020-09-14 08:01:13 +00:00
|
|
|
|
2024-07-31 10:10:15 +00:00
|
|
|
avail_len = skb->len - offset;
|
|
|
|
incr = limit >= avail_len ? avail_len + fin : limit;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("discarding=%d len=%d offset=%d seq=%d\n", incr, skb->len,
|
2024-07-31 10:10:15 +00:00
|
|
|
offset, subflow->map_subflow_seq);
|
2020-09-14 08:01:14 +00:00
|
|
|
MPTCP_INC_STATS(sock_net(ssk), MPTCP_MIB_DUPDATA);
|
2020-09-14 08:01:13 +00:00
|
|
|
tcp_sk(ssk)->copied_seq += incr;
|
2024-07-31 10:10:15 +00:00
|
|
|
|
|
|
|
out:
|
2020-09-14 08:01:13 +00:00
|
|
|
if (!before(tcp_sk(ssk)->copied_seq, TCP_SKB_CB(skb)->end_seq))
|
|
|
|
sk_eat_skb(ssk, skb);
|
|
|
|
if (mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len)
|
|
|
|
subflow->map_valid = 0;
|
2020-09-14 08:01:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-12 23:59:56 +00:00
|
|
|
/* sched mptcp worker to remove the subflow if no more data is pending */
|
|
|
|
static void subflow_sched_work_if_closed(struct mptcp_sock *msk, struct sock *ssk)
|
|
|
|
{
|
mptcp: close subflow when receiving TCP+FIN
When a peer decides to close one subflow in the middle of a connection
having multiple subflows, the receiver of the first FIN should accept
that, and close the subflow on its side as well. If not, the subflow
will stay half closed, and would even continue to be used until the end
of the MPTCP connection or a reset from the network.
The issue has not been seen before, probably because the in-kernel
path-manager always sends a RM_ADDR before closing the subflow. Upon the
reception of this RM_ADDR, the other peer will initiate the closure on
its side as well. On the other hand, if the RM_ADDR is lost, or if the
path-manager of the other peer only closes the subflow without sending a
RM_ADDR, the subflow would switch to TCP_CLOSE_WAIT, but that's it,
leaving the subflow half-closed.
So now, when the subflow switches to the TCP_CLOSE_WAIT state, and if
the MPTCP connection has not been closed before with a DATA_FIN, the
kernel owning the subflow schedules its worker to initiate the closure
on its side as well.
This issue can be easily reproduced with packetdrill, as visible in [1],
by creating an additional subflow, injecting a FIN+ACK before sending
the DATA_FIN, and expecting a FIN+ACK in return.
Fixes: 40947e13997a ("mptcp: schedule worker when subflow is closed")
Cc: stable@vger.kernel.org
Link: https://github.com/multipath-tcp/packetdrill/pull/154 [1]
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-1-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:18 +00:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
|
|
|
|
if (likely(ssk->sk_state != TCP_CLOSE &&
|
|
|
|
(ssk->sk_state != TCP_CLOSE_WAIT ||
|
|
|
|
inet_sk_state_load(sk) != TCP_ESTABLISHED)))
|
2021-02-12 23:59:56 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (skb_queue_empty(&ssk->sk_receive_queue) &&
|
2023-04-11 20:42:09 +00:00
|
|
|
!test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW, &msk->flags))
|
mptcp: close subflow when receiving TCP+FIN
When a peer decides to close one subflow in the middle of a connection
having multiple subflows, the receiver of the first FIN should accept
that, and close the subflow on its side as well. If not, the subflow
will stay half closed, and would even continue to be used until the end
of the MPTCP connection or a reset from the network.
The issue has not been seen before, probably because the in-kernel
path-manager always sends a RM_ADDR before closing the subflow. Upon the
reception of this RM_ADDR, the other peer will initiate the closure on
its side as well. On the other hand, if the RM_ADDR is lost, or if the
path-manager of the other peer only closes the subflow without sending a
RM_ADDR, the subflow would switch to TCP_CLOSE_WAIT, but that's it,
leaving the subflow half-closed.
So now, when the subflow switches to the TCP_CLOSE_WAIT state, and if
the MPTCP connection has not been closed before with a DATA_FIN, the
kernel owning the subflow schedules its worker to initiate the closure
on its side as well.
This issue can be easily reproduced with packetdrill, as visible in [1],
by creating an additional subflow, injecting a FIN+ACK before sending
the DATA_FIN, and expecting a FIN+ACK in return.
Fixes: 40947e13997a ("mptcp: schedule worker when subflow is closed")
Cc: stable@vger.kernel.org
Link: https://github.com/multipath-tcp/packetdrill/pull/154 [1]
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-1-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:18 +00:00
|
|
|
mptcp_schedule_work(sk);
|
2021-02-12 23:59:56 +00:00
|
|
|
}
|
|
|
|
|
mptcp: Do TCP fallback on early DSS checksum failure
RFC 8684 section 3.7 describes several opportunities for a MPTCP
connection to "fall back" to regular TCP early in the connection
process, before it has been confirmed that MPTCP options can be
successfully propagated on all SYN, SYN/ACK, and data packets. If a peer
acknowledges the first received data packet with a regular TCP header
(no MPTCP options), fallback is allowed.
If the recipient of that first data packet finds a MPTCP DSS checksum
error, this provides an opportunity to fail gracefully with a TCP
fallback rather than resetting the connection (as might happen if a
checksum failure were detected later).
This commit modifies the checksum failure code to attempt fallback on
the initial subflow of a MPTCP connection, only if it's a failure in the
first data mapping. In cases where the peer initiates the connection,
requests checksums, is the first to send data, and the peer is sending
incorrect checksums (see
https://github.com/multipath-tcp/mptcp_net-next/issues/275), this allows
the connection to proceed as TCP rather than reset.
Fixes: dd8bcd1768ff ("mptcp: validate the data checksum")
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-17 18:02:12 +00:00
|
|
|
static bool subflow_can_fallback(struct mptcp_subflow_context *subflow)
|
|
|
|
{
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
|
|
|
|
|
|
|
if (subflow->mp_join)
|
|
|
|
return false;
|
|
|
|
else if (READ_ONCE(msk->csum_enabled))
|
|
|
|
return !subflow->valid_csum_seen;
|
|
|
|
else
|
mptcp: fallback when MPTCP opts are dropped after 1st data
As reported by Christoph [1], before this patch, an MPTCP connection was
wrongly reset when a host received a first data packet with MPTCP
options after the 3wHS, but got the next ones without.
According to the MPTCP v1 specs [2], a fallback should happen in this
case, because the host didn't receive a DATA_ACK from the other peer,
nor receive data for more than the initial window which implies a
DATA_ACK being received by the other peer.
The patch here re-uses the same logic as the one used in other places:
by looking at allow_infinite_fallback, which is disabled at the creation
of an additional subflow. It's not looking at the first DATA_ACK (or
implying one received from the other side) as suggested by the RFC, but
it is in continuation with what was already done, which is safer, and it
fixes the reported issue. The next step, looking at this first DATA_ACK,
is tracked in [4].
This patch has been validated using the following Packetdrill script:
0 socket(..., SOCK_STREAM, IPPROTO_MPTCP) = 3
+0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+0 bind(3, ..., ...) = 0
+0 listen(3, 1) = 0
// 3WHS is OK
+0.0 < S 0:0(0) win 65535 <mss 1460, sackOK, nop, nop, nop, wscale 6, mpcapable v1 flags[flag_h] nokey>
+0.0 > S. 0:0(0) ack 1 <mss 1460, nop, nop, sackOK, nop, wscale 8, mpcapable v1 flags[flag_h] key[skey]>
+0.1 < . 1:1(0) ack 1 win 2048 <mpcapable v1 flags[flag_h] key[ckey=2, skey]>
+0 accept(3, ..., ...) = 4
// Data from the client with valid MPTCP options (no DATA_ACK: normal)
+0.1 < P. 1:501(500) ack 1 win 2048 <mpcapable v1 flags[flag_h] key[skey, ckey] mpcdatalen 500, nop, nop>
// From here, the MPTCP options will be dropped by a middlebox
+0.0 > . 1:1(0) ack 501 <dss dack8=501 dll=0 nocs>
+0.1 read(4, ..., 500) = 500
+0 write(4, ..., 100) = 100
// The server replies with data, still thinking MPTCP is being used
+0.0 > P. 1:101(100) ack 501 <dss dack8=501 dsn8=1 ssn=1 dll=100 nocs, nop, nop>
// But the client already did a fallback to TCP, because the two previous packets have been received without MPTCP options
+0.1 < . 501:501(0) ack 101 win 2048
+0.0 < P. 501:601(100) ack 101 win 2048
// The server should fallback to TCP, not reset: it didn't get a DATA_ACK, nor data for more than the initial window
+0.0 > . 101:101(0) ack 601
Note that this script requires Packetdrill with MPTCP support, see [3].
Fixes: dea2b1ea9c70 ("mptcp: do not reset MP_CAPABLE subflow on mapping errors")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/518 [1]
Link: https://datatracker.ietf.org/doc/html/rfc8684#name-fallback [2]
Link: https://github.com/multipath-tcp/packetdrill [3]
Link: https://github.com/multipath-tcp/mptcp_net-next/issues/519 [4]
Reviewed-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20241008-net-mptcp-fallback-fixes-v1-3-c6fb8e93e551@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-10-08 11:04:54 +00:00
|
|
|
return READ_ONCE(msk->allow_infinite_fallback);
|
mptcp: Do TCP fallback on early DSS checksum failure
RFC 8684 section 3.7 describes several opportunities for a MPTCP
connection to "fall back" to regular TCP early in the connection
process, before it has been confirmed that MPTCP options can be
successfully propagated on all SYN, SYN/ACK, and data packets. If a peer
acknowledges the first received data packet with a regular TCP header
(no MPTCP options), fallback is allowed.
If the recipient of that first data packet finds a MPTCP DSS checksum
error, this provides an opportunity to fail gracefully with a TCP
fallback rather than resetting the connection (as might happen if a
checksum failure were detected later).
This commit modifies the checksum failure code to attempt fallback on
the initial subflow of a MPTCP connection, only if it's a failure in the
first data mapping. In cases where the peer initiates the connection,
requests checksums, is the first to send data, and the peer is sending
incorrect checksums (see
https://github.com/multipath-tcp/mptcp_net-next/issues/275), this allows
the connection to proceed as TCP rather than reset.
Fixes: dd8bcd1768ff ("mptcp: validate the data checksum")
Acked-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-17 18:02:12 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 01:02:37 +00:00
|
|
|
static void mptcp_subflow_fail(struct mptcp_sock *msk, struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
unsigned long fail_tout;
|
|
|
|
|
2024-05-02 15:47:40 +00:00
|
|
|
/* graceful failure can happen only on the MPC subflow */
|
2022-06-28 01:02:37 +00:00
|
|
|
if (WARN_ON_ONCE(ssk != READ_ONCE(msk->first)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* since the close timeout take precedence on the fail one,
|
|
|
|
* no need to start the latter when the first is already set
|
|
|
|
*/
|
|
|
|
if (sock_flag((struct sock *)msk, SOCK_DEAD))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* we don't need extreme accuracy here, use a zero fail_tout as special
|
|
|
|
* value meaning no fail timeout at all;
|
|
|
|
*/
|
|
|
|
fail_tout = jiffies + TCP_RTO_MAX;
|
|
|
|
if (!fail_tout)
|
|
|
|
fail_tout = 1;
|
|
|
|
WRITE_ONCE(subflow->fail_tout, fail_tout);
|
|
|
|
tcp_send_ack(ssk);
|
|
|
|
|
2023-09-16 10:52:48 +00:00
|
|
|
mptcp_reset_tout_timer(msk, subflow->fail_tout);
|
2022-06-28 01:02:37 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
static bool subflow_check_data_avail(struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
enum mapping_status status;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
2020-09-14 08:01:08 +00:00
|
|
|
if (!skb_peek(&ssk->sk_receive_queue))
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, false);
|
2020-01-22 00:56:24 +00:00
|
|
|
if (subflow->data_avail)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
msk = mptcp_sk(subflow->conn);
|
|
|
|
for (;;) {
|
|
|
|
u64 ack_seq;
|
|
|
|
u64 old_ack;
|
|
|
|
|
2020-07-28 22:12:06 +00:00
|
|
|
status = get_mapping_status(ssk, msk);
|
2021-04-16 22:38:07 +00:00
|
|
|
trace_subflow_check_data_avail(status, skb_peek(&ssk->sk_receive_queue));
|
2022-06-28 01:02:36 +00:00
|
|
|
if (unlikely(status == MAPPING_INVALID || status == MAPPING_DUMMY ||
|
2024-10-21 15:14:06 +00:00
|
|
|
status == MAPPING_BAD_CSUM || status == MAPPING_NODSS))
|
2021-05-27 23:31:39 +00:00
|
|
|
goto fallback;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
if (status != MAPPING_OK)
|
2021-02-12 23:59:56 +00:00
|
|
|
goto no_data;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
skb = skb_peek(&ssk->sk_receive_queue);
|
|
|
|
if (WARN_ON_ONCE(!skb))
|
2021-02-12 23:59:56 +00:00
|
|
|
goto no_data;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
2022-11-25 22:29:49 +00:00
|
|
|
if (unlikely(!READ_ONCE(msk->can_ack)))
|
|
|
|
goto fallback;
|
2020-01-22 00:56:32 +00:00
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
old_ack = READ_ONCE(msk->ack_seq);
|
|
|
|
ack_seq = mptcp_subflow_get_mapped_dsn(subflow);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("msk ack_seq=%llx subflow ack_seq=%llx\n", old_ack,
|
2020-01-22 00:56:24 +00:00
|
|
|
ack_seq);
|
mptcp: wake-up readers only for in sequence data
Currently we rely on the subflow->data_avail field, which is subject to
races:
ssk1
skb len = 500 DSS(seq=1, len=1000, off=0)
# data_avail == MPTCP_SUBFLOW_DATA_AVAIL
ssk2
skb len = 500 DSS(seq = 501, len=1000)
# data_avail == MPTCP_SUBFLOW_DATA_AVAIL
ssk1
skb len = 500 DSS(seq = 1, len=1000, off =500)
# still data_avail == MPTCP_SUBFLOW_DATA_AVAIL,
# as the skb is covered by a pre-existing map,
# which was in-sequence at reception time.
Instead we can explicitly check if some has been received in-sequence,
propagating the info from __mptcp_move_skbs_from_subflow().
Additionally add the 'ONCE' annotation to the 'data_avail' memory
access, as msk will read it outside the subflow socket lock.
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-10 22:59:41 +00:00
|
|
|
if (unlikely(before64(ack_seq, old_ack))) {
|
|
|
|
mptcp_subflow_discard_data(ssk, skb, old_ack - ack_seq);
|
|
|
|
continue;
|
2020-09-14 08:01:08 +00:00
|
|
|
}
|
2020-01-22 00:56:24 +00:00
|
|
|
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, true);
|
mptcp: wake-up readers only for in sequence data
Currently we rely on the subflow->data_avail field, which is subject to
races:
ssk1
skb len = 500 DSS(seq=1, len=1000, off=0)
# data_avail == MPTCP_SUBFLOW_DATA_AVAIL
ssk2
skb len = 500 DSS(seq = 501, len=1000)
# data_avail == MPTCP_SUBFLOW_DATA_AVAIL
ssk1
skb len = 500 DSS(seq = 1, len=1000, off =500)
# still data_avail == MPTCP_SUBFLOW_DATA_AVAIL,
# as the skb is covered by a pre-existing map,
# which was in-sequence at reception time.
Instead we can explicitly check if some has been received in-sequence,
propagating the info from __mptcp_move_skbs_from_subflow().
Additionally add the 'ONCE' annotation to the 'data_avail' memory
access, as msk will read it outside the subflow socket lock.
Fixes: 648ef4b88673 ("mptcp: Implement MPTCP receive path")
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-06-10 22:59:41 +00:00
|
|
|
break;
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
2021-02-12 23:59:56 +00:00
|
|
|
no_data:
|
|
|
|
subflow_sched_work_if_closed(msk, ssk);
|
|
|
|
return false;
|
2021-05-27 23:31:39 +00:00
|
|
|
|
|
|
|
fallback:
|
2022-04-22 21:55:37 +00:00
|
|
|
if (!__mptcp_check_fallback(msk)) {
|
|
|
|
/* RFC 8684 section 3.7. */
|
2022-06-28 01:02:36 +00:00
|
|
|
if (status == MAPPING_BAD_CSUM &&
|
|
|
|
(subflow->mp_join || subflow->valid_csum_seen)) {
|
|
|
|
subflow->send_mp_fail = 1;
|
|
|
|
|
2022-05-18 22:04:43 +00:00
|
|
|
if (!READ_ONCE(msk->allow_infinite_fallback)) {
|
2022-04-22 21:55:37 +00:00
|
|
|
subflow->reset_transient = 0;
|
|
|
|
subflow->reset_reason = MPTCP_RST_EMIDDLEBOX;
|
2022-06-28 01:02:39 +00:00
|
|
|
goto reset;
|
2022-04-22 21:55:37 +00:00
|
|
|
}
|
2022-06-28 01:02:39 +00:00
|
|
|
mptcp_subflow_fail(msk, ssk);
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, true);
|
2022-04-22 21:55:37 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-05-19 18:23:59 +00:00
|
|
|
if (!subflow_can_fallback(subflow) && subflow->map_data_len) {
|
2022-04-22 21:55:37 +00:00
|
|
|
/* fatal protocol error, close the socket.
|
|
|
|
* subflow_error_report() will introduce the appropriate barriers
|
|
|
|
*/
|
2022-04-22 21:55:36 +00:00
|
|
|
subflow->reset_transient = 0;
|
2024-10-21 15:14:06 +00:00
|
|
|
subflow->reset_reason = status == MAPPING_NODSS ?
|
|
|
|
MPTCP_RST_EMIDDLEBOX :
|
|
|
|
MPTCP_RST_EMPTCP;
|
2022-06-28 01:02:39 +00:00
|
|
|
|
|
|
|
reset:
|
2023-03-15 20:57:45 +00:00
|
|
|
WRITE_ONCE(ssk->sk_err, EBADMSG);
|
2022-06-28 01:02:39 +00:00
|
|
|
tcp_set_state(ssk, TCP_CLOSE);
|
|
|
|
while ((skb = skb_peek(&ssk->sk_receive_queue)))
|
|
|
|
sk_eat_skb(ssk, skb);
|
2024-04-25 03:13:39 +00:00
|
|
|
mptcp_send_active_reset_reason(ssk);
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, false);
|
2022-04-22 21:55:37 +00:00
|
|
|
return false;
|
2021-08-24 23:26:17 +00:00
|
|
|
}
|
|
|
|
|
2022-06-28 01:02:38 +00:00
|
|
|
mptcp_do_fallback(ssk);
|
2021-05-27 23:31:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
skb = skb_peek(&ssk->sk_receive_queue);
|
|
|
|
subflow->map_valid = 1;
|
|
|
|
subflow->map_seq = READ_ONCE(msk->ack_seq);
|
|
|
|
subflow->map_data_len = skb->len;
|
|
|
|
subflow->map_subflow_seq = tcp_sk(ssk)->copied_seq - subflow->ssn_offset;
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, true);
|
2021-05-27 23:31:39 +00:00
|
|
|
return true;
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool mptcp_subflow_data_available(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
|
|
|
|
/* check if current mapping is still valid */
|
|
|
|
if (subflow->map_valid &&
|
|
|
|
mptcp_subflow_get_map_offset(subflow) >= subflow->map_data_len) {
|
|
|
|
subflow->map_valid = 0;
|
2023-10-23 20:44:36 +00:00
|
|
|
WRITE_ONCE(subflow->data_avail, false);
|
2020-01-22 00:56:24 +00:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("Done with mapping: seq=%u data_len=%u\n",
|
2020-01-22 00:56:24 +00:00
|
|
|
subflow->map_subflow_seq,
|
|
|
|
subflow->map_data_len);
|
|
|
|
}
|
|
|
|
|
2020-09-14 08:01:08 +00:00
|
|
|
return subflow_check_data_avail(sk);
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
2020-04-24 10:31:50 +00:00
|
|
|
/* If ssk has an mptcp parent socket, use the mptcp rcvbuf occupancy,
|
|
|
|
* not the ssk one.
|
|
|
|
*
|
|
|
|
* In mptcp, rwin is about the mptcp-level connection data.
|
|
|
|
*
|
|
|
|
* Data that is still on the ssk rx queue can thus be ignored,
|
2021-03-26 23:12:46 +00:00
|
|
|
* as far as mptcp peer is concerned that data is still inflight.
|
2020-04-24 10:31:50 +00:00
|
|
|
* DSS ACK is updated when skb is moved to the mptcp rx queue.
|
|
|
|
*/
|
|
|
|
void mptcp_space(const struct sock *ssk, int *space, int *full_space)
|
|
|
|
{
|
|
|
|
const struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
const struct sock *sk = subflow->conn;
|
|
|
|
|
2020-11-19 19:46:03 +00:00
|
|
|
*space = __mptcp_space(sk);
|
2023-07-20 18:47:50 +00:00
|
|
|
*full_space = mptcp_win_from_space(sk, READ_ONCE(sk->sk_rcvbuf));
|
2020-04-24 10:31:50 +00:00
|
|
|
}
|
|
|
|
|
2021-02-11 23:30:37 +00:00
|
|
|
static void subflow_error_report(struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
|
|
|
|
|
2023-03-09 14:49:57 +00:00
|
|
|
/* bail early if this is a no-op, so that we avoid introducing a
|
|
|
|
* problematic lockdep dependency between TCP accept queue lock
|
|
|
|
* and msk socket spinlock
|
|
|
|
*/
|
|
|
|
if (!sk->sk_socket)
|
|
|
|
return;
|
|
|
|
|
2021-02-11 23:30:37 +00:00
|
|
|
mptcp_data_lock(sk);
|
|
|
|
if (!sock_owned_by_user(sk))
|
|
|
|
__mptcp_error_report(sk);
|
|
|
|
else
|
2022-01-07 00:20:26 +00:00
|
|
|
__set_bit(MPTCP_ERROR_REPORT, &mptcp_sk(sk)->cb_flags);
|
2021-02-11 23:30:37 +00:00
|
|
|
mptcp_data_unlock(sk);
|
|
|
|
}
|
|
|
|
|
2021-06-10 22:59:44 +00:00
|
|
|
static void subflow_data_ready(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
u16 state = 1 << inet_sk_state_load(sk);
|
|
|
|
struct sock *parent = subflow->conn;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
|
2023-01-20 00:45:16 +00:00
|
|
|
trace_sk_data_ready(sk);
|
|
|
|
|
2021-06-10 22:59:44 +00:00
|
|
|
msk = mptcp_sk(parent);
|
|
|
|
if (state & TCPF_LISTEN) {
|
|
|
|
/* MPJ subflow are removed from accept queue before reaching here,
|
|
|
|
* avoid stray wakeups
|
|
|
|
*/
|
|
|
|
if (reqsk_queue_empty(&inet_csk(sk)->icsk_accept_queue))
|
|
|
|
return;
|
|
|
|
|
|
|
|
parent->sk_data_ready(parent);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
WARN_ON_ONCE(!__mptcp_check_fallback(msk) && !subflow->mp_capable &&
|
|
|
|
!subflow->mp_join && !(state & TCPF_CLOSE));
|
|
|
|
|
2023-10-23 20:44:38 +00:00
|
|
|
if (mptcp_subflow_data_available(sk)) {
|
2021-06-10 22:59:44 +00:00
|
|
|
mptcp_data_ready(parent, sk);
|
2023-10-23 20:44:38 +00:00
|
|
|
|
|
|
|
/* subflow-level lowat test are not relevant.
|
|
|
|
* respect the msk-level threshold eventually mandating an immediate ack
|
|
|
|
*/
|
|
|
|
if (mptcp_data_avail(msk) < parent->sk_rcvlowat &&
|
|
|
|
(tcp_sk(sk)->rcv_nxt - tcp_sk(sk)->rcv_wup) > inet_csk(sk)->icsk_ack.rcv_mss)
|
|
|
|
inet_csk(sk)->icsk_ack.pending |= ICSK_ACK_NOW;
|
|
|
|
} else if (unlikely(sk->sk_err)) {
|
2021-06-10 22:59:44 +00:00
|
|
|
subflow_error_report(sk);
|
2023-10-23 20:44:38 +00:00
|
|
|
}
|
2021-06-10 22:59:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void subflow_write_space(struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct sock *sk = mptcp_subflow_ctx(ssk)->conn;
|
|
|
|
|
|
|
|
mptcp_propagate_sndbuf(sk, ssk);
|
|
|
|
mptcp_write_space(sk);
|
|
|
|
}
|
|
|
|
|
2022-02-16 02:11:29 +00:00
|
|
|
static const struct inet_connection_sock_af_ops *
|
2020-01-22 00:56:18 +00:00
|
|
|
subflow_default_af_ops(struct sock *sk)
|
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (sk->sk_family == AF_INET6)
|
|
|
|
return &subflow_v6_specific;
|
|
|
|
#endif
|
|
|
|
return &subflow_specific;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2020-01-30 09:45:26 +00:00
|
|
|
void mptcpv6_handle_mapped(struct sock *sk, bool mapped)
|
|
|
|
{
|
2020-01-22 00:56:18 +00:00
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
2022-02-16 02:11:29 +00:00
|
|
|
const struct inet_connection_sock_af_ops *target;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
target = mapped ? &subflow_v6m_specific : subflow_default_af_ops(sk);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p family=%d ops=%p target=%p mapped=%d\n",
|
2020-01-25 00:04:03 +00:00
|
|
|
subflow, sk->sk_family, icsk->icsk_af_ops, target, mapped);
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
if (likely(icsk->icsk_af_ops == target))
|
|
|
|
return;
|
|
|
|
|
|
|
|
subflow->icsk_af_ops = icsk->icsk_af_ops;
|
|
|
|
icsk->icsk_af_ops = target;
|
|
|
|
}
|
2020-01-30 09:45:26 +00:00
|
|
|
#endif
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2021-02-01 23:09:12 +00:00
|
|
|
void mptcp_info2sockaddr(const struct mptcp_addr_info *info,
|
|
|
|
struct sockaddr_storage *addr,
|
|
|
|
unsigned short family)
|
2020-03-27 21:48:40 +00:00
|
|
|
{
|
|
|
|
memset(addr, 0, sizeof(*addr));
|
2021-01-25 18:59:00 +00:00
|
|
|
addr->ss_family = family;
|
2020-03-27 21:48:40 +00:00
|
|
|
if (addr->ss_family == AF_INET) {
|
|
|
|
struct sockaddr_in *in_addr = (struct sockaddr_in *)addr;
|
|
|
|
|
2021-01-25 18:59:00 +00:00
|
|
|
if (info->family == AF_INET)
|
|
|
|
in_addr->sin_addr = info->addr;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (ipv6_addr_v4mapped(&info->addr6))
|
|
|
|
in_addr->sin_addr.s_addr = info->addr6.s6_addr32[3];
|
|
|
|
#endif
|
2020-03-27 21:48:40 +00:00
|
|
|
in_addr->sin_port = info->port;
|
|
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (addr->ss_family == AF_INET6) {
|
|
|
|
struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)addr;
|
|
|
|
|
2021-01-25 18:59:00 +00:00
|
|
|
if (info->family == AF_INET)
|
|
|
|
ipv6_addr_set_v4mapped(info->addr.s_addr,
|
|
|
|
&in6_addr->sin6_addr);
|
|
|
|
else
|
|
|
|
in6_addr->sin6_addr = info->addr6;
|
2020-03-27 21:48:40 +00:00
|
|
|
in6_addr->sin6_port = info->port;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2024-09-02 10:45:53 +00:00
|
|
|
int __mptcp_subflow_connect(struct sock *sk, const struct mptcp_pm_local *local,
|
2021-08-17 22:07:22 +00:00
|
|
|
const struct mptcp_addr_info *remote)
|
2020-03-27 21:48:40 +00:00
|
|
|
{
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(sk);
|
|
|
|
struct mptcp_subflow_context *subflow;
|
2024-09-02 10:45:53 +00:00
|
|
|
int local_id = local->addr.id;
|
2020-03-27 21:48:40 +00:00
|
|
|
struct sockaddr_storage addr;
|
2020-09-08 02:49:39 +00:00
|
|
|
int remote_id = remote->id;
|
2022-05-12 23:26:41 +00:00
|
|
|
int err = -ENOTCONN;
|
2020-03-27 21:48:40 +00:00
|
|
|
struct socket *sf;
|
2020-06-30 14:38:26 +00:00
|
|
|
struct sock *ssk;
|
2020-03-27 21:48:40 +00:00
|
|
|
u32 remote_token;
|
|
|
|
int addrlen;
|
|
|
|
|
2024-09-02 10:45:54 +00:00
|
|
|
/* The userspace PM sent the request too early? */
|
2020-07-23 11:02:32 +00:00
|
|
|
if (!mptcp_is_fully_established(sk))
|
2022-05-12 23:26:41 +00:00
|
|
|
goto err_out;
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2024-09-02 10:45:53 +00:00
|
|
|
err = mptcp_subflow_create_socket(sk, local->addr.family, &sf);
|
2024-09-02 10:45:54 +00:00
|
|
|
if (err) {
|
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNTXCREATSKERR);
|
|
|
|
pr_debug("msk=%p local=%d remote=%d create sock error: %d\n",
|
|
|
|
msk, local_id, remote_id, err);
|
2022-05-12 23:26:41 +00:00
|
|
|
goto err_out;
|
2024-09-02 10:45:54 +00:00
|
|
|
}
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2020-06-30 14:38:26 +00:00
|
|
|
ssk = sf->sk;
|
|
|
|
subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
do {
|
|
|
|
get_random_bytes(&subflow->local_nonce, sizeof(u32));
|
|
|
|
} while (!subflow->local_nonce);
|
|
|
|
|
2024-09-02 10:45:53 +00:00
|
|
|
/* if 'IPADDRANY', the ID will be set later, after the routing */
|
|
|
|
if (local->addr.family == AF_INET) {
|
|
|
|
if (!local->addr.addr.s_addr)
|
|
|
|
local_id = -1;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
} else if (sk->sk_family == AF_INET6) {
|
|
|
|
if (ipv6_addr_any(&local->addr.addr6))
|
|
|
|
local_id = -1;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
if (local_id >= 0)
|
2022-03-07 20:44:37 +00:00
|
|
|
subflow_set_local_id(subflow, local_id);
|
2020-06-30 14:38:26 +00:00
|
|
|
|
2022-11-25 22:29:49 +00:00
|
|
|
subflow->remote_key_valid = 1;
|
2024-02-02 11:40:07 +00:00
|
|
|
subflow->remote_key = READ_ONCE(msk->remote_key);
|
|
|
|
subflow->local_key = READ_ONCE(msk->local_key);
|
2020-03-27 21:48:40 +00:00
|
|
|
subflow->token = msk->token;
|
2024-09-02 10:45:53 +00:00
|
|
|
mptcp_info2sockaddr(&local->addr, &addr, ssk->sk_family);
|
2020-03-27 21:48:40 +00:00
|
|
|
|
|
|
|
addrlen = sizeof(struct sockaddr_in);
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2021-01-25 18:59:00 +00:00
|
|
|
if (addr.ss_family == AF_INET6)
|
2020-03-27 21:48:40 +00:00
|
|
|
addrlen = sizeof(struct sockaddr_in6);
|
|
|
|
#endif
|
2024-09-02 10:45:53 +00:00
|
|
|
ssk->sk_bound_dev_if = local->ifindex;
|
2020-03-27 21:48:40 +00:00
|
|
|
err = kernel_bind(sf, (struct sockaddr *)&addr, addrlen);
|
2024-09-02 10:45:54 +00:00
|
|
|
if (err) {
|
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNTXBINDERR);
|
|
|
|
pr_debug("msk=%p local=%d remote=%d bind error: %d\n",
|
|
|
|
msk, local_id, remote_id, err);
|
2020-03-27 21:48:40 +00:00
|
|
|
goto failed;
|
2024-09-02 10:45:54 +00:00
|
|
|
}
|
2020-03-27 21:48:40 +00:00
|
|
|
|
|
|
|
mptcp_crypto_key_sha(subflow->remote_key, &remote_token, NULL);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("msk=%p remote_token=%u local_id=%d remote_id=%d\n", msk,
|
2020-09-08 02:49:39 +00:00
|
|
|
remote_token, local_id, remote_id);
|
2020-03-27 21:48:40 +00:00
|
|
|
subflow->remote_token = remote_token;
|
2024-02-15 18:25:32 +00:00
|
|
|
WRITE_ONCE(subflow->remote_id, remote_id);
|
2020-03-27 21:48:40 +00:00
|
|
|
subflow->request_join = 1;
|
2024-09-02 10:45:53 +00:00
|
|
|
subflow->request_bkup = !!(local->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
2023-06-20 16:30:17 +00:00
|
|
|
subflow->subflow_id = msk->subflow_id++;
|
2021-01-25 18:59:00 +00:00
|
|
|
mptcp_info2sockaddr(remote, &addr, ssk->sk_family);
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2022-01-07 00:20:25 +00:00
|
|
|
sock_hold(ssk);
|
|
|
|
list_add_tail(&subflow->node, &msk->conn_list);
|
2020-03-27 21:48:40 +00:00
|
|
|
err = kernel_connect(sf, (struct sockaddr *)&addr, addrlen, O_NONBLOCK);
|
2024-09-02 10:45:54 +00:00
|
|
|
if (err && err != -EINPROGRESS) {
|
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNTXCONNECTERR);
|
|
|
|
pr_debug("msk=%p local=%d remote=%d connect error: %d\n",
|
|
|
|
msk, local_id, remote_id, err);
|
2020-12-09 11:03:29 +00:00
|
|
|
goto failed_unlink;
|
2024-09-02 10:45:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_JOINSYNTX);
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2021-01-20 14:39:10 +00:00
|
|
|
/* discard the subflow socket */
|
|
|
|
mptcp_sock_graft(ssk, sk->sk_socket);
|
|
|
|
iput(SOCK_INODE(sf));
|
2022-04-22 21:55:38 +00:00
|
|
|
WRITE_ONCE(msk->allow_infinite_fallback, false);
|
2023-09-16 10:52:49 +00:00
|
|
|
mptcp_stop_tout_timer(sk);
|
2022-07-25 20:52:31 +00:00
|
|
|
return 0;
|
2020-03-27 21:48:40 +00:00
|
|
|
|
2020-12-09 11:03:29 +00:00
|
|
|
failed_unlink:
|
|
|
|
list_del(&subflow->node);
|
2021-03-04 21:32:09 +00:00
|
|
|
sock_put(mptcp_subflow_tcp_sock(subflow));
|
2020-03-27 21:48:40 +00:00
|
|
|
|
|
|
|
failed:
|
2020-11-16 09:48:09 +00:00
|
|
|
subflow->disposable = 1;
|
2020-03-27 21:48:40 +00:00
|
|
|
sock_release(sf);
|
2022-05-12 23:26:41 +00:00
|
|
|
|
|
|
|
err_out:
|
|
|
|
/* we account subflows before the creation, and this failures will not
|
|
|
|
* be caught by sk_state_change()
|
|
|
|
*/
|
|
|
|
mptcp_pm_close_subflow(msk);
|
2020-03-27 21:48:40 +00:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-12-10 22:24:58 +00:00
|
|
|
static void mptcp_attach_cgroup(struct sock *parent, struct sock *child)
|
|
|
|
{
|
|
|
|
#ifdef CONFIG_SOCK_CGROUP_DATA
|
|
|
|
struct sock_cgroup_data *parent_skcd = &parent->sk_cgrp_data,
|
|
|
|
*child_skcd = &child->sk_cgrp_data;
|
|
|
|
|
|
|
|
/* only the additional subflows created by kworkers have to be modified */
|
|
|
|
if (cgroup_id(sock_cgroup_ptr(parent_skcd)) !=
|
|
|
|
cgroup_id(sock_cgroup_ptr(child_skcd))) {
|
|
|
|
#ifdef CONFIG_MEMCG
|
|
|
|
struct mem_cgroup *memcg = parent->sk_memcg;
|
|
|
|
|
|
|
|
mem_cgroup_sk_free(child);
|
|
|
|
if (memcg && css_tryget(&memcg->css))
|
|
|
|
child->sk_memcg = memcg;
|
|
|
|
#endif /* CONFIG_MEMCG */
|
|
|
|
|
|
|
|
cgroup_sk_free(child_skcd);
|
|
|
|
*child_skcd = *parent_skcd;
|
|
|
|
cgroup_sk_clone(child_skcd);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_SOCK_CGROUP_DATA */
|
|
|
|
}
|
|
|
|
|
2021-01-20 14:39:14 +00:00
|
|
|
static void mptcp_subflow_ops_override(struct sock *ssk)
|
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (ssk->sk_prot == &tcpv6_prot)
|
|
|
|
ssk->sk_prot = &tcpv6_prot_override;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
ssk->sk_prot = &tcp_prot_override;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mptcp_subflow_ops_undo_override(struct sock *ssk)
|
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (ssk->sk_prot == &tcpv6_prot_override)
|
|
|
|
ssk->sk_prot = &tcpv6_prot;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
ssk->sk_prot = &tcp_prot;
|
|
|
|
}
|
2023-01-12 17:42:51 +00:00
|
|
|
|
|
|
|
int mptcp_subflow_create_socket(struct sock *sk, unsigned short family,
|
|
|
|
struct socket **new_sock)
|
2020-01-22 00:56:17 +00:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
struct net *net = sock_net(sk);
|
|
|
|
struct socket *sf;
|
|
|
|
int err;
|
|
|
|
|
2020-08-04 16:31:06 +00:00
|
|
|
/* un-accepted server sockets can reach here - on bad configuration
|
|
|
|
* bail early to avoid greater trouble later
|
|
|
|
*/
|
|
|
|
if (unlikely(!sk->sk_socket))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2023-01-12 17:42:51 +00:00
|
|
|
err = sock_create_kern(net, family, SOCK_STREAM, IPPROTO_TCP, &sf);
|
2020-01-22 00:56:17 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2023-02-07 13:04:15 +00:00
|
|
|
lock_sock_nested(sf->sk, SINGLE_DEPTH_NESTING);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
2023-04-20 17:17:13 +00:00
|
|
|
err = security_mptcp_add_subflow(sk, sf->sk);
|
|
|
|
if (err)
|
2023-10-23 20:44:40 +00:00
|
|
|
goto err_free;
|
2023-04-20 17:17:13 +00:00
|
|
|
|
2020-12-10 22:24:58 +00:00
|
|
|
/* the newly created socket has to be in the same cgroup as its parent */
|
|
|
|
mptcp_attach_cgroup(sk, sf->sk);
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
/* kernel sockets do not by default acquire net ref, but TCP timer
|
|
|
|
* needs it.
|
2022-10-25 18:05:46 +00:00
|
|
|
* Update ns_tracker to current stack trace and refcounted tracker.
|
2020-01-22 00:56:17 +00:00
|
|
|
*/
|
2022-10-25 18:05:46 +00:00
|
|
|
__netns_tracker_free(net, &sf->sk->ns_tracker, false);
|
2020-01-22 00:56:17 +00:00
|
|
|
sf->sk->sk_net_refcnt = 1;
|
2021-12-14 04:32:08 +00:00
|
|
|
get_net_track(net, &sf->sk->ns_tracker, GFP_KERNEL);
|
2021-11-15 17:11:48 +00:00
|
|
|
sock_inuse_add(net, 1);
|
2020-01-22 00:56:17 +00:00
|
|
|
err = tcp_set_ulp(sf->sk, "mptcp");
|
2023-10-23 20:44:40 +00:00
|
|
|
if (err)
|
|
|
|
goto err_free;
|
2023-04-20 17:17:13 +00:00
|
|
|
|
2023-10-23 20:44:40 +00:00
|
|
|
mptcp_sockopt_sync_locked(mptcp_sk(sk), sf->sk);
|
2020-01-22 00:56:17 +00:00
|
|
|
release_sock(sf->sk);
|
|
|
|
|
2024-06-05 07:15:42 +00:00
|
|
|
/* the newly created socket really belongs to the owning MPTCP
|
2020-05-07 16:53:24 +00:00
|
|
|
* socket, even if for additional subflows the allocation is performed
|
|
|
|
* by a kernel workqueue. Adjust inode references, so that the
|
2022-06-27 12:16:25 +00:00
|
|
|
* procfs/diag interfaces really show this one belonging to the correct
|
2020-05-07 16:53:24 +00:00
|
|
|
* user.
|
|
|
|
*/
|
|
|
|
SOCK_INODE(sf)->i_ino = SOCK_INODE(sk->sk_socket)->i_ino;
|
|
|
|
SOCK_INODE(sf)->i_uid = SOCK_INODE(sk->sk_socket)->i_uid;
|
|
|
|
SOCK_INODE(sf)->i_gid = SOCK_INODE(sk->sk_socket)->i_gid;
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
subflow = mptcp_subflow_ctx(sf->sk);
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p\n", subflow);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
*new_sock = sf;
|
2020-01-22 00:56:20 +00:00
|
|
|
sock_hold(sk);
|
2020-01-22 00:56:17 +00:00
|
|
|
subflow->conn = sk;
|
2021-01-20 14:39:14 +00:00
|
|
|
mptcp_subflow_ops_override(sf->sk);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
return 0;
|
2023-10-23 20:44:40 +00:00
|
|
|
|
|
|
|
err_free:
|
|
|
|
release_sock(sf->sk);
|
|
|
|
sock_release(sf);
|
|
|
|
return err;
|
2020-01-22 00:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static struct mptcp_subflow_context *subflow_create_ctx(struct sock *sk,
|
|
|
|
gfp_t priority)
|
|
|
|
{
|
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
|
|
|
struct mptcp_subflow_context *ctx;
|
|
|
|
|
|
|
|
ctx = kzalloc(sizeof(*ctx), priority);
|
|
|
|
if (!ctx)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
rcu_assign_pointer(icsk->icsk_ulp_data, ctx);
|
2020-01-22 00:56:18 +00:00
|
|
|
INIT_LIST_HEAD(&ctx->node);
|
2021-01-20 14:39:14 +00:00
|
|
|
INIT_LIST_HEAD(&ctx->delegated_node);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p\n", ctx);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
ctx->tcp_sock = sk;
|
2024-02-15 18:25:31 +00:00
|
|
|
WRITE_ONCE(ctx->local_id, -1);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
return ctx;
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
static void __subflow_state_change(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct socket_wq *wq;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
wq = rcu_dereference(sk->sk_wq);
|
|
|
|
if (skwq_has_sleeper(wq))
|
|
|
|
wake_up_interruptible_all(&wq->wait);
|
|
|
|
rcu_read_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool subflow_is_done(const struct sock *sk)
|
|
|
|
{
|
|
|
|
return sk->sk_shutdown & RCV_SHUTDOWN || sk->sk_state == TCP_CLOSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void subflow_state_change(struct sock *sk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk);
|
2020-03-13 15:52:42 +00:00
|
|
|
struct sock *parent = subflow->conn;
|
2023-06-20 16:24:21 +00:00
|
|
|
struct mptcp_sock *msk;
|
2020-01-22 00:56:24 +00:00
|
|
|
|
|
|
|
__subflow_state_change(sk);
|
|
|
|
|
2023-06-20 16:24:21 +00:00
|
|
|
msk = mptcp_sk(parent);
|
mptcp: fallback in case of simultaneous connect
when a MPTCP client tries to connect to itself, tcp_finish_connect() is
never reached. Because of this, depending on the socket current state,
multiple faulty behaviours can be observed:
1) a WARN_ON() in subflow_data_ready() is hit
WARNING: CPU: 2 PID: 882 at net/mptcp/subflow.c:911 subflow_data_ready+0x18b/0x230
[...]
CPU: 2 PID: 882 Comm: gh35 Not tainted 5.7.0+ #187
[...]
RIP: 0010:subflow_data_ready+0x18b/0x230
[...]
Call Trace:
tcp_data_queue+0xd2f/0x4250
tcp_rcv_state_process+0xb1c/0x49d3
tcp_v4_do_rcv+0x2bc/0x790
__release_sock+0x153/0x2d0
release_sock+0x4f/0x170
mptcp_shutdown+0x167/0x4e0
__sys_shutdown+0xe6/0x180
__x64_sys_shutdown+0x50/0x70
do_syscall_64+0x9a/0x370
entry_SYSCALL_64_after_hwframe+0x44/0xa9
2) client is stuck forever in mptcp_sendmsg() because the socket is not
TCP_ESTABLISHED
crash> bt 4847
PID: 4847 TASK: ffff88814b2fb100 CPU: 1 COMMAND: "gh35"
#0 [ffff8881376ff680] __schedule at ffffffff97248da4
#1 [ffff8881376ff778] schedule at ffffffff9724a34f
#2 [ffff8881376ff7a0] schedule_timeout at ffffffff97252ba0
#3 [ffff8881376ff8a8] wait_woken at ffffffff958ab4ba
#4 [ffff8881376ff940] sk_stream_wait_connect at ffffffff96c2d859
#5 [ffff8881376ffa28] mptcp_sendmsg at ffffffff97207fca
#6 [ffff8881376ffbc0] sock_sendmsg at ffffffff96be1b5b
#7 [ffff8881376ffbe8] sock_write_iter at ffffffff96be1daa
#8 [ffff8881376ffce8] new_sync_write at ffffffff95e5cb52
#9 [ffff8881376ffe50] vfs_write at ffffffff95e6547f
#10 [ffff8881376ffe90] ksys_write at ffffffff95e65d26
#11 [ffff8881376fff28] do_syscall_64 at ffffffff956088ba
#12 [ffff8881376fff50] entry_SYSCALL_64_after_hwframe at ffffffff9740008c
RIP: 00007f126f6956ed RSP: 00007ffc2a320278 RFLAGS: 00000217
RAX: ffffffffffffffda RBX: 0000000020000044 RCX: 00007f126f6956ed
RDX: 0000000000000004 RSI: 00000000004007b8 RDI: 0000000000000003
RBP: 00007ffc2a3202a0 R8: 0000000000400720 R9: 0000000000400720
R10: 0000000000400720 R11: 0000000000000217 R12: 00000000004004b0
R13: 00007ffc2a320380 R14: 0000000000000000 R15: 0000000000000000
ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
3) tcpdump captures show that DSS is exchanged even when MP_CAPABLE handshake
didn't complete.
$ tcpdump -tnnr bad.pcap
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S], seq 3208913911, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291694721,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S.], seq 3208913911, ack 3208913912, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291706876,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 1, win 512, options [nop,nop,TS val 3291706876 ecr 3291706876], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [F.], seq 1, ack 1, win 512, options [nop,nop,TS val 3291707876 ecr 3291706876,mptcp dss fin seq 0 subseq 0 len 1,nop,nop], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 2, win 512, options [nop,nop,TS val 3291707876 ecr 3291707876], length 0
force a fallback to TCP in these cases, and adjust the main socket
state to avoid hanging in mptcp_sendmsg().
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/35
Reported-by: Christoph Paasch <cpaasch@apple.com>
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-06-29 20:26:21 +00:00
|
|
|
if (subflow_simultaneous_connect(sk)) {
|
|
|
|
mptcp_do_fallback(sk);
|
2023-06-20 16:24:21 +00:00
|
|
|
pr_fallback(msk);
|
mptcp: fallback in case of simultaneous connect
when a MPTCP client tries to connect to itself, tcp_finish_connect() is
never reached. Because of this, depending on the socket current state,
multiple faulty behaviours can be observed:
1) a WARN_ON() in subflow_data_ready() is hit
WARNING: CPU: 2 PID: 882 at net/mptcp/subflow.c:911 subflow_data_ready+0x18b/0x230
[...]
CPU: 2 PID: 882 Comm: gh35 Not tainted 5.7.0+ #187
[...]
RIP: 0010:subflow_data_ready+0x18b/0x230
[...]
Call Trace:
tcp_data_queue+0xd2f/0x4250
tcp_rcv_state_process+0xb1c/0x49d3
tcp_v4_do_rcv+0x2bc/0x790
__release_sock+0x153/0x2d0
release_sock+0x4f/0x170
mptcp_shutdown+0x167/0x4e0
__sys_shutdown+0xe6/0x180
__x64_sys_shutdown+0x50/0x70
do_syscall_64+0x9a/0x370
entry_SYSCALL_64_after_hwframe+0x44/0xa9
2) client is stuck forever in mptcp_sendmsg() because the socket is not
TCP_ESTABLISHED
crash> bt 4847
PID: 4847 TASK: ffff88814b2fb100 CPU: 1 COMMAND: "gh35"
#0 [ffff8881376ff680] __schedule at ffffffff97248da4
#1 [ffff8881376ff778] schedule at ffffffff9724a34f
#2 [ffff8881376ff7a0] schedule_timeout at ffffffff97252ba0
#3 [ffff8881376ff8a8] wait_woken at ffffffff958ab4ba
#4 [ffff8881376ff940] sk_stream_wait_connect at ffffffff96c2d859
#5 [ffff8881376ffa28] mptcp_sendmsg at ffffffff97207fca
#6 [ffff8881376ffbc0] sock_sendmsg at ffffffff96be1b5b
#7 [ffff8881376ffbe8] sock_write_iter at ffffffff96be1daa
#8 [ffff8881376ffce8] new_sync_write at ffffffff95e5cb52
#9 [ffff8881376ffe50] vfs_write at ffffffff95e6547f
#10 [ffff8881376ffe90] ksys_write at ffffffff95e65d26
#11 [ffff8881376fff28] do_syscall_64 at ffffffff956088ba
#12 [ffff8881376fff50] entry_SYSCALL_64_after_hwframe at ffffffff9740008c
RIP: 00007f126f6956ed RSP: 00007ffc2a320278 RFLAGS: 00000217
RAX: ffffffffffffffda RBX: 0000000020000044 RCX: 00007f126f6956ed
RDX: 0000000000000004 RSI: 00000000004007b8 RDI: 0000000000000003
RBP: 00007ffc2a3202a0 R8: 0000000000400720 R9: 0000000000400720
R10: 0000000000400720 R11: 0000000000000217 R12: 00000000004004b0
R13: 00007ffc2a320380 R14: 0000000000000000 R15: 0000000000000000
ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
3) tcpdump captures show that DSS is exchanged even when MP_CAPABLE handshake
didn't complete.
$ tcpdump -tnnr bad.pcap
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S], seq 3208913911, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291694721,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S.], seq 3208913911, ack 3208913912, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291706876,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 1, win 512, options [nop,nop,TS val 3291706876 ecr 3291706876], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [F.], seq 1, ack 1, win 512, options [nop,nop,TS val 3291707876 ecr 3291706876,mptcp dss fin seq 0 subseq 0 len 1,nop,nop], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 2, win 512, options [nop,nop,TS val 3291707876 ecr 3291707876], length 0
force a fallback to TCP in these cases, and adjust the main socket
state to avoid hanging in mptcp_sendmsg().
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/35
Reported-by: Christoph Paasch <cpaasch@apple.com>
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-06-29 20:26:21 +00:00
|
|
|
subflow->conn_finished = 1;
|
2024-02-08 18:03:52 +00:00
|
|
|
mptcp_propagate_state(parent, sk, subflow, NULL);
|
mptcp: fallback in case of simultaneous connect
when a MPTCP client tries to connect to itself, tcp_finish_connect() is
never reached. Because of this, depending on the socket current state,
multiple faulty behaviours can be observed:
1) a WARN_ON() in subflow_data_ready() is hit
WARNING: CPU: 2 PID: 882 at net/mptcp/subflow.c:911 subflow_data_ready+0x18b/0x230
[...]
CPU: 2 PID: 882 Comm: gh35 Not tainted 5.7.0+ #187
[...]
RIP: 0010:subflow_data_ready+0x18b/0x230
[...]
Call Trace:
tcp_data_queue+0xd2f/0x4250
tcp_rcv_state_process+0xb1c/0x49d3
tcp_v4_do_rcv+0x2bc/0x790
__release_sock+0x153/0x2d0
release_sock+0x4f/0x170
mptcp_shutdown+0x167/0x4e0
__sys_shutdown+0xe6/0x180
__x64_sys_shutdown+0x50/0x70
do_syscall_64+0x9a/0x370
entry_SYSCALL_64_after_hwframe+0x44/0xa9
2) client is stuck forever in mptcp_sendmsg() because the socket is not
TCP_ESTABLISHED
crash> bt 4847
PID: 4847 TASK: ffff88814b2fb100 CPU: 1 COMMAND: "gh35"
#0 [ffff8881376ff680] __schedule at ffffffff97248da4
#1 [ffff8881376ff778] schedule at ffffffff9724a34f
#2 [ffff8881376ff7a0] schedule_timeout at ffffffff97252ba0
#3 [ffff8881376ff8a8] wait_woken at ffffffff958ab4ba
#4 [ffff8881376ff940] sk_stream_wait_connect at ffffffff96c2d859
#5 [ffff8881376ffa28] mptcp_sendmsg at ffffffff97207fca
#6 [ffff8881376ffbc0] sock_sendmsg at ffffffff96be1b5b
#7 [ffff8881376ffbe8] sock_write_iter at ffffffff96be1daa
#8 [ffff8881376ffce8] new_sync_write at ffffffff95e5cb52
#9 [ffff8881376ffe50] vfs_write at ffffffff95e6547f
#10 [ffff8881376ffe90] ksys_write at ffffffff95e65d26
#11 [ffff8881376fff28] do_syscall_64 at ffffffff956088ba
#12 [ffff8881376fff50] entry_SYSCALL_64_after_hwframe at ffffffff9740008c
RIP: 00007f126f6956ed RSP: 00007ffc2a320278 RFLAGS: 00000217
RAX: ffffffffffffffda RBX: 0000000020000044 RCX: 00007f126f6956ed
RDX: 0000000000000004 RSI: 00000000004007b8 RDI: 0000000000000003
RBP: 00007ffc2a3202a0 R8: 0000000000400720 R9: 0000000000400720
R10: 0000000000400720 R11: 0000000000000217 R12: 00000000004004b0
R13: 00007ffc2a320380 R14: 0000000000000000 R15: 0000000000000000
ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b
3) tcpdump captures show that DSS is exchanged even when MP_CAPABLE handshake
didn't complete.
$ tcpdump -tnnr bad.pcap
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S], seq 3208913911, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291694721,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [S.], seq 3208913911, ack 3208913912, win 65483, options [mss 65495,sackOK,TS val 3291706876 ecr 3291706876,nop,wscale 7,mptcp capable v1], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 1, win 512, options [nop,nop,TS val 3291706876 ecr 3291706876], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [F.], seq 1, ack 1, win 512, options [nop,nop,TS val 3291707876 ecr 3291706876,mptcp dss fin seq 0 subseq 0 len 1,nop,nop], length 0
IP 127.0.0.1.20000 > 127.0.0.1.20000: Flags [.], ack 2, win 512, options [nop,nop,TS val 3291707876 ecr 3291707876], length 0
force a fallback to TCP in these cases, and adjust the main socket
state to avoid hanging in mptcp_sendmsg().
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/35
Reported-by: Christoph Paasch <cpaasch@apple.com>
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Reviewed-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2020-06-29 20:26:21 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
/* as recvmsg() does not acquire the subflow socket for ssk selection
|
|
|
|
* a fin packet carrying a DSS can be unnoticed if we don't trigger
|
|
|
|
* the data available machinery here.
|
|
|
|
*/
|
2020-06-29 20:26:20 +00:00
|
|
|
if (mptcp_subflow_data_available(sk))
|
2020-02-26 09:14:51 +00:00
|
|
|
mptcp_data_ready(parent, sk);
|
2021-06-10 22:59:44 +00:00
|
|
|
else if (unlikely(sk->sk_err))
|
|
|
|
subflow_error_report(sk);
|
2020-01-22 00:56:24 +00:00
|
|
|
|
2021-02-12 23:59:56 +00:00
|
|
|
subflow_sched_work_if_closed(mptcp_sk(parent), sk);
|
|
|
|
|
2023-06-20 16:24:21 +00:00
|
|
|
/* when the fallback subflow closes the rx side, trigger a 'dummy'
|
|
|
|
* ingress data fin, so that the msk state will follow along
|
|
|
|
*/
|
|
|
|
if (__mptcp_check_fallback(msk) && subflow_is_done(sk) && msk->first == sk &&
|
|
|
|
mptcp_update_rcv_data_fin(msk, READ_ONCE(msk->ack_seq), true))
|
|
|
|
mptcp_schedule_work(parent);
|
2020-01-22 00:56:24 +00:00
|
|
|
}
|
|
|
|
|
2023-04-17 14:00:40 +00:00
|
|
|
void mptcp_subflow_queue_clean(struct sock *listener_sk, struct sock *listener_ssk)
|
|
|
|
{
|
|
|
|
struct request_sock_queue *queue = &inet_csk(listener_ssk)->icsk_accept_queue;
|
mptcp: fix disconnect vs accept race
Despite commit 0ad529d9fd2b ("mptcp: fix possible divide by zero in
recvmsg()"), the mptcp protocol is still prone to a race between
disconnect() (or shutdown) and accept.
The root cause is that the mentioned commit checks the msk-level
flag, but mptcp_stream_accept() does acquire the msk-level lock,
as it can rely directly on the first subflow lock.
As reported by Christoph than can lead to a race where an msk
socket is accepted after that mptcp_subflow_queue_clean() releases
the listener socket lock and just before it takes destructive
actions leading to the following splat:
BUG: kernel NULL pointer dereference, address: 0000000000000012
PGD 5a4ca067 P4D 5a4ca067 PUD 37d4c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 2 PID: 10955 Comm: syz-executor.5 Not tainted 6.5.0-rc1-gdc7b257ee5dd #37
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014
RIP: 0010:mptcp_stream_accept+0x1ee/0x2f0 include/net/inet_sock.h:330
Code: 0a 09 00 48 8b 1b 4c 39 e3 74 07 e8 bc 7c 7f fe eb a1 e8 b5 7c 7f fe 4c 8b 6c 24 08 eb 05 e8 a9 7c 7f fe 49 8b 85 d8 09 00 00 <0f> b6 40 12 88 44 24 07 0f b6 6c 24 07 bf 07 00 00 00 89 ee e8 89
RSP: 0018:ffffc90000d07dc0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888037e8d020 RCX: ffff88803b093300
RDX: 0000000000000000 RSI: ffffffff833822c5 RDI: ffffffff8333896a
RBP: 0000607f82031520 R08: ffff88803b093300 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000003e83 R12: ffff888037e8d020
R13: ffff888037e8c680 R14: ffff888009af7900 R15: ffff888009af6880
FS: 00007fc26d708640(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000012 CR3: 0000000066bc5001 CR4: 0000000000370ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
do_accept+0x1ae/0x260 net/socket.c:1872
__sys_accept4+0x9b/0x110 net/socket.c:1913
__do_sys_accept4 net/socket.c:1954 [inline]
__se_sys_accept4 net/socket.c:1951 [inline]
__x64_sys_accept4+0x20/0x30 net/socket.c:1951
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x47/0xa0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Address the issue by temporary removing the pending request socket
from the accept queue, so that racing accept() can't touch them.
After depleting the msk - the ssk still exists, as plain TCP sockets,
re-insert them into the accept queue, so that later inet_csk_listen_stop()
will complete the tcp socket disposal.
Fixes: 2a6a870e44dd ("mptcp: stops worker on unaccepted sockets at listener close")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/423
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230803-upstream-net-20230803-misc-fixes-6-5-v1-4-6671b1ab11cc@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-03 16:27:30 +00:00
|
|
|
struct request_sock *req, *head, *tail;
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
struct sock *sk, *ssk;
|
2023-04-17 14:00:40 +00:00
|
|
|
|
mptcp: fix disconnect vs accept race
Despite commit 0ad529d9fd2b ("mptcp: fix possible divide by zero in
recvmsg()"), the mptcp protocol is still prone to a race between
disconnect() (or shutdown) and accept.
The root cause is that the mentioned commit checks the msk-level
flag, but mptcp_stream_accept() does acquire the msk-level lock,
as it can rely directly on the first subflow lock.
As reported by Christoph than can lead to a race where an msk
socket is accepted after that mptcp_subflow_queue_clean() releases
the listener socket lock and just before it takes destructive
actions leading to the following splat:
BUG: kernel NULL pointer dereference, address: 0000000000000012
PGD 5a4ca067 P4D 5a4ca067 PUD 37d4c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 2 PID: 10955 Comm: syz-executor.5 Not tainted 6.5.0-rc1-gdc7b257ee5dd #37
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014
RIP: 0010:mptcp_stream_accept+0x1ee/0x2f0 include/net/inet_sock.h:330
Code: 0a 09 00 48 8b 1b 4c 39 e3 74 07 e8 bc 7c 7f fe eb a1 e8 b5 7c 7f fe 4c 8b 6c 24 08 eb 05 e8 a9 7c 7f fe 49 8b 85 d8 09 00 00 <0f> b6 40 12 88 44 24 07 0f b6 6c 24 07 bf 07 00 00 00 89 ee e8 89
RSP: 0018:ffffc90000d07dc0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888037e8d020 RCX: ffff88803b093300
RDX: 0000000000000000 RSI: ffffffff833822c5 RDI: ffffffff8333896a
RBP: 0000607f82031520 R08: ffff88803b093300 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000003e83 R12: ffff888037e8d020
R13: ffff888037e8c680 R14: ffff888009af7900 R15: ffff888009af6880
FS: 00007fc26d708640(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000012 CR3: 0000000066bc5001 CR4: 0000000000370ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
do_accept+0x1ae/0x260 net/socket.c:1872
__sys_accept4+0x9b/0x110 net/socket.c:1913
__do_sys_accept4 net/socket.c:1954 [inline]
__se_sys_accept4 net/socket.c:1951 [inline]
__x64_sys_accept4+0x20/0x30 net/socket.c:1951
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x47/0xa0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Address the issue by temporary removing the pending request socket
from the accept queue, so that racing accept() can't touch them.
After depleting the msk - the ssk still exists, as plain TCP sockets,
re-insert them into the accept queue, so that later inet_csk_listen_stop()
will complete the tcp socket disposal.
Fixes: 2a6a870e44dd ("mptcp: stops worker on unaccepted sockets at listener close")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/423
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230803-upstream-net-20230803-misc-fixes-6-5-v1-4-6671b1ab11cc@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-03 16:27:30 +00:00
|
|
|
/* Due to lock dependencies no relevant lock can be acquired under rskq_lock.
|
|
|
|
* Splice the req list, so that accept() can not reach the pending ssk after
|
|
|
|
* the listener socket is released below.
|
|
|
|
*/
|
2023-04-17 14:00:40 +00:00
|
|
|
spin_lock_bh(&queue->rskq_lock);
|
mptcp: fix disconnect vs accept race
Despite commit 0ad529d9fd2b ("mptcp: fix possible divide by zero in
recvmsg()"), the mptcp protocol is still prone to a race between
disconnect() (or shutdown) and accept.
The root cause is that the mentioned commit checks the msk-level
flag, but mptcp_stream_accept() does acquire the msk-level lock,
as it can rely directly on the first subflow lock.
As reported by Christoph than can lead to a race where an msk
socket is accepted after that mptcp_subflow_queue_clean() releases
the listener socket lock and just before it takes destructive
actions leading to the following splat:
BUG: kernel NULL pointer dereference, address: 0000000000000012
PGD 5a4ca067 P4D 5a4ca067 PUD 37d4c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 2 PID: 10955 Comm: syz-executor.5 Not tainted 6.5.0-rc1-gdc7b257ee5dd #37
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014
RIP: 0010:mptcp_stream_accept+0x1ee/0x2f0 include/net/inet_sock.h:330
Code: 0a 09 00 48 8b 1b 4c 39 e3 74 07 e8 bc 7c 7f fe eb a1 e8 b5 7c 7f fe 4c 8b 6c 24 08 eb 05 e8 a9 7c 7f fe 49 8b 85 d8 09 00 00 <0f> b6 40 12 88 44 24 07 0f b6 6c 24 07 bf 07 00 00 00 89 ee e8 89
RSP: 0018:ffffc90000d07dc0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888037e8d020 RCX: ffff88803b093300
RDX: 0000000000000000 RSI: ffffffff833822c5 RDI: ffffffff8333896a
RBP: 0000607f82031520 R08: ffff88803b093300 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000003e83 R12: ffff888037e8d020
R13: ffff888037e8c680 R14: ffff888009af7900 R15: ffff888009af6880
FS: 00007fc26d708640(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000012 CR3: 0000000066bc5001 CR4: 0000000000370ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
do_accept+0x1ae/0x260 net/socket.c:1872
__sys_accept4+0x9b/0x110 net/socket.c:1913
__do_sys_accept4 net/socket.c:1954 [inline]
__se_sys_accept4 net/socket.c:1951 [inline]
__x64_sys_accept4+0x20/0x30 net/socket.c:1951
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x47/0xa0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Address the issue by temporary removing the pending request socket
from the accept queue, so that racing accept() can't touch them.
After depleting the msk - the ssk still exists, as plain TCP sockets,
re-insert them into the accept queue, so that later inet_csk_listen_stop()
will complete the tcp socket disposal.
Fixes: 2a6a870e44dd ("mptcp: stops worker on unaccepted sockets at listener close")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/423
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230803-upstream-net-20230803-misc-fixes-6-5-v1-4-6671b1ab11cc@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-03 16:27:30 +00:00
|
|
|
head = queue->rskq_accept_head;
|
|
|
|
tail = queue->rskq_accept_tail;
|
|
|
|
queue->rskq_accept_head = NULL;
|
|
|
|
queue->rskq_accept_tail = NULL;
|
|
|
|
spin_unlock_bh(&queue->rskq_lock);
|
|
|
|
|
|
|
|
if (!head)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* can't acquire the msk socket lock under the subflow one,
|
|
|
|
* or will cause ABBA deadlock
|
|
|
|
*/
|
|
|
|
release_sock(listener_ssk);
|
2023-04-17 14:00:40 +00:00
|
|
|
|
mptcp: fix disconnect vs accept race
Despite commit 0ad529d9fd2b ("mptcp: fix possible divide by zero in
recvmsg()"), the mptcp protocol is still prone to a race between
disconnect() (or shutdown) and accept.
The root cause is that the mentioned commit checks the msk-level
flag, but mptcp_stream_accept() does acquire the msk-level lock,
as it can rely directly on the first subflow lock.
As reported by Christoph than can lead to a race where an msk
socket is accepted after that mptcp_subflow_queue_clean() releases
the listener socket lock and just before it takes destructive
actions leading to the following splat:
BUG: kernel NULL pointer dereference, address: 0000000000000012
PGD 5a4ca067 P4D 5a4ca067 PUD 37d4c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 2 PID: 10955 Comm: syz-executor.5 Not tainted 6.5.0-rc1-gdc7b257ee5dd #37
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014
RIP: 0010:mptcp_stream_accept+0x1ee/0x2f0 include/net/inet_sock.h:330
Code: 0a 09 00 48 8b 1b 4c 39 e3 74 07 e8 bc 7c 7f fe eb a1 e8 b5 7c 7f fe 4c 8b 6c 24 08 eb 05 e8 a9 7c 7f fe 49 8b 85 d8 09 00 00 <0f> b6 40 12 88 44 24 07 0f b6 6c 24 07 bf 07 00 00 00 89 ee e8 89
RSP: 0018:ffffc90000d07dc0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888037e8d020 RCX: ffff88803b093300
RDX: 0000000000000000 RSI: ffffffff833822c5 RDI: ffffffff8333896a
RBP: 0000607f82031520 R08: ffff88803b093300 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000003e83 R12: ffff888037e8d020
R13: ffff888037e8c680 R14: ffff888009af7900 R15: ffff888009af6880
FS: 00007fc26d708640(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000012 CR3: 0000000066bc5001 CR4: 0000000000370ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
do_accept+0x1ae/0x260 net/socket.c:1872
__sys_accept4+0x9b/0x110 net/socket.c:1913
__do_sys_accept4 net/socket.c:1954 [inline]
__se_sys_accept4 net/socket.c:1951 [inline]
__x64_sys_accept4+0x20/0x30 net/socket.c:1951
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x47/0xa0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Address the issue by temporary removing the pending request socket
from the accept queue, so that racing accept() can't touch them.
After depleting the msk - the ssk still exists, as plain TCP sockets,
re-insert them into the accept queue, so that later inet_csk_listen_stop()
will complete the tcp socket disposal.
Fixes: 2a6a870e44dd ("mptcp: stops worker on unaccepted sockets at listener close")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/423
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230803-upstream-net-20230803-misc-fixes-6-5-v1-4-6671b1ab11cc@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-03 16:27:30 +00:00
|
|
|
for (req = head; req; req = req->dl_next) {
|
|
|
|
ssk = req->sk;
|
2023-04-17 14:00:40 +00:00
|
|
|
if (!sk_is_mptcp(ssk))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
if (!subflow || !subflow->conn)
|
|
|
|
continue;
|
|
|
|
|
2023-04-17 14:00:41 +00:00
|
|
|
sk = subflow->conn;
|
|
|
|
sock_hold(sk);
|
2023-04-17 14:00:40 +00:00
|
|
|
|
|
|
|
lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
|
2023-04-17 14:00:41 +00:00
|
|
|
__mptcp_unaccepted_force_close(sk);
|
2023-04-17 14:00:40 +00:00
|
|
|
release_sock(sk);
|
|
|
|
|
|
|
|
/* lockdep will report a false positive ABBA deadlock
|
|
|
|
* between cancel_work_sync and the listener socket.
|
|
|
|
* The involved locks belong to different sockets WRT
|
|
|
|
* the existing AB chain.
|
|
|
|
* Using a per socket key is problematic as key
|
|
|
|
* deregistration requires process context and must be
|
|
|
|
* performed at socket disposal time, in atomic
|
|
|
|
* context.
|
|
|
|
* Just tell lockdep to consider the listener socket
|
|
|
|
* released here.
|
|
|
|
*/
|
|
|
|
mutex_release(&listener_sk->sk_lock.dep_map, _RET_IP_);
|
|
|
|
mptcp_cancel_work(sk);
|
|
|
|
mutex_acquire(&listener_sk->sk_lock.dep_map, 0, 0, _RET_IP_);
|
|
|
|
|
|
|
|
sock_put(sk);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* we are still under the listener msk socket lock */
|
|
|
|
lock_sock_nested(listener_ssk, SINGLE_DEPTH_NESTING);
|
mptcp: fix disconnect vs accept race
Despite commit 0ad529d9fd2b ("mptcp: fix possible divide by zero in
recvmsg()"), the mptcp protocol is still prone to a race between
disconnect() (or shutdown) and accept.
The root cause is that the mentioned commit checks the msk-level
flag, but mptcp_stream_accept() does acquire the msk-level lock,
as it can rely directly on the first subflow lock.
As reported by Christoph than can lead to a race where an msk
socket is accepted after that mptcp_subflow_queue_clean() releases
the listener socket lock and just before it takes destructive
actions leading to the following splat:
BUG: kernel NULL pointer dereference, address: 0000000000000012
PGD 5a4ca067 P4D 5a4ca067 PUD 37d4c067 PMD 0
Oops: 0000 [#1] PREEMPT SMP
CPU: 2 PID: 10955 Comm: syz-executor.5 Not tainted 6.5.0-rc1-gdc7b257ee5dd #37
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.11.0-2.el7 04/01/2014
RIP: 0010:mptcp_stream_accept+0x1ee/0x2f0 include/net/inet_sock.h:330
Code: 0a 09 00 48 8b 1b 4c 39 e3 74 07 e8 bc 7c 7f fe eb a1 e8 b5 7c 7f fe 4c 8b 6c 24 08 eb 05 e8 a9 7c 7f fe 49 8b 85 d8 09 00 00 <0f> b6 40 12 88 44 24 07 0f b6 6c 24 07 bf 07 00 00 00 89 ee e8 89
RSP: 0018:ffffc90000d07dc0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffff888037e8d020 RCX: ffff88803b093300
RDX: 0000000000000000 RSI: ffffffff833822c5 RDI: ffffffff8333896a
RBP: 0000607f82031520 R08: ffff88803b093300 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000003e83 R12: ffff888037e8d020
R13: ffff888037e8c680 R14: ffff888009af7900 R15: ffff888009af6880
FS: 00007fc26d708640(0000) GS:ffff88807dd00000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000012 CR3: 0000000066bc5001 CR4: 0000000000370ee0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
do_accept+0x1ae/0x260 net/socket.c:1872
__sys_accept4+0x9b/0x110 net/socket.c:1913
__do_sys_accept4 net/socket.c:1954 [inline]
__se_sys_accept4 net/socket.c:1951 [inline]
__x64_sys_accept4+0x20/0x30 net/socket.c:1951
do_syscall_x64 arch/x86/entry/common.c:50 [inline]
do_syscall_64+0x47/0xa0 arch/x86/entry/common.c:80
entry_SYSCALL_64_after_hwframe+0x6e/0xd8
Address the issue by temporary removing the pending request socket
from the accept queue, so that racing accept() can't touch them.
After depleting the msk - the ssk still exists, as plain TCP sockets,
re-insert them into the accept queue, so that later inet_csk_listen_stop()
will complete the tcp socket disposal.
Fixes: 2a6a870e44dd ("mptcp: stops worker on unaccepted sockets at listener close")
Cc: stable@vger.kernel.org
Reported-by: Christoph Paasch <cpaasch@apple.com>
Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/423
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Signed-off-by: Matthieu Baerts <matthieu.baerts@tessares.net>
Link: https://lore.kernel.org/r/20230803-upstream-net-20230803-misc-fixes-6-5-v1-4-6671b1ab11cc@tessares.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2023-08-03 16:27:30 +00:00
|
|
|
|
|
|
|
/* restore the listener queue, to let the TCP code clean it up */
|
|
|
|
spin_lock_bh(&queue->rskq_lock);
|
|
|
|
WARN_ON_ONCE(queue->rskq_accept_head);
|
|
|
|
queue->rskq_accept_head = head;
|
|
|
|
queue->rskq_accept_tail = tail;
|
|
|
|
spin_unlock_bh(&queue->rskq_lock);
|
2023-04-17 14:00:40 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
static int subflow_ulp_init(struct sock *sk)
|
|
|
|
{
|
2020-01-22 00:56:18 +00:00
|
|
|
struct inet_connection_sock *icsk = inet_csk(sk);
|
2020-01-22 00:56:17 +00:00
|
|
|
struct mptcp_subflow_context *ctx;
|
|
|
|
struct tcp_sock *tp = tcp_sk(sk);
|
|
|
|
int err = 0;
|
|
|
|
|
|
|
|
/* disallow attaching ULP to a socket unless it has been
|
|
|
|
* created with sock_create_kern()
|
|
|
|
*/
|
|
|
|
if (!sk->sk_kern_sock) {
|
|
|
|
err = -EOPNOTSUPP;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx = subflow_create_ctx(sk, GFP_KERNEL);
|
|
|
|
if (!ctx) {
|
|
|
|
err = -ENOMEM;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
pr_debug() have been added in various places in MPTCP code to help
developers to debug some situations. With the dynamic debug feature, it
is easy to enable all or some of them, and asks users to reproduce
issues with extra debug.
Many of these pr_debug() don't end with a new line, while no 'pr_cont()'
are used in MPTCP code. So the goal was not to display multiple debug
messages on one line: they were then not missing the '\n' on purpose.
Not having the new line at the end causes these messages to be printed
with a delay, when something else needs to be printed. This issue is not
visible when many messages need to be printed, but it is annoying and
confusing when only specific messages are expected, e.g.
# echo "func mptcp_pm_add_addr_echoed +fmp" \
> /sys/kernel/debug/dynamic_debug/control
# ./mptcp_join.sh "signal address"; \
echo "$(awk '{print $1}' /proc/uptime) - end"; \
sleep 5s; \
echo "$(awk '{print $1}' /proc/uptime) - restart"; \
./mptcp_join.sh "signal address"
013 signal address
(...)
10.75 - end
15.76 - restart
013 signal address
[ 10.367935] mptcp:mptcp_pm_add_addr_echoed: MPTCP: msk=(...)
(...)
=> a delay of 5 seconds: printed with a 10.36 ts, but after 'restart'
which was printed at the 15.76 ts.
The 'Fixes' tag here below points to the first pr_debug() used without
'\n' in net/mptcp. This patch could be split in many small ones, with
different Fixes tag, but it doesn't seem worth it, because it is easy to
re-generate this patch with this simple 'sed' command:
git grep -l pr_debug -- net/mptcp |
xargs sed -i "s/\(pr_debug(\".*[^n]\)\(\"[,)]\)/\1\\\n\2/g"
So in case of conflicts, simply drop the modifications, and launch this
command.
Fixes: f870fa0b5768 ("mptcp: Add MPTCP socket stubs")
Cc: stable@vger.kernel.org
Reviewed-by: Geliang Tang <geliang@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240826-net-mptcp-close-extra-sf-fin-v1-4-905199fe1172@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2024-08-26 17:11:21 +00:00
|
|
|
pr_debug("subflow=%p, family=%d\n", ctx, sk->sk_family);
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
tp->is_mptcp = 1;
|
2020-01-22 00:56:18 +00:00
|
|
|
ctx->icsk_af_ops = icsk->icsk_af_ops;
|
|
|
|
icsk->icsk_af_ops = subflow_default_af_ops(sk);
|
2020-01-22 00:56:24 +00:00
|
|
|
ctx->tcp_state_change = sk->sk_state_change;
|
2021-02-11 23:30:37 +00:00
|
|
|
ctx->tcp_error_report = sk->sk_error_report;
|
2022-02-16 02:11:30 +00:00
|
|
|
|
|
|
|
WARN_ON_ONCE(sk->sk_data_ready != sock_def_readable);
|
|
|
|
WARN_ON_ONCE(sk->sk_write_space != sk_stream_write_space);
|
|
|
|
|
2020-01-22 00:56:24 +00:00
|
|
|
sk->sk_data_ready = subflow_data_ready;
|
|
|
|
sk->sk_write_space = subflow_write_space;
|
|
|
|
sk->sk_state_change = subflow_state_change;
|
2021-02-11 23:30:37 +00:00
|
|
|
sk->sk_error_report = subflow_error_report;
|
2020-01-22 00:56:17 +00:00
|
|
|
out:
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2020-11-16 09:48:09 +00:00
|
|
|
static void subflow_ulp_release(struct sock *ssk)
|
2020-01-22 00:56:17 +00:00
|
|
|
{
|
2020-11-16 09:48:09 +00:00
|
|
|
struct mptcp_subflow_context *ctx = mptcp_subflow_ctx(ssk);
|
|
|
|
bool release = true;
|
|
|
|
struct sock *sk;
|
2020-01-22 00:56:17 +00:00
|
|
|
|
|
|
|
if (!ctx)
|
|
|
|
return;
|
|
|
|
|
2020-11-16 09:48:09 +00:00
|
|
|
sk = ctx->conn;
|
|
|
|
if (sk) {
|
|
|
|
/* if the msk has been orphaned, keep the ctx
|
2020-12-09 11:03:30 +00:00
|
|
|
* alive, will be freed by __mptcp_close_ssk(),
|
|
|
|
* when the subflow is still unaccepted
|
2020-11-16 09:48:09 +00:00
|
|
|
*/
|
2020-12-09 11:03:30 +00:00
|
|
|
release = ctx->disposable || list_empty(&ctx->node);
|
2023-03-09 14:49:59 +00:00
|
|
|
|
|
|
|
/* inet_child_forget() does not call sk_state_change(),
|
|
|
|
* explicitly trigger the socket close machinery
|
|
|
|
*/
|
|
|
|
if (!release && !test_and_set_bit(MPTCP_WORK_CLOSE_SUBFLOW,
|
|
|
|
&mptcp_sk(sk)->flags))
|
|
|
|
mptcp_schedule_work(sk);
|
2020-11-16 09:48:09 +00:00
|
|
|
sock_put(sk);
|
|
|
|
}
|
2020-01-22 00:56:20 +00:00
|
|
|
|
2021-01-20 14:39:14 +00:00
|
|
|
mptcp_subflow_ops_undo_override(ssk);
|
2020-11-16 09:48:09 +00:00
|
|
|
if (release)
|
|
|
|
kfree_rcu(ctx, rcu);
|
2020-01-22 00:56:17 +00:00
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
static void subflow_ulp_clone(const struct request_sock *req,
|
|
|
|
struct sock *newsk,
|
|
|
|
const gfp_t priority)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_request_sock *subflow_req = mptcp_subflow_rsk(req);
|
|
|
|
struct mptcp_subflow_context *old_ctx = mptcp_subflow_ctx(newsk);
|
|
|
|
struct mptcp_subflow_context *new_ctx;
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
if (!tcp_rsk(req)->is_mptcp ||
|
|
|
|
(!subflow_req->mp_capable && !subflow_req->mp_join)) {
|
2020-01-22 00:56:24 +00:00
|
|
|
subflow_ulp_fallback(newsk, old_ctx);
|
2020-01-22 00:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_ctx = subflow_create_ctx(newsk, priority);
|
2020-01-25 00:04:03 +00:00
|
|
|
if (!new_ctx) {
|
2020-01-22 00:56:24 +00:00
|
|
|
subflow_ulp_fallback(newsk, old_ctx);
|
2020-01-22 00:56:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
new_ctx->conn_finished = 1;
|
|
|
|
new_ctx->icsk_af_ops = old_ctx->icsk_af_ops;
|
2020-01-22 00:56:24 +00:00
|
|
|
new_ctx->tcp_state_change = old_ctx->tcp_state_change;
|
2021-02-11 23:30:37 +00:00
|
|
|
new_ctx->tcp_error_report = old_ctx->tcp_error_report;
|
2020-03-13 15:52:41 +00:00
|
|
|
new_ctx->rel_write_seq = 1;
|
|
|
|
|
2020-03-27 21:48:39 +00:00
|
|
|
if (subflow_req->mp_capable) {
|
|
|
|
/* see comments in subflow_syn_recv_sock(), MPTCP connection
|
|
|
|
* is fully established only after we receive the remote key
|
|
|
|
*/
|
|
|
|
new_ctx->mp_capable = 1;
|
|
|
|
new_ctx->local_key = subflow_req->local_key;
|
|
|
|
new_ctx->token = subflow_req->token;
|
|
|
|
new_ctx->ssn_offset = subflow_req->ssn_offset;
|
|
|
|
new_ctx->idsn = subflow_req->idsn;
|
2022-03-07 20:44:37 +00:00
|
|
|
|
|
|
|
/* this is the first subflow, id is always 0 */
|
2024-02-15 18:25:31 +00:00
|
|
|
subflow_set_local_id(new_ctx, 0);
|
2020-03-27 21:48:39 +00:00
|
|
|
} else if (subflow_req->mp_join) {
|
2020-03-27 21:48:40 +00:00
|
|
|
new_ctx->ssn_offset = subflow_req->ssn_offset;
|
2020-03-27 21:48:39 +00:00
|
|
|
new_ctx->mp_join = 1;
|
2024-10-21 15:14:04 +00:00
|
|
|
WRITE_ONCE(new_ctx->fully_established, true);
|
2022-11-25 22:29:49 +00:00
|
|
|
new_ctx->remote_key_valid = 1;
|
2020-03-27 21:48:39 +00:00
|
|
|
new_ctx->backup = subflow_req->backup;
|
2024-07-27 10:01:24 +00:00
|
|
|
new_ctx->request_bkup = subflow_req->request_bkup;
|
2024-02-15 18:25:32 +00:00
|
|
|
WRITE_ONCE(new_ctx->remote_id, subflow_req->remote_id);
|
2020-03-27 21:48:39 +00:00
|
|
|
new_ctx->token = subflow_req->token;
|
|
|
|
new_ctx->thmac = subflow_req->thmac;
|
2022-03-07 20:44:37 +00:00
|
|
|
|
|
|
|
/* the subflow req id is valid, fetched via subflow_check_req()
|
|
|
|
* and subflow_token_join_request()
|
|
|
|
*/
|
|
|
|
subflow_set_local_id(new_ctx, subflow_req->local_id);
|
2020-03-27 21:48:39 +00:00
|
|
|
}
|
2020-01-22 00:56:18 +00:00
|
|
|
}
|
|
|
|
|
2021-01-20 14:39:14 +00:00
|
|
|
static void tcp_release_cb_override(struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
2023-10-04 20:38:11 +00:00
|
|
|
long status;
|
2021-01-20 14:39:14 +00:00
|
|
|
|
2023-10-04 20:38:11 +00:00
|
|
|
/* process and clear all the pending actions, but leave the subflow into
|
|
|
|
* the napi queue. To respect locking, only the same CPU that originated
|
|
|
|
* the action can touch the list. mptcp_napi_poll will take care of it.
|
|
|
|
*/
|
|
|
|
status = set_mask_bits(&subflow->delegated_status, MPTCP_DELEGATE_ACTIONS_MASK, 0);
|
|
|
|
if (status)
|
|
|
|
mptcp_subflow_process_delegated(ssk, status);
|
2021-01-20 14:39:14 +00:00
|
|
|
|
|
|
|
tcp_release_cb(ssk);
|
|
|
|
}
|
|
|
|
|
2023-12-26 12:10:18 +00:00
|
|
|
static int tcp_abort_override(struct sock *ssk, int err)
|
|
|
|
{
|
|
|
|
/* closing a listener subflow requires a great deal of care.
|
|
|
|
* keep it simple and just prevent such operation
|
|
|
|
*/
|
|
|
|
if (inet_sk_state_load(ssk) == TCP_LISTEN)
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
return tcp_abort(ssk, err);
|
|
|
|
}
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
static struct tcp_ulp_ops subflow_ulp_ops __read_mostly = {
|
|
|
|
.name = "mptcp",
|
|
|
|
.owner = THIS_MODULE,
|
|
|
|
.init = subflow_ulp_init,
|
|
|
|
.release = subflow_ulp_release,
|
2020-01-22 00:56:18 +00:00
|
|
|
.clone = subflow_ulp_clone,
|
2020-01-22 00:56:17 +00:00
|
|
|
};
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
static int subflow_ops_init(struct request_sock_ops *subflow_ops)
|
|
|
|
{
|
|
|
|
subflow_ops->obj_size = sizeof(struct mptcp_subflow_request_sock);
|
|
|
|
|
|
|
|
subflow_ops->slab = kmem_cache_create(subflow_ops->slab_name,
|
|
|
|
subflow_ops->obj_size, 0,
|
|
|
|
SLAB_ACCOUNT |
|
|
|
|
SLAB_TYPESAFE_BY_RCU,
|
|
|
|
NULL);
|
|
|
|
if (!subflow_ops->slab)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-06-26 17:29:59 +00:00
|
|
|
void __init mptcp_subflow_init(void)
|
2020-01-22 00:56:17 +00:00
|
|
|
{
|
2022-12-10 00:28:09 +00:00
|
|
|
mptcp_subflow_v4_request_sock_ops = tcp_request_sock_ops;
|
|
|
|
mptcp_subflow_v4_request_sock_ops.slab_name = "request_sock_subflow_v4";
|
2022-12-10 00:28:10 +00:00
|
|
|
mptcp_subflow_v4_request_sock_ops.destructor = subflow_v4_req_destructor;
|
|
|
|
|
2022-12-10 00:28:09 +00:00
|
|
|
if (subflow_ops_init(&mptcp_subflow_v4_request_sock_ops) != 0)
|
|
|
|
panic("MPTCP: failed to init subflow v4 request sock ops\n");
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
subflow_request_sock_ipv4_ops = tcp_request_sock_ipv4_ops;
|
2020-11-30 15:36:30 +00:00
|
|
|
subflow_request_sock_ipv4_ops.route_req = subflow_v4_route_req;
|
2022-11-25 22:29:51 +00:00
|
|
|
subflow_request_sock_ipv4_ops.send_synack = subflow_v4_send_synack;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
subflow_specific = ipv4_specific;
|
|
|
|
subflow_specific.conn_request = subflow_v4_conn_request;
|
|
|
|
subflow_specific.syn_recv_sock = subflow_syn_recv_sock;
|
|
|
|
subflow_specific.sk_rx_dst_set = subflow_finish_connect;
|
2022-03-07 20:44:37 +00:00
|
|
|
subflow_specific.rebuild_header = subflow_rebuild_header;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
2021-01-20 14:39:14 +00:00
|
|
|
tcp_prot_override = tcp_prot;
|
|
|
|
tcp_prot_override.release_cb = tcp_release_cb_override;
|
2023-12-26 12:10:18 +00:00
|
|
|
tcp_prot_override.diag_destroy = tcp_abort_override;
|
2021-01-20 14:39:14 +00:00
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2022-12-10 00:28:09 +00:00
|
|
|
/* In struct mptcp_subflow_request_sock, we assume the TCP request sock
|
|
|
|
* structures for v4 and v6 have the same size. It should not changed in
|
|
|
|
* the future but better to make sure to be warned if it is no longer
|
|
|
|
* the case.
|
|
|
|
*/
|
|
|
|
BUILD_BUG_ON(sizeof(struct tcp_request_sock) != sizeof(struct tcp6_request_sock));
|
|
|
|
|
|
|
|
mptcp_subflow_v6_request_sock_ops = tcp6_request_sock_ops;
|
|
|
|
mptcp_subflow_v6_request_sock_ops.slab_name = "request_sock_subflow_v6";
|
2022-12-10 00:28:10 +00:00
|
|
|
mptcp_subflow_v6_request_sock_ops.destructor = subflow_v6_req_destructor;
|
|
|
|
|
2022-12-10 00:28:09 +00:00
|
|
|
if (subflow_ops_init(&mptcp_subflow_v6_request_sock_ops) != 0)
|
|
|
|
panic("MPTCP: failed to init subflow v6 request sock ops\n");
|
|
|
|
|
2020-01-22 00:56:18 +00:00
|
|
|
subflow_request_sock_ipv6_ops = tcp_request_sock_ipv6_ops;
|
2020-11-30 15:36:30 +00:00
|
|
|
subflow_request_sock_ipv6_ops.route_req = subflow_v6_route_req;
|
2022-11-25 22:29:51 +00:00
|
|
|
subflow_request_sock_ipv6_ops.send_synack = subflow_v6_send_synack;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
subflow_v6_specific = ipv6_specific;
|
|
|
|
subflow_v6_specific.conn_request = subflow_v6_conn_request;
|
|
|
|
subflow_v6_specific.syn_recv_sock = subflow_syn_recv_sock;
|
|
|
|
subflow_v6_specific.sk_rx_dst_set = subflow_finish_connect;
|
2022-03-07 20:44:37 +00:00
|
|
|
subflow_v6_specific.rebuild_header = subflow_v6_rebuild_header;
|
2020-01-22 00:56:18 +00:00
|
|
|
|
|
|
|
subflow_v6m_specific = subflow_v6_specific;
|
|
|
|
subflow_v6m_specific.queue_xmit = ipv4_specific.queue_xmit;
|
|
|
|
subflow_v6m_specific.send_check = ipv4_specific.send_check;
|
|
|
|
subflow_v6m_specific.net_header_len = ipv4_specific.net_header_len;
|
|
|
|
subflow_v6m_specific.mtu_reduced = ipv4_specific.mtu_reduced;
|
2022-03-07 20:44:37 +00:00
|
|
|
subflow_v6m_specific.rebuild_header = subflow_rebuild_header;
|
2021-01-20 14:39:14 +00:00
|
|
|
|
|
|
|
tcpv6_prot_override = tcpv6_prot;
|
|
|
|
tcpv6_prot_override.release_cb = tcp_release_cb_override;
|
2023-12-26 12:10:18 +00:00
|
|
|
tcpv6_prot_override.diag_destroy = tcp_abort_override;
|
2020-01-22 00:56:18 +00:00
|
|
|
#endif
|
|
|
|
|
2020-03-27 21:48:49 +00:00
|
|
|
mptcp_diag_subflow_init(&subflow_ulp_ops);
|
|
|
|
|
2020-01-22 00:56:17 +00:00
|
|
|
if (tcp_register_ulp(&subflow_ulp_ops) != 0)
|
|
|
|
panic("MPTCP: failed to register subflows to ULP\n");
|
|
|
|
}
|