mISDN: make sure device name is NUL terminated [Linux 4.14.129]

mISDN: make sure device name is NUL terminated [Linux 4.14.129]

This Linux kernel change "mISDN: make sure device name is NUL terminated" is included in the Linux 4.14.129 release. This change is authored by Dan Carpenter <dan.carpenter [at] oracle.com> on Wed May 22 11:45:13 2019 +0300. The commit for this change in Linux stable tree is dca534e (patch) which is from upstream commit ccfb62f. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream ccfb62f.

mISDN: make sure device name is NUL terminated

[ Upstream commit ccfb62f27beb295103e9392462b20a6ed807d0ea ]

The user can change the device_name with the IMSETDEVNAME ioctl, but we
need to ensure that the user's name is NUL terminated.  Otherwise it
could result in a buffer overflow when we copy the name back to the user
with IMGETDEVINFO ioctl.

I also changed two strcpy() calls which handle the name to strscpy().
Hopefully, there aren't any other ways to create a too long name, but
it's nice to do this as a kernel hardening measure.

Signed-off-by: Dan Carpenter <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>

There are 5 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/isdn/mISDN/socket.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 65cb4aa..477e070 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -394,7 +394,7 @@ static void mISDN_sock_unlink(struct mISDN_sock_list *l, struct sock *sk)
            memcpy(di.channelmap, dev->channelmap,
                   sizeof(di.channelmap));
            di.nrbchan = dev->nrbchan;
-           strcpy(di.name, dev_name(&dev->dev));
+           strscpy(di.name, dev_name(&dev->dev), sizeof(di.name));
            if (copy_to_user((void __user *)arg, &di, sizeof(di)))
                err = -EFAULT;
        } else
@@ -678,7 +678,7 @@ static int data_sock_getsockopt(struct socket *sock, int level, int optname,
            memcpy(di.channelmap, dev->channelmap,
                   sizeof(di.channelmap));
            di.nrbchan = dev->nrbchan;
-           strcpy(di.name, dev_name(&dev->dev));
+           strscpy(di.name, dev_name(&dev->dev), sizeof(di.name));
            if (copy_to_user((void __user *)arg, &di, sizeof(di)))
                err = -EFAULT;
        } else
@@ -692,6 +692,7 @@ static int data_sock_getsockopt(struct socket *sock, int level, int optname,
            err = -EFAULT;
            break;
        }
+       dn.name[sizeof(dn.name) - 1] = '\0';
        dev = get_mdevice(dn.id);
        if (dev)
            err = device_rename(&dev->dev, dn.name);

Leave a Reply

Your email address will not be published. Required fields are marked *