Revert "mptcp: pm: avoid possible UaF when selecting endp"

This reverts commit 7f092ac2f1.
This commit is contained in:
Ksawlii 2024-11-24 00:23:45 +01:00
parent 4a63b68b74
commit 40ac982c85

View file

@ -127,13 +127,11 @@ static bool lookup_subflow_by_saddr(const struct list_head *list,
return false; return false;
} }
static bool static struct mptcp_pm_addr_entry *
select_local_address(const struct pm_nl_pernet *pernet, select_local_address(const struct pm_nl_pernet *pernet,
struct mptcp_sock *msk, struct mptcp_sock *msk)
struct mptcp_pm_addr_entry *new_entry)
{ {
struct mptcp_pm_addr_entry *entry; struct mptcp_pm_addr_entry *entry, *ret = NULL;
bool found = false;
rcu_read_lock(); rcu_read_lock();
spin_lock_bh(&msk->join_list_lock); spin_lock_bh(&msk->join_list_lock);
@ -147,23 +145,19 @@ select_local_address(const struct pm_nl_pernet *pernet,
if (entry->addr.family == ((struct sock *)msk)->sk_family && if (entry->addr.family == ((struct sock *)msk)->sk_family &&
!lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) && !lookup_subflow_by_saddr(&msk->conn_list, &entry->addr) &&
!lookup_subflow_by_saddr(&msk->join_list, &entry->addr)) { !lookup_subflow_by_saddr(&msk->join_list, &entry->addr)) {
*new_entry = *entry; ret = entry;
found = true;
break; break;
} }
} }
spin_unlock_bh(&msk->join_list_lock); spin_unlock_bh(&msk->join_list_lock);
rcu_read_unlock(); rcu_read_unlock();
return ret;
return found;
} }
static bool static struct mptcp_pm_addr_entry *
select_signal_address(struct pm_nl_pernet *pernet, unsigned int pos, select_signal_address(struct pm_nl_pernet *pernet, unsigned int pos)
struct mptcp_pm_addr_entry *new_entry)
{ {
struct mptcp_pm_addr_entry *entry; struct mptcp_pm_addr_entry *entry, *ret = NULL;
bool found = false;
int i = 0; int i = 0;
rcu_read_lock(); rcu_read_lock();
@ -176,14 +170,12 @@ select_signal_address(struct pm_nl_pernet *pernet, unsigned int pos,
if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL)) if (!(entry->addr.flags & MPTCP_PM_ADDR_FLAG_SIGNAL))
continue; continue;
if (i++ == pos) { if (i++ == pos) {
*new_entry = *entry; ret = entry;
found = true;
break; break;
} }
} }
rcu_read_unlock(); rcu_read_unlock();
return ret;
return found;
} }
static void check_work_pending(struct mptcp_sock *msk) static void check_work_pending(struct mptcp_sock *msk)
@ -313,7 +305,7 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
{ {
struct mptcp_addr_info remote = { 0 }; struct mptcp_addr_info remote = { 0 };
struct sock *sk = (struct sock *)msk; struct sock *sk = (struct sock *)msk;
struct mptcp_pm_addr_entry local; struct mptcp_pm_addr_entry *local;
struct pm_nl_pernet *pernet; struct pm_nl_pernet *pernet;
pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id); pernet = net_generic(sock_net((struct sock *)msk), pm_nl_pernet_id);
@ -325,11 +317,13 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
/* check first for announce */ /* check first for announce */
if (msk->pm.add_addr_signaled < msk->pm.add_addr_signal_max) { if (msk->pm.add_addr_signaled < msk->pm.add_addr_signal_max) {
if (select_signal_address(pernet, msk->pm.add_addr_signaled, local = select_signal_address(pernet,
&local)) { msk->pm.add_addr_signaled);
if (mptcp_pm_alloc_anno_list(msk, &local)) {
if (local) {
if (mptcp_pm_alloc_anno_list(msk, local)) {
msk->pm.add_addr_signaled++; msk->pm.add_addr_signaled++;
mptcp_pm_announce_addr(msk, &local.addr, false); mptcp_pm_announce_addr(msk, &local->addr, false);
} }
} else { } else {
/* pick failed, avoid fourther attempts later */ /* pick failed, avoid fourther attempts later */
@ -344,12 +338,13 @@ static void mptcp_pm_create_subflow_or_signal_addr(struct mptcp_sock *msk)
msk->pm.subflows < msk->pm.subflows_max) { msk->pm.subflows < msk->pm.subflows_max) {
remote_address((struct sock_common *)sk, &remote); remote_address((struct sock_common *)sk, &remote);
if (select_local_address(pernet, msk, &local)) { local = select_local_address(pernet, msk);
if (local) {
msk->pm.local_addr_used++; msk->pm.local_addr_used++;
msk->pm.subflows++; msk->pm.subflows++;
check_work_pending(msk); check_work_pending(msk);
spin_unlock_bh(&msk->pm.lock); spin_unlock_bh(&msk->pm.lock);
__mptcp_subflow_connect(sk, &local.addr, &remote); __mptcp_subflow_connect(sk, &local->addr, &remote);
spin_lock_bh(&msk->pm.lock); spin_lock_bh(&msk->pm.lock);
return; return;
} }