Skip to content

Commit 428f81f

Browse files
ian-abbottSGCMarkus
authored andcommitted
staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
commit 926234f1b8434c4409aa4c53637aa3362ca07cea upstream. The `INSN_CONFIG` comedi instruction with sub-instruction code `INSN_CONFIG_DIGITAL_TRIG` includes a base channel in `data[3]`. This is used as a right shift amount for other bitmask values without being checked. Shift amounts greater than or equal to 32 will result in undefined behavior. Add code to deal with this. Fixes: 1e15687 ("staging: comedi: addi_apci_1564: add Change-of-State interrupt subdevice and required functions") Cc: <[email protected]> #3.17+ Signed-off-by: Ian Abbott <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent c9ffb3c commit 428f81f

File tree

1 file changed

+14
-6
lines changed

1 file changed

+14
-6
lines changed

drivers/staging/comedi/drivers/addi_apci_1564.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -340,14 +340,22 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
340340
unsigned int *data)
341341
{
342342
struct apci1564_private *devpriv = dev->private;
343-
unsigned int shift, oldmask;
343+
unsigned int shift, oldmask, himask, lomask;
344344

345345
switch (data[0]) {
346346
case INSN_CONFIG_DIGITAL_TRIG:
347347
if (data[1] != 0)
348348
return -EINVAL;
349349
shift = data[3];
350-
oldmask = (1U << shift) - 1;
350+
if (shift < 32) {
351+
oldmask = (1U << shift) - 1;
352+
himask = data[4] << shift;
353+
lomask = data[5] << shift;
354+
} else {
355+
oldmask = 0xffffffffu;
356+
himask = 0;
357+
lomask = 0;
358+
}
351359
switch (data[2]) {
352360
case COMEDI_DIGITAL_TRIG_DISABLE:
353361
devpriv->ctrl = 0;
@@ -371,8 +379,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
371379
devpriv->mode2 &= oldmask;
372380
}
373381
/* configure specified channels */
374-
devpriv->mode1 |= data[4] << shift;
375-
devpriv->mode2 |= data[5] << shift;
382+
devpriv->mode1 |= himask;
383+
devpriv->mode2 |= lomask;
376384
break;
377385
case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
378386
if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA |
@@ -389,8 +397,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
389397
devpriv->mode2 &= oldmask;
390398
}
391399
/* configure specified channels */
392-
devpriv->mode1 |= data[4] << shift;
393-
devpriv->mode2 |= data[5] << shift;
400+
devpriv->mode1 |= himask;
401+
devpriv->mode2 |= lomask;
394402
break;
395403
default:
396404
return -EINVAL;

0 commit comments

Comments
 (0)