Merge branch 'mptcp-fixes'
Mat Martineau says: ==================== mptcp: Bug fixes Here are two bug fixes for the net tree: Patch 1 fixes a memory leak that could be encountered when clearing the list of advertised MPTCP addresses. Patch 2 fixes a protocol issue early in an MPTCP connection, to ensure both peers correctly understand that the full MPTCP connection handshake has completed even when the server side quickly sends an ADD_ADDR option. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d98c821067
|
@ -885,20 +885,16 @@ static bool check_fully_established(struct mptcp_sock *msk, struct sock *ssk,
|
|||
return subflow->mp_capable;
|
||||
}
|
||||
|
||||
if (mp_opt->dss && mp_opt->use_ack) {
|
||||
if ((mp_opt->dss && mp_opt->use_ack) ||
|
||||
(mp_opt->add_addr && !mp_opt->echo)) {
|
||||
/* subflows are fully established as soon as we get any
|
||||
* additional ack.
|
||||
* additional ack, including ADD_ADDR.
|
||||
*/
|
||||
subflow->fully_established = 1;
|
||||
WRITE_ONCE(msk->fully_established, true);
|
||||
goto fully_established;
|
||||
}
|
||||
|
||||
if (mp_opt->add_addr) {
|
||||
WRITE_ONCE(msk->fully_established, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* If the first established packet does not contain MP_CAPABLE + data
|
||||
* then fallback to TCP. Fallback scenarios requires a reset for
|
||||
* MP_JOIN subflows.
|
||||
|
|
|
@ -1135,37 +1135,13 @@ next:
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct addr_entry_release_work {
|
||||
struct rcu_work rwork;
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
};
|
||||
|
||||
static void mptcp_pm_release_addr_entry(struct work_struct *work)
|
||||
/* caller must ensure the RCU grace period is already elapsed */
|
||||
static void __mptcp_pm_release_addr_entry(struct mptcp_pm_addr_entry *entry)
|
||||
{
|
||||
struct addr_entry_release_work *w;
|
||||
struct mptcp_pm_addr_entry *entry;
|
||||
|
||||
w = container_of(to_rcu_work(work), struct addr_entry_release_work, rwork);
|
||||
entry = w->entry;
|
||||
if (entry) {
|
||||
if (entry->lsk)
|
||||
sock_release(entry->lsk);
|
||||
kfree(entry);
|
||||
}
|
||||
kfree(w);
|
||||
}
|
||||
|
||||
static void mptcp_pm_free_addr_entry(struct mptcp_pm_addr_entry *entry)
|
||||
{
|
||||
struct addr_entry_release_work *w;
|
||||
|
||||
w = kmalloc(sizeof(*w), GFP_ATOMIC);
|
||||
if (w) {
|
||||
INIT_RCU_WORK(&w->rwork, mptcp_pm_release_addr_entry);
|
||||
w->entry = entry;
|
||||
queue_rcu_work(system_wq, &w->rwork);
|
||||
}
|
||||
}
|
||||
|
||||
static int mptcp_nl_remove_id_zero_address(struct net *net,
|
||||
struct mptcp_addr_info *addr)
|
||||
|
@ -1244,7 +1220,8 @@ static int mptcp_nl_cmd_del_addr(struct sk_buff *skb, struct genl_info *info)
|
|||
spin_unlock_bh(&pernet->lock);
|
||||
|
||||
mptcp_nl_remove_subflow_and_signal_addr(sock_net(skb->sk), &entry->addr);
|
||||
mptcp_pm_free_addr_entry(entry);
|
||||
synchronize_rcu();
|
||||
__mptcp_pm_release_addr_entry(entry);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1297,6 +1274,7 @@ static void mptcp_nl_remove_addrs_list(struct net *net,
|
|||
}
|
||||
}
|
||||
|
||||
/* caller must ensure the RCU grace period is already elapsed */
|
||||
static void __flush_addrs(struct list_head *list)
|
||||
{
|
||||
while (!list_empty(list)) {
|
||||
|
@ -1305,7 +1283,7 @@ static void __flush_addrs(struct list_head *list)
|
|||
cur = list_entry(list->next,
|
||||
struct mptcp_pm_addr_entry, list);
|
||||
list_del_rcu(&cur->list);
|
||||
mptcp_pm_free_addr_entry(cur);
|
||||
__mptcp_pm_release_addr_entry(cur);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1329,6 +1307,7 @@ static int mptcp_nl_cmd_flush_addrs(struct sk_buff *skb, struct genl_info *info)
|
|||
bitmap_zero(pernet->id_bitmap, MAX_ADDR_ID + 1);
|
||||
spin_unlock_bh(&pernet->lock);
|
||||
mptcp_nl_remove_addrs_list(sock_net(skb->sk), &free_list);
|
||||
synchronize_rcu();
|
||||
__flush_addrs(&free_list);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1939,7 +1918,8 @@ static void __net_exit pm_nl_exit_net(struct list_head *net_list)
|
|||
struct pm_nl_pernet *pernet = net_generic(net, pm_nl_pernet_id);
|
||||
|
||||
/* net is removed from namespace list, can't race with
|
||||
* other modifiers
|
||||
* other modifiers, also netns core already waited for a
|
||||
* RCU grace period.
|
||||
*/
|
||||
__flush_addrs(&pernet->local_addr_list);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue