Skip to content

Commit 56f51df

Browse files
committed
Merge branch 'mptcp-prevent-mpc-handshake-on-port-based-signal-endpoints'
Matthieu Baerts says: ==================== mptcp: prevent MPC handshake on port-based signal endpoints MPTCP connection requests toward a listening socket created by the in-kernel PM for a port based signal endpoint will never be accepted, they need to be explicitly rejected. - Patch 1: Explicitly reject such requests. A fix for >= v5.12. - Patch 2: Cover this case in the MPTCP selftests to avoid regressions. Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org> v1: https://lore.kernel.org/20240908180620.822579-1-xiyou.wangcong@gmail.com Link: https://lore.kernel.org/a5289a0d-2557-40b8-9575-6f1a0bbf06e4@redhat.com ==================== Link: https://patch.msgid.link/20241014-net-mptcp-mpc-port-endp-v2-0-7faea8e6b6ae@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 82ac39e + 5afca7e commit 56f51df

File tree

6 files changed

+100
-30
lines changed

6 files changed

+100
-30
lines changed

net/mptcp/mib.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ static const struct snmp_mib mptcp_snmp_list[] = {
1717
SNMP_MIB_ITEM("MPCapableFallbackSYNACK", MPTCP_MIB_MPCAPABLEACTIVEFALLBACK),
1818
SNMP_MIB_ITEM("MPCapableSYNTXDrop", MPTCP_MIB_MPCAPABLEACTIVEDROP),
1919
SNMP_MIB_ITEM("MPCapableSYNTXDisabled", MPTCP_MIB_MPCAPABLEACTIVEDISABLED),
20+
SNMP_MIB_ITEM("MPCapableEndpAttempt", MPTCP_MIB_MPCAPABLEENDPATTEMPT),
2021
SNMP_MIB_ITEM("MPFallbackTokenInit", MPTCP_MIB_TOKENFALLBACKINIT),
2122
SNMP_MIB_ITEM("MPTCPRetrans", MPTCP_MIB_RETRANSSEGS),
2223
SNMP_MIB_ITEM("MPJoinNoTokenFound", MPTCP_MIB_JOINNOTOKEN),

net/mptcp/mib.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ enum linux_mptcp_mib_field {
1212
MPTCP_MIB_MPCAPABLEACTIVEFALLBACK, /* Client-side fallback during 3-way handshake */
1313
MPTCP_MIB_MPCAPABLEACTIVEDROP, /* Client-side fallback due to a MPC drop */
1414
MPTCP_MIB_MPCAPABLEACTIVEDISABLED, /* Client-side disabled due to past issues */
15+
MPTCP_MIB_MPCAPABLEENDPATTEMPT, /* Prohibited MPC to port-based endp */
1516
MPTCP_MIB_TOKENFALLBACKINIT, /* Could not init/allocate token */
1617
MPTCP_MIB_RETRANSSEGS, /* Segments retransmitted at the MPTCP-level */
1718
MPTCP_MIB_JOINNOTOKEN, /* Received MP_JOIN but the token was not found */

net/mptcp/pm_netlink.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,7 @@ static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
11211121
*/
11221122
inet_sk_state_store(newsk, TCP_LISTEN);
11231123
lock_sock(ssk);
1124+
WRITE_ONCE(mptcp_subflow_ctx(ssk)->pm_listener, true);
11241125
err = __inet_listen_sk(ssk, backlog);
11251126
if (!err)
11261127
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CREATED);

net/mptcp/protocol.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,7 @@ struct mptcp_subflow_context {
535535
__unused : 8;
536536
bool data_avail;
537537
bool scheduled;
538+
bool pm_listener; /* a listener managed by the kernel PM? */
538539
u32 remote_nonce;
539540
u64 thmac;
540541
u32 local_nonce;

net/mptcp/subflow.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,13 @@ static void subflow_add_reset_reason(struct sk_buff *skb, u8 reason)
132132
}
133133
}
134134

135+
static int subflow_reset_req_endp(struct request_sock *req, struct sk_buff *skb)
136+
{
137+
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEENDPATTEMPT);
138+
subflow_add_reset_reason(skb, MPTCP_RST_EPROHIBIT);
139+
return -EPERM;
140+
}
141+
135142
/* Init mptcp request socket.
136143
*
137144
* Returns an error code if a JOIN has failed and a TCP reset
@@ -165,13 +172,17 @@ static int subflow_check_req(struct request_sock *req,
165172
if (opt_mp_capable) {
166173
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_MPCAPABLEPASSIVE);
167174

175+
if (unlikely(listener->pm_listener))
176+
return subflow_reset_req_endp(req, skb);
168177
if (opt_mp_join)
169178
return 0;
170179
} else if (opt_mp_join) {
171180
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNRX);
172181

173182
if (mp_opt.backup)
174183
SUBFLOW_REQ_INC_STATS(req, MPTCP_MIB_JOINSYNBACKUPRX);
184+
} else if (unlikely(listener->pm_listener)) {
185+
return subflow_reset_req_endp(req, skb);
175186
}
176187

177188
if (opt_mp_capable && listener->request_mptcp) {

tools/testing/selftests/net/mptcp/mptcp_join.sh

Lines changed: 85 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ tmpfile=""
2323
cout=""
2424
err=""
2525
capout=""
26+
cappid=""
2627
ns1=""
2728
ns2=""
2829
iptables="iptables"
@@ -887,40 +888,62 @@ check_cestab()
887888
fi
888889
}
889890

890-
do_transfer()
891+
cond_start_capture()
891892
{
892-
local listener_ns="$1"
893-
local connector_ns="$2"
894-
local cl_proto="$3"
895-
local srv_proto="$4"
896-
local connect_addr="$5"
897-
898-
local port=$((10000 + MPTCP_LIB_TEST_COUNTER - 1))
899-
local cappid
900-
local FAILING_LINKS=${FAILING_LINKS:-""}
901-
local fastclose=${fastclose:-""}
902-
local speed=${speed:-"fast"}
893+
local ns="$1"
903894

904-
:> "$cout"
905-
:> "$sout"
906895
:> "$capout"
907896

908897
if $capture; then
909-
local capuser
910-
if [ -z $SUDO_USER ] ; then
898+
local capuser capfile
899+
if [ -z $SUDO_USER ]; then
911900
capuser=""
912901
else
913902
capuser="-Z $SUDO_USER"
914903
fi
915904

916-
capfile=$(printf "mp_join-%02u-%s.pcap" "$MPTCP_LIB_TEST_COUNTER" "${listener_ns}")
905+
capfile=$(printf "mp_join-%02u-%s.pcap" "$MPTCP_LIB_TEST_COUNTER" "$ns")
917906

918907
echo "Capturing traffic for test $MPTCP_LIB_TEST_COUNTER into $capfile"
919-
ip netns exec ${listener_ns} tcpdump -i any -s 65535 -B 32768 $capuser -w $capfile > "$capout" 2>&1 &
908+
ip netns exec "$ns" tcpdump -i any -s 65535 -B 32768 $capuser -w "$capfile" > "$capout" 2>&1 &
920909
cappid=$!
921910

922911
sleep 1
923912
fi
913+
}
914+
915+
cond_stop_capture()
916+
{
917+
if $capture; then
918+
sleep 1
919+
kill $cappid
920+
cat "$capout"
921+
fi
922+
}
923+
924+
get_port()
925+
{
926+
echo "$((10000 + MPTCP_LIB_TEST_COUNTER - 1))"
927+
}
928+
929+
do_transfer()
930+
{
931+
local listener_ns="$1"
932+
local connector_ns="$2"
933+
local cl_proto="$3"
934+
local srv_proto="$4"
935+
local connect_addr="$5"
936+
local port
937+
938+
local FAILING_LINKS=${FAILING_LINKS:-""}
939+
local fastclose=${fastclose:-""}
940+
local speed=${speed:-"fast"}
941+
port=$(get_port)
942+
943+
:> "$cout"
944+
:> "$sout"
945+
946+
cond_start_capture ${listener_ns}
924947

925948
NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
926949
nstat -n
@@ -1007,10 +1030,7 @@ do_transfer()
10071030
wait $spid
10081031
local rets=$?
10091032

1010-
if $capture; then
1011-
sleep 1
1012-
kill $cappid
1013-
fi
1033+
cond_stop_capture
10141034

10151035
NSTAT_HISTORY=/tmp/${listener_ns}.nstat ip netns exec ${listener_ns} \
10161036
nstat | grep Tcp > /tmp/${listener_ns}.out
@@ -1026,7 +1046,6 @@ do_transfer()
10261046
ip netns exec ${connector_ns} ss -Menita 1>&2 -o "dport = :$port"
10271047
cat /tmp/${connector_ns}.out
10281048

1029-
cat "$capout"
10301049
return 1
10311050
fi
10321051

@@ -1043,13 +1062,7 @@ do_transfer()
10431062
fi
10441063
rets=$?
10451064

1046-
if [ $retc -eq 0 ] && [ $rets -eq 0 ];then
1047-
cat "$capout"
1048-
return 0
1049-
fi
1050-
1051-
cat "$capout"
1052-
return 1
1065+
[ $retc -eq 0 ] && [ $rets -eq 0 ]
10531066
}
10541067

10551068
make_file()
@@ -2873,6 +2886,32 @@ verify_listener_events()
28732886
fail_test
28742887
}
28752888

2889+
chk_mpc_endp_attempt()
2890+
{
2891+
local retl=$1
2892+
local attempts=$2
2893+
2894+
print_check "Connect"
2895+
2896+
if [ ${retl} = 124 ]; then
2897+
fail_test "timeout on connect"
2898+
elif [ ${retl} = 0 ]; then
2899+
fail_test "unexpected successful connect"
2900+
else
2901+
print_ok
2902+
2903+
print_check "Attempts"
2904+
count=$(mptcp_lib_get_counter ${ns1} "MPTcpExtMPCapableEndpAttempt")
2905+
if [ -z "$count" ]; then
2906+
print_skip
2907+
elif [ "$count" != "$attempts" ]; then
2908+
fail_test "got ${count} MPC attempt[s] on port-based endpoint, expected ${attempts}"
2909+
else
2910+
print_ok
2911+
fi
2912+
fi
2913+
}
2914+
28762915
add_addr_ports_tests()
28772916
{
28782917
# signal address with port
@@ -2963,6 +3002,22 @@ add_addr_ports_tests()
29633002
chk_join_nr 2 2 2
29643003
chk_add_nr 2 2 2
29653004
fi
3005+
3006+
if reset "port-based signal endpoint must not accept mpc"; then
3007+
local port retl count
3008+
port=$(get_port)
3009+
3010+
cond_start_capture ${ns1}
3011+
pm_nl_add_endpoint ${ns1} 10.0.2.1 flags signal port ${port}
3012+
mptcp_lib_wait_local_port_listen ${ns1} ${port}
3013+
3014+
timeout 1 ip netns exec ${ns2} \
3015+
./mptcp_connect -t ${timeout_poll} -p $port -s MPTCP 10.0.2.1 >/dev/null 2>&1
3016+
retl=$?
3017+
cond_stop_capture
3018+
3019+
chk_mpc_endp_attempt ${retl} 1
3020+
fi
29663021
}
29673022

29683023
syncookies_tests()

0 commit comments

Comments
 (0)