mirror of
https://github.com/torvalds/linux.git
synced 2024-11-11 14:42:24 +00:00
Merge branch 'sctp-Some-sockopt-optlen-fixes'
Marcelo Ricardo Leitner says: ==================== sctp: Some sockopt optlen fixes Hangbin Liu reported that some SCTP sockopt are allowing the user to get the kernel to allocate really large buffers by not having a ceiling on optlen. This patchset address this issue (in patch 2), replace an GFP_ATOMIC that isn't needed and avoid calculating the option size multiple times in some setsockopt. ==================== Acked-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
e5143f863c
@ -2277,7 +2277,7 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval,
|
|||||||
|
|
||||||
if (asoc && sctp_outq_is_empty(&asoc->outqueue)) {
|
if (asoc && sctp_outq_is_empty(&asoc->outqueue)) {
|
||||||
event = sctp_ulpevent_make_sender_dry_event(asoc,
|
event = sctp_ulpevent_make_sender_dry_event(asoc,
|
||||||
GFP_ATOMIC);
|
GFP_USER | __GFP_NOWARN);
|
||||||
if (!event)
|
if (!event)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
@ -3498,6 +3498,8 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk,
|
|||||||
|
|
||||||
if (optlen < sizeof(struct sctp_hmacalgo))
|
if (optlen < sizeof(struct sctp_hmacalgo))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
optlen = min_t(unsigned int, optlen, sizeof(struct sctp_hmacalgo) +
|
||||||
|
SCTP_AUTH_NUM_HMACS * sizeof(u16));
|
||||||
|
|
||||||
hmacs = memdup_user(optval, optlen);
|
hmacs = memdup_user(optval, optlen);
|
||||||
if (IS_ERR(hmacs))
|
if (IS_ERR(hmacs))
|
||||||
@ -3536,6 +3538,11 @@ static int sctp_setsockopt_auth_key(struct sock *sk,
|
|||||||
|
|
||||||
if (optlen <= sizeof(struct sctp_authkey))
|
if (optlen <= sizeof(struct sctp_authkey))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
/* authkey->sca_keylength is u16, so optlen can't be bigger than
|
||||||
|
* this.
|
||||||
|
*/
|
||||||
|
optlen = min_t(unsigned int, optlen, USHRT_MAX +
|
||||||
|
sizeof(struct sctp_authkey));
|
||||||
|
|
||||||
authkey = memdup_user(optval, optlen);
|
authkey = memdup_user(optval, optlen);
|
||||||
if (IS_ERR(authkey))
|
if (IS_ERR(authkey))
|
||||||
@ -3893,6 +3900,9 @@ static int sctp_setsockopt_reset_streams(struct sock *sk,
|
|||||||
|
|
||||||
if (optlen < sizeof(*params))
|
if (optlen < sizeof(*params))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
/* srs_number_streams is u16, so optlen can't be bigger than this. */
|
||||||
|
optlen = min_t(unsigned int, optlen, USHRT_MAX +
|
||||||
|
sizeof(__u16) * sizeof(*params));
|
||||||
|
|
||||||
params = memdup_user(optval, optlen);
|
params = memdup_user(optval, optlen);
|
||||||
if (IS_ERR(params))
|
if (IS_ERR(params))
|
||||||
@ -5015,7 +5025,7 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv
|
|||||||
len = sizeof(int);
|
len = sizeof(int);
|
||||||
if (put_user(len, optlen))
|
if (put_user(len, optlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (copy_to_user(optval, &sctp_sk(sk)->autoclose, sizeof(int)))
|
if (copy_to_user(optval, &sctp_sk(sk)->autoclose, len))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -5645,6 +5655,9 @@ copy_getaddrs:
|
|||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
/* XXX: We should have accounted for sizeof(struct sctp_getaddrs) too,
|
||||||
|
* but we can't change it anymore.
|
||||||
|
*/
|
||||||
if (put_user(bytes_copied, optlen))
|
if (put_user(bytes_copied, optlen))
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
out:
|
out:
|
||||||
@ -6081,7 +6094,7 @@ static int sctp_getsockopt_maxseg(struct sock *sk, int len,
|
|||||||
params.assoc_id = 0;
|
params.assoc_id = 0;
|
||||||
} else if (len >= sizeof(struct sctp_assoc_value)) {
|
} else if (len >= sizeof(struct sctp_assoc_value)) {
|
||||||
len = sizeof(struct sctp_assoc_value);
|
len = sizeof(struct sctp_assoc_value);
|
||||||
if (copy_from_user(¶ms, optval, sizeof(params)))
|
if (copy_from_user(¶ms, optval, len))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
} else
|
} else
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@ -6251,7 +6264,9 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
|
|||||||
|
|
||||||
if (len < sizeof(struct sctp_authkeyid))
|
if (len < sizeof(struct sctp_authkeyid))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (copy_from_user(&val, optval, sizeof(struct sctp_authkeyid)))
|
|
||||||
|
len = sizeof(struct sctp_authkeyid);
|
||||||
|
if (copy_from_user(&val, optval, len))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
asoc = sctp_id2assoc(sk, val.scact_assoc_id);
|
asoc = sctp_id2assoc(sk, val.scact_assoc_id);
|
||||||
@ -6263,7 +6278,6 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len,
|
|||||||
else
|
else
|
||||||
val.scact_keynumber = ep->active_key_id;
|
val.scact_keynumber = ep->active_key_id;
|
||||||
|
|
||||||
len = sizeof(struct sctp_authkeyid);
|
|
||||||
if (put_user(len, optlen))
|
if (put_user(len, optlen))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
if (copy_to_user(optval, &val, len))
|
if (copy_to_user(optval, &val, len))
|
||||||
@ -6289,7 +6303,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len,
|
|||||||
if (len < sizeof(struct sctp_authchunks))
|
if (len < sizeof(struct sctp_authchunks))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
|
if (copy_from_user(&val, optval, sizeof(val)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
to = p->gauth_chunks;
|
to = p->gauth_chunks;
|
||||||
@ -6334,7 +6348,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len,
|
|||||||
if (len < sizeof(struct sctp_authchunks))
|
if (len < sizeof(struct sctp_authchunks))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
if (copy_from_user(&val, optval, sizeof(struct sctp_authchunks)))
|
if (copy_from_user(&val, optval, sizeof(val)))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
to = p->gauth_chunks;
|
to = p->gauth_chunks;
|
||||||
|
Loading…
Reference in New Issue
Block a user