Skip to content

Commit f96ab42

Browse files
ian-abbottgregkh
authored andcommitted
staging: comedi: addi_apci_1564: check INSN_CONFIG_DIGITAL_TRIG shift
commit 926234f 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]> raspberrypi#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 3027b25 commit f96ab42

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
@@ -331,14 +331,22 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
331331
unsigned int *data)
332332
{
333333
struct apci1564_private *devpriv = dev->private;
334-
unsigned int shift, oldmask;
334+
unsigned int shift, oldmask, himask, lomask;
335335

336336
switch (data[0]) {
337337
case INSN_CONFIG_DIGITAL_TRIG:
338338
if (data[1] != 0)
339339
return -EINVAL;
340340
shift = data[3];
341-
oldmask = (1U << shift) - 1;
341+
if (shift < 32) {
342+
oldmask = (1U << shift) - 1;
343+
himask = data[4] << shift;
344+
lomask = data[5] << shift;
345+
} else {
346+
oldmask = 0xffffffffu;
347+
himask = 0;
348+
lomask = 0;
349+
}
342350
switch (data[2]) {
343351
case COMEDI_DIGITAL_TRIG_DISABLE:
344352
devpriv->ctrl = 0;
@@ -362,8 +370,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
362370
devpriv->mode2 &= oldmask;
363371
}
364372
/* configure specified channels */
365-
devpriv->mode1 |= data[4] << shift;
366-
devpriv->mode2 |= data[5] << shift;
373+
devpriv->mode1 |= himask;
374+
devpriv->mode2 |= lomask;
367375
break;
368376
case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
369377
if (devpriv->ctrl != (APCI1564_DI_IRQ_ENA |
@@ -380,8 +388,8 @@ static int apci1564_cos_insn_config(struct comedi_device *dev,
380388
devpriv->mode2 &= oldmask;
381389
}
382390
/* configure specified channels */
383-
devpriv->mode1 |= data[4] << shift;
384-
devpriv->mode2 |= data[5] << shift;
391+
devpriv->mode1 |= himask;
392+
devpriv->mode2 |= lomask;
385393
break;
386394
default:
387395
return -EINVAL;

0 commit comments

Comments
 (0)