Skip to content
This repository has been archived by the owner on Apr 18, 2024. It is now read-only.

Websocket on MPTCP keep raising warning: getsockopt: Bad Address. #489

Open
ArthurCChen opened this issue May 25, 2022 · 1 comment
Open
Labels

Comments

@ArthurCChen
Copy link

Hi, My MPTCP pair: AWS EC2(as the server) & PC(as the client) (Both Ubuntu18.04 and Linux 4.19.234) works correctly according to the Wireshark. However, after adding the module:

  struct mptcp_info minfo;
  struct mptcp_meta_info meta_info;
  struct tcp_info initial;
  struct tcp_info *others; // increase it if needed
  struct mptcp_sub_info others_info[3]; // same
  socklen_t len;
  len = sizeof(minfo);
  minfo.tcp_info_len = sizeof(struct tcp_info);
  minfo.sub_len = sizeof(others);
  minfo.meta_len = sizeof(struct mptcp_meta_info);
  minfo.meta_info = &meta_info;
  minfo.initial = &initial;
  minfo.subflows = others;
  minfo.sub_info_len = sizeof(struct mptcp_sub_info);
  minfo.total_sub_info_len = sizeof(others_info);
  minfo.subflow_info = others_info;

  cout << 'Before getting the MPTCP_INFO, minfo: ' << minfo.total_sub_info_len << endl;

  #define MPTCP_INFO_FLAG_SAVE_MASTER 0x01
  int val = MPTCP_INFO_FLAG_SAVE_MASTER;
  CheckSystemCall( "setsockopt", ::setsockopt( fd_num(), IPPROTO_TCP, MPTCP_INFO,
                                                 &val, sizeof( val ) ) );

  getsockopt(<fd num>, IPPROTO_TCP, MPTCP_INFO, &minfo &len);

it now continuously closes my WebSocket connection and reconnect. Exactly at this line:
getsockopt(<fd num>, IPPROTO_TCP, MPTCP_INFO, &minfo &len);

  • How did you install it?
    A: I downloaded MPTCP-V0.95 from the home page of MPTCP.(git clone) Then I make menuconfig and compile it and change the kernel according to the instruction

  • Which command are you using to compile this code?
    A: All the process is here:

git clone --depth=1 git://github.com/multipath-tcp/mptcp.git
cd mptcp
sudo make menuconfig
sudo make
sudo make modules_install
sudo make install
  • All the previous setsockopt here were OK?
    A: Yes.

  • The return value of this getsockopt?
    A: It's not -1.

@matttbe
Copy link
Member

matttbe commented May 30, 2022

Hello,

EFAULT error, also known as Bad address error, is returned if there is not enough space for the kernel to write data in.

You issue might come from:

  struct tcp_info *others; // increase it if needed

You should not have a pointer here but an array that is big enough to store info for each subflows, e.g. others[3].

Note that another common source of issue is when your system has kernel C headers for an older kernel versions and structure are not big enough.
You can debug that by printing the sizeof sizes but also by looking at what the kernel has managed to write. You can find the order the kernel is writing info in by looking at where copy_from_user() functions are used in mptcp_get_info()

mptcp/net/mptcp/mptcp_ctrl.c

Lines 2791 to 2909 in 7fa887b

int mptcp_get_info(const struct sock *meta_sk, char __user *optval, int optlen)
{
const struct tcp_sock *meta_tp = tcp_sk(meta_sk);
struct mptcp_meta_info meta_info;
struct mptcp_info m_info;
unsigned int info_len;
/* Check again with the lock held */
if (!mptcp(meta_tp))
return -EINVAL;
if (copy_from_user(&m_info, optval, optlen))
return -EFAULT;
if (m_info.meta_info) {
unsigned int len;
__mptcp_get_info(meta_sk, &meta_info);
/* Need to set this, if user thinks that tcp_info is bigger than ours */
len = min_t(unsigned int, m_info.meta_len, sizeof(meta_info));
m_info.meta_len = len;
if (copy_to_user((void __user *)m_info.meta_info, &meta_info, len))
return -EFAULT;
}
/* Need to set this, if user thinks that tcp_info is bigger than ours */
info_len = min_t(unsigned int, m_info.tcp_info_len, sizeof(struct tcp_info));
m_info.tcp_info_len = info_len;
if (m_info.initial) {
struct mptcp_cb *mpcb = meta_tp->mpcb;
if (mpcb->master_sk) {
struct tcp_info info;
tcp_get_info(mpcb->master_sk, &info, true);
if (copy_to_user((void __user *)m_info.initial, &info, info_len))
return -EFAULT;
} else if (meta_tp->record_master_info && mpcb->master_info) {
if (copy_to_user((void __user *)m_info.initial, mpcb->master_info, info_len))
return -EFAULT;
} else {
return meta_tp->record_master_info ? -ENOMEM : -EINVAL;
}
}
if (m_info.subflows) {
unsigned int len, sub_len = 0;
struct mptcp_tcp_sock *mptcp;
char __user *ptr;
ptr = (char __user *)m_info.subflows;
len = m_info.sub_len;
mptcp_for_each_sub(meta_tp->mpcb, mptcp) {
struct tcp_info t_info;
unsigned int tmp_len;
tcp_get_info(mptcp_to_sock(mptcp), &t_info, true);
tmp_len = min_t(unsigned int, len, info_len);
len -= tmp_len;
if (copy_to_user(ptr, &t_info, tmp_len))
return -EFAULT;
ptr += tmp_len;
sub_len += tmp_len;
if (len == 0)
break;
}
m_info.sub_len = sub_len;
}
if (m_info.subflow_info) {
unsigned int len, sub_info_len, total_sub_info_len = 0;
struct mptcp_tcp_sock *mptcp;
char __user *ptr;
ptr = (char __user *)m_info.subflow_info;
len = m_info.total_sub_info_len;
sub_info_len = min_t(unsigned int, m_info.sub_info_len,
sizeof(struct mptcp_sub_info));
m_info.sub_info_len = sub_info_len;
mptcp_for_each_sub(meta_tp->mpcb, mptcp) {
struct mptcp_sub_info m_sub_info;
unsigned int tmp_len;
mptcp_get_sub_info(mptcp_to_sock(mptcp), &m_sub_info);
tmp_len = min_t(unsigned int, len, sub_info_len);
len -= tmp_len;
if (copy_to_user(ptr, &m_sub_info, tmp_len))
return -EFAULT;
ptr += tmp_len;
total_sub_info_len += tmp_len;
if (len == 0)
break;
}
m_info.total_sub_info_len = total_sub_info_len;
}
if (copy_to_user(optval, &m_info, optlen))
return -EFAULT;
return 0;
}

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

2 participants