Skip to content

Commit fc846e9

Browse files
ian-abbottgregkh
authored andcommitted
staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
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, adjusting the checks for invalid channels so that enabled channel bits that would have been lost by shifting are also checked for validity. Only channels 0 to 15 are valid. Fixes: a8c66b6 ("staging: comedi: addi_apci_1500: rewrite the subdevice support functions") Cc: <[email protected]> #4.0+: ef75e14: staging: comedi: verify array index is correct before using it Cc: <[email protected]> #4.0+ 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 0bd0db4 commit fc846e9

File tree

1 file changed

+19
-5
lines changed

1 file changed

+19
-5
lines changed

drivers/staging/comedi/drivers/addi_apci_1500.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -452,21 +452,35 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
452452
struct apci1500_private *devpriv = dev->private;
453453
unsigned int trig = data[1];
454454
unsigned int shift = data[3];
455-
unsigned int hi_mask = data[4] << shift;
456-
unsigned int lo_mask = data[5] << shift;
457-
unsigned int chan_mask = hi_mask | lo_mask;
458-
unsigned int old_mask = (1 << shift) - 1;
455+
unsigned int hi_mask;
456+
unsigned int lo_mask;
457+
unsigned int chan_mask;
458+
unsigned int old_mask;
459459
unsigned int pm;
460460
unsigned int pt;
461461
unsigned int pp;
462+
unsigned int invalid_chan;
462463

463464
if (trig > 1) {
464465
dev_dbg(dev->class_dev,
465466
"invalid digital trigger number (0=AND, 1=OR)\n");
466467
return -EINVAL;
467468
}
468469

469-
if (chan_mask > 0xffff) {
470+
if (shift <= 16) {
471+
hi_mask = data[4] << shift;
472+
lo_mask = data[5] << shift;
473+
old_mask = (1U << shift) - 1;
474+
invalid_chan = (data[4] | data[5]) >> (16 - shift);
475+
} else {
476+
hi_mask = 0;
477+
lo_mask = 0;
478+
old_mask = 0xffff;
479+
invalid_chan = data[4] | data[5];
480+
}
481+
chan_mask = hi_mask | lo_mask;
482+
483+
if (invalid_chan) {
470484
dev_dbg(dev->class_dev, "invalid digital trigger channel\n");
471485
return -EINVAL;
472486
}

0 commit comments

Comments
 (0)