mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2026-07-25 16:19:48 +02:00
net/iucv: fix locking in .getsockopt
[ Upstream commit3589d20a66] Mirror iucv_sock_setsockopt() and wrap the whole switch in lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock becomes redundant and is removed. Any AF_IUCV HIPER user can potentially crash the kernel by racing recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences iucv->hs_dev->mtu after iucv_sock_close() (called from the racing recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference oops. Suggested-by: Stanislav Fomichev <sdf.kernel@gmail.com> Fixes:51363b8751("af_iucv: allow retrieval of maximum message size") Signed-off-by: Breno Leitao <leitao@debian.org> Reviewed-by: Alexandra Winter <wintera@linux.ibm.com> Tested-by: Alexandra Winter <wintera@linux.ibm.com> Link: https://patch.msgid.link/20260521-af_iucv_fix2-v1-1-f16b1c510aa9@debian.org Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
64c96e497d
commit
1fc30bd4e5
+14
-6
@@ -1539,7 +1539,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
|
||||
struct sock *sk = sock->sk;
|
||||
struct iucv_sock *iucv = iucv_sk(sk);
|
||||
unsigned int val;
|
||||
int len;
|
||||
int len, rc;
|
||||
|
||||
if (level != SOL_IUCV)
|
||||
return -ENOPROTOOPT;
|
||||
@@ -1552,26 +1552,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,
|
||||
|
||||
len = min_t(unsigned int, len, sizeof(int));
|
||||
|
||||
rc = 0;
|
||||
|
||||
lock_sock(sk);
|
||||
switch (optname) {
|
||||
case SO_IPRMDATA_MSG:
|
||||
val = (iucv->flags & IUCV_IPRMDATA) ? 1 : 0;
|
||||
break;
|
||||
case SO_MSGLIMIT:
|
||||
lock_sock(sk);
|
||||
val = (iucv->path != NULL) ? iucv->path->msglim /* connected */
|
||||
: iucv->msglimit; /* default */
|
||||
release_sock(sk);
|
||||
break;
|
||||
case SO_MSGSIZE:
|
||||
if (sk->sk_state == IUCV_OPEN)
|
||||
return -EBADFD;
|
||||
if (sk->sk_state == IUCV_OPEN) {
|
||||
rc = -EBADFD;
|
||||
break;
|
||||
}
|
||||
val = (iucv->hs_dev) ? iucv->hs_dev->mtu -
|
||||
sizeof(struct af_iucv_trans_hdr) - ETH_HLEN :
|
||||
0x7fffffff;
|
||||
break;
|
||||
default:
|
||||
return -ENOPROTOOPT;
|
||||
rc = -ENOPROTOOPT;
|
||||
break;
|
||||
}
|
||||
release_sock(sk);
|
||||
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (put_user(len, optlen))
|
||||
return -EFAULT;
|
||||
|
||||
Reference in New Issue
Block a user