media: av7110: fix a spectre vulnerability
authorMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Tue, 15 Oct 2024 07:24:24 +0000 (09:24 +0200)
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>
Fri, 18 Oct 2024 08:43:03 +0000 (10:43 +0200)
As warned by smatch:
drivers/staging/media/av7110/av7110_ca.c:270 dvb_ca_ioctl() warn: potential spectre issue 'av7110->ci_slot' [w] (local cap)

There is a spectre-related vulnerability at the code. Fix it.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
drivers/staging/media/av7110/av7110.h
drivers/staging/media/av7110/av7110_ca.c

index ec461fd..b584754 100644 (file)
@@ -88,6 +88,8 @@ struct infrared {
        u32                     ir_config;
 };
 
+#define MAX_CI_SLOTS   2
+
 /* place to store all the necessary device information */
 struct av7110 {
        /* devices */
@@ -163,7 +165,7 @@ struct av7110 {
 
        /* CA */
 
-       struct ca_slot_info     ci_slot[2];
+       struct ca_slot_info     ci_slot[MAX_CI_SLOTS];
 
        enum av7110_video_mode  vidmode;
        struct dmxdev           dmxdev;
index 6ce212c..fce4023 100644 (file)
 
 void CI_handle(struct av7110 *av7110, u8 *data, u16 len)
 {
+       unsigned slot_num;
+
        dprintk(8, "av7110:%p\n", av7110);
 
        if (len < 3)
                return;
        switch (data[0]) {
        case CI_MSG_CI_INFO:
-               if (data[2] != 1 && data[2] != 2)
+               if (data[2] != 1 && data[2] != MAX_CI_SLOTS)
                        break;
+
+               slot_num = array_index_nospec(data[2] - 1, MAX_CI_SLOTS);
+
                switch (data[1]) {
                case 0:
-                       av7110->ci_slot[data[2] - 1].flags = 0;
+                       av7110->ci_slot[slot_num].flags = 0;
                        break;
                case 1:
-                       av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_PRESENT;
+                       av7110->ci_slot[slot_num].flags |= CA_CI_MODULE_PRESENT;
                        break;
                case 2:
-                       av7110->ci_slot[data[2] - 1].flags |= CA_CI_MODULE_READY;
+                       av7110->ci_slot[slot_num].flags |= CA_CI_MODULE_READY;
                        break;
                }
                break;
@@ -262,15 +267,19 @@ static int dvb_ca_ioctl(struct file *file, unsigned int cmd, void *parg)
        case CA_GET_SLOT_INFO:
        {
                struct ca_slot_info *info = (struct ca_slot_info *)parg;
+               unsigned int slot_num;
 
                if (info->num < 0 || info->num > 1) {
                        mutex_unlock(&av7110->ioctl_mutex);
                        return -EINVAL;
                }
-               av7110->ci_slot[info->num].num = info->num;
-               av7110->ci_slot[info->num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
-                                                       CA_CI_LINK : CA_CI;
-               memcpy(info, &av7110->ci_slot[info->num], sizeof(struct ca_slot_info));
+               slot_num = array_index_nospec(info->num, MAX_CI_SLOTS);
+
+               av7110->ci_slot[slot_num].num = info->num;
+               av7110->ci_slot[slot_num].type = FW_CI_LL_SUPPORT(av7110->arm_app) ?
+                                                CA_CI_LINK : CA_CI;
+               memcpy(info, &av7110->ci_slot[slot_num],
+                      sizeof(struct ca_slot_info));
                break;
        }