diff options
author | Xin Long <lucien.xin@gmail.com> | 2021-07-17 17:19:19 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-07-28 14:35:38 +0200 |
commit | 096a8dca8ca5191292bcc6409c552a7b7f5e7362 (patch) | |
tree | 83e4ed87d38494ccbd2126bc4bae9742be397290 | |
parent | 8e9662fde6d63c78eb1350f6167f64c9d71a865b (diff) | |
download | linux-stable-096a8dca8ca5191292bcc6409c552a7b7f5e7362.tar.gz linux-stable-096a8dca8ca5191292bcc6409c552a7b7f5e7362.tar.bz2 linux-stable-096a8dca8ca5191292bcc6409c552a7b7f5e7362.zip |
sctp: trim optlen when it's a huge value in sctp_setsockopt
[ Upstream commit 2f3fdd8d4805015fa964807e1c7f3d88f31bd389 ]
After commit ca84bd058dae ("sctp: copy the optval from user space in
sctp_setsockopt"), it does memory allocation in sctp_setsockopt with
the optlen, and it would fail the allocation and return error if the
optlen from user space is a huge value.
This breaks some sockopts, like SCTP_HMAC_IDENT, SCTP_RESET_STREAMS and
SCTP_AUTH_KEY, as when processing these sockopts before, optlen would
be trimmed to a biggest value it needs when optlen is a huge value,
instead of failing the allocation and returning error.
This patch is to fix the allocation failure when it's a huge optlen from
user space by trimming it to the biggest size sctp sockopt may need when
necessary, and this biggest size is from sctp_setsockopt_reset_streams()
for SCTP_RESET_STREAMS, which is bigger than those for SCTP_HMAC_IDENT
and SCTP_AUTH_KEY.
Fixes: ca84bd058dae ("sctp: copy the optval from user space in sctp_setsockopt")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | net/sctp/socket.c | 4 |
1 files changed, 4 insertions, 0 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3ac6b21ecf2c..e872bc50bbe6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -4471,6 +4471,10 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, } if (optlen > 0) { + /* Trim it to the biggest size sctp sockopt may need if necessary */ + optlen = min_t(unsigned int, optlen, + PAGE_ALIGN(USHRT_MAX + + sizeof(__u16) * sizeof(struct sctp_reset_streams))); kopt = memdup_sockptr(optval, optlen); if (IS_ERR(kopt)) return PTR_ERR(kopt); |