vcc_setsockopt() never checked optlen for ATM-specific options (SO_ATMQOS
and SO_SETCLP) and called copy_from_sockptr() assuming optval contained
sufficient space for struct atm_qos or unsigned long.
While copy_from_user() previously copied from a user buffer without checking
optlen, the introduction of sockptr_t and cgroup BPF setsockopt filters allows
optval to point to a kernel memory buffer allocated with a reduced optlen.
Because copy_from_sockptr() on kernel pointers uses memcpy(), this leads to a
KASAN slab-out-of-bounds read when optlen is smaller than the expected structure
size.
Fix this by using copy_safe_from_sockptr(), which validates that optlen is at
least the expected size before copying.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: syzbot+6c98d6eb7aabb6b1ad39@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/netdev/6a71fd31.9511d2ce.1fc5b9.033c.GAE@google.com/T/#u (local)
Signed-off-by: Eric Dumazet <edumazet@google.com>
---
net/atm/common.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/net/atm/common.c b/net/atm/common.c
index c7f92405daf050ecd2a507e41efdd622ab8dc6a8..6a0c5184c0d6380deaa95f68cb97c7745b4f7b56 100644
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -722,8 +722,9 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
{
struct atm_qos qos;
- if (copy_from_sockptr(&qos, optval, sizeof(qos)))
- return -EFAULT;
+ error = copy_safe_from_sockptr(&qos, sizeof(qos), optval, optlen);
+ if (error)
+ return error;
error = check_qos(&qos);
if (error)
return error;@@ -737,8 +738,9 @@ int vcc_setsockopt(struct socket *sock, int level, int optname,
return 0;
}
case SO_SETCLP:
- if (copy_from_sockptr(&value, optval, sizeof(value)))
- return -EFAULT;
+ error = copy_safe_from_sockptr(&value, sizeof(value), optval, optlen);
+ if (error)
+ return error;
if (value)
vcc->atm_options |= ATM_ATMOPT_CLP;
else
--
2.55.0.571.g244d577d93-goog