sctp: Fix regression introduced by new sctp_connectx api

A new (unrealeased to the user) sctp_connectx api

c6ba68a266
    sctp: support non-blocking version of the new sctp_connectx() API

introduced a regression cought by the user regression test
suite.  In particular, the API requires the user library to
re-allocate the buffer and could potentially trigger a SIGFAULT.

This change corrects that regression by passing the original
address buffer to the kernel unmodified, but still allows for
a returned association id.

Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Vlad Yasevich 2009-11-11 08:19:24 +00:00 коммит произвёл David S. Miller
Родитель 409b95aff3
Коммит f9c67811eb
1 изменённых файлов: 13 добавлений и 5 удалений

Просмотреть файл

@ -1276,22 +1276,30 @@ SCTP_STATIC int sctp_setsockopt_connectx(struct sock* sk,
} }
/* /*
* New (hopefully final) interface for the API. The option buffer is used * New (hopefully final) interface for the API.
* both for the returned association id and the addresses. * We use the sctp_getaddrs_old structure so that use-space library
* can avoid any unnecessary allocations. The only defferent part
* is that we store the actual length of the address buffer into the
* addrs_num structure member. That way we can re-use the existing
* code.
*/ */
SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len,
char __user *optval, char __user *optval,
int __user *optlen) int __user *optlen)
{ {
struct sctp_getaddrs_old param;
sctp_assoc_t assoc_id = 0; sctp_assoc_t assoc_id = 0;
int err = 0; int err = 0;
if (len < sizeof(assoc_id)) if (len < sizeof(param))
return -EINVAL; return -EINVAL;
if (copy_from_user(&param, optval, sizeof(param)))
return -EFAULT;
err = __sctp_setsockopt_connectx(sk, err = __sctp_setsockopt_connectx(sk,
(struct sockaddr __user *)(optval + sizeof(assoc_id)), (struct sockaddr __user *)param.addrs,
len - sizeof(assoc_id), &assoc_id); param.addr_num, &assoc_id);
if (err == 0 || err == -EINPROGRESS) { if (err == 0 || err == -EINPROGRESS) {
if (copy_to_user(optval, &assoc_id, sizeof(assoc_id))) if (copy_to_user(optval, &assoc_id, sizeof(assoc_id)))