mirror of https://gitee.com/openkylin/linux.git
sctp: pass a kernel pointer to __sctp_setsockopt_connectx
Use the kernel pointer that sctp_setsockopt has available instead of directly handling the user pointer. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
8c7517f54c
commit
ce5b2f8929
|
@ -1286,36 +1286,29 @@ static int __sctp_connect(struct sock *sk, struct sockaddr *kaddrs,
|
||||||
* it.
|
* it.
|
||||||
*
|
*
|
||||||
* sk The sk of the socket
|
* sk The sk of the socket
|
||||||
* addrs The pointer to the addresses in user land
|
* addrs The pointer to the addresses
|
||||||
* addrssize Size of the addrs buffer
|
* addrssize Size of the addrs buffer
|
||||||
*
|
*
|
||||||
* Returns >=0 if ok, <0 errno code on error.
|
* Returns >=0 if ok, <0 errno code on error.
|
||||||
*/
|
*/
|
||||||
static int __sctp_setsockopt_connectx(struct sock *sk,
|
static int __sctp_setsockopt_connectx(struct sock *sk, struct sockaddr *kaddrs,
|
||||||
struct sockaddr __user *addrs,
|
int addrs_size, sctp_assoc_t *assoc_id)
|
||||||
int addrs_size,
|
|
||||||
sctp_assoc_t *assoc_id)
|
|
||||||
{
|
{
|
||||||
struct sockaddr *kaddrs;
|
|
||||||
int err = 0, flags = 0;
|
int err = 0, flags = 0;
|
||||||
|
|
||||||
pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n",
|
pr_debug("%s: sk:%p addrs:%p addrs_size:%d\n",
|
||||||
__func__, sk, addrs, addrs_size);
|
__func__, sk, kaddrs, addrs_size);
|
||||||
|
|
||||||
/* make sure the 1st addr's sa_family is accessible later */
|
/* make sure the 1st addr's sa_family is accessible later */
|
||||||
if (unlikely(addrs_size < sizeof(sa_family_t)))
|
if (unlikely(addrs_size < sizeof(sa_family_t)))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
kaddrs = memdup_user(addrs, addrs_size);
|
|
||||||
if (IS_ERR(kaddrs))
|
|
||||||
return PTR_ERR(kaddrs);
|
|
||||||
|
|
||||||
/* Allow security module to validate connectx addresses. */
|
/* Allow security module to validate connectx addresses. */
|
||||||
err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX,
|
err = security_sctp_bind_connect(sk, SCTP_SOCKOPT_CONNECTX,
|
||||||
(struct sockaddr *)kaddrs,
|
(struct sockaddr *)kaddrs,
|
||||||
addrs_size);
|
addrs_size);
|
||||||
if (err)
|
if (err)
|
||||||
goto out_free;
|
return err;
|
||||||
|
|
||||||
/* in-kernel sockets don't generally have a file allocated to them
|
/* in-kernel sockets don't generally have a file allocated to them
|
||||||
* if all they do is call sock_create_kern().
|
* if all they do is call sock_create_kern().
|
||||||
|
@ -1323,12 +1316,7 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
|
||||||
if (sk->sk_socket->file)
|
if (sk->sk_socket->file)
|
||||||
flags = sk->sk_socket->file->f_flags;
|
flags = sk->sk_socket->file->f_flags;
|
||||||
|
|
||||||
err = __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id);
|
return __sctp_connect(sk, kaddrs, addrs_size, flags, assoc_id);
|
||||||
|
|
||||||
out_free:
|
|
||||||
kfree(kaddrs);
|
|
||||||
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1336,10 +1324,10 @@ static int __sctp_setsockopt_connectx(struct sock *sk,
|
||||||
* to the option that doesn't provide association id.
|
* to the option that doesn't provide association id.
|
||||||
*/
|
*/
|
||||||
static int sctp_setsockopt_connectx_old(struct sock *sk,
|
static int sctp_setsockopt_connectx_old(struct sock *sk,
|
||||||
struct sockaddr __user *addrs,
|
struct sockaddr *kaddrs,
|
||||||
int addrs_size)
|
int addrs_size)
|
||||||
{
|
{
|
||||||
return __sctp_setsockopt_connectx(sk, addrs, addrs_size, NULL);
|
return __sctp_setsockopt_connectx(sk, kaddrs, addrs_size, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1349,13 +1337,13 @@ static int sctp_setsockopt_connectx_old(struct sock *sk,
|
||||||
* always positive.
|
* always positive.
|
||||||
*/
|
*/
|
||||||
static int sctp_setsockopt_connectx(struct sock *sk,
|
static int sctp_setsockopt_connectx(struct sock *sk,
|
||||||
struct sockaddr __user *addrs,
|
struct sockaddr *kaddrs,
|
||||||
int addrs_size)
|
int addrs_size)
|
||||||
{
|
{
|
||||||
sctp_assoc_t assoc_id = 0;
|
sctp_assoc_t assoc_id = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
err = __sctp_setsockopt_connectx(sk, addrs, addrs_size, &assoc_id);
|
err = __sctp_setsockopt_connectx(sk, kaddrs, addrs_size, &assoc_id);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -1385,6 +1373,7 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len,
|
||||||
{
|
{
|
||||||
struct sctp_getaddrs_old param;
|
struct sctp_getaddrs_old param;
|
||||||
sctp_assoc_t assoc_id = 0;
|
sctp_assoc_t assoc_id = 0;
|
||||||
|
struct sockaddr *kaddrs;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
#ifdef CONFIG_COMPAT
|
#ifdef CONFIG_COMPAT
|
||||||
|
@ -1408,9 +1397,12 @@ static int sctp_getsockopt_connectx3(struct sock *sk, int len,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = __sctp_setsockopt_connectx(sk, (struct sockaddr __user *)
|
kaddrs = memdup_user(param.addrs, param.addr_num);
|
||||||
param.addrs, param.addr_num,
|
if (IS_ERR(kaddrs))
|
||||||
&assoc_id);
|
return PTR_ERR(kaddrs);
|
||||||
|
|
||||||
|
err = __sctp_setsockopt_connectx(sk, kaddrs, param.addr_num, &assoc_id);
|
||||||
|
kfree(kaddrs);
|
||||||
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)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@ -4700,16 +4692,12 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname,
|
||||||
|
|
||||||
case SCTP_SOCKOPT_CONNECTX_OLD:
|
case SCTP_SOCKOPT_CONNECTX_OLD:
|
||||||
/* 'optlen' is the size of the addresses buffer. */
|
/* 'optlen' is the size of the addresses buffer. */
|
||||||
retval = sctp_setsockopt_connectx_old(sk,
|
retval = sctp_setsockopt_connectx_old(sk, kopt, optlen);
|
||||||
(struct sockaddr __user *)optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCTP_SOCKOPT_CONNECTX:
|
case SCTP_SOCKOPT_CONNECTX:
|
||||||
/* 'optlen' is the size of the addresses buffer. */
|
/* 'optlen' is the size of the addresses buffer. */
|
||||||
retval = sctp_setsockopt_connectx(sk,
|
retval = sctp_setsockopt_connectx(sk, kopt, optlen);
|
||||||
(struct sockaddr __user *)optval,
|
|
||||||
optlen);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCTP_DISABLE_FRAGMENTS:
|
case SCTP_DISABLE_FRAGMENTS:
|
||||||
|
|
Loading…
Reference in New Issue