n_gsm: Use array_index_nospec() with index that comes from userspace
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tue, 11 Apr 2023 16:45:32 +0000 (19:45 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 20 Apr 2023 12:11:33 +0000 (14:11 +0200)
dc.channel used for indexing comes directly from copy_from_user(). Use
array_index_nospec() to mitigate speculative side-channel.

Link: https://lore.kernel.org/linux-serial/64306d13.ONswMlyWlVKLGkKR%25lkp@intel.com/
Cc: stable <stable@kernel.org>
Fixes: afe3154ba87e ("tty: n_gsm: add ioctl for DLC config via ldisc handle")
Reported-by: kernel test robot <lkp@intel.com>
Reviewed-by: Daniel Starke <daniel.starke@siemens.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20230411164532.64175-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_gsm.c

index c42c8b8..b411a26 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/math.h>
+#include <linux/nospec.h>
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/poll.h>
@@ -3717,8 +3718,8 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
        struct gsm_config_ext ce;
        struct gsm_dlci_config dc;
        struct gsm_mux *gsm = tty->disc_data;
+       unsigned int base, addr;
        struct gsm_dlci *dlci;
-       unsigned int base;
 
        switch (cmd) {
        case GSMIOC_GETCONF:
@@ -3747,9 +3748,10 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
                        return -EFAULT;
                if (dc.channel == 0 || dc.channel >= NUM_DLCI)
                        return -EINVAL;
-               dlci = gsm->dlci[dc.channel];
+               addr = array_index_nospec(dc.channel, NUM_DLCI);
+               dlci = gsm->dlci[addr];
                if (!dlci) {
-                       dlci = gsm_dlci_alloc(gsm, dc.channel);
+                       dlci = gsm_dlci_alloc(gsm, addr);
                        if (!dlci)
                                return -ENOMEM;
                }
@@ -3762,9 +3764,10 @@ static int gsmld_ioctl(struct tty_struct *tty, unsigned int cmd,
                        return -EFAULT;
                if (dc.channel == 0 || dc.channel >= NUM_DLCI)
                        return -EINVAL;
-               dlci = gsm->dlci[dc.channel];
+               addr = array_index_nospec(dc.channel, NUM_DLCI);
+               dlci = gsm->dlci[addr];
                if (!dlci) {
-                       dlci = gsm_dlci_alloc(gsm, dc.channel);
+                       dlci = gsm_dlci_alloc(gsm, addr);
                        if (!dlci)
                                return -ENOMEM;
                }