2020-03-28 05:48:51 +08:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/* Multipath TCP
|
|
|
|
*
|
|
|
|
* Copyright (c) 2020, Red Hat, Inc.
|
|
|
|
*/
|
|
|
|
|
2020-04-03 17:14:08 +08:00
|
|
|
#define pr_fmt(fmt) "MPTCP: " fmt
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
#include <linux/inet.h>
|
|
|
|
#include <linux/kernel.h>
|
|
|
|
#include <net/tcp.h>
|
2023-08-11 23:57:24 +08:00
|
|
|
#include <net/inet_common.h>
|
2020-03-28 05:48:51 +08:00
|
|
|
#include <net/netns/generic.h>
|
|
|
|
#include <net/mptcp.h>
|
|
|
|
#include <net/genetlink.h>
|
|
|
|
#include <uapi/linux/mptcp.h>
|
|
|
|
|
|
|
|
#include "protocol.h"
|
2020-09-24 08:29:56 +08:00
|
|
|
#include "mib.h"
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
/* forward declaration */
|
|
|
|
static struct genl_family mptcp_genl_family;
|
|
|
|
|
|
|
|
static int pm_nl_pernet_id;
|
|
|
|
|
2020-09-24 08:30:00 +08:00
|
|
|
struct mptcp_pm_add_entry {
|
|
|
|
struct list_head list;
|
|
|
|
struct mptcp_addr_info addr;
|
2023-06-18 17:46:46 +08:00
|
|
|
u8 retrans_times;
|
2020-09-24 08:30:02 +08:00
|
|
|
struct timer_list add_timer;
|
|
|
|
struct mptcp_sock *sock;
|
2020-09-24 08:30:00 +08:00
|
|
|
};
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
struct pm_nl_pernet {
|
|
|
|
/* protects pernet updates */
|
|
|
|
spinlock_t lock;
|
|
|
|
struct list_head local_addr_list;
|
|
|
|
unsigned int addrs;
|
2021-08-14 06:15:45 +08:00
|
|
|
unsigned int stale_loss_cnt;
|
2020-03-28 05:48:51 +08:00
|
|
|
unsigned int add_addr_signal_max;
|
|
|
|
unsigned int add_addr_accept_max;
|
|
|
|
unsigned int local_addr_max;
|
|
|
|
unsigned int subflows_max;
|
|
|
|
unsigned int next_id;
|
2022-01-07 08:20:22 +08:00
|
|
|
DECLARE_BITMAP(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
2020-03-28 05:48:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
#define MPTCP_PM_ADDR_MAX 8
|
2020-09-24 08:30:02 +08:00
|
|
|
#define ADD_ADDR_RETRANS_MAX 3
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2022-04-09 03:45:57 +08:00
|
|
|
static struct pm_nl_pernet *pm_nl_get_pernet(const struct net *net)
|
|
|
|
{
|
|
|
|
return net_generic(net, pm_nl_pernet_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct pm_nl_pernet *
|
|
|
|
pm_nl_get_pernet_from_msk(const struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
return pm_nl_get_pernet(sock_net((struct sock *)msk));
|
|
|
|
}
|
|
|
|
|
2022-05-04 10:38:49 +08:00
|
|
|
bool mptcp_addresses_equal(const struct mptcp_addr_info *a,
|
|
|
|
const struct mptcp_addr_info *b, bool use_port)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
bool addr_equals = false;
|
|
|
|
|
2021-01-26 02:59:01 +08:00
|
|
|
if (a->family == b->family) {
|
|
|
|
if (a->family == AF_INET)
|
|
|
|
addr_equals = a->addr.s_addr == b->addr.s_addr;
|
2020-03-28 05:48:51 +08:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2021-01-26 02:59:01 +08:00
|
|
|
else
|
|
|
|
addr_equals = !ipv6_addr_cmp(&a->addr6, &b->addr6);
|
|
|
|
} else if (a->family == AF_INET) {
|
|
|
|
if (ipv6_addr_v4mapped(&b->addr6))
|
|
|
|
addr_equals = a->addr.s_addr == b->addr6.s6_addr32[3];
|
|
|
|
} else if (b->family == AF_INET) {
|
|
|
|
if (ipv6_addr_v4mapped(&a->addr6))
|
|
|
|
addr_equals = a->addr6.s6_addr32[3] == b->addr.s_addr;
|
2020-03-28 05:48:51 +08:00
|
|
|
#endif
|
2021-01-26 02:59:01 +08:00
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
if (!addr_equals)
|
|
|
|
return false;
|
|
|
|
if (!use_port)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
return a->port == b->port;
|
|
|
|
}
|
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
void mptcp_local_address(const struct sock_common *skc, struct mptcp_addr_info *addr)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
addr->family = skc->skc_family;
|
2021-02-02 07:09:15 +08:00
|
|
|
addr->port = htons(skc->skc_num);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (addr->family == AF_INET)
|
|
|
|
addr->addr.s_addr = skc->skc_rcv_saddr;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (addr->family == AF_INET6)
|
|
|
|
addr->addr6 = skc->skc_v6_rcv_saddr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void remote_address(const struct sock_common *skc,
|
|
|
|
struct mptcp_addr_info *addr)
|
|
|
|
{
|
|
|
|
addr->family = skc->skc_family;
|
|
|
|
addr->port = skc->skc_dport;
|
|
|
|
if (addr->family == AF_INET)
|
|
|
|
addr->addr.s_addr = skc->skc_daddr;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (addr->family == AF_INET6)
|
|
|
|
addr->addr6 = skc->skc_v6_daddr;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool lookup_subflow_by_saddr(const struct list_head *list,
|
2022-02-16 10:11:28 +08:00
|
|
|
const struct mptcp_addr_info *saddr)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
struct mptcp_addr_info cur;
|
|
|
|
struct sock_common *skc;
|
|
|
|
|
|
|
|
list_for_each_entry(subflow, list, node) {
|
|
|
|
skc = (struct sock_common *)mptcp_subflow_tcp_sock(subflow);
|
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
mptcp_local_address(skc, &cur);
|
2022-05-04 10:38:49 +08:00
|
|
|
if (mptcp_addresses_equal(&cur, saddr, saddr->port))
|
2020-03-28 05:48:51 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2021-03-27 02:26:32 +08:00
|
|
|
static bool lookup_subflow_by_daddr(const struct list_head *list,
|
2022-02-16 10:11:28 +08:00
|
|
|
const struct mptcp_addr_info *daddr)
|
2021-03-27 02:26:32 +08:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
struct mptcp_addr_info cur;
|
|
|
|
|
|
|
|
list_for_each_entry(subflow, list, node) {
|
2024-08-28 14:14:28 +08:00
|
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
|
|
|
|
|
|
|
if (!((1 << inet_sk_state_load(ssk)) &
|
|
|
|
(TCPF_ESTABLISHED | TCPF_SYN_SENT | TCPF_SYN_RECV)))
|
|
|
|
continue;
|
2021-03-27 02:26:32 +08:00
|
|
|
|
2024-08-28 14:14:28 +08:00
|
|
|
remote_address((struct sock_common *)ssk, &cur);
|
2022-05-04 10:38:49 +08:00
|
|
|
if (mptcp_addresses_equal(&cur, daddr, daddr->port))
|
2021-03-27 02:26:32 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
static bool
|
2020-03-28 05:48:51 +08:00
|
|
|
select_local_address(const struct pm_nl_pernet *pernet,
|
2024-08-20 03:45:32 +08:00
|
|
|
const struct mptcp_sock *msk,
|
|
|
|
struct mptcp_pm_addr_entry *new_entry)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2024-08-20 03:45:32 +08:00
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
bool found = false;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2021-02-05 07:23:30 +08:00
|
|
|
msk_owned_by_me(msk);
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
|
2021-04-07 08:15:57 +08:00
|
|
|
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW))
|
2020-03-28 05:48:51 +08:00
|
|
|
continue;
|
|
|
|
|
2022-01-07 08:20:22 +08:00
|
|
|
if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap))
|
|
|
|
continue;
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
*new_entry = *entry;
|
|
|
|
found = true;
|
2022-01-07 08:20:22 +08:00
|
|
|
break;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
2024-08-20 03:45:32 +08:00
|
|
|
|
|
|
|
return found;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
static bool
|
|
|
|
select_signal_address(struct pm_nl_pernet *pernet, const struct mptcp_sock *msk,
|
|
|
|
struct mptcp_pm_addr_entry *new_entry)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2024-08-20 03:45:32 +08:00
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
bool found = false;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
/* do not keep any additional per socket state, just signal
|
|
|
|
* the address list in order.
|
|
|
|
* Note: removal from the local address list during the msk life-cycle
|
|
|
|
* can lead to additional addresses not being announced.
|
|
|
|
*/
|
|
|
|
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
|
2022-01-07 08:20:22 +08:00
|
|
|
if (!test_bit(entry->addr.id, msk->pm.id_avail_bitmap))
|
|
|
|
continue;
|
|
|
|
|
2021-04-07 08:15:57 +08:00
|
|
|
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
|
2020-03-28 05:48:51 +08:00
|
|
|
continue;
|
2022-01-07 08:20:22 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
*new_entry = *entry;
|
|
|
|
found = true;
|
2022-01-07 08:20:22 +08:00
|
|
|
break;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
2024-08-20 03:45:32 +08:00
|
|
|
|
|
|
|
return found;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2022-02-16 10:11:28 +08:00
|
|
|
unsigned int mptcp_pm_get_add_addr_signal_max(const struct mptcp_sock *msk)
|
2021-02-02 07:09:07 +08:00
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
const struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
2021-02-02 07:09:07 +08:00
|
|
|
|
|
|
|
return READ_ONCE(pernet->add_addr_signal_max);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(mptcp_pm_get_add_addr_signal_max);
|
|
|
|
|
2022-02-16 10:11:28 +08:00
|
|
|
unsigned int mptcp_pm_get_add_addr_accept_max(const struct mptcp_sock *msk)
|
2021-02-02 07:09:07 +08:00
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
2021-02-02 07:09:07 +08:00
|
|
|
|
|
|
|
return READ_ONCE(pernet->add_addr_accept_max);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(mptcp_pm_get_add_addr_accept_max);
|
|
|
|
|
2022-02-16 10:11:28 +08:00
|
|
|
unsigned int mptcp_pm_get_subflows_max(const struct mptcp_sock *msk)
|
2021-02-02 07:09:07 +08:00
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
2021-02-02 07:09:07 +08:00
|
|
|
|
|
|
|
return READ_ONCE(pernet->subflows_max);
|
|
|
|
}
|
|
|
|
EXPORT_SYMBOL_GPL(mptcp_pm_get_subflows_max);
|
|
|
|
|
2022-02-16 10:11:28 +08:00
|
|
|
unsigned int mptcp_pm_get_local_addr_max(const struct mptcp_sock *msk)
|
2021-02-02 07:09:07 +08:00
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
2021-02-02 07:09:07 +08:00
|
|
|
|
|
|
|
return READ_ONCE(pernet->local_addr_max);
|
|
|
|
}
|
2021-02-13 08:52:02 +08:00
|
|
|
EXPORT_SYMBOL_GPL(mptcp_pm_get_local_addr_max);
|
2021-02-02 07:09:07 +08:00
|
|
|
|
2022-01-07 08:20:23 +08:00
|
|
|
bool mptcp_pm_nl_check_work_pending(struct mptcp_sock *msk)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
2022-01-07 08:20:22 +08:00
|
|
|
|
|
|
|
if (msk->pm.subflows == mptcp_pm_get_subflows_max(msk) ||
|
|
|
|
(find_next_and_bit(pernet->id_bitmap, msk->pm.id_avail_bitmap,
|
2022-01-07 08:20:23 +08:00
|
|
|
MPTCP_PM_MAX_ADDR_ID + 1, 0) == MPTCP_PM_MAX_ADDR_ID + 1)) {
|
2020-03-28 05:48:51 +08:00
|
|
|
WRITE_ONCE(msk->pm.work_pending, false);
|
2022-01-07 08:20:23 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2021-03-27 02:26:37 +08:00
|
|
|
struct mptcp_pm_add_entry *
|
2022-02-16 10:11:28 +08:00
|
|
|
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
|
|
|
|
const struct mptcp_addr_info *addr)
|
2020-09-24 08:29:54 +08:00
|
|
|
{
|
2020-09-24 08:30:00 +08:00
|
|
|
struct mptcp_pm_add_entry *entry;
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2021-02-05 07:23:30 +08:00
|
|
|
lockdep_assert_held(&msk->pm.lock);
|
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
2022-05-04 10:38:49 +08:00
|
|
|
if (mptcp_addresses_equal(&entry->addr, addr, true))
|
2020-09-24 08:30:02 +08:00
|
|
|
return entry;
|
2020-09-24 08:29:54 +08:00
|
|
|
}
|
|
|
|
|
2020-09-24 08:30:02 +08:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-02 07:09:15 +08:00
|
|
|
bool mptcp_pm_sport_in_anno_list(struct mptcp_sock *msk, const struct sock *sk)
|
|
|
|
{
|
|
|
|
struct mptcp_pm_add_entry *entry;
|
|
|
|
struct mptcp_addr_info saddr;
|
|
|
|
bool ret = false;
|
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
mptcp_local_address((struct sock_common *)sk, &saddr);
|
2021-02-02 07:09:15 +08:00
|
|
|
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
list_for_each_entry(entry, &msk->pm.anno_list, list) {
|
2022-05-04 10:38:49 +08:00
|
|
|
if (mptcp_addresses_equal(&entry->addr, &saddr, true)) {
|
2021-02-02 07:09:15 +08:00
|
|
|
ret = true;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2020-09-24 08:30:02 +08:00
|
|
|
static void mptcp_pm_add_timer(struct timer_list *timer)
|
|
|
|
{
|
|
|
|
struct mptcp_pm_add_entry *entry = from_timer(entry, timer, add_timer);
|
|
|
|
struct mptcp_sock *msk = entry->sock;
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("msk=%p\n", msk);
|
2020-09-24 08:30:02 +08:00
|
|
|
|
|
|
|
if (!msk)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (inet_sk_state_load(sk) == TCP_CLOSE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (!entry->addr.id)
|
|
|
|
return;
|
|
|
|
|
2021-08-24 09:05:40 +08:00
|
|
|
if (mptcp_pm_should_add_signal_addr(msk)) {
|
2020-09-24 08:30:02 +08:00
|
|
|
sk_reset_timer(sk, timer, jiffies + TCP_RTO_MAX / 8);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
|
2021-08-24 09:05:40 +08:00
|
|
|
if (!mptcp_pm_should_add_signal_addr(msk)) {
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("retransmit ADD_ADDR id=%d\n", entry->addr.id);
|
2021-03-27 02:26:31 +08:00
|
|
|
mptcp_pm_announce_addr(msk, &entry->addr, false);
|
2020-11-20 03:46:00 +08:00
|
|
|
mptcp_pm_add_addr_send_ack(msk);
|
2020-09-24 08:30:02 +08:00
|
|
|
entry->retrans_times++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->retrans_times < ADD_ADDR_RETRANS_MAX)
|
2020-11-04 03:05:07 +08:00
|
|
|
sk_reset_timer(sk, timer,
|
2020-11-10 11:01:43 +08:00
|
|
|
jiffies + mptcp_get_add_addr_timeout(sock_net(sk)));
|
2020-09-24 08:30:02 +08:00
|
|
|
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
|
2021-03-27 02:26:34 +08:00
|
|
|
if (entry->retrans_times == ADD_ADDR_RETRANS_MAX)
|
|
|
|
mptcp_pm_subflow_established(msk);
|
|
|
|
|
2020-09-24 08:30:02 +08:00
|
|
|
out:
|
|
|
|
__sock_put(sk);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct mptcp_pm_add_entry *
|
|
|
|
mptcp_pm_del_add_timer(struct mptcp_sock *msk,
|
2022-02-16 10:11:28 +08:00
|
|
|
const struct mptcp_addr_info *addr, bool check_id)
|
2020-09-24 08:30:02 +08:00
|
|
|
{
|
|
|
|
struct mptcp_pm_add_entry *entry;
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
2024-09-10 17:58:56 +08:00
|
|
|
struct timer_list *add_timer = NULL;
|
2020-09-24 08:30:02 +08:00
|
|
|
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2021-03-27 02:26:37 +08:00
|
|
|
entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
2024-09-10 17:58:56 +08:00
|
|
|
if (entry && (!check_id || entry->addr.id == addr->id)) {
|
2020-09-24 08:30:02 +08:00
|
|
|
entry->retrans_times = ADD_ADDR_RETRANS_MAX;
|
2024-09-10 17:58:56 +08:00
|
|
|
add_timer = &entry->add_timer;
|
|
|
|
}
|
|
|
|
if (!check_id && entry)
|
|
|
|
list_del(&entry->list);
|
2020-09-24 08:30:02 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
|
2024-09-10 17:58:56 +08:00
|
|
|
/* no lock, because sk_stop_timer_sync() is calling del_timer_sync() */
|
|
|
|
if (add_timer)
|
|
|
|
sk_stop_timer_sync(sk, add_timer);
|
2020-09-24 08:30:02 +08:00
|
|
|
|
|
|
|
return entry;
|
2020-09-24 08:29:54 +08:00
|
|
|
}
|
|
|
|
|
2022-05-04 10:38:52 +08:00
|
|
|
bool mptcp_pm_alloc_anno_list(struct mptcp_sock *msk,
|
2023-06-21 00:30:22 +08:00
|
|
|
const struct mptcp_addr_info *addr)
|
2020-09-24 08:29:54 +08:00
|
|
|
{
|
2020-09-24 08:30:00 +08:00
|
|
|
struct mptcp_pm_add_entry *add_entry = NULL;
|
2020-09-24 08:30:02 +08:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
2020-11-04 03:05:07 +08:00
|
|
|
struct net *net = sock_net(sk);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2021-02-05 07:23:30 +08:00
|
|
|
lockdep_assert_held(&msk->pm.lock);
|
|
|
|
|
2023-06-21 00:30:22 +08:00
|
|
|
add_entry = mptcp_lookup_anno_list_by_saddr(msk, addr);
|
2022-05-03 04:52:37 +08:00
|
|
|
|
|
|
|
if (add_entry) {
|
2024-08-12 23:30:53 +08:00
|
|
|
if (WARN_ON_ONCE(mptcp_pm_is_kernel(msk)))
|
2022-05-03 04:52:37 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
sk_reset_timer(sk, &add_entry->add_timer,
|
|
|
|
jiffies + mptcp_get_add_addr_timeout(net));
|
|
|
|
return true;
|
|
|
|
}
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2020-09-24 08:30:00 +08:00
|
|
|
add_entry = kmalloc(sizeof(*add_entry), GFP_ATOMIC);
|
|
|
|
if (!add_entry)
|
2020-09-24 08:29:54 +08:00
|
|
|
return false;
|
|
|
|
|
2020-09-24 08:30:00 +08:00
|
|
|
list_add(&add_entry->list, &msk->pm.anno_list);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2023-06-21 00:30:22 +08:00
|
|
|
add_entry->addr = *addr;
|
2020-09-24 08:30:02 +08:00
|
|
|
add_entry->sock = msk;
|
|
|
|
add_entry->retrans_times = 0;
|
|
|
|
|
|
|
|
timer_setup(&add_entry->add_timer, mptcp_pm_add_timer, 0);
|
2020-11-04 03:05:07 +08:00
|
|
|
sk_reset_timer(sk, &add_entry->add_timer,
|
|
|
|
jiffies + mptcp_get_add_addr_timeout(net));
|
2020-09-24 08:30:02 +08:00
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void mptcp_pm_free_anno_list(struct mptcp_sock *msk)
|
|
|
|
{
|
2020-09-24 08:30:00 +08:00
|
|
|
struct mptcp_pm_add_entry *entry, *tmp;
|
2020-09-24 08:30:02 +08:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
LIST_HEAD(free_list);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("msk=%p\n", msk);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2020-09-24 08:30:02 +08:00
|
|
|
list_splice_init(&msk->pm.anno_list, &free_list);
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
|
|
|
|
list_for_each_entry_safe(entry, tmp, &free_list, list) {
|
|
|
|
sk_stop_timer_sync(sk, &entry->add_timer);
|
2020-09-24 08:29:54 +08:00
|
|
|
kfree(entry);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-18 06:07:23 +08:00
|
|
|
/* Fill all the remote addresses into the array addrs[],
|
|
|
|
* and return the array size.
|
|
|
|
*/
|
2023-01-25 18:47:21 +08:00
|
|
|
static unsigned int fill_remote_addresses_vec(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_addr_info *local,
|
|
|
|
bool fullmesh,
|
2021-08-18 06:07:23 +08:00
|
|
|
struct mptcp_addr_info *addrs)
|
|
|
|
{
|
2022-01-07 08:20:23 +08:00
|
|
|
bool deny_id0 = READ_ONCE(msk->pm.remote_deny_join_id0);
|
2021-08-18 06:07:23 +08:00
|
|
|
struct sock *sk = (struct sock *)msk, *ssk;
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
struct mptcp_addr_info remote = { 0 };
|
|
|
|
unsigned int subflows_max;
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
subflows_max = mptcp_pm_get_subflows_max(msk);
|
2022-01-07 08:20:23 +08:00
|
|
|
remote_address((struct sock_common *)sk, &remote);
|
2021-08-18 06:07:23 +08:00
|
|
|
|
|
|
|
/* Non-fullmesh endpoint, fill in the single entry
|
|
|
|
* corresponding to the primary MPC subflow remote address
|
|
|
|
*/
|
|
|
|
if (!fullmesh) {
|
2022-01-07 08:20:23 +08:00
|
|
|
if (deny_id0)
|
|
|
|
return 0;
|
|
|
|
|
2023-01-25 18:47:21 +08:00
|
|
|
if (!mptcp_pm_addr_families_match(sk, local, &remote))
|
|
|
|
return 0;
|
|
|
|
|
2021-08-18 06:07:23 +08:00
|
|
|
msk->pm.subflows++;
|
|
|
|
addrs[i++] = remote;
|
|
|
|
} else {
|
2024-02-16 02:25:33 +08:00
|
|
|
DECLARE_BITMAP(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);
|
|
|
|
|
|
|
|
/* Forbid creation of new subflows matching existing
|
|
|
|
* ones, possibly already created by incoming ADD_ADDR
|
|
|
|
*/
|
|
|
|
bitmap_zero(unavail_id, MPTCP_PM_MAX_ADDR_ID + 1);
|
|
|
|
mptcp_for_each_subflow(msk, subflow)
|
|
|
|
if (READ_ONCE(subflow->local_id) == local->id)
|
|
|
|
__set_bit(subflow->remote_id, unavail_id);
|
|
|
|
|
2021-08-18 06:07:23 +08:00
|
|
|
mptcp_for_each_subflow(msk, subflow) {
|
|
|
|
ssk = mptcp_subflow_tcp_sock(subflow);
|
2022-01-07 08:20:23 +08:00
|
|
|
remote_address((struct sock_common *)ssk, &addrs[i]);
|
2024-02-16 02:25:32 +08:00
|
|
|
addrs[i].id = READ_ONCE(subflow->remote_id);
|
2022-07-12 03:16:30 +08:00
|
|
|
if (deny_id0 && !addrs[i].id)
|
2022-01-07 08:20:23 +08:00
|
|
|
continue;
|
|
|
|
|
2024-02-16 02:25:33 +08:00
|
|
|
if (test_bit(addrs[i].id, unavail_id))
|
|
|
|
continue;
|
|
|
|
|
2023-01-25 18:47:21 +08:00
|
|
|
if (!mptcp_pm_addr_families_match(sk, local, &addrs[i]))
|
|
|
|
continue;
|
|
|
|
|
2024-02-16 02:25:33 +08:00
|
|
|
if (msk->pm.subflows < subflows_max) {
|
|
|
|
/* forbid creating multiple address towards
|
|
|
|
* this id
|
|
|
|
*/
|
|
|
|
__set_bit(addrs[i].id, unavail_id);
|
2021-08-18 06:07:23 +08:00
|
|
|
msk->pm.subflows++;
|
2022-01-07 08:20:23 +08:00
|
|
|
i++;
|
2021-08-18 06:07:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2022-07-12 03:16:29 +08:00
|
|
|
static void __mptcp_pm_send_ack(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
|
|
|
|
bool prio, bool backup)
|
|
|
|
{
|
|
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
|
|
|
bool slow;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("send ack for %s\n",
|
2022-07-12 03:16:29 +08:00
|
|
|
prio ? "mp_prio" : (mptcp_pm_should_add_signal(msk) ? "add_addr" : "rm_addr"));
|
|
|
|
|
|
|
|
slow = lock_sock_fast(ssk);
|
|
|
|
if (prio) {
|
|
|
|
subflow->send_mp_prio = 1;
|
|
|
|
subflow->request_bkup = backup;
|
|
|
|
}
|
|
|
|
|
|
|
|
__mptcp_subflow_send_ack(ssk);
|
|
|
|
unlock_sock_fast(ssk, slow);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void mptcp_pm_send_ack(struct mptcp_sock *msk, struct mptcp_subflow_context *subflow,
|
|
|
|
bool prio, bool backup)
|
|
|
|
{
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
__mptcp_pm_send_ack(msk, subflow, prio, backup);
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
}
|
|
|
|
|
2022-01-07 08:20:22 +08:00
|
|
|
static struct mptcp_pm_addr_entry *
|
|
|
|
__lookup_addr_by_id(struct pm_nl_pernet *pernet, unsigned int id)
|
|
|
|
{
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
|
|
|
|
list_for_each_entry(entry, &pernet->local_addr_list, list) {
|
|
|
|
if (entry->addr.id == id)
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-01-21 08:35:27 +08:00
|
|
|
static struct mptcp_pm_addr_entry *
|
|
|
|
__lookup_addr(struct pm_nl_pernet *pernet, const struct mptcp_addr_info *info,
|
|
|
|
bool lookup_by_id)
|
|
|
|
{
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
|
|
|
|
list_for_each_entry(entry, &pernet->local_addr_list, list) {
|
2022-07-12 03:16:31 +08:00
|
|
|
if ((!lookup_by_id &&
|
|
|
|
mptcp_addresses_equal(&entry->addr, info, entry->addr.port)) ||
|
2022-01-21 08:35:27 +08:00
|
|
|
(lookup_by_id && entry->addr.id == info->id))
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
2024-08-20 03:45:32 +08:00
|
|
|
struct mptcp_pm_addr_entry local;
|
2021-02-02 07:09:07 +08:00
|
|
|
unsigned int add_addr_signal_max;
|
2024-08-20 03:45:32 +08:00
|
|
|
bool signal_and_subflow = false;
|
2021-02-02 07:09:07 +08:00
|
|
|
unsigned int local_addr_max;
|
2020-03-28 05:48:51 +08:00
|
|
|
struct pm_nl_pernet *pernet;
|
2021-02-02 07:09:07 +08:00
|
|
|
unsigned int subflows_max;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2022-04-09 03:45:57 +08:00
|
|
|
pernet = pm_nl_get_pernet(sock_net(sk));
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2021-02-02 07:09:07 +08:00
|
|
|
add_addr_signal_max = mptcp_pm_get_add_addr_signal_max(msk);
|
|
|
|
local_addr_max = mptcp_pm_get_local_addr_max(msk);
|
|
|
|
subflows_max = mptcp_pm_get_subflows_max(msk);
|
|
|
|
|
2022-01-07 08:20:22 +08:00
|
|
|
/* do lazy endpoint usage accounting for the MPC subflows */
|
|
|
|
if (unlikely(!(msk->pm.status & BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED))) && msk->first) {
|
2022-07-12 03:16:31 +08:00
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(msk->first);
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
2022-01-07 08:20:23 +08:00
|
|
|
struct mptcp_addr_info mpc_addr;
|
2022-07-12 03:16:31 +08:00
|
|
|
bool backup = false;
|
2022-01-07 08:20:22 +08:00
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
mptcp_local_address((struct sock_common *)msk->first, &mpc_addr);
|
2022-07-12 03:16:31 +08:00
|
|
|
rcu_read_lock();
|
|
|
|
entry = __lookup_addr(pernet, &mpc_addr, false);
|
|
|
|
if (entry) {
|
|
|
|
__clear_bit(entry->addr.id, msk->pm.id_avail_bitmap);
|
2022-07-12 03:16:32 +08:00
|
|
|
msk->mpc_endpoint_id = entry->addr.id;
|
2022-07-12 03:16:31 +08:00
|
|
|
backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
if (backup)
|
|
|
|
mptcp_pm_send_ack(msk, subflow, true, backup);
|
2022-01-07 08:20:22 +08:00
|
|
|
|
|
|
|
msk->pm.status |= BIT(MPTCP_PM_MPC_ENDPOINT_ACCOUNTED);
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
pr_debug("local %d:%d signal %d:%d subflows %d:%d\n",
|
2021-02-02 07:09:07 +08:00
|
|
|
msk->pm.local_addr_used, local_addr_max,
|
|
|
|
msk->pm.add_addr_signaled, add_addr_signal_max,
|
|
|
|
msk->pm.subflows, subflows_max);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
/* check first for announce */
|
2021-02-02 07:09:07 +08:00
|
|
|
if (msk->pm.add_addr_signaled < add_addr_signal_max) {
|
2022-02-19 05:35:40 +08:00
|
|
|
/* due to racing events on both ends we can reach here while
|
|
|
|
* previous add address is still running: if we invoke now
|
|
|
|
* mptcp_pm_announce_addr(), that will fail and the
|
|
|
|
* corresponding id will be marked as used.
|
|
|
|
* Instead let the PM machinery reschedule us when the
|
|
|
|
* current address announce will be completed.
|
|
|
|
*/
|
|
|
|
if (msk->pm.addr_signal & BIT(MPTCP_ADD_ADDR_SIGNAL))
|
|
|
|
return;
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
if (!select_signal_address(pernet, msk, &local))
|
2024-08-12 23:30:52 +08:00
|
|
|
goto subflow;
|
|
|
|
|
2024-08-12 23:30:53 +08:00
|
|
|
/* If the alloc fails, we are on memory pressure, not worth
|
|
|
|
* continuing, and trying to create subflows.
|
|
|
|
*/
|
2024-08-20 03:45:32 +08:00
|
|
|
if (!mptcp_pm_alloc_anno_list(msk, &local.addr))
|
2024-08-12 23:30:53 +08:00
|
|
|
return;
|
2024-08-12 23:30:52 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
|
2024-08-12 23:30:52 +08:00
|
|
|
msk->pm.add_addr_signaled++;
|
2024-08-28 14:14:24 +08:00
|
|
|
|
|
|
|
/* Special case for ID0: set the correct ID */
|
|
|
|
if (local.addr.id == msk->mpc_endpoint_id)
|
|
|
|
local.addr.id = 0;
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
mptcp_pm_announce_addr(msk, &local.addr, false);
|
2024-08-12 23:30:52 +08:00
|
|
|
mptcp_pm_nl_addr_send_ack(msk);
|
mptcp: pm: do not ignore 'subflow' if 'signal' flag is also set
commit 85df533a787bf07bf4367ce2a02b822ff1fba1a3 upstream.
Up to the 'Fixes' commit, having an endpoint with both the 'signal' and
'subflow' flags, resulted in the creation of a subflow and an address
announcement using the address linked to this endpoint. After this
commit, only the address announcement was done, ignoring the 'subflow'
flag.
That's because the same bitmap is used for the two flags. It is OK to
keep this single bitmap, the already selected local endpoint simply have
to be re-used, but not via select_local_address() not to look at the
just modified bitmap.
Note that it is unusual to set the two flags together: creating a new
subflow using a new local address will implicitly advertise it to the
other peer. So in theory, no need to advertise it explicitly as well.
Maybe there are use-cases -- the subflow might not reach the other peer
that way, we can ask the other peer to try initiating the new subflow
without delay -- or very likely the user is confused, and put both flags
"just to be sure at least the right one is set". Still, if it is
allowed, the kernel should do what has been asked: using this endpoint
to announce the address and to create a new subflow from it.
An alternative is to forbid the use of the two flags together, but
that's probably too late, there are maybe use-cases, and it was working
before. This patch will avoid people complaining subflows are not
created using the endpoint they added with the 'subflow' and 'signal'
flag.
Note that with the current patch, the subflow might not be created in
some corner cases, e.g. if the 'subflows' limit was reached when sending
the ADD_ADDR, but changed later on. It is probably not worth splitting
id_avail_bitmap per target ('signal', 'subflow'), which will add another
large field to the msk "just" to track (again) endpoints. Anyway,
currently when the limits are changed, the kernel doesn't check if new
subflows can be created or removed, because we would need to keep track
of the received ADD_ADDR, and more. It sounds OK to assume that the
limits should be properly configured before establishing new
connections.
Fixes: 86e39e04482b ("mptcp: keep track of local endpoint still available for each msk")
Cc: stable@vger.kernel.org
Suggested-by: Paolo Abeni <pabeni@redhat.com>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://patch.msgid.link/20240731-upstream-net-20240731-mptcp-endp-subflow-signal-v1-5-c8a9b036493b@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-08-12 23:30:54 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
if (local.flags & MPTCP_PM_ADDR_FLAG_SUBFLOW)
|
|
|
|
signal_and_subflow = true;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2024-08-12 23:30:52 +08:00
|
|
|
subflow:
|
2020-03-28 05:48:51 +08:00
|
|
|
/* check if should create a new subflow */
|
2022-01-07 08:20:23 +08:00
|
|
|
while (msk->pm.local_addr_used < local_addr_max &&
|
|
|
|
msk->pm.subflows < subflows_max) {
|
|
|
|
struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX];
|
|
|
|
bool fullmesh;
|
|
|
|
int i, nr;
|
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
if (signal_and_subflow)
|
|
|
|
signal_and_subflow = false;
|
|
|
|
else if (!select_local_address(pernet, msk, &local))
|
|
|
|
break;
|
2021-01-26 02:59:02 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
fullmesh = !!(local.flags & MPTCP_PM_ADDR_FLAG_FULLMESH);
|
2022-01-07 08:20:23 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
__clear_bit(local.addr.id, msk->pm.id_avail_bitmap);
|
2024-08-28 14:14:24 +08:00
|
|
|
|
|
|
|
/* Special case for ID0: set the correct ID */
|
|
|
|
if (local.addr.id == msk->mpc_endpoint_id)
|
|
|
|
local.addr.id = 0;
|
2024-08-28 14:14:33 +08:00
|
|
|
else /* local_addr_used is not decr for ID 0 */
|
|
|
|
msk->pm.local_addr_used++;
|
2024-08-28 14:14:24 +08:00
|
|
|
|
2024-08-20 03:45:32 +08:00
|
|
|
nr = fill_remote_addresses_vec(msk, &local.addr, fullmesh, addrs);
|
2023-01-25 18:47:21 +08:00
|
|
|
if (nr == 0)
|
|
|
|
continue;
|
|
|
|
|
2022-01-07 08:20:23 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
for (i = 0; i < nr; i++)
|
2024-08-20 03:45:32 +08:00
|
|
|
__mptcp_subflow_connect(sk, &local.addr, &addrs[i]);
|
2022-01-07 08:20:23 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
2022-01-07 08:20:23 +08:00
|
|
|
mptcp_pm_nl_check_work_pending(msk);
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2021-02-13 07:59:54 +08:00
|
|
|
static void mptcp_pm_nl_fully_established(struct mptcp_sock *msk)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
mptcp_pm_create_subflow_or_signal_addr(msk);
|
|
|
|
}
|
|
|
|
|
2021-02-13 07:59:54 +08:00
|
|
|
static void mptcp_pm_nl_subflow_established(struct mptcp_sock *msk)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
mptcp_pm_create_subflow_or_signal_addr(msk);
|
|
|
|
}
|
|
|
|
|
2021-08-18 06:07:24 +08:00
|
|
|
/* Fill all the local addresses into the array addrs[],
|
|
|
|
* and return the array size.
|
|
|
|
*/
|
|
|
|
static unsigned int fill_local_addresses_vec(struct mptcp_sock *msk,
|
2023-01-25 18:47:21 +08:00
|
|
|
struct mptcp_addr_info *remote,
|
2021-08-18 06:07:24 +08:00
|
|
|
struct mptcp_addr_info *addrs)
|
|
|
|
{
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
2024-08-20 03:45:30 +08:00
|
|
|
struct mptcp_addr_info mpc_addr;
|
2021-08-18 06:07:24 +08:00
|
|
|
struct pm_nl_pernet *pernet;
|
|
|
|
unsigned int subflows_max;
|
|
|
|
int i = 0;
|
|
|
|
|
2022-04-09 03:45:57 +08:00
|
|
|
pernet = pm_nl_get_pernet_from_msk(msk);
|
2021-08-18 06:07:24 +08:00
|
|
|
subflows_max = mptcp_pm_get_subflows_max(msk);
|
|
|
|
|
2024-08-20 03:45:30 +08:00
|
|
|
mptcp_local_address((struct sock_common *)msk, &mpc_addr);
|
|
|
|
|
2021-08-18 06:07:24 +08:00
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
|
|
|
|
if (!(entry->flags & MPTCP_PM_ADDR_FLAG_FULLMESH))
|
|
|
|
continue;
|
|
|
|
|
2023-01-25 18:47:21 +08:00
|
|
|
if (!mptcp_pm_addr_families_match(sk, &entry->addr, remote))
|
|
|
|
continue;
|
2021-08-18 06:07:24 +08:00
|
|
|
|
|
|
|
if (msk->pm.subflows < subflows_max) {
|
|
|
|
msk->pm.subflows++;
|
2024-08-20 03:45:30 +08:00
|
|
|
addrs[i] = entry->addr;
|
|
|
|
|
|
|
|
/* Special case for ID0: set the correct ID */
|
|
|
|
if (mptcp_addresses_equal(&entry->addr, &mpc_addr, entry->addr.port))
|
|
|
|
addrs[i].id = 0;
|
|
|
|
|
|
|
|
i++;
|
2021-08-18 06:07:24 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
/* If the array is empty, fill in the single
|
|
|
|
* 'IPADDRANY' local address
|
|
|
|
*/
|
|
|
|
if (!i) {
|
2023-01-25 18:47:21 +08:00
|
|
|
struct mptcp_addr_info local;
|
|
|
|
|
2021-08-18 06:07:24 +08:00
|
|
|
memset(&local, 0, sizeof(local));
|
2023-01-25 18:47:21 +08:00
|
|
|
local.family =
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
remote->family == AF_INET6 &&
|
|
|
|
ipv6_addr_v4mapped(&remote->addr6) ? AF_INET :
|
|
|
|
#endif
|
|
|
|
remote->family;
|
|
|
|
|
|
|
|
if (!mptcp_pm_addr_families_match(sk, &local, remote))
|
|
|
|
return 0;
|
2021-08-18 06:07:24 +08:00
|
|
|
|
|
|
|
msk->pm.subflows++;
|
|
|
|
addrs[i++] = local;
|
|
|
|
}
|
|
|
|
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2021-02-13 07:59:54 +08:00
|
|
|
static void mptcp_pm_nl_add_addr_received(struct mptcp_sock *msk)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2021-08-18 06:07:24 +08:00
|
|
|
struct mptcp_addr_info addrs[MPTCP_PM_ADDR_MAX];
|
2020-03-28 05:48:51 +08:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
2021-02-02 07:09:07 +08:00
|
|
|
unsigned int add_addr_accept_max;
|
2020-03-28 05:48:51 +08:00
|
|
|
struct mptcp_addr_info remote;
|
2021-02-02 07:09:07 +08:00
|
|
|
unsigned int subflows_max;
|
mptcp: pm: update add_addr counters after connect
commit 40eec1795cc27b076d49236649a29507c7ed8c2d upstream.
The creation of new subflows can fail for different reasons. If no
subflow have been created using the received ADD_ADDR, the related
counters should not be updated, otherwise they will never be decremented
for events related to this ID later on.
For the moment, the number of accepted ADD_ADDR is only decremented upon
the reception of a related RM_ADDR, and only if the remote address ID is
currently being used by at least one subflow. In other words, if no
subflow can be created with the received address, the counter will not
be decremented. In this case, it is then important not to increment
pm.add_addr_accepted counter, and not to modify pm.accept_addr bit.
Note that this patch does not modify the behaviour in case of failures
later on, e.g. if the MP Join is dropped or rejected.
The "remove invalid addresses" MP Join subtest has been modified to
validate this case. The broadcast IP address is added before the "valid"
address that will be used to successfully create a subflow, and the
limit is decreased by one: without this patch, it was not possible to
create the last subflow, because:
- the broadcast address would have been accepted even if it was not
usable: the creation of a subflow to this address results in an error,
- the limit of 2 accepted ADD_ADDR would have then been reached.
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: YonglongLi <liyonglong@chinatelecom.cn>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://lore.kernel.org/r/20240607-upstream-net-20240607-misc-fixes-v1-3-1ab9ddfa3d00@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-06-07 23:01:50 +08:00
|
|
|
bool sf_created = false;
|
2021-08-18 06:07:24 +08:00
|
|
|
int i, nr;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2021-02-02 07:09:07 +08:00
|
|
|
add_addr_accept_max = mptcp_pm_get_add_addr_accept_max(msk);
|
|
|
|
subflows_max = mptcp_pm_get_subflows_max(msk);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("accepted %d:%d remote family %d\n",
|
2021-02-02 07:09:07 +08:00
|
|
|
msk->pm.add_addr_accepted, add_addr_accept_max,
|
2020-03-28 05:48:51 +08:00
|
|
|
msk->pm.remote.family);
|
2021-03-27 02:26:32 +08:00
|
|
|
|
2022-02-19 05:35:41 +08:00
|
|
|
remote = msk->pm.remote;
|
2022-03-18 06:14:44 +08:00
|
|
|
mptcp_pm_announce_addr(msk, &remote, true);
|
|
|
|
mptcp_pm_nl_addr_send_ack(msk);
|
|
|
|
|
2022-02-19 05:35:41 +08:00
|
|
|
if (lookup_subflow_by_daddr(&msk->conn_list, &remote))
|
2022-03-18 06:14:44 +08:00
|
|
|
return;
|
2021-03-27 02:26:32 +08:00
|
|
|
|
2022-02-19 05:35:41 +08:00
|
|
|
/* pick id 0 port, if none is provided the remote address */
|
2022-03-18 06:14:44 +08:00
|
|
|
if (!remote.port)
|
2022-02-19 05:35:41 +08:00
|
|
|
remote.port = sk->sk_dport;
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
/* connect to the specified remote address, using whatever
|
|
|
|
* local address the routing configuration will pick.
|
|
|
|
*/
|
2023-01-25 18:47:21 +08:00
|
|
|
nr = fill_local_addresses_vec(msk, &remote, addrs);
|
|
|
|
if (nr == 0)
|
|
|
|
return;
|
2021-08-18 06:07:24 +08:00
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
2021-08-18 06:07:24 +08:00
|
|
|
for (i = 0; i < nr; i++)
|
mptcp: pm: update add_addr counters after connect
commit 40eec1795cc27b076d49236649a29507c7ed8c2d upstream.
The creation of new subflows can fail for different reasons. If no
subflow have been created using the received ADD_ADDR, the related
counters should not be updated, otherwise they will never be decremented
for events related to this ID later on.
For the moment, the number of accepted ADD_ADDR is only decremented upon
the reception of a related RM_ADDR, and only if the remote address ID is
currently being used by at least one subflow. In other words, if no
subflow can be created with the received address, the counter will not
be decremented. In this case, it is then important not to increment
pm.add_addr_accepted counter, and not to modify pm.accept_addr bit.
Note that this patch does not modify the behaviour in case of failures
later on, e.g. if the MP Join is dropped or rejected.
The "remove invalid addresses" MP Join subtest has been modified to
validate this case. The broadcast IP address is added before the "valid"
address that will be used to successfully create a subflow, and the
limit is decreased by one: without this patch, it was not possible to
create the last subflow, because:
- the broadcast address would have been accepted even if it was not
usable: the creation of a subflow to this address results in an error,
- the limit of 2 accepted ADD_ADDR would have then been reached.
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: YonglongLi <liyonglong@chinatelecom.cn>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://lore.kernel.org/r/20240607-upstream-net-20240607-misc-fixes-v1-3-1ab9ddfa3d00@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-06-07 23:01:50 +08:00
|
|
|
if (__mptcp_subflow_connect(sk, &addrs[i], &remote) == 0)
|
|
|
|
sf_created = true;
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
mptcp: pm: update add_addr counters after connect
commit 40eec1795cc27b076d49236649a29507c7ed8c2d upstream.
The creation of new subflows can fail for different reasons. If no
subflow have been created using the received ADD_ADDR, the related
counters should not be updated, otherwise they will never be decremented
for events related to this ID later on.
For the moment, the number of accepted ADD_ADDR is only decremented upon
the reception of a related RM_ADDR, and only if the remote address ID is
currently being used by at least one subflow. In other words, if no
subflow can be created with the received address, the counter will not
be decremented. In this case, it is then important not to increment
pm.add_addr_accepted counter, and not to modify pm.accept_addr bit.
Note that this patch does not modify the behaviour in case of failures
later on, e.g. if the MP Join is dropped or rejected.
The "remove invalid addresses" MP Join subtest has been modified to
validate this case. The broadcast IP address is added before the "valid"
address that will be used to successfully create a subflow, and the
limit is decreased by one: without this patch, it was not possible to
create the last subflow, because:
- the broadcast address would have been accepted even if it was not
usable: the creation of a subflow to this address results in an error,
- the limit of 2 accepted ADD_ADDR would have then been reached.
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: YonglongLi <liyonglong@chinatelecom.cn>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://lore.kernel.org/r/20240607-upstream-net-20240607-misc-fixes-v1-3-1ab9ddfa3d00@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-06-07 23:01:50 +08:00
|
|
|
|
|
|
|
if (sf_created) {
|
2024-08-28 14:14:33 +08:00
|
|
|
/* add_addr_accepted is not decr for ID 0 */
|
|
|
|
if (remote.id)
|
|
|
|
msk->pm.add_addr_accepted++;
|
mptcp: pm: update add_addr counters after connect
commit 40eec1795cc27b076d49236649a29507c7ed8c2d upstream.
The creation of new subflows can fail for different reasons. If no
subflow have been created using the received ADD_ADDR, the related
counters should not be updated, otherwise they will never be decremented
for events related to this ID later on.
For the moment, the number of accepted ADD_ADDR is only decremented upon
the reception of a related RM_ADDR, and only if the remote address ID is
currently being used by at least one subflow. In other words, if no
subflow can be created with the received address, the counter will not
be decremented. In this case, it is then important not to increment
pm.add_addr_accepted counter, and not to modify pm.accept_addr bit.
Note that this patch does not modify the behaviour in case of failures
later on, e.g. if the MP Join is dropped or rejected.
The "remove invalid addresses" MP Join subtest has been modified to
validate this case. The broadcast IP address is added before the "valid"
address that will be used to successfully create a subflow, and the
limit is decreased by one: without this patch, it was not possible to
create the last subflow, because:
- the broadcast address would have been accepted even if it was not
usable: the creation of a subflow to this address results in an error,
- the limit of 2 accepted ADD_ADDR would have then been reached.
Fixes: 01cacb00b35c ("mptcp: add netlink-based PM")
Cc: stable@vger.kernel.org
Co-developed-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: YonglongLi <liyonglong@chinatelecom.cn>
Reviewed-by: Mat Martineau <martineau@kernel.org>
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Link: https://lore.kernel.org/r/20240607-upstream-net-20240607-misc-fixes-v1-3-1ab9ddfa3d00@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-06-07 23:01:50 +08:00
|
|
|
if (msk->pm.add_addr_accepted >= add_addr_accept_max ||
|
|
|
|
msk->pm.subflows >= subflows_max)
|
|
|
|
WRITE_ONCE(msk->pm.accept_addr, false);
|
|
|
|
}
|
2020-11-20 03:46:00 +08:00
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:37 +08:00
|
|
|
bool mptcp_pm_nl_is_init_remote_addr(struct mptcp_sock *msk,
|
|
|
|
const struct mptcp_addr_info *remote)
|
|
|
|
{
|
|
|
|
struct mptcp_addr_info mpc_remote;
|
|
|
|
|
|
|
|
remote_address((struct sock_common *)msk, &mpc_remote);
|
|
|
|
return mptcp_addresses_equal(&mpc_remote, remote, remote->port);
|
|
|
|
}
|
|
|
|
|
2021-03-27 02:26:41 +08:00
|
|
|
void mptcp_pm_nl_addr_send_ack(struct mptcp_sock *msk)
|
2020-11-20 03:46:00 +08:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
|
2021-02-05 07:23:30 +08:00
|
|
|
msk_owned_by_me(msk);
|
|
|
|
lockdep_assert_held(&msk->pm.lock);
|
|
|
|
|
2021-03-27 02:26:40 +08:00
|
|
|
if (!mptcp_pm_should_add_signal(msk) &&
|
|
|
|
!mptcp_pm_should_rm_signal(msk))
|
2020-11-20 03:46:00 +08:00
|
|
|
return;
|
|
|
|
|
2024-08-28 14:14:27 +08:00
|
|
|
mptcp_for_each_subflow(msk, subflow) {
|
|
|
|
if (__mptcp_subflow_active(subflow)) {
|
|
|
|
mptcp_pm_send_ack(msk, subflow, false, false);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2022-07-06 05:32:14 +08:00
|
|
|
int mptcp_pm_nl_mp_prio_send_ack(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_addr_info *addr,
|
|
|
|
struct mptcp_addr_info *rem,
|
|
|
|
u8 bkup)
|
2021-01-09 08:47:57 +08:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow;
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("bkup=%d\n", bkup);
|
2021-01-09 08:47:57 +08:00
|
|
|
|
|
|
|
mptcp_for_each_subflow(msk, subflow) {
|
|
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
2022-07-06 05:32:14 +08:00
|
|
|
struct mptcp_addr_info local, remote;
|
2021-01-09 08:47:57 +08:00
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
mptcp_local_address((struct sock_common *)ssk, &local);
|
2022-05-04 10:38:49 +08:00
|
|
|
if (!mptcp_addresses_equal(&local, addr, addr->port))
|
2021-01-09 08:47:57 +08:00
|
|
|
continue;
|
|
|
|
|
2022-07-06 05:32:14 +08:00
|
|
|
if (rem && rem->family != AF_UNSPEC) {
|
|
|
|
remote_address((struct sock_common *)ssk, &remote);
|
|
|
|
if (!mptcp_addresses_equal(&remote, rem, rem->port))
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-07-12 03:16:29 +08:00
|
|
|
__mptcp_pm_send_ack(msk, subflow, true, bkup);
|
2021-01-09 08:47:57 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2021-03-31 08:08:52 +08:00
|
|
|
static void mptcp_pm_nl_rm_addr_or_subflow(struct mptcp_sock *msk,
|
|
|
|
const struct mptcp_rm_list *rm_list,
|
|
|
|
enum linux_mptcp_mib_field rm_type)
|
2020-09-24 08:29:49 +08:00
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *subflow, *tmp;
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
2021-03-13 09:16:15 +08:00
|
|
|
u8 i;
|
2020-09-24 08:29:49 +08:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("%s rm_list_nr %d\n",
|
2021-03-31 08:08:52 +08:00
|
|
|
rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow", rm_list->nr);
|
2020-09-24 08:29:49 +08:00
|
|
|
|
2021-02-05 07:23:30 +08:00
|
|
|
msk_owned_by_me(msk);
|
|
|
|
|
2021-12-12 00:11:12 +08:00
|
|
|
if (sk->sk_state == TCP_LISTEN)
|
|
|
|
return;
|
|
|
|
|
2021-03-31 08:08:52 +08:00
|
|
|
if (!rm_list->nr)
|
2020-09-24 08:29:49 +08:00
|
|
|
return;
|
|
|
|
|
|
|
|
if (list_empty(&msk->conn_list))
|
|
|
|
return;
|
|
|
|
|
2021-03-31 08:08:52 +08:00
|
|
|
for (i = 0; i < rm_list->nr; i++) {
|
2022-07-12 03:16:32 +08:00
|
|
|
u8 rm_id = rm_list->ids[i];
|
2022-01-07 08:20:20 +08:00
|
|
|
bool removed = false;
|
|
|
|
|
2022-09-07 04:55:39 +08:00
|
|
|
mptcp_for_each_subflow_safe(msk, subflow, tmp) {
|
2021-03-13 09:16:15 +08:00
|
|
|
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
|
2024-02-16 02:25:32 +08:00
|
|
|
u8 remote_id = READ_ONCE(subflow->remote_id);
|
2021-03-13 09:16:15 +08:00
|
|
|
int how = RCV_SHUTDOWN | SEND_SHUTDOWN;
|
2024-02-16 02:25:31 +08:00
|
|
|
u8 id = subflow_get_local_id(subflow);
|
2021-03-31 08:08:52 +08:00
|
|
|
|
2024-10-08 19:04:55 +08:00
|
|
|
if ((1 << inet_sk_state_load(ssk)) &
|
|
|
|
(TCPF_FIN_WAIT1 | TCPF_FIN_WAIT2 | TCPF_CLOSING | TCPF_CLOSE))
|
2024-08-28 14:14:32 +08:00
|
|
|
continue;
|
2024-02-16 02:25:32 +08:00
|
|
|
if (rm_type == MPTCP_MIB_RMADDR && remote_id != rm_id)
|
2022-07-12 03:16:32 +08:00
|
|
|
continue;
|
2024-08-28 14:14:25 +08:00
|
|
|
if (rm_type == MPTCP_MIB_RMSUBFLOW && id != rm_id)
|
2021-03-13 09:16:15 +08:00
|
|
|
continue;
|
2020-09-24 08:29:49 +08:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug(" -> %s rm_list_ids[%d]=%u local_id=%u remote_id=%u mpc_id=%u\n",
|
2021-03-31 08:08:52 +08:00
|
|
|
rm_type == MPTCP_MIB_RMADDR ? "address" : "subflow",
|
2024-02-16 02:25:32 +08:00
|
|
|
i, rm_id, id, remote_id, msk->mpc_endpoint_id);
|
2021-03-13 09:16:15 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
mptcp_subflow_shutdown(sk, ssk, how);
|
mptcp: pm: fix UaF read in mptcp_pm_nl_rm_addr_or_subflow
commit 7decd1f5904a489d3ccdcf131972f94645681689 upstream.
Syzkaller reported this splat:
==================================================================
BUG: KASAN: slab-use-after-free in mptcp_pm_nl_rm_addr_or_subflow+0xb44/0xcc0 net/mptcp/pm_netlink.c:881
Read of size 4 at addr ffff8880569ac858 by task syz.1.2799/14662
CPU: 0 UID: 0 PID: 14662 Comm: syz.1.2799 Not tainted 6.12.0-rc2-syzkaller-00307-g36c254515dc6 #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:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:377 [inline]
print_report+0xc3/0x620 mm/kasan/report.c:488
kasan_report+0xd9/0x110 mm/kasan/report.c:601
mptcp_pm_nl_rm_addr_or_subflow+0xb44/0xcc0 net/mptcp/pm_netlink.c:881
mptcp_pm_nl_rm_subflow_received net/mptcp/pm_netlink.c:914 [inline]
mptcp_nl_remove_id_zero_address+0x305/0x4a0 net/mptcp/pm_netlink.c:1572
mptcp_pm_nl_del_addr_doit+0x5c9/0x770 net/mptcp/pm_netlink.c:1603
genl_family_rcv_msg_doit+0x202/0x2f0 net/netlink/genetlink.c:1115
genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
genl_rcv_msg+0x565/0x800 net/netlink/genetlink.c:1210
netlink_rcv_skb+0x165/0x410 net/netlink/af_netlink.c:2551
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
netlink_unicast_kernel net/netlink/af_netlink.c:1331 [inline]
netlink_unicast+0x53c/0x7f0 net/netlink/af_netlink.c:1357
netlink_sendmsg+0x8b8/0xd70 net/netlink/af_netlink.c:1901
sock_sendmsg_nosec net/socket.c:729 [inline]
__sock_sendmsg net/socket.c:744 [inline]
____sys_sendmsg+0x9ae/0xb40 net/socket.c:2607
___sys_sendmsg+0x135/0x1e0 net/socket.c:2661
__sys_sendmsg+0x117/0x1f0 net/socket.c:2690
do_syscall_32_irqs_on arch/x86/entry/common.c:165 [inline]
__do_fast_syscall_32+0x73/0x120 arch/x86/entry/common.c:386
do_fast_syscall_32+0x32/0x80 arch/x86/entry/common.c:411
entry_SYSENTER_compat_after_hwframe+0x84/0x8e
RIP: 0023:0xf7fe4579
Code: b8 01 10 06 03 74 b4 01 10 07 03 74 b0 01 10 08 03 74 d8 01 00 00 00 00 00 00 00 00 00 00 00 00 00 51 52 55 89 e5 0f 34 cd 80 <5d> 5a 59 c3 90 90 90 90 8d b4 26 00 00 00 00 8d b4 26 00 00 00 00
RSP: 002b:00000000f574556c EFLAGS: 00000296 ORIG_RAX: 0000000000000172
RAX: ffffffffffffffda RBX: 000000000000000b RCX: 0000000020000140
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000296 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
</TASK>
Allocated by task 5387:
kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
kasan_save_track+0x14/0x30 mm/kasan/common.c:68
poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
__kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
kmalloc_noprof include/linux/slab.h:878 [inline]
kzalloc_noprof include/linux/slab.h:1014 [inline]
subflow_create_ctx+0x87/0x2a0 net/mptcp/subflow.c:1803
subflow_ulp_init+0xc3/0x4d0 net/mptcp/subflow.c:1956
__tcp_set_ulp net/ipv4/tcp_ulp.c:146 [inline]
tcp_set_ulp+0x326/0x7f0 net/ipv4/tcp_ulp.c:167
mptcp_subflow_create_socket+0x4ae/0x10a0 net/mptcp/subflow.c:1764
__mptcp_subflow_connect+0x3cc/0x1490 net/mptcp/subflow.c:1592
mptcp_pm_create_subflow_or_signal_addr+0xbda/0x23a0 net/mptcp/pm_netlink.c:642
mptcp_pm_nl_fully_established net/mptcp/pm_netlink.c:650 [inline]
mptcp_pm_nl_work+0x3a1/0x4f0 net/mptcp/pm_netlink.c:943
mptcp_worker+0x15a/0x1240 net/mptcp/protocol.c:2777
process_one_work+0x958/0x1b30 kernel/workqueue.c:3229
process_scheduled_works kernel/workqueue.c:3310 [inline]
worker_thread+0x6c8/0xf00 kernel/workqueue.c:3391
kthread+0x2c1/0x3a0 kernel/kthread.c:389
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
Freed by task 113:
kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
kasan_save_track+0x14/0x30 mm/kasan/common.c:68
kasan_save_free_info+0x3b/0x60 mm/kasan/generic.c:579
poison_slab_object mm/kasan/common.c:247 [inline]
__kasan_slab_free+0x51/0x70 mm/kasan/common.c:264
kasan_slab_free include/linux/kasan.h:230 [inline]
slab_free_hook mm/slub.c:2342 [inline]
slab_free mm/slub.c:4579 [inline]
kfree+0x14f/0x4b0 mm/slub.c:4727
kvfree+0x47/0x50 mm/util.c:701
kvfree_rcu_list+0xf5/0x2c0 kernel/rcu/tree.c:3423
kvfree_rcu_drain_ready kernel/rcu/tree.c:3563 [inline]
kfree_rcu_monitor+0x503/0x8b0 kernel/rcu/tree.c:3632
kfree_rcu_shrink_scan+0x245/0x3a0 kernel/rcu/tree.c:3966
do_shrink_slab+0x44f/0x11c0 mm/shrinker.c:435
shrink_slab+0x32b/0x12a0 mm/shrinker.c:662
shrink_one+0x47e/0x7b0 mm/vmscan.c:4818
shrink_many mm/vmscan.c:4879 [inline]
lru_gen_shrink_node mm/vmscan.c:4957 [inline]
shrink_node+0x2452/0x39d0 mm/vmscan.c:5937
kswapd_shrink_node mm/vmscan.c:6765 [inline]
balance_pgdat+0xc19/0x18f0 mm/vmscan.c:6957
kswapd+0x5ea/0xbf0 mm/vmscan.c:7226
kthread+0x2c1/0x3a0 kernel/kthread.c:389
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
Last potentially related work creation:
kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
__kasan_record_aux_stack+0xba/0xd0 mm/kasan/generic.c:541
kvfree_call_rcu+0x74/0xbe0 kernel/rcu/tree.c:3810
subflow_ulp_release+0x2ae/0x350 net/mptcp/subflow.c:2009
tcp_cleanup_ulp+0x7c/0x130 net/ipv4/tcp_ulp.c:124
tcp_v4_destroy_sock+0x1c5/0x6a0 net/ipv4/tcp_ipv4.c:2541
inet_csk_destroy_sock+0x1a3/0x440 net/ipv4/inet_connection_sock.c:1293
tcp_done+0x252/0x350 net/ipv4/tcp.c:4870
tcp_rcv_state_process+0x379b/0x4f30 net/ipv4/tcp_input.c:6933
tcp_v4_do_rcv+0x1ad/0xa90 net/ipv4/tcp_ipv4.c:1938
sk_backlog_rcv include/net/sock.h:1115 [inline]
__release_sock+0x31b/0x400 net/core/sock.c:3072
__tcp_close+0x4f3/0xff0 net/ipv4/tcp.c:3142
__mptcp_close_ssk+0x331/0x14d0 net/mptcp/protocol.c:2489
mptcp_close_ssk net/mptcp/protocol.c:2543 [inline]
mptcp_close_ssk+0x150/0x220 net/mptcp/protocol.c:2526
mptcp_pm_nl_rm_addr_or_subflow+0x2be/0xcc0 net/mptcp/pm_netlink.c:878
mptcp_pm_nl_rm_subflow_received net/mptcp/pm_netlink.c:914 [inline]
mptcp_nl_remove_id_zero_address+0x305/0x4a0 net/mptcp/pm_netlink.c:1572
mptcp_pm_nl_del_addr_doit+0x5c9/0x770 net/mptcp/pm_netlink.c:1603
genl_family_rcv_msg_doit+0x202/0x2f0 net/netlink/genetlink.c:1115
genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
genl_rcv_msg+0x565/0x800 net/netlink/genetlink.c:1210
netlink_rcv_skb+0x165/0x410 net/netlink/af_netlink.c:2551
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
netlink_unicast_kernel net/netlink/af_netlink.c:1331 [inline]
netlink_unicast+0x53c/0x7f0 net/netlink/af_netlink.c:1357
netlink_sendmsg+0x8b8/0xd70 net/netlink/af_netlink.c:1901
sock_sendmsg_nosec net/socket.c:729 [inline]
__sock_sendmsg net/socket.c:744 [inline]
____sys_sendmsg+0x9ae/0xb40 net/socket.c:2607
___sys_sendmsg+0x135/0x1e0 net/socket.c:2661
__sys_sendmsg+0x117/0x1f0 net/socket.c:2690
do_syscall_32_irqs_on arch/x86/entry/common.c:165 [inline]
__do_fast_syscall_32+0x73/0x120 arch/x86/entry/common.c:386
do_fast_syscall_32+0x32/0x80 arch/x86/entry/common.c:411
entry_SYSENTER_compat_after_hwframe+0x84/0x8e
The buggy address belongs to the object at ffff8880569ac800
which belongs to the cache kmalloc-512 of size 512
The buggy address is located 88 bytes inside of
freed 512-byte region [ffff8880569ac800, ffff8880569aca00)
The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x569ac
head: order:2 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x4fff00000000040(head|node=1|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 04fff00000000040 ffff88801ac42c80 dead000000000100 dead000000000122
raw: 0000000000000000 0000000080100010 00000001f5000000 0000000000000000
head: 04fff00000000040 ffff88801ac42c80 dead000000000100 dead000000000122
head: 0000000000000000 0000000080100010 00000001f5000000 0000000000000000
head: 04fff00000000002 ffffea00015a6b01 ffffffffffffffff 0000000000000000
head: 0000000000000004 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 2, migratetype Unmovable, gfp_mask 0xd20c0(__GFP_IO|__GFP_FS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 10238, tgid 10238 (kworker/u32:6), ts 597403252405, free_ts 597177952947
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x2d1/0x350 mm/page_alloc.c:1537
prep_new_page mm/page_alloc.c:1545 [inline]
get_page_from_freelist+0x101e/0x3070 mm/page_alloc.c:3457
__alloc_pages_noprof+0x223/0x25a0 mm/page_alloc.c:4733
alloc_pages_mpol_noprof+0x2c9/0x610 mm/mempolicy.c:2265
alloc_slab_page mm/slub.c:2412 [inline]
allocate_slab mm/slub.c:2578 [inline]
new_slab+0x2ba/0x3f0 mm/slub.c:2631
___slab_alloc+0xd1d/0x16f0 mm/slub.c:3818
__slab_alloc.constprop.0+0x56/0xb0 mm/slub.c:3908
__slab_alloc_node mm/slub.c:3961 [inline]
slab_alloc_node mm/slub.c:4122 [inline]
__kmalloc_cache_noprof+0x2c5/0x310 mm/slub.c:4290
kmalloc_noprof include/linux/slab.h:878 [inline]
kzalloc_noprof include/linux/slab.h:1014 [inline]
mld_add_delrec net/ipv6/mcast.c:743 [inline]
igmp6_leave_group net/ipv6/mcast.c:2625 [inline]
igmp6_group_dropped+0x4ab/0xe40 net/ipv6/mcast.c:723
__ipv6_dev_mc_dec+0x281/0x360 net/ipv6/mcast.c:979
addrconf_leave_solict net/ipv6/addrconf.c:2253 [inline]
__ipv6_ifa_notify+0x3f6/0xc30 net/ipv6/addrconf.c:6283
addrconf_ifdown.isra.0+0xef9/0x1a20 net/ipv6/addrconf.c:3982
addrconf_notify+0x220/0x19c0 net/ipv6/addrconf.c:3781
notifier_call_chain+0xb9/0x410 kernel/notifier.c:93
call_netdevice_notifiers_info+0xbe/0x140 net/core/dev.c:1996
call_netdevice_notifiers_extack net/core/dev.c:2034 [inline]
call_netdevice_notifiers net/core/dev.c:2048 [inline]
dev_close_many+0x333/0x6a0 net/core/dev.c:1589
page last free pid 13136 tgid 13136 stack trace:
reset_page_owner include/linux/page_owner.h:25 [inline]
free_pages_prepare mm/page_alloc.c:1108 [inline]
free_unref_page+0x5f4/0xdc0 mm/page_alloc.c:2638
stack_depot_save_flags+0x2da/0x900 lib/stackdepot.c:666
kasan_save_stack+0x42/0x60 mm/kasan/common.c:48
kasan_save_track+0x14/0x30 mm/kasan/common.c:68
unpoison_slab_object mm/kasan/common.c:319 [inline]
__kasan_slab_alloc+0x89/0x90 mm/kasan/common.c:345
kasan_slab_alloc include/linux/kasan.h:247 [inline]
slab_post_alloc_hook mm/slub.c:4085 [inline]
slab_alloc_node mm/slub.c:4134 [inline]
kmem_cache_alloc_noprof+0x121/0x2f0 mm/slub.c:4141
skb_clone+0x190/0x3f0 net/core/skbuff.c:2084
do_one_broadcast net/netlink/af_netlink.c:1462 [inline]
netlink_broadcast_filtered+0xb11/0xef0 net/netlink/af_netlink.c:1540
netlink_broadcast+0x39/0x50 net/netlink/af_netlink.c:1564
uevent_net_broadcast_untagged lib/kobject_uevent.c:331 [inline]
kobject_uevent_net_broadcast lib/kobject_uevent.c:410 [inline]
kobject_uevent_env+0xacd/0x1670 lib/kobject_uevent.c:608
device_del+0x623/0x9f0 drivers/base/core.c:3882
snd_card_disconnect.part.0+0x58a/0x7c0 sound/core/init.c:546
snd_card_disconnect+0x1f/0x30 sound/core/init.c:495
snd_usx2y_disconnect+0xe9/0x1f0 sound/usb/usx2y/usbusx2y.c:417
usb_unbind_interface+0x1e8/0x970 drivers/usb/core/driver.c:461
device_remove drivers/base/dd.c:569 [inline]
device_remove+0x122/0x170 drivers/base/dd.c:561
That's because 'subflow' is used just after 'mptcp_close_ssk(subflow)',
which will initiate the release of its memory. Even if it is very likely
the release and the re-utilisation will be done later on, it is of
course better to avoid any issues and read the content of 'subflow'
before closing it.
Fixes: 1c1f72137598 ("mptcp: pm: only decrement add_addr_accepted for MPJ req")
Cc: stable@vger.kernel.org
Reported-by: syzbot+3c8b7a8e7df6a2a226ca@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/670d7337.050a0220.4cbc0.004f.GAE@google.com
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/20241015-net-mptcp-uaf-pm-rm-v1-1-c4ee5d987a64@kernel.org
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-10-15 16:38:47 +08:00
|
|
|
removed |= subflow->request_join;
|
2022-01-07 08:20:23 +08:00
|
|
|
|
|
|
|
/* the following takes care of updating the subflows counter */
|
2021-03-13 09:16:15 +08:00
|
|
|
mptcp_close_ssk(sk, ssk, subflow);
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2020-09-24 08:29:49 +08:00
|
|
|
|
2024-06-07 23:01:49 +08:00
|
|
|
if (rm_type == MPTCP_MIB_RMSUBFLOW)
|
|
|
|
__MPTCP_INC_STATS(sock_net(sk), rm_type);
|
2021-03-13 09:16:15 +08:00
|
|
|
}
|
2024-08-20 03:45:26 +08:00
|
|
|
|
|
|
|
if (rm_type == MPTCP_MIB_RMADDR)
|
2024-06-07 23:01:49 +08:00
|
|
|
__MPTCP_INC_STATS(sock_net(sk), rm_type);
|
2024-08-20 03:45:26 +08:00
|
|
|
|
2022-01-07 08:20:20 +08:00
|
|
|
if (!removed)
|
|
|
|
continue;
|
|
|
|
|
2022-05-03 04:52:31 +08:00
|
|
|
if (!mptcp_pm_is_kernel(msk))
|
|
|
|
continue;
|
|
|
|
|
2024-08-20 03:45:27 +08:00
|
|
|
if (rm_type == MPTCP_MIB_RMADDR && rm_id &&
|
|
|
|
!WARN_ON_ONCE(msk->pm.add_addr_accepted == 0)) {
|
|
|
|
/* Note: if the subflow has been closed before, this
|
|
|
|
* add_addr_accepted counter will not be decremented.
|
|
|
|
*/
|
2024-08-20 03:45:28 +08:00
|
|
|
if (--msk->pm.add_addr_accepted < mptcp_pm_get_add_addr_accept_max(msk))
|
|
|
|
WRITE_ONCE(msk->pm.accept_addr, true);
|
2022-01-07 08:20:20 +08:00
|
|
|
}
|
2020-09-24 08:29:49 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-31 08:08:52 +08:00
|
|
|
static void mptcp_pm_nl_rm_addr_received(struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
mptcp_pm_nl_rm_addr_or_subflow(msk, &msk->pm.rm_list_rx, MPTCP_MIB_RMADDR);
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:45:25 +08:00
|
|
|
static void mptcp_pm_nl_rm_subflow_received(struct mptcp_sock *msk,
|
|
|
|
const struct mptcp_rm_list *rm_list)
|
2021-03-31 08:08:52 +08:00
|
|
|
{
|
|
|
|
mptcp_pm_nl_rm_addr_or_subflow(msk, rm_list, MPTCP_MIB_RMSUBFLOW);
|
|
|
|
}
|
|
|
|
|
2021-02-13 07:59:54 +08:00
|
|
|
void mptcp_pm_nl_work(struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
struct mptcp_pm_data *pm = &msk->pm;
|
|
|
|
|
|
|
|
msk_owned_by_me(msk);
|
|
|
|
|
2022-01-07 08:20:22 +08:00
|
|
|
if (!(pm->status & MPTCP_PM_WORK_MASK))
|
|
|
|
return;
|
|
|
|
|
2021-02-13 07:59:54 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("msk=%p status=%x\n", msk, pm->status);
|
2021-02-13 07:59:54 +08:00
|
|
|
if (pm->status & BIT(MPTCP_PM_ADD_ADDR_RECEIVED)) {
|
|
|
|
pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_RECEIVED);
|
|
|
|
mptcp_pm_nl_add_addr_received(msk);
|
|
|
|
}
|
|
|
|
if (pm->status & BIT(MPTCP_PM_ADD_ADDR_SEND_ACK)) {
|
|
|
|
pm->status &= ~BIT(MPTCP_PM_ADD_ADDR_SEND_ACK);
|
2021-03-27 02:26:41 +08:00
|
|
|
mptcp_pm_nl_addr_send_ack(msk);
|
2021-02-13 07:59:54 +08:00
|
|
|
}
|
|
|
|
if (pm->status & BIT(MPTCP_PM_RM_ADDR_RECEIVED)) {
|
|
|
|
pm->status &= ~BIT(MPTCP_PM_RM_ADDR_RECEIVED);
|
|
|
|
mptcp_pm_nl_rm_addr_received(msk);
|
|
|
|
}
|
|
|
|
if (pm->status & BIT(MPTCP_PM_ESTABLISHED)) {
|
|
|
|
pm->status &= ~BIT(MPTCP_PM_ESTABLISHED);
|
|
|
|
mptcp_pm_nl_fully_established(msk);
|
|
|
|
}
|
|
|
|
if (pm->status & BIT(MPTCP_PM_SUBFLOW_ESTABLISHED)) {
|
|
|
|
pm->status &= ~BIT(MPTCP_PM_SUBFLOW_ESTABLISHED);
|
|
|
|
mptcp_pm_nl_subflow_established(msk);
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static bool address_use_port(struct mptcp_pm_addr_entry *entry)
|
|
|
|
{
|
2021-04-07 08:15:57 +08:00
|
|
|
return (entry->flags &
|
2020-03-28 05:48:51 +08:00
|
|
|
(MPTCP_PM_ADDR_FLAG_SIGNAL | MPTCP_PM_ADDR_FLAG_SUBFLOW)) ==
|
|
|
|
MPTCP_PM_ADDR_FLAG_SIGNAL;
|
|
|
|
}
|
|
|
|
|
2022-03-08 04:44:36 +08:00
|
|
|
/* caller must ensure the RCU grace period is already elapsed */
|
|
|
|
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
|
|
|
|
{
|
|
|
|
if (entry->lsk)
|
|
|
|
sock_release(entry->lsk);
|
|
|
|
kfree(entry);
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static int mptcp_pm_nl_append_new_local_addr(struct pm_nl_pernet *pernet,
|
2024-02-16 02:25:29 +08:00
|
|
|
struct mptcp_pm_addr_entry *entry,
|
|
|
|
bool needs_id)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2022-03-08 04:44:36 +08:00
|
|
|
struct mptcp_pm_addr_entry *cur, *del_entry = NULL;
|
2021-02-02 07:09:06 +08:00
|
|
|
unsigned int addr_max;
|
2020-03-28 05:48:51 +08:00
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
|
|
|
/* to keep the code simple, don't do IDR-like allocation for address ID,
|
|
|
|
* just bail when we exceed limits
|
|
|
|
*/
|
2022-01-07 08:20:22 +08:00
|
|
|
if (pernet->next_id == MPTCP_PM_MAX_ADDR_ID)
|
2021-01-09 08:47:55 +08:00
|
|
|
pernet->next_id = 1;
|
2022-11-19 02:46:08 +08:00
|
|
|
if (pernet->addrs >= MPTCP_PM_ADDR_MAX) {
|
|
|
|
ret = -ERANGE;
|
2020-03-28 05:48:51 +08:00
|
|
|
goto out;
|
2022-11-19 02:46:08 +08:00
|
|
|
}
|
|
|
|
if (test_bit(entry->addr.id, pernet->id_bitmap)) {
|
|
|
|
ret = -EBUSY;
|
2021-01-09 08:47:55 +08:00
|
|
|
goto out;
|
2022-11-19 02:46:08 +08:00
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
/* do not insert duplicate address, differentiate on port only
|
|
|
|
* singled addresses
|
|
|
|
*/
|
2022-07-12 03:16:30 +08:00
|
|
|
if (!address_use_port(entry))
|
|
|
|
entry->addr.port = 0;
|
2020-03-28 05:48:51 +08:00
|
|
|
list_for_each_entry(cur, &pernet->local_addr_list, list) {
|
2022-05-04 10:38:49 +08:00
|
|
|
if (mptcp_addresses_equal(&cur->addr, &entry->addr,
|
2022-07-12 03:16:30 +08:00
|
|
|
cur->addr.port || entry->addr.port)) {
|
2022-03-08 04:44:36 +08:00
|
|
|
/* allow replacing the exiting endpoint only if such
|
|
|
|
* endpoint is an implicit one and the user-space
|
|
|
|
* did not provide an endpoint id
|
|
|
|
*/
|
2022-11-19 02:46:08 +08:00
|
|
|
if (!(cur->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT)) {
|
|
|
|
ret = -EEXIST;
|
2022-03-08 04:44:36 +08:00
|
|
|
goto out;
|
2022-11-19 02:46:08 +08:00
|
|
|
}
|
2022-03-08 04:44:36 +08:00
|
|
|
if (entry->addr.id)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
pernet->addrs--;
|
|
|
|
entry->addr.id = cur->addr.id;
|
|
|
|
list_del_rcu(&cur->list);
|
|
|
|
del_entry = cur;
|
|
|
|
break;
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2024-02-16 02:25:29 +08:00
|
|
|
if (!entry->addr.id && needs_id) {
|
2021-01-09 08:47:55 +08:00
|
|
|
find_next:
|
|
|
|
entry->addr.id = find_next_zero_bit(pernet->id_bitmap,
|
2022-01-07 08:20:22 +08:00
|
|
|
MPTCP_PM_MAX_ADDR_ID + 1,
|
2021-01-09 08:47:55 +08:00
|
|
|
pernet->next_id);
|
2021-12-18 07:37:02 +08:00
|
|
|
if (!entry->addr.id && pernet->next_id != 1) {
|
2021-01-09 08:47:55 +08:00
|
|
|
pernet->next_id = 1;
|
|
|
|
goto find_next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-16 02:25:29 +08:00
|
|
|
if (!entry->addr.id && needs_id)
|
2021-01-09 08:47:55 +08:00
|
|
|
goto out;
|
|
|
|
|
|
|
|
__set_bit(entry->addr.id, pernet->id_bitmap);
|
|
|
|
if (entry->addr.id > pernet->next_id)
|
|
|
|
pernet->next_id = entry->addr.id;
|
|
|
|
|
2021-04-07 08:15:57 +08:00
|
|
|
if (entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
|
2021-02-02 07:09:06 +08:00
|
|
|
addr_max = pernet->add_addr_signal_max;
|
|
|
|
WRITE_ONCE(pernet->add_addr_signal_max, addr_max + 1);
|
|
|
|
}
|
2021-04-07 08:15:57 +08:00
|
|
|
if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
|
2021-02-02 07:09:06 +08:00
|
|
|
addr_max = pernet->local_addr_max;
|
|
|
|
WRITE_ONCE(pernet->local_addr_max, addr_max + 1);
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
pernet->addrs++;
|
2022-07-12 03:16:30 +08:00
|
|
|
if (!entry->addr.port)
|
|
|
|
list_add_tail_rcu(&entry->list, &pernet->local_addr_list);
|
|
|
|
else
|
|
|
|
list_add_rcu(&entry->list, &pernet->local_addr_list);
|
2020-03-28 05:48:51 +08:00
|
|
|
ret = entry->addr.id;
|
|
|
|
|
|
|
|
out:
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
2022-03-08 04:44:36 +08:00
|
|
|
|
|
|
|
/* just replaced an existing entry, free it */
|
|
|
|
if (del_entry) {
|
|
|
|
synchronize_rcu();
|
|
|
|
__mptcp_pm_release_addr_entry(del_entry);
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-03-09 22:50:04 +08:00
|
|
|
static struct lock_class_key mptcp_slock_keys[2];
|
|
|
|
static struct lock_class_key mptcp_keys[2];
|
|
|
|
|
2021-02-02 07:09:12 +08:00
|
|
|
static int mptcp_pm_nl_create_listen_socket(struct sock *sk,
|
|
|
|
struct mptcp_pm_addr_entry *entry)
|
|
|
|
{
|
2023-03-09 22:50:04 +08:00
|
|
|
bool is_ipv6 = sk->sk_family == AF_INET6;
|
2022-02-10 09:25:08 +08:00
|
|
|
int addrlen = sizeof(struct sockaddr_in);
|
2021-02-02 07:09:12 +08:00
|
|
|
struct sockaddr_storage addr;
|
2023-08-11 23:57:24 +08:00
|
|
|
struct sock *newsk, *ssk;
|
2021-02-02 07:09:12 +08:00
|
|
|
int backlog = 1024;
|
|
|
|
int err;
|
|
|
|
|
|
|
|
err = sock_create_kern(sock_net(sk), entry->addr.family,
|
|
|
|
SOCK_STREAM, IPPROTO_MPTCP, &entry->lsk);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2023-02-07 21:04:15 +08:00
|
|
|
newsk = entry->lsk->sk;
|
|
|
|
if (!newsk)
|
2022-11-19 02:46:07 +08:00
|
|
|
return -EINVAL;
|
2021-02-02 07:09:12 +08:00
|
|
|
|
2023-03-09 22:50:04 +08:00
|
|
|
/* The subflow socket lock is acquired in a nested to the msk one
|
|
|
|
* in several places, even by the TCP stack, and this msk is a kernel
|
|
|
|
* socket: lockdep complains. Instead of propagating the _nested
|
|
|
|
* modifiers in several places, re-init the lock class for the msk
|
|
|
|
* socket to an mptcp specific one.
|
|
|
|
*/
|
|
|
|
sock_lock_init_class_and_name(newsk,
|
|
|
|
is_ipv6 ? "mlock-AF_INET6" : "mlock-AF_INET",
|
|
|
|
&mptcp_slock_keys[is_ipv6],
|
|
|
|
is_ipv6 ? "msk_lock-AF_INET6" : "msk_lock-AF_INET",
|
|
|
|
&mptcp_keys[is_ipv6]);
|
|
|
|
|
2023-02-07 21:04:15 +08:00
|
|
|
lock_sock(newsk);
|
2023-08-11 23:57:25 +08:00
|
|
|
ssk = __mptcp_nmpc_sk(mptcp_sk(newsk));
|
2023-02-07 21:04:15 +08:00
|
|
|
release_sock(newsk);
|
2023-08-11 23:57:25 +08:00
|
|
|
if (IS_ERR(ssk))
|
|
|
|
return PTR_ERR(ssk);
|
2021-02-02 07:09:12 +08:00
|
|
|
|
|
|
|
mptcp_info2sockaddr(&entry->addr, &addr, entry->addr.family);
|
2022-02-10 09:25:08 +08:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (entry->addr.family == AF_INET6)
|
|
|
|
addrlen = sizeof(struct sockaddr_in6);
|
|
|
|
#endif
|
2023-08-11 23:57:24 +08:00
|
|
|
if (ssk->sk_family == AF_INET)
|
|
|
|
err = inet_bind_sk(ssk, (struct sockaddr *)&addr, addrlen);
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
else if (ssk->sk_family == AF_INET6)
|
|
|
|
err = inet6_bind_sk(ssk, (struct sockaddr *)&addr, addrlen);
|
|
|
|
#endif
|
2022-11-19 02:46:08 +08:00
|
|
|
if (err)
|
2022-11-19 02:46:07 +08:00
|
|
|
return err;
|
2021-02-02 07:09:12 +08:00
|
|
|
|
2023-12-22 20:47:23 +08:00
|
|
|
/* We don't use mptcp_set_state() here because it needs to be called
|
|
|
|
* under the msk socket lock. For the moment, that will not bring
|
|
|
|
* anything more than only calling inet_sk_state_store(), because the
|
|
|
|
* old status is known (TCP_CLOSE).
|
|
|
|
*/
|
2023-06-21 00:24:23 +08:00
|
|
|
inet_sk_state_store(newsk, TCP_LISTEN);
|
2023-08-11 23:57:24 +08:00
|
|
|
lock_sock(ssk);
|
mptcp: prevent MPC handshake on port-based signal endpoints
commit 3d041393ea8c815f773020fb4a995331a69c0139 upstream.
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>
[ Conflicts in mib.[ch], because commit 6982826fe5e5 ("mptcp: fallback
to TCP after SYN+MPC drops"), and commit 27069e7cb3d1 ("mptcp: disable
active MPTCP in case of blackhole") are linked to new features, not
available in this version. Resolving the conflicts is easy, simply
adding the new lines declaring the new "endpoint attempt" MIB entry. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-10-14 22:06:00 +08:00
|
|
|
WRITE_ONCE(mptcp_subflow_ctx(ssk)->pm_listener, true);
|
2023-08-11 23:57:24 +08:00
|
|
|
err = __inet_listen_sk(ssk, backlog);
|
|
|
|
if (!err)
|
|
|
|
mptcp_event_pm_listener(ssk, MPTCP_EVENT_LISTENER_CREATED);
|
|
|
|
release_sock(ssk);
|
|
|
|
return err;
|
2021-02-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
|
2023-06-08 21:20:50 +08:00
|
|
|
int mptcp_pm_nl_get_local_id(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
struct pm_nl_pernet *pernet;
|
|
|
|
int ret = -1;
|
|
|
|
|
2022-04-09 03:45:57 +08:00
|
|
|
pernet = pm_nl_get_pernet_from_msk(msk);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
|
2023-06-08 21:20:50 +08:00
|
|
|
if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
|
2020-03-28 05:48:51 +08:00
|
|
|
ret = entry->addr.id;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
if (ret >= 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
/* address not found, add to local list */
|
2020-09-09 11:01:24 +08:00
|
|
|
entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (!entry)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
2023-06-08 21:20:50 +08:00
|
|
|
entry->addr = *skc;
|
2021-01-09 08:47:55 +08:00
|
|
|
entry->addr.id = 0;
|
2021-02-02 07:09:12 +08:00
|
|
|
entry->addr.port = 0;
|
2021-04-07 08:15:57 +08:00
|
|
|
entry->ifindex = 0;
|
2022-03-08 04:44:36 +08:00
|
|
|
entry->flags = MPTCP_PM_ADDR_FLAG_IMPLICIT;
|
2021-02-02 07:09:12 +08:00
|
|
|
entry->lsk = NULL;
|
2024-02-16 02:25:29 +08:00
|
|
|
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry, true);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (ret < 0)
|
|
|
|
kfree(entry);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-07-27 18:01:28 +08:00
|
|
|
bool mptcp_pm_nl_is_backup(struct mptcp_sock *msk, struct mptcp_addr_info *skc)
|
|
|
|
{
|
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet_from_msk(msk);
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
bool backup = false;
|
|
|
|
|
|
|
|
rcu_read_lock();
|
|
|
|
list_for_each_entry_rcu(entry, &pernet->local_addr_list, list) {
|
|
|
|
if (mptcp_addresses_equal(&entry->addr, skc, entry->addr.port)) {
|
|
|
|
backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rcu_read_unlock();
|
|
|
|
|
|
|
|
return backup;
|
|
|
|
}
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
#define MPTCP_PM_CMD_GRP_OFFSET 0
|
|
|
|
#define MPTCP_PM_EV_GRP_OFFSET 1
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
static const struct genl_multicast_group mptcp_pm_mcgrps[] = {
|
|
|
|
[MPTCP_PM_CMD_GRP_OFFSET] = { .name = MPTCP_PM_CMD_GRP_NAME, },
|
2021-02-13 08:00:01 +08:00
|
|
|
[MPTCP_PM_EV_GRP_OFFSET] = { .name = MPTCP_PM_EV_GRP_NAME,
|
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
|
|
|
},
|
2020-03-28 05:48:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static const struct nla_policy
|
|
|
|
mptcp_pm_addr_policy[MPTCP_PM_ADDR_ATTR_MAX + 1] = {
|
|
|
|
[MPTCP_PM_ADDR_ATTR_FAMILY] = { .type = NLA_U16, },
|
|
|
|
[MPTCP_PM_ADDR_ATTR_ID] = { .type = NLA_U8, },
|
|
|
|
[MPTCP_PM_ADDR_ATTR_ADDR4] = { .type = NLA_U32, },
|
2020-08-18 16:17:31 +08:00
|
|
|
[MPTCP_PM_ADDR_ATTR_ADDR6] =
|
|
|
|
NLA_POLICY_EXACT_LEN(sizeof(struct in6_addr)),
|
2020-03-28 05:48:51 +08:00
|
|
|
[MPTCP_PM_ADDR_ATTR_PORT] = { .type = NLA_U16 },
|
|
|
|
[MPTCP_PM_ADDR_ATTR_FLAGS] = { .type = NLA_U32 },
|
|
|
|
[MPTCP_PM_ADDR_ATTR_IF_IDX] = { .type = NLA_S32 },
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct nla_policy mptcp_pm_policy[MPTCP_PM_ATTR_MAX + 1] = {
|
|
|
|
[MPTCP_PM_ATTR_ADDR] =
|
|
|
|
NLA_POLICY_NESTED(mptcp_pm_addr_policy),
|
|
|
|
[MPTCP_PM_ATTR_RCV_ADD_ADDRS] = { .type = NLA_U32, },
|
|
|
|
[MPTCP_PM_ATTR_SUBFLOWS] = { .type = NLA_U32, },
|
2022-05-04 10:38:52 +08:00
|
|
|
[MPTCP_PM_ATTR_TOKEN] = { .type = NLA_U32, },
|
2022-05-04 10:38:54 +08:00
|
|
|
[MPTCP_PM_ATTR_LOC_ID] = { .type = NLA_U8, },
|
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 10:38:56 +08:00
|
|
|
[MPTCP_PM_ATTR_ADDR_REMOTE] =
|
|
|
|
NLA_POLICY_NESTED(mptcp_pm_addr_policy),
|
2020-03-28 05:48:51 +08:00
|
|
|
};
|
|
|
|
|
2021-08-14 06:15:45 +08:00
|
|
|
void mptcp_pm_nl_subflow_chk_stale(const struct mptcp_sock *msk, struct sock *ssk)
|
|
|
|
{
|
|
|
|
struct mptcp_subflow_context *iter, *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
unsigned int active_max_loss_cnt;
|
|
|
|
struct net *net = sock_net(sk);
|
|
|
|
unsigned int stale_loss_cnt;
|
|
|
|
bool slow;
|
|
|
|
|
|
|
|
stale_loss_cnt = mptcp_stale_loss_cnt(net);
|
|
|
|
if (subflow->stale || !stale_loss_cnt || subflow->stale_count <= stale_loss_cnt)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* look for another available subflow not in loss state */
|
|
|
|
active_max_loss_cnt = max_t(int, stale_loss_cnt - 1, 1);
|
|
|
|
mptcp_for_each_subflow(msk, iter) {
|
|
|
|
if (iter != subflow && mptcp_subflow_active(iter) &&
|
|
|
|
iter->stale_count < active_max_loss_cnt) {
|
|
|
|
/* we have some alternatives, try to mark this subflow as idle ...*/
|
|
|
|
slow = lock_sock_fast(ssk);
|
|
|
|
if (!tcp_rtx_and_write_queues_empty(ssk)) {
|
|
|
|
subflow->stale = 1;
|
|
|
|
__mptcp_retransmit_pending_data(sk);
|
2023-01-07 02:57:18 +08:00
|
|
|
MPTCP_INC_STATS(net, MPTCP_MIB_SUBFLOWSTALE);
|
2021-08-14 06:15:45 +08:00
|
|
|
}
|
|
|
|
unlock_sock_fast(ssk, slow);
|
|
|
|
|
2022-06-27 20:16:25 +08:00
|
|
|
/* always try to push the pending data regardless of re-injections:
|
2021-08-14 06:15:45 +08:00
|
|
|
* we can possibly use backup subflows now, and subflow selection
|
|
|
|
* is cheap under the msk socket lock
|
|
|
|
*/
|
|
|
|
__mptcp_push_pending(sk, 0);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static int mptcp_pm_family_to_addr(int family)
|
|
|
|
{
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
if (family == AF_INET6)
|
|
|
|
return MPTCP_PM_ADDR_ATTR_ADDR6;
|
|
|
|
#endif
|
|
|
|
return MPTCP_PM_ADDR_ATTR_ADDR4;
|
|
|
|
}
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
static int mptcp_pm_parse_pm_addr_attr(struct nlattr *tb[],
|
|
|
|
const struct nlattr *attr,
|
|
|
|
struct genl_info *info,
|
|
|
|
struct mptcp_addr_info *addr,
|
|
|
|
bool require_family)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
int err, addr_addr;
|
|
|
|
|
|
|
|
if (!attr) {
|
|
|
|
GENL_SET_ERR_MSG(info, "missing address info");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* no validation needed - was already done via nested policy */
|
|
|
|
err = nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
|
|
|
|
mptcp_pm_addr_policy, info->extack);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
if (tb[MPTCP_PM_ADDR_ATTR_ID])
|
|
|
|
addr->id = nla_get_u8(tb[MPTCP_PM_ADDR_ATTR_ID]);
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
if (!tb[MPTCP_PM_ADDR_ATTR_FAMILY]) {
|
|
|
|
if (!require_family)
|
2022-12-09 08:44:31 +08:00
|
|
|
return 0;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
NL_SET_ERR_MSG_ATTR(info->extack, attr,
|
|
|
|
"missing family");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
addr->family = nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_FAMILY]);
|
|
|
|
if (addr->family != AF_INET
|
2020-03-28 05:48:51 +08:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2022-05-04 10:38:51 +08:00
|
|
|
&& addr->family != AF_INET6
|
2020-03-28 05:48:51 +08:00
|
|
|
#endif
|
|
|
|
) {
|
|
|
|
NL_SET_ERR_MSG_ATTR(info->extack, attr,
|
|
|
|
"unknown address family");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
2022-05-04 10:38:51 +08:00
|
|
|
addr_addr = mptcp_pm_family_to_addr(addr->family);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (!tb[addr_addr]) {
|
|
|
|
NL_SET_ERR_MSG_ATTR(info->extack, attr,
|
|
|
|
"missing address data");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2022-05-04 10:38:51 +08:00
|
|
|
if (addr->family == AF_INET6)
|
|
|
|
addr->addr6 = nla_get_in6_addr(tb[addr_addr]);
|
2020-03-28 05:48:51 +08:00
|
|
|
else
|
|
|
|
#endif
|
2022-05-04 10:38:51 +08:00
|
|
|
addr->addr.s_addr = nla_get_in_addr(tb[addr_addr]);
|
|
|
|
|
|
|
|
if (tb[MPTCP_PM_ADDR_ATTR_PORT])
|
|
|
|
addr->port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
|
|
|
|
|
2022-12-09 08:44:31 +08:00
|
|
|
return 0;
|
2022-05-04 10:38:51 +08:00
|
|
|
}
|
|
|
|
|
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 10:38:56 +08:00
|
|
|
int mptcp_pm_parse_addr(struct nlattr *attr, struct genl_info *info,
|
|
|
|
struct mptcp_addr_info *addr)
|
|
|
|
{
|
|
|
|
struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
|
|
|
|
|
|
|
|
memset(addr, 0, sizeof(*addr));
|
|
|
|
|
|
|
|
return mptcp_pm_parse_pm_addr_attr(tb, attr, info, addr, true);
|
|
|
|
}
|
|
|
|
|
2022-05-04 10:38:52 +08:00
|
|
|
int mptcp_pm_parse_entry(struct nlattr *attr, struct genl_info *info,
|
|
|
|
bool require_family,
|
|
|
|
struct mptcp_pm_addr_entry *entry)
|
2022-05-04 10:38:51 +08:00
|
|
|
{
|
|
|
|
struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
|
|
|
|
int err;
|
|
|
|
|
|
|
|
memset(entry, 0, sizeof(*entry));
|
|
|
|
|
|
|
|
err = mptcp_pm_parse_pm_addr_attr(tb, attr, info, &entry->addr, require_family);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2020-09-14 16:01:15 +08:00
|
|
|
if (tb[MPTCP_PM_ADDR_ATTR_IF_IDX]) {
|
|
|
|
u32 val = nla_get_s32(tb[MPTCP_PM_ADDR_ATTR_IF_IDX]);
|
|
|
|
|
2021-04-07 08:15:57 +08:00
|
|
|
entry->ifindex = val;
|
2020-09-14 16:01:15 +08:00
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
if (tb[MPTCP_PM_ADDR_ATTR_FLAGS])
|
2021-04-07 08:15:57 +08:00
|
|
|
entry->flags = nla_get_u32(tb[MPTCP_PM_ADDR_ATTR_FLAGS]);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2022-02-05 08:03:29 +08:00
|
|
|
if (tb[MPTCP_PM_ADDR_ATTR_PORT])
|
2021-02-02 07:09:17 +08:00
|
|
|
entry->addr.port = htons(nla_get_u16(tb[MPTCP_PM_ADDR_ATTR_PORT]));
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct pm_nl_pernet *genl_info_pm_nl(struct genl_info *info)
|
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
return pm_nl_get_pernet(genl_info_net(info));
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:29 +08:00
|
|
|
static int mptcp_nl_add_subflow_or_signal_addr(struct net *net,
|
|
|
|
struct mptcp_addr_info *addr)
|
2021-02-02 07:09:08 +08:00
|
|
|
{
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
long s_slot = 0, s_num = 0;
|
|
|
|
|
|
|
|
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
2024-08-28 14:14:29 +08:00
|
|
|
struct mptcp_addr_info mpc_addr;
|
2021-02-02 07:09:08 +08:00
|
|
|
|
2022-04-28 06:50:00 +08:00
|
|
|
if (!READ_ONCE(msk->fully_established) ||
|
|
|
|
mptcp_pm_is_userspace(msk))
|
2021-02-02 07:09:08 +08:00
|
|
|
goto next;
|
|
|
|
|
2024-08-28 14:14:29 +08:00
|
|
|
/* if the endp linked to the init sf is re-added with a != ID */
|
|
|
|
mptcp_local_address((struct sock_common *)msk, &mpc_addr);
|
|
|
|
|
2021-02-02 07:09:08 +08:00
|
|
|
lock_sock(sk);
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2024-08-28 14:14:29 +08:00
|
|
|
if (mptcp_addresses_equal(addr, &mpc_addr, addr->port))
|
|
|
|
msk->mpc_endpoint_id = addr->id;
|
2021-02-02 07:09:08 +08:00
|
|
|
mptcp_pm_create_subflow_or_signal_addr(msk);
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
release_sock(sk);
|
|
|
|
|
|
|
|
next:
|
|
|
|
sock_put(sk);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-02-16 02:25:29 +08:00
|
|
|
static bool mptcp_pm_has_addr_attr_id(const struct nlattr *attr,
|
|
|
|
struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct nlattr *tb[MPTCP_PM_ADDR_ATTR_MAX + 1];
|
|
|
|
|
|
|
|
if (!nla_parse_nested_deprecated(tb, MPTCP_PM_ADDR_ATTR_MAX, attr,
|
|
|
|
mptcp_pm_addr_policy, info->extack) &&
|
|
|
|
tb[MPTCP_PM_ADDR_ATTR_ID])
|
|
|
|
return true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static int mptcp_nl_cmd_add_addr(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
|
|
|
struct mptcp_pm_addr_entry addr, *entry;
|
|
|
|
int ret;
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
ret = mptcp_pm_parse_entry(attr, info, true, &addr);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2024-07-31 19:05:54 +08:00
|
|
|
if (addr.addr.port && !address_use_port(&addr)) {
|
|
|
|
GENL_SET_ERR_MSG(info, "flags must have signal and not subflow when using port");
|
2022-02-05 08:03:29 +08:00
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-03-08 04:44:39 +08:00
|
|
|
if (addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL &&
|
|
|
|
addr.flags & MPTCP_PM_ADDR_FLAG_FULLMESH) {
|
|
|
|
GENL_SET_ERR_MSG(info, "flags mustn't have both signal and fullmesh");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-03-08 04:44:36 +08:00
|
|
|
if (addr.flags & MPTCP_PM_ADDR_FLAG_IMPLICIT) {
|
|
|
|
GENL_SET_ERR_MSG(info, "can't create IMPLICIT endpoint");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
2022-11-19 02:46:07 +08:00
|
|
|
entry = kzalloc(sizeof(*entry), GFP_KERNEL_ACCOUNT);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (!entry) {
|
|
|
|
GENL_SET_ERR_MSG(info, "can't allocate addr");
|
|
|
|
return -ENOMEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
*entry = addr;
|
2021-02-02 07:09:12 +08:00
|
|
|
if (entry->addr.port) {
|
|
|
|
ret = mptcp_pm_nl_create_listen_socket(skb->sk, entry);
|
|
|
|
if (ret) {
|
2022-11-19 02:46:08 +08:00
|
|
|
GENL_SET_ERR_MSG_FMT(info, "create listen socket error: %d", ret);
|
2022-11-19 02:46:07 +08:00
|
|
|
goto out_free;
|
2021-02-02 07:09:12 +08:00
|
|
|
}
|
|
|
|
}
|
2024-02-16 02:25:29 +08:00
|
|
|
ret = mptcp_pm_nl_append_new_local_addr(pernet, entry,
|
|
|
|
!mptcp_pm_has_addr_attr_id(attr, info));
|
2020-03-28 05:48:51 +08:00
|
|
|
if (ret < 0) {
|
2022-11-19 02:46:08 +08:00
|
|
|
GENL_SET_ERR_MSG_FMT(info, "too many addresses or duplicate one: %d", ret);
|
2022-11-19 02:46:07 +08:00
|
|
|
goto out_free;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:29 +08:00
|
|
|
mptcp_nl_add_subflow_or_signal_addr(sock_net(skb->sk), &entry->addr);
|
2020-03-28 05:48:51 +08:00
|
|
|
return 0;
|
2022-11-19 02:46:07 +08:00
|
|
|
|
|
|
|
out_free:
|
|
|
|
__mptcp_pm_release_addr_entry(entry);
|
|
|
|
return ret;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
|
2023-06-08 21:20:51 +08:00
|
|
|
int mptcp_pm_nl_get_flags_and_ifindex_by_id(struct mptcp_sock *msk, unsigned int id,
|
|
|
|
u8 *flags, int *ifindex)
|
2021-08-18 06:07:22 +08:00
|
|
|
{
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
2022-05-04 10:38:50 +08:00
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
struct net *net = sock_net(sk);
|
2021-08-18 06:07:22 +08:00
|
|
|
|
2024-08-20 03:45:29 +08:00
|
|
|
/* No entries with ID 0 */
|
|
|
|
if (id == 0)
|
|
|
|
return 0;
|
|
|
|
|
2023-06-08 21:20:51 +08:00
|
|
|
rcu_read_lock();
|
|
|
|
entry = __lookup_addr_by_id(pm_nl_get_pernet(net), id);
|
|
|
|
if (entry) {
|
|
|
|
*flags = entry->flags;
|
|
|
|
*ifindex = entry->ifindex;
|
2021-08-18 06:07:22 +08:00
|
|
|
}
|
2023-06-08 21:20:51 +08:00
|
|
|
rcu_read_unlock();
|
2021-08-18 06:07:22 +08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
|
2022-02-16 10:11:28 +08:00
|
|
|
const struct mptcp_addr_info *addr)
|
2020-09-24 08:29:54 +08:00
|
|
|
{
|
2020-09-24 08:30:02 +08:00
|
|
|
struct mptcp_pm_add_entry *entry;
|
2020-09-24 08:29:54 +08:00
|
|
|
|
mptcp: validate 'id' when stopping the ADD_ADDR retransmit timer
when Linux receives an echo-ed ADD_ADDR, it checks the IP address against
the list of "announced" addresses. In case of a positive match, the timer
that handles retransmissions is stopped regardless of the 'Address Id' in
the received packet: this behaviour does not comply with RFC8684 3.4.1.
Fix it by validating the 'Address Id' in received echo-ed ADD_ADDRs.
Tested using packetdrill, with the following captured output:
unpatched kernel:
Out <...> Flags [.], ack 1, win 256, options [mptcp add-addr v1 id 1 198.51.100.2 hmac 0xfd2e62517888fe29,mptcp dss ack 3007449509], length 0
In <...> Flags [.], ack 1, win 257, options [mptcp add-addr v1-echo id 1 1.2.3.4,mptcp dss ack 3013740213], length 0
Out <...> Flags [.], ack 1, win 256, options [mptcp add-addr v1 id 1 198.51.100.2 hmac 0xfd2e62517888fe29,mptcp dss ack 3007449509], length 0
In <...> Flags [.], ack 1, win 257, options [mptcp add-addr v1-echo id 90 198.51.100.2,mptcp dss ack 3013740213], length 0
^^^ retransmission is stopped here, but 'Address Id' is 90
patched kernel:
Out <...> Flags [.], ack 1, win 256, options [mptcp add-addr v1 id 1 198.51.100.2 hmac 0x1cf372d59e05f4b8,mptcp dss ack 3007449509], length 0
In <...> Flags [.], ack 1, win 257, options [mptcp add-addr v1-echo id 1 1.2.3.4,mptcp dss ack 1672384568], length 0
Out <...> Flags [.], ack 1, win 256, options [mptcp add-addr v1 id 1 198.51.100.2 hmac 0x1cf372d59e05f4b8,mptcp dss ack 3007449509], length 0
In <...> Flags [.], ack 1, win 257, options [mptcp add-addr v1-echo id 90 198.51.100.2,mptcp dss ack 1672384568], length 0
Out <...> Flags [.], ack 1, win 256, options [mptcp add-addr v1 id 1 198.51.100.2 hmac 0x1cf372d59e05f4b8,mptcp dss ack 3007449509], length 0
In <...> Flags [.], ack 1, win 257, options [mptcp add-addr v1-echo id 1 198.51.100.2,mptcp dss ack 1672384568], length 0
^^^ retransmission is stopped here, only when both 'Address Id' and 'IP Address' match
Fixes: 00cfd77b9063 ("mptcp: retransmit ADD_ADDR when timeout")
Signed-off-by: Davide Caratti <dcaratti@redhat.com>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2021-05-26 05:23:13 +08:00
|
|
|
entry = mptcp_pm_del_add_timer(msk, addr, false);
|
2020-09-24 08:30:02 +08:00
|
|
|
if (entry) {
|
|
|
|
kfree(entry);
|
|
|
|
return true;
|
2020-09-24 08:29:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
static u8 mptcp_endp_get_local_id(struct mptcp_sock *msk,
|
|
|
|
const struct mptcp_addr_info *addr)
|
|
|
|
{
|
|
|
|
return msk->mpc_endpoint_id == addr->id ? 0 : addr->id;
|
|
|
|
}
|
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
|
2022-02-16 10:11:28 +08:00
|
|
|
const struct mptcp_addr_info *addr,
|
2020-09-24 08:29:54 +08:00
|
|
|
bool force)
|
|
|
|
{
|
2021-03-13 09:16:12 +08:00
|
|
|
struct mptcp_rm_list list = { .nr = 0 };
|
2020-09-24 08:29:54 +08:00
|
|
|
bool ret;
|
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
|
2021-03-13 09:16:12 +08:00
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
ret = remove_anno_list_by_saddr(msk, addr);
|
2020-09-24 08:30:02 +08:00
|
|
|
if (ret || force) {
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2024-08-20 03:45:19 +08:00
|
|
|
if (ret) {
|
|
|
|
__set_bit(addr->id, msk->pm.id_avail_bitmap);
|
|
|
|
msk->pm.add_addr_signaled--;
|
|
|
|
}
|
2021-03-13 09:16:12 +08:00
|
|
|
mptcp_pm_remove_addr(msk, &list);
|
2020-09-24 08:30:02 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
}
|
2020-09-24 08:29:54 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-08-20 03:45:26 +08:00
|
|
|
static void __mark_subflow_endp_available(struct mptcp_sock *msk, u8 id)
|
|
|
|
{
|
|
|
|
/* If it was marked as used, and not ID 0, decrement local_addr_used */
|
|
|
|
if (!__test_and_set_bit(id ? : msk->mpc_endpoint_id, msk->pm.id_avail_bitmap) &&
|
|
|
|
id && !WARN_ON_ONCE(msk->pm.local_addr_used == 0))
|
|
|
|
msk->pm.local_addr_used--;
|
|
|
|
}
|
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
|
2022-03-08 04:44:36 +08:00
|
|
|
const struct mptcp_pm_addr_entry *entry)
|
2020-09-24 08:29:54 +08:00
|
|
|
{
|
2022-03-08 04:44:36 +08:00
|
|
|
const struct mptcp_addr_info *addr = &entry->addr;
|
2024-08-28 14:14:25 +08:00
|
|
|
struct mptcp_rm_list list = { .nr = 1 };
|
2022-03-08 04:44:36 +08:00
|
|
|
long s_slot = 0, s_num = 0;
|
|
|
|
struct mptcp_sock *msk;
|
2020-09-24 08:29:54 +08:00
|
|
|
|
mptcp: pr_debug: add missing \n at the end
commit cb41b195e634d3f1ecfcd845314e64fd4bb3c7aa upstream.
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>
[ As mentioned above, conflicts were expected, and resolved by using the
'sed' command which is visible above. ]
Signed-off-by: Matthieu Baerts (NGI0) <matttbe@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2024-09-03 18:09:58 +08:00
|
|
|
pr_debug("remove_id=%d\n", addr->id);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
|
|
|
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
bool remove_subflow;
|
|
|
|
|
2022-04-28 06:50:00 +08:00
|
|
|
if (mptcp_pm_is_userspace(msk))
|
|
|
|
goto next;
|
|
|
|
|
2020-09-24 08:29:54 +08:00
|
|
|
if (list_empty(&msk->conn_list)) {
|
|
|
|
mptcp_pm_remove_anno_addr(msk, addr, false);
|
|
|
|
goto next;
|
|
|
|
}
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
|
2022-03-08 04:44:36 +08:00
|
|
|
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
|
|
|
|
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
|
2024-08-20 03:45:21 +08:00
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
list.ids[0] = mptcp_endp_get_local_id(msk, addr);
|
2024-08-20 03:45:21 +08:00
|
|
|
if (remove_subflow) {
|
2024-08-20 03:45:25 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
mptcp_pm_nl_rm_subflow_received(msk, &list);
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
2024-08-20 03:45:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
|
2024-08-20 03:45:21 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2024-08-20 03:45:26 +08:00
|
|
|
__mark_subflow_endp_available(msk, list.ids[0]);
|
2024-08-20 03:45:21 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:29 +08:00
|
|
|
if (msk->mpc_endpoint_id == entry->addr.id)
|
|
|
|
msk->mpc_endpoint_id = 0;
|
2020-09-24 08:29:54 +08:00
|
|
|
release_sock(sk);
|
|
|
|
|
|
|
|
next:
|
|
|
|
sock_put(sk);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-03-31 08:08:53 +08:00
|
|
|
static int mptcp_nl_remove_id_zero_address(struct net *net,
|
|
|
|
struct mptcp_addr_info *addr)
|
|
|
|
{
|
|
|
|
struct mptcp_rm_list list = { .nr = 0 };
|
|
|
|
long s_slot = 0, s_num = 0;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
|
|
|
|
list.ids[list.nr++] = 0;
|
|
|
|
|
|
|
|
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
struct mptcp_addr_info msk_local;
|
|
|
|
|
2022-04-28 06:50:00 +08:00
|
|
|
if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
|
2021-03-31 08:08:53 +08:00
|
|
|
goto next;
|
|
|
|
|
2023-06-08 21:20:49 +08:00
|
|
|
mptcp_local_address((struct sock_common *)msk, &msk_local);
|
2022-05-04 10:38:49 +08:00
|
|
|
if (!mptcp_addresses_equal(&msk_local, addr, addr->port))
|
2021-03-31 08:08:53 +08:00
|
|
|
goto next;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
|
|
|
mptcp_pm_remove_addr(msk, &list);
|
|
|
|
mptcp_pm_nl_rm_subflow_received(msk, &list);
|
2024-08-20 03:45:26 +08:00
|
|
|
__mark_subflow_endp_available(msk, 0);
|
2021-03-31 08:08:53 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
release_sock(sk);
|
|
|
|
|
|
|
|
next:
|
|
|
|
sock_put(sk);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
|
|
|
struct mptcp_pm_addr_entry addr, *entry;
|
2021-02-02 07:09:06 +08:00
|
|
|
unsigned int addr_max;
|
2020-03-28 05:48:51 +08:00
|
|
|
int ret;
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
ret = mptcp_pm_parse_entry(attr, info, false, &addr);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2021-03-31 08:08:53 +08:00
|
|
|
/* the zero id address is special: the first address used by the msk
|
|
|
|
* always gets such an id, so different subflows can have different zero
|
|
|
|
* id addresses. Additionally zero id is not accounted for in id_bitmap.
|
|
|
|
* Let's use an 'mptcp_rm_list' instead of the common remove code.
|
|
|
|
*/
|
|
|
|
if (addr.addr.id == 0)
|
|
|
|
return mptcp_nl_remove_id_zero_address(sock_net(skb->sk), &addr.addr);
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_lock_bh(&pernet->lock);
|
|
|
|
entry = __lookup_addr_by_id(pernet, addr.addr.id);
|
|
|
|
if (!entry) {
|
|
|
|
GENL_SET_ERR_MSG(info, "address not found");
|
2020-09-24 08:29:54 +08:00
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
return -EINVAL;
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
2021-04-07 08:15:57 +08:00
|
|
|
if (entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL) {
|
2021-02-02 07:09:06 +08:00
|
|
|
addr_max = pernet->add_addr_signal_max;
|
|
|
|
WRITE_ONCE(pernet->add_addr_signal_max, addr_max - 1);
|
|
|
|
}
|
2021-04-07 08:15:57 +08:00
|
|
|
if (entry->flags & MPTCP_PM_ADDR_FLAG_SUBFLOW) {
|
2021-02-02 07:09:06 +08:00
|
|
|
addr_max = pernet->local_addr_max;
|
|
|
|
WRITE_ONCE(pernet->local_addr_max, addr_max - 1);
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
pernet->addrs--;
|
|
|
|
list_del_rcu(&entry->list);
|
2021-01-09 08:47:55 +08:00
|
|
|
__clear_bit(entry->addr.id, pernet->id_bitmap);
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_unlock_bh(&pernet->lock);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2022-03-08 04:44:36 +08:00
|
|
|
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), entry);
|
2021-08-19 07:42:36 +08:00
|
|
|
synchronize_rcu();
|
|
|
|
__mptcp_pm_release_addr_entry(entry);
|
2020-09-24 08:29:54 +08:00
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
/* Called from the userspace PM only */
|
2023-06-05 11:25:17 +08:00
|
|
|
void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
|
|
|
|
{
|
|
|
|
struct mptcp_rm_list alist = { .nr = 0 };
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
2024-07-27 17:03:59 +08:00
|
|
|
int anno_nr = 0;
|
2023-06-05 11:25:17 +08:00
|
|
|
|
|
|
|
list_for_each_entry(entry, rm_list, list) {
|
2024-07-27 17:03:59 +08:00
|
|
|
if (alist.nr >= MPTCP_RM_IDS_MAX)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* only delete if either announced or matching a subflow */
|
|
|
|
if (remove_anno_list_by_saddr(msk, &entry->addr))
|
|
|
|
anno_nr++;
|
|
|
|
else if (!lookup_subflow_by_saddr(&msk->conn_list,
|
|
|
|
&entry->addr))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
alist.ids[alist.nr++] = entry->addr.id;
|
2023-06-05 11:25:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (alist.nr) {
|
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2024-07-27 17:03:59 +08:00
|
|
|
msk->pm.add_addr_signaled -= anno_nr;
|
2023-06-05 11:25:17 +08:00
|
|
|
mptcp_pm_remove_addr(msk, &alist);
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
/* Called from the in-kernel PM only */
|
2024-03-02 02:18:25 +08:00
|
|
|
static void mptcp_pm_remove_addrs_and_subflows(struct mptcp_sock *msk,
|
|
|
|
struct list_head *rm_list)
|
2021-03-13 09:16:17 +08:00
|
|
|
{
|
|
|
|
struct mptcp_rm_list alist = { .nr = 0 }, slist = { .nr = 0 };
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
|
|
|
|
list_for_each_entry(entry, rm_list, list) {
|
2024-07-27 17:04:00 +08:00
|
|
|
if (slist.nr < MPTCP_RM_IDS_MAX &&
|
|
|
|
lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
|
2024-08-28 14:14:25 +08:00
|
|
|
slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
|
2022-03-08 04:44:35 +08:00
|
|
|
|
2024-07-27 17:04:00 +08:00
|
|
|
if (alist.nr < MPTCP_RM_IDS_MAX &&
|
|
|
|
remove_anno_list_by_saddr(msk, &entry->addr))
|
2024-08-28 14:14:25 +08:00
|
|
|
alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
|
2021-03-13 09:16:17 +08:00
|
|
|
}
|
|
|
|
|
2024-08-20 03:45:25 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2021-03-13 09:16:17 +08:00
|
|
|
if (alist.nr) {
|
2024-07-27 17:04:00 +08:00
|
|
|
msk->pm.add_addr_signaled -= alist.nr;
|
2021-03-13 09:16:17 +08:00
|
|
|
mptcp_pm_remove_addr(msk, &alist);
|
|
|
|
}
|
|
|
|
if (slist.nr)
|
2024-08-20 03:45:25 +08:00
|
|
|
mptcp_pm_nl_rm_subflow_received(msk, &slist);
|
2024-08-20 03:45:23 +08:00
|
|
|
/* Reset counters: maybe some subflows have been removed before */
|
|
|
|
bitmap_fill(msk->pm.id_avail_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
|
|
|
msk->pm.local_addr_used = 0;
|
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
2021-03-13 09:16:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void mptcp_nl_remove_addrs_list(struct net *net,
|
|
|
|
struct list_head *rm_list)
|
|
|
|
{
|
|
|
|
long s_slot = 0, s_num = 0;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
|
|
|
|
if (list_empty(rm_list))
|
|
|
|
return;
|
|
|
|
|
|
|
|
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
|
2022-04-28 06:50:00 +08:00
|
|
|
if (!mptcp_pm_is_userspace(msk)) {
|
|
|
|
lock_sock(sk);
|
|
|
|
mptcp_pm_remove_addrs_and_subflows(msk, rm_list);
|
|
|
|
release_sock(sk);
|
|
|
|
}
|
2021-03-13 09:16:17 +08:00
|
|
|
|
|
|
|
sock_put(sk);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-19 07:42:36 +08:00
|
|
|
/* caller must ensure the RCU grace period is already elapsed */
|
2021-03-13 09:16:18 +08:00
|
|
|
static void __flush_addrs(struct list_head *list)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
2020-12-11 06:24:59 +08:00
|
|
|
while (!list_empty(list)) {
|
2020-03-28 05:48:51 +08:00
|
|
|
struct mptcp_pm_addr_entry *cur;
|
|
|
|
|
2020-12-11 06:24:59 +08:00
|
|
|
cur = list_entry(list->next,
|
2020-03-28 05:48:51 +08:00
|
|
|
struct mptcp_pm_addr_entry, list);
|
|
|
|
list_del_rcu(&cur->list);
|
2021-08-19 07:42:36 +08:00
|
|
|
__mptcp_pm_release_addr_entry(cur);
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __reset_counters(struct pm_nl_pernet *pernet)
|
|
|
|
{
|
2021-02-02 07:09:06 +08:00
|
|
|
WRITE_ONCE(pernet->add_addr_signal_max, 0);
|
|
|
|
WRITE_ONCE(pernet->add_addr_accept_max, 0);
|
|
|
|
WRITE_ONCE(pernet->local_addr_max, 0);
|
2020-03-28 05:48:51 +08:00
|
|
|
pernet->addrs = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
2020-12-11 06:24:59 +08:00
|
|
|
LIST_HEAD(free_list);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
2020-12-11 06:24:59 +08:00
|
|
|
list_splice_init(&pernet->local_addr_list, &free_list);
|
2020-03-28 05:48:51 +08:00
|
|
|
__reset_counters(pernet);
|
2021-01-09 08:47:55 +08:00
|
|
|
pernet->next_id = 1;
|
2022-01-07 08:20:22 +08:00
|
|
|
bitmap_zero(pernet->id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_unlock_bh(&pernet->lock);
|
2021-03-13 09:16:18 +08:00
|
|
|
mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
|
2021-08-19 07:42:36 +08:00
|
|
|
synchronize_rcu();
|
2021-03-13 09:16:18 +08:00
|
|
|
__flush_addrs(&free_list);
|
2020-03-28 05:48:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_nl_fill_addr(struct sk_buff *skb,
|
|
|
|
struct mptcp_pm_addr_entry *entry)
|
|
|
|
{
|
|
|
|
struct mptcp_addr_info *addr = &entry->addr;
|
|
|
|
struct nlattr *attr;
|
|
|
|
|
|
|
|
attr = nla_nest_start(skb, MPTCP_PM_ATTR_ADDR);
|
|
|
|
if (!attr)
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (nla_put_u16(skb, MPTCP_PM_ADDR_ATTR_FAMILY, addr->family))
|
|
|
|
goto nla_put_failure;
|
2021-02-02 07:09:17 +08:00
|
|
|
if (nla_put_u16(skb, MPTCP_PM_ADDR_ATTR_PORT, ntohs(addr->port)))
|
|
|
|
goto nla_put_failure;
|
2020-03-28 05:48:51 +08:00
|
|
|
if (nla_put_u8(skb, MPTCP_PM_ADDR_ATTR_ID, addr->id))
|
|
|
|
goto nla_put_failure;
|
2021-04-07 08:15:57 +08:00
|
|
|
if (nla_put_u32(skb, MPTCP_PM_ADDR_ATTR_FLAGS, entry->flags))
|
2020-03-28 05:48:51 +08:00
|
|
|
goto nla_put_failure;
|
2021-04-07 08:15:57 +08:00
|
|
|
if (entry->ifindex &&
|
|
|
|
nla_put_s32(skb, MPTCP_PM_ADDR_ATTR_IF_IDX, entry->ifindex))
|
2020-03-28 05:48:51 +08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
2020-04-23 10:10:03 +08:00
|
|
|
if (addr->family == AF_INET &&
|
|
|
|
nla_put_in_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR4,
|
|
|
|
addr->addr.s_addr))
|
|
|
|
goto nla_put_failure;
|
2020-03-28 05:48:51 +08:00
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
2020-04-23 10:10:03 +08:00
|
|
|
else if (addr->family == AF_INET6 &&
|
|
|
|
nla_put_in6_addr(skb, MPTCP_PM_ADDR_ATTR_ADDR6, &addr->addr6))
|
|
|
|
goto nla_put_failure;
|
2020-03-28 05:48:51 +08:00
|
|
|
#endif
|
|
|
|
nla_nest_end(skb, attr);
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
nla_put_failure:
|
|
|
|
nla_nest_cancel(skb, attr);
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_nl_cmd_get_addr(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
|
|
|
struct mptcp_pm_addr_entry addr, *entry;
|
|
|
|
struct sk_buff *msg;
|
|
|
|
void *reply;
|
|
|
|
int ret;
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
ret = mptcp_pm_parse_entry(attr, info, false, &addr);
|
2020-03-28 05:48:51 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
|
|
|
|
info->genlhdr->cmd);
|
|
|
|
if (!reply) {
|
|
|
|
GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
|
|
|
|
ret = -EMSGSIZE;
|
|
|
|
goto fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
|
|
|
entry = __lookup_addr_by_id(pernet, addr.addr.id);
|
|
|
|
if (!entry) {
|
|
|
|
GENL_SET_ERR_MSG(info, "address not found");
|
|
|
|
ret = -EINVAL;
|
|
|
|
goto unlock_fail;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = mptcp_nl_fill_addr(msg, entry);
|
|
|
|
if (ret)
|
|
|
|
goto unlock_fail;
|
|
|
|
|
|
|
|
genlmsg_end(msg, reply);
|
|
|
|
ret = genlmsg_reply(msg, info);
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
unlock_fail:
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
nlmsg_free(msg);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_nl_cmd_dump_addrs(struct sk_buff *msg,
|
|
|
|
struct netlink_callback *cb)
|
|
|
|
{
|
|
|
|
struct net *net = sock_net(msg->sk);
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
struct pm_nl_pernet *pernet;
|
|
|
|
int id = cb->args[0];
|
|
|
|
void *hdr;
|
2021-01-09 08:47:55 +08:00
|
|
|
int i;
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2022-04-09 03:45:57 +08:00
|
|
|
pernet = pm_nl_get_pernet(net);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
2022-01-07 08:20:22 +08:00
|
|
|
for (i = id; i < MPTCP_PM_MAX_ADDR_ID + 1; i++) {
|
2021-01-09 08:47:55 +08:00
|
|
|
if (test_bit(i, pernet->id_bitmap)) {
|
|
|
|
entry = __lookup_addr_by_id(pernet, i);
|
|
|
|
if (!entry)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (entry->addr.id <= id)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
hdr = genlmsg_put(msg, NETLINK_CB(cb->skb).portid,
|
|
|
|
cb->nlh->nlmsg_seq, &mptcp_genl_family,
|
|
|
|
NLM_F_MULTI, MPTCP_PM_CMD_GET_ADDR);
|
|
|
|
if (!hdr)
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (mptcp_nl_fill_addr(msg, entry) < 0) {
|
|
|
|
genlmsg_cancel(msg, hdr);
|
|
|
|
break;
|
|
|
|
}
|
2020-03-28 05:48:51 +08:00
|
|
|
|
2021-01-09 08:47:55 +08:00
|
|
|
id = entry->addr.id;
|
|
|
|
genlmsg_end(msg, hdr);
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
|
|
|
|
cb->args[0] = id;
|
|
|
|
return msg->len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int parse_limit(struct genl_info *info, int id, unsigned int *limit)
|
|
|
|
{
|
|
|
|
struct nlattr *attr = info->attrs[id];
|
|
|
|
|
|
|
|
if (!attr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
*limit = nla_get_u32(attr);
|
|
|
|
if (*limit > MPTCP_PM_ADDR_MAX) {
|
|
|
|
GENL_SET_ERR_MSG(info, "limit greater than maximum");
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mptcp_nl_cmd_set_limits(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
|
|
|
unsigned int rcv_addrs, subflows;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
|
|
|
rcv_addrs = pernet->add_addr_accept_max;
|
|
|
|
ret = parse_limit(info, MPTCP_PM_ATTR_RCV_ADD_ADDRS, &rcv_addrs);
|
|
|
|
if (ret)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
subflows = pernet->subflows_max;
|
|
|
|
ret = parse_limit(info, MPTCP_PM_ATTR_SUBFLOWS, &subflows);
|
|
|
|
if (ret)
|
|
|
|
goto unlock;
|
|
|
|
|
|
|
|
WRITE_ONCE(pernet->add_addr_accept_max, rcv_addrs);
|
|
|
|
WRITE_ONCE(pernet->subflows_max, subflows);
|
|
|
|
|
|
|
|
unlock:
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
mptcp_nl_cmd_get_limits(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
|
|
|
struct pm_nl_pernet *pernet = genl_info_pm_nl(info);
|
|
|
|
struct sk_buff *msg;
|
|
|
|
void *reply;
|
|
|
|
|
|
|
|
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
|
if (!msg)
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
reply = genlmsg_put_reply(msg, info, &mptcp_genl_family, 0,
|
|
|
|
MPTCP_PM_CMD_GET_LIMITS);
|
|
|
|
if (!reply)
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (nla_put_u32(msg, MPTCP_PM_ATTR_RCV_ADD_ADDRS,
|
|
|
|
READ_ONCE(pernet->add_addr_accept_max)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
if (nla_put_u32(msg, MPTCP_PM_ATTR_SUBFLOWS,
|
|
|
|
READ_ONCE(pernet->subflows_max)))
|
|
|
|
goto fail;
|
|
|
|
|
|
|
|
genlmsg_end(msg, reply);
|
|
|
|
return genlmsg_reply(msg, info);
|
|
|
|
|
|
|
|
fail:
|
|
|
|
GENL_SET_ERR_MSG(info, "not enough space in Netlink message");
|
|
|
|
nlmsg_free(msg);
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
2022-02-03 09:03:41 +08:00
|
|
|
static void mptcp_pm_nl_fullmesh(struct mptcp_sock *msk,
|
|
|
|
struct mptcp_addr_info *addr)
|
|
|
|
{
|
|
|
|
struct mptcp_rm_list list = { .nr = 0 };
|
|
|
|
|
2024-08-28 14:14:25 +08:00
|
|
|
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
|
2022-02-03 09:03:41 +08:00
|
|
|
|
2022-07-06 05:32:12 +08:00
|
|
|
spin_lock_bh(&msk->pm.lock);
|
2022-02-03 09:03:41 +08:00
|
|
|
mptcp_pm_nl_rm_subflow_received(msk, &list);
|
2024-08-20 03:45:26 +08:00
|
|
|
__mark_subflow_endp_available(msk, list.ids[0]);
|
2022-02-03 09:03:41 +08:00
|
|
|
mptcp_pm_create_subflow_or_signal_addr(msk);
|
2022-07-06 05:32:12 +08:00
|
|
|
spin_unlock_bh(&msk->pm.lock);
|
2022-02-03 09:03:41 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_nl_set_flags(struct net *net,
|
|
|
|
struct mptcp_addr_info *addr,
|
|
|
|
u8 bkup, u8 changed)
|
2021-01-09 08:47:59 +08:00
|
|
|
{
|
|
|
|
long s_slot = 0, s_num = 0;
|
|
|
|
struct mptcp_sock *msk;
|
|
|
|
int ret = -EINVAL;
|
|
|
|
|
|
|
|
while ((msk = mptcp_token_iter_next(net, &s_slot, &s_num)) != NULL) {
|
|
|
|
struct sock *sk = (struct sock *)msk;
|
|
|
|
|
2022-04-28 06:50:00 +08:00
|
|
|
if (list_empty(&msk->conn_list) || mptcp_pm_is_userspace(msk))
|
2021-01-09 08:47:59 +08:00
|
|
|
goto next;
|
|
|
|
|
|
|
|
lock_sock(sk);
|
2022-02-03 09:03:41 +08:00
|
|
|
if (changed & MPTCP_PM_ADDR_FLAG_BACKUP)
|
2022-07-06 05:32:14 +08:00
|
|
|
ret = mptcp_pm_nl_mp_prio_send_ack(msk, addr, NULL, bkup);
|
2022-02-03 09:03:41 +08:00
|
|
|
if (changed & MPTCP_PM_ADDR_FLAG_FULLMESH)
|
|
|
|
mptcp_pm_nl_fullmesh(msk, addr);
|
2021-01-09 08:47:59 +08:00
|
|
|
release_sock(sk);
|
|
|
|
|
|
|
|
next:
|
|
|
|
sock_put(sk);
|
|
|
|
cond_resched();
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2023-06-08 21:20:52 +08:00
|
|
|
int mptcp_pm_nl_set_flags(struct net *net, struct mptcp_pm_addr_entry *addr, u8 bkup)
|
|
|
|
{
|
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet(net);
|
|
|
|
u8 changed, mask = MPTCP_PM_ADDR_FLAG_BACKUP |
|
|
|
|
MPTCP_PM_ADDR_FLAG_FULLMESH;
|
|
|
|
struct mptcp_pm_addr_entry *entry;
|
|
|
|
u8 lookup_by_id = 0;
|
|
|
|
|
|
|
|
if (addr->addr.family == AF_UNSPEC) {
|
|
|
|
lookup_by_id = 1;
|
|
|
|
if (!addr->addr.id)
|
|
|
|
return -EOPNOTSUPP;
|
|
|
|
}
|
|
|
|
|
|
|
|
spin_lock_bh(&pernet->lock);
|
|
|
|
entry = __lookup_addr(pernet, &addr->addr, lookup_by_id);
|
|
|
|
if (!entry) {
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
if ((addr->flags & MPTCP_PM_ADDR_FLAG_FULLMESH) &&
|
|
|
|
(entry->flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) {
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
return -EINVAL;
|
|
|
|
}
|
|
|
|
|
|
|
|
changed = (addr->flags ^ entry->flags) & mask;
|
|
|
|
entry->flags = (entry->flags & ~mask) | (addr->flags & mask);
|
|
|
|
*addr = *entry;
|
|
|
|
spin_unlock_bh(&pernet->lock);
|
|
|
|
|
|
|
|
mptcp_nl_set_flags(net, &addr->addr, bkup, changed);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-01-09 08:47:59 +08:00
|
|
|
static int mptcp_nl_cmd_set_flags(struct sk_buff *skb, struct genl_info *info)
|
|
|
|
{
|
2022-07-06 05:32:14 +08:00
|
|
|
struct mptcp_pm_addr_entry remote = { .addr = { .family = AF_UNSPEC }, };
|
2023-06-08 21:20:52 +08:00
|
|
|
struct mptcp_pm_addr_entry addr = { .addr = { .family = AF_UNSPEC }, };
|
2022-07-06 05:32:14 +08:00
|
|
|
struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
|
|
|
|
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
|
2021-01-09 08:47:59 +08:00
|
|
|
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
|
|
|
|
struct net *net = sock_net(skb->sk);
|
2023-06-08 21:20:52 +08:00
|
|
|
u8 bkup = 0;
|
2021-01-09 08:47:59 +08:00
|
|
|
int ret;
|
|
|
|
|
2022-05-04 10:38:51 +08:00
|
|
|
ret = mptcp_pm_parse_entry(attr, info, false, &addr);
|
2021-01-09 08:47:59 +08:00
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
|
2022-07-06 05:32:14 +08:00
|
|
|
if (attr_rem) {
|
|
|
|
ret = mptcp_pm_parse_entry(attr_rem, info, false, &remote);
|
|
|
|
if (ret < 0)
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2021-04-07 08:15:57 +08:00
|
|
|
if (addr.flags & MPTCP_PM_ADDR_FLAG_BACKUP)
|
2021-01-09 08:47:59 +08:00
|
|
|
bkup = 1;
|
|
|
|
|
2023-06-08 21:20:52 +08:00
|
|
|
return mptcp_pm_set_flags(net, token, &addr, &remote, bkup);
|
2021-01-09 08:47:59 +08:00
|
|
|
}
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
static void mptcp_nl_mcast_send(struct net *net, struct sk_buff *nlskb, gfp_t gfp)
|
|
|
|
{
|
|
|
|
genlmsg_multicast_netns(&mptcp_genl_family, net,
|
|
|
|
nlskb, 0, MPTCP_PM_EV_GRP_OFFSET, gfp);
|
|
|
|
}
|
|
|
|
|
2022-05-03 04:52:31 +08:00
|
|
|
bool mptcp_userspace_pm_active(const struct mptcp_sock *msk)
|
|
|
|
{
|
|
|
|
return genl_has_listeners(&mptcp_genl_family,
|
|
|
|
sock_net((const struct sock *)msk),
|
|
|
|
MPTCP_PM_EV_GRP_OFFSET);
|
|
|
|
}
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
static int mptcp_event_add_subflow(struct sk_buff *skb, const struct sock *ssk)
|
|
|
|
{
|
|
|
|
const struct inet_sock *issk = inet_sk(ssk);
|
|
|
|
const struct mptcp_subflow_context *sf;
|
|
|
|
|
|
|
|
if (nla_put_u16(skb, MPTCP_ATTR_FAMILY, ssk->sk_family))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
switch (ssk->sk_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (nla_put_in_addr(skb, MPTCP_ATTR_SADDR4, issk->inet_saddr))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
if (nla_put_in_addr(skb, MPTCP_ATTR_DADDR4, issk->inet_daddr))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
break;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
case AF_INET6: {
|
|
|
|
const struct ipv6_pinfo *np = inet6_sk(ssk);
|
|
|
|
|
|
|
|
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &ssk->sk_v6_daddr))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
return -EMSGSIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nla_put_be16(skb, MPTCP_ATTR_SPORT, issk->inet_sport))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
if (nla_put_be16(skb, MPTCP_ATTR_DPORT, issk->inet_dport))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
sf = mptcp_subflow_ctx(ssk);
|
|
|
|
if (WARN_ON_ONCE(!sf))
|
|
|
|
return -EINVAL;
|
|
|
|
|
2024-02-16 02:25:31 +08:00
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_LOC_ID, subflow_get_local_id(sf)))
|
2021-02-13 08:00:01 +08:00
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, sf->remote_id))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_event_put_token_and_ssk(struct sk_buff *skb,
|
|
|
|
const struct mptcp_sock *msk,
|
|
|
|
const struct sock *ssk)
|
|
|
|
{
|
|
|
|
const struct sock *sk = (const struct sock *)msk;
|
|
|
|
const struct mptcp_subflow_context *sf;
|
|
|
|
u8 sk_err;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, msk->token))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (mptcp_event_add_subflow(skb, ssk))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
sf = mptcp_subflow_ctx(ssk);
|
|
|
|
if (WARN_ON_ONCE(!sf))
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_BACKUP, sf->backup))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (ssk->sk_bound_dev_if &&
|
|
|
|
nla_put_s32(skb, MPTCP_ATTR_IF_IDX, ssk->sk_bound_dev_if))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2023-03-16 04:57:45 +08:00
|
|
|
sk_err = READ_ONCE(ssk->sk_err);
|
2021-02-13 08:00:01 +08:00
|
|
|
if (sk_err && sk->sk_state == TCP_ESTABLISHED &&
|
|
|
|
nla_put_u8(skb, MPTCP_ATTR_ERROR, sk_err))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_event_sub_established(struct sk_buff *skb,
|
|
|
|
const struct mptcp_sock *msk,
|
|
|
|
const struct sock *ssk)
|
|
|
|
{
|
|
|
|
return mptcp_event_put_token_and_ssk(skb, msk, ssk);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_event_sub_closed(struct sk_buff *skb,
|
|
|
|
const struct mptcp_sock *msk,
|
|
|
|
const struct sock *ssk)
|
|
|
|
{
|
2021-04-02 07:19:44 +08:00
|
|
|
const struct mptcp_subflow_context *sf;
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
if (mptcp_event_put_token_and_ssk(skb, msk, ssk))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2021-04-02 07:19:44 +08:00
|
|
|
sf = mptcp_subflow_ctx(ssk);
|
|
|
|
if (!sf->reset_seen)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_RESET_REASON, sf->reset_reason))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_RESET_FLAGS, sf->reset_transient))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int mptcp_event_created(struct sk_buff *skb,
|
|
|
|
const struct mptcp_sock *msk,
|
|
|
|
const struct sock *ssk)
|
|
|
|
{
|
|
|
|
int err = nla_put_u32(skb, MPTCP_ATTR_TOKEN, msk->token);
|
|
|
|
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2022-05-03 04:52:36 +08:00
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_SERVER_SIDE, READ_ONCE(msk->pm.server_side)))
|
|
|
|
return -EMSGSIZE;
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
return mptcp_event_add_subflow(skb, ssk);
|
|
|
|
}
|
|
|
|
|
|
|
|
void mptcp_event_addr_removed(const struct mptcp_sock *msk, uint8_t id)
|
|
|
|
{
|
|
|
|
struct net *net = sock_net((const struct sock *)msk);
|
|
|
|
struct nlmsghdr *nlh;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
|
|
|
|
return;
|
|
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, MPTCP_EVENT_REMOVED);
|
|
|
|
if (!nlh)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, msk->token))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, id))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
genlmsg_end(skb, nlh);
|
|
|
|
mptcp_nl_mcast_send(net, skb, GFP_ATOMIC);
|
|
|
|
return;
|
|
|
|
|
|
|
|
nla_put_failure:
|
2022-12-09 08:44:30 +08:00
|
|
|
nlmsg_free(skb);
|
2021-02-13 08:00:01 +08:00
|
|
|
}
|
|
|
|
|
2022-05-03 04:52:34 +08:00
|
|
|
void mptcp_event_addr_announced(const struct sock *ssk,
|
2021-02-13 08:00:01 +08:00
|
|
|
const struct mptcp_addr_info *info)
|
|
|
|
{
|
2022-05-03 04:52:34 +08:00
|
|
|
struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
|
|
|
|
struct mptcp_sock *msk = mptcp_sk(subflow->conn);
|
|
|
|
struct net *net = sock_net(ssk);
|
2021-02-13 08:00:01 +08:00
|
|
|
struct nlmsghdr *nlh;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
|
|
|
|
return;
|
|
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0,
|
|
|
|
MPTCP_EVENT_ANNOUNCED);
|
|
|
|
if (!nlh)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, msk->token))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u8(skb, MPTCP_ATTR_REM_ID, info->id))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
2022-05-03 04:52:34 +08:00
|
|
|
if (nla_put_be16(skb, MPTCP_ATTR_DPORT,
|
|
|
|
info->port == 0 ?
|
|
|
|
inet_sk(ssk)->inet_dport :
|
|
|
|
info->port))
|
2021-02-13 08:00:01 +08:00
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
switch (info->family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (nla_put_in_addr(skb, MPTCP_ATTR_DADDR4, info->addr.s_addr))
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
case AF_INET6:
|
|
|
|
if (nla_put_in6_addr(skb, MPTCP_ATTR_DADDR6, &info->addr6))
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
goto nla_put_failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
genlmsg_end(skb, nlh);
|
|
|
|
mptcp_nl_mcast_send(net, skb, GFP_ATOMIC);
|
|
|
|
return;
|
|
|
|
|
|
|
|
nla_put_failure:
|
2022-12-09 08:44:30 +08:00
|
|
|
nlmsg_free(skb);
|
2021-02-13 08:00:01 +08:00
|
|
|
}
|
|
|
|
|
2022-11-30 22:06:28 +08:00
|
|
|
void mptcp_event_pm_listener(const struct sock *ssk,
|
|
|
|
enum mptcp_event_type event)
|
|
|
|
{
|
|
|
|
const struct inet_sock *issk = inet_sk(ssk);
|
|
|
|
struct net *net = sock_net(ssk);
|
|
|
|
struct nlmsghdr *nlh;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
|
|
|
|
return;
|
|
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, event);
|
|
|
|
if (!nlh)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_u16(skb, MPTCP_ATTR_FAMILY, ssk->sk_family))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
if (nla_put_be16(skb, MPTCP_ATTR_SPORT, issk->inet_sport))
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
switch (ssk->sk_family) {
|
|
|
|
case AF_INET:
|
|
|
|
if (nla_put_in_addr(skb, MPTCP_ATTR_SADDR4, issk->inet_saddr))
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
|
|
|
|
case AF_INET6: {
|
|
|
|
const struct ipv6_pinfo *np = inet6_sk(ssk);
|
|
|
|
|
|
|
|
if (nla_put_in6_addr(skb, MPTCP_ATTR_SADDR6, &np->saddr))
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
goto nla_put_failure;
|
|
|
|
}
|
|
|
|
|
|
|
|
genlmsg_end(skb, nlh);
|
|
|
|
mptcp_nl_mcast_send(net, skb, GFP_KERNEL);
|
|
|
|
return;
|
|
|
|
|
|
|
|
nla_put_failure:
|
2022-12-09 08:44:30 +08:00
|
|
|
nlmsg_free(skb);
|
2022-11-30 22:06:28 +08:00
|
|
|
}
|
|
|
|
|
2021-02-13 08:00:01 +08:00
|
|
|
void mptcp_event(enum mptcp_event_type type, const struct mptcp_sock *msk,
|
|
|
|
const struct sock *ssk, gfp_t gfp)
|
|
|
|
{
|
|
|
|
struct net *net = sock_net((const struct sock *)msk);
|
|
|
|
struct nlmsghdr *nlh;
|
|
|
|
struct sk_buff *skb;
|
|
|
|
|
|
|
|
if (!genl_has_listeners(&mptcp_genl_family, net, MPTCP_PM_EV_GRP_OFFSET))
|
|
|
|
return;
|
|
|
|
|
|
|
|
skb = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
|
|
|
|
if (!skb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nlh = genlmsg_put(skb, 0, 0, &mptcp_genl_family, 0, type);
|
|
|
|
if (!nlh)
|
|
|
|
goto nla_put_failure;
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case MPTCP_EVENT_UNSPEC:
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
break;
|
|
|
|
case MPTCP_EVENT_CREATED:
|
|
|
|
case MPTCP_EVENT_ESTABLISHED:
|
|
|
|
if (mptcp_event_created(skb, msk, ssk) < 0)
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
case MPTCP_EVENT_CLOSED:
|
|
|
|
if (nla_put_u32(skb, MPTCP_ATTR_TOKEN, msk->token) < 0)
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
case MPTCP_EVENT_ANNOUNCED:
|
|
|
|
case MPTCP_EVENT_REMOVED:
|
|
|
|
/* call mptcp_event_addr_announced()/removed instead */
|
|
|
|
WARN_ON_ONCE(1);
|
|
|
|
break;
|
|
|
|
case MPTCP_EVENT_SUB_ESTABLISHED:
|
|
|
|
case MPTCP_EVENT_SUB_PRIORITY:
|
|
|
|
if (mptcp_event_sub_established(skb, msk, ssk) < 0)
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
|
|
|
case MPTCP_EVENT_SUB_CLOSED:
|
|
|
|
if (mptcp_event_sub_closed(skb, msk, ssk) < 0)
|
|
|
|
goto nla_put_failure;
|
|
|
|
break;
|
2022-11-30 22:06:28 +08:00
|
|
|
case MPTCP_EVENT_LISTENER_CREATED:
|
|
|
|
case MPTCP_EVENT_LISTENER_CLOSED:
|
|
|
|
break;
|
2021-02-13 08:00:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
genlmsg_end(skb, nlh);
|
|
|
|
mptcp_nl_mcast_send(net, skb, gfp);
|
|
|
|
return;
|
|
|
|
|
|
|
|
nla_put_failure:
|
2022-12-09 08:44:30 +08:00
|
|
|
nlmsg_free(skb);
|
2021-02-13 08:00:01 +08:00
|
|
|
}
|
|
|
|
|
2020-10-05 07:44:16 +08:00
|
|
|
static const struct genl_small_ops mptcp_pm_ops[] = {
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_ADD_ADDR,
|
|
|
|
.doit = mptcp_nl_cmd_add_addr,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2020-03-28 05:48:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_DEL_ADDR,
|
|
|
|
.doit = mptcp_nl_cmd_del_addr,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2020-03-28 05:48:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_FLUSH_ADDRS,
|
|
|
|
.doit = mptcp_nl_cmd_flush_addrs,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2020-03-28 05:48:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_GET_ADDR,
|
|
|
|
.doit = mptcp_nl_cmd_get_addr,
|
|
|
|
.dumpit = mptcp_nl_cmd_dump_addrs,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_SET_LIMITS,
|
|
|
|
.doit = mptcp_nl_cmd_set_limits,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2020-03-28 05:48:51 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_GET_LIMITS,
|
|
|
|
.doit = mptcp_nl_cmd_get_limits,
|
|
|
|
},
|
2021-01-09 08:47:59 +08:00
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_SET_FLAGS,
|
|
|
|
.doit = mptcp_nl_cmd_set_flags,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2021-01-09 08:47:59 +08:00
|
|
|
},
|
2022-05-04 10:38:52 +08:00
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_ANNOUNCE,
|
|
|
|
.doit = mptcp_nl_cmd_announce,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2022-05-04 10:38:52 +08:00
|
|
|
},
|
2022-05-04 10:38:54 +08:00
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_REMOVE,
|
|
|
|
.doit = mptcp_nl_cmd_remove,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
2022-05-04 10:38:54 +08:00
|
|
|
},
|
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 10:38:56 +08:00
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_SUBFLOW_CREATE,
|
|
|
|
.doit = mptcp_nl_cmd_sf_create,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 10:38:56 +08:00
|
|
|
},
|
|
|
|
{
|
|
|
|
.cmd = MPTCP_PM_CMD_SUBFLOW_DESTROY,
|
|
|
|
.doit = mptcp_nl_cmd_sf_destroy,
|
2022-09-07 04:55:42 +08:00
|
|
|
.flags = GENL_UNS_ADMIN_PERM,
|
mptcp: netlink: allow userspace-driven subflow establishment
This allows userspace to tell kernel to add a new subflow to an existing
mptcp connection.
Userspace provides the token to identify the mptcp-level connection
that needs a change in active subflows and the local and remote
addresses of the new or the to-be-removed subflow.
MPTCP_PM_CMD_SUBFLOW_CREATE requires the following parameters:
{ token, { loc_id, family, loc_addr4 | loc_addr6 }, { family, rem_addr4 |
rem_addr6, rem_port }
MPTCP_PM_CMD_SUBFLOW_DESTROY requires the following parameters:
{ token, { family, loc_addr4 | loc_addr6, loc_port }, { family, rem_addr4 |
rem_addr6, rem_port }
Acked-by: Paolo Abeni <pabeni@redhat.com>
Co-developed-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Kishen Maloor <kishen.maloor@intel.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Mat Martineau <mathew.j.martineau@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2022-05-04 10:38:56 +08:00
|
|
|
},
|
2020-03-28 05:48:51 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct genl_family mptcp_genl_family __ro_after_init = {
|
|
|
|
.name = MPTCP_PM_NAME,
|
|
|
|
.version = MPTCP_PM_VER,
|
|
|
|
.maxattr = MPTCP_PM_ATTR_MAX,
|
|
|
|
.policy = mptcp_pm_policy,
|
|
|
|
.netnsok = true,
|
|
|
|
.module = THIS_MODULE,
|
2020-10-03 05:49:54 +08:00
|
|
|
.small_ops = mptcp_pm_ops,
|
|
|
|
.n_small_ops = ARRAY_SIZE(mptcp_pm_ops),
|
2022-08-25 08:18:30 +08:00
|
|
|
.resv_start_op = MPTCP_PM_CMD_SUBFLOW_DESTROY + 1,
|
2020-03-28 05:48:51 +08:00
|
|
|
.mcgrps = mptcp_pm_mcgrps,
|
|
|
|
.n_mcgrps = ARRAY_SIZE(mptcp_pm_mcgrps),
|
|
|
|
};
|
|
|
|
|
|
|
|
static int __net_init pm_nl_init_net(struct net *net)
|
|
|
|
{
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet(net);
|
2020-03-28 05:48:51 +08:00
|
|
|
|
|
|
|
INIT_LIST_HEAD_RCU(&pernet->local_addr_list);
|
2021-10-16 07:05:51 +08:00
|
|
|
|
|
|
|
/* Cit. 2 subflows ought to be enough for anybody. */
|
|
|
|
pernet->subflows_max = 2;
|
2020-03-28 05:48:51 +08:00
|
|
|
pernet->next_id = 1;
|
2021-08-14 06:15:45 +08:00
|
|
|
pernet->stale_loss_cnt = 4;
|
2020-03-28 05:48:51 +08:00
|
|
|
spin_lock_init(&pernet->lock);
|
2021-05-28 07:54:27 +08:00
|
|
|
|
|
|
|
/* No need to initialize other pernet fields, the struct is zeroed at
|
|
|
|
* allocation time.
|
|
|
|
*/
|
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void __net_exit pm_nl_exit_net(struct list_head *net_list)
|
|
|
|
{
|
|
|
|
struct net *net;
|
|
|
|
|
|
|
|
list_for_each_entry(net, net_list, exit_list) {
|
2022-04-09 03:45:57 +08:00
|
|
|
struct pm_nl_pernet *pernet = pm_nl_get_pernet(net);
|
2020-12-11 06:24:59 +08:00
|
|
|
|
2020-03-28 05:48:51 +08:00
|
|
|
/* net is removed from namespace list, can't race with
|
2021-08-19 07:42:36 +08:00
|
|
|
* other modifiers, also netns core already waited for a
|
|
|
|
* RCU grace period.
|
2020-03-28 05:48:51 +08:00
|
|
|
*/
|
2021-03-13 09:16:18 +08:00
|
|
|
__flush_addrs(&pernet->local_addr_list);
|
2020-03-28 05:48:51 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct pernet_operations mptcp_pm_pernet_ops = {
|
|
|
|
.init = pm_nl_init_net,
|
|
|
|
.exit_batch = pm_nl_exit_net,
|
|
|
|
.id = &pm_nl_pernet_id,
|
|
|
|
.size = sizeof(struct pm_nl_pernet),
|
|
|
|
};
|
|
|
|
|
2020-06-27 01:29:59 +08:00
|
|
|
void __init mptcp_pm_nl_init(void)
|
2020-03-28 05:48:51 +08:00
|
|
|
{
|
|
|
|
if (register_pernet_subsys(&mptcp_pm_pernet_ops) < 0)
|
|
|
|
panic("Failed to register MPTCP PM pernet subsystem.\n");
|
|
|
|
|
|
|
|
if (genl_register_family(&mptcp_genl_family))
|
|
|
|
panic("Failed to register MPTCP PM netlink family\n");
|
|
|
|
}
|