This is a note to let you know that I've just added the patch titled net: don't unconditionally copy_from_user a struct ifreq for socket ioctls to the 5.4-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: net-don-t-unconditionally-copy_from_user-a-struct-ifreq-for-socket-ioctls.patch and it can be found in the queue-5.4 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From d0efb16294d145d157432feda83877ae9d7cdf37 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne <pcc@xxxxxxxxxx> Date: Thu, 26 Aug 2021 12:46:01 -0700 Subject: net: don't unconditionally copy_from_user a struct ifreq for socket ioctls From: Peter Collingbourne <pcc@xxxxxxxxxx> commit d0efb16294d145d157432feda83877ae9d7cdf37 upstream. A common implementation of isatty(3) involves calling a ioctl passing a dummy struct argument and checking whether the syscall failed -- bionic and glibc use TCGETS (passing a struct termios), and musl uses TIOCGWINSZ (passing a struct winsize). If the FD is a socket, we will copy sizeof(struct ifreq) bytes of data from the argument and return -EFAULT if that fails. The result is that the isatty implementations may return a non-POSIX-compliant value in errno in the case where part of the dummy struct argument is inaccessible, as both struct termios and struct winsize are smaller than struct ifreq (at least on arm64). Although there is usually enough stack space following the argument on the stack that this did not present a practical problem up to now, with MTE stack instrumentation it's more likely for the copy to fail, as the memory following the struct may have a different tag. Fix the problem by adding an early check for whether the ioctl is a valid socket ioctl, and return -ENOTTY if it isn't. Fixes: 44c02a2c3dc5 ("dev_ioctl(): move copyin/copyout to callers") Link: https://linux-review.googlesource.com/id/I869da6cf6daabc3e4b7b82ac979683ba05e27d4d Signed-off-by: Peter Collingbourne <pcc@xxxxxxxxxx> Cc: <stable@xxxxxxxxxxxxxxx> # 4.19 Signed-off-by: David S. Miller <davem@xxxxxxxxxxxxx> Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- include/linux/netdevice.h | 4 ++++ net/socket.c | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -3684,6 +3684,10 @@ int netdev_rx_handler_register(struct ne void netdev_rx_handler_unregister(struct net_device *dev); bool dev_valid_name(const char *name); +static inline bool is_socket_ioctl_cmd(unsigned int cmd) +{ + return _IOC_TYPE(cmd) == SOCK_IOC_TYPE; +} int dev_ioctl(struct net *net, unsigned int cmd, struct ifreq *ifr, bool *need_copyout); int dev_ifconf(struct net *net, struct ifconf *, int); --- a/net/socket.c +++ b/net/socket.c @@ -1053,7 +1053,7 @@ static long sock_do_ioctl(struct net *ne rtnl_unlock(); if (!err && copy_to_user(argp, &ifc, sizeof(struct ifconf))) err = -EFAULT; - } else { + } else if (is_socket_ioctl_cmd(cmd)) { struct ifreq ifr; bool need_copyout; if (copy_from_user(&ifr, argp, sizeof(struct ifreq))) @@ -1062,6 +1062,8 @@ static long sock_do_ioctl(struct net *ne if (!err && need_copyout) if (copy_to_user(argp, &ifr, sizeof(struct ifreq))) return -EFAULT; + } else { + err = -ENOTTY; } return err; } @@ -3228,6 +3230,8 @@ static int compat_ifr_data_ioctl(struct struct ifreq ifreq; u32 data32; + if (!is_socket_ioctl_cmd(cmd)) + return -ENOTTY; if (copy_from_user(ifreq.ifr_name, u_ifreq32->ifr_name, IFNAMSIZ)) return -EFAULT; if (get_user(data32, &u_ifreq32->ifr_data)) Patches currently in stable-queue which might be from pcc@xxxxxxxxxx are queue-5.4/net-don-t-unconditionally-copy_from_user-a-struct-ifreq-for-socket-ioctls.patch