Skip to content

Commit 1eddbd3

Browse files
ian-abbottgregkh
authored andcommitted
staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
commit fc846e9db67c7e808d77bf9e2ef3d49e3820ce5d 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, 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: <stable@vger.kernel.org> OnePlusOSS#4.0+: ef75e14a6c93: staging: comedi: verify array index is correct before using it Cc: <stable@vger.kernel.org> OnePlusOSS#4.0+ Signed-off-by: Ian Abbott <abbotti@mev.co.uk> Link: https://lore.kernel.org/r/20200717145257.112660-5-abbotti@mev.co.uk Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 7358de4 commit 1eddbd3

1 file changed

Lines changed: 19 additions & 5 deletions

File tree

drivers/staging/comedi/drivers/addi_apci_1500.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -461,21 +461,35 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
461461
struct apci1500_private *devpriv = dev->private;
462462
unsigned int trig = data[1];
463463
unsigned int shift = data[3];
464-
unsigned int hi_mask = data[4] << shift;
465-
unsigned int lo_mask = data[5] << shift;
466-
unsigned int chan_mask = hi_mask | lo_mask;
467-
unsigned int old_mask = (1 << shift) - 1;
464+
unsigned int hi_mask;
465+
unsigned int lo_mask;
466+
unsigned int chan_mask;
467+
unsigned int old_mask;
468468
unsigned int pm;
469469
unsigned int pt;
470470
unsigned int pp;
471+
unsigned int invalid_chan;
471472

472473
if (trig > 1) {
473474
dev_dbg(dev->class_dev,
474475
"invalid digital trigger number (0=AND, 1=OR)\n");
475476
return -EINVAL;
476477
}
477478

478-
if (chan_mask > 0xffff) {
479+
if (shift <= 16) {
480+
hi_mask = data[4] << shift;
481+
lo_mask = data[5] << shift;
482+
old_mask = (1U << shift) - 1;
483+
invalid_chan = (data[4] | data[5]) >> (16 - shift);
484+
} else {
485+
hi_mask = 0;
486+
lo_mask = 0;
487+
old_mask = 0xffff;
488+
invalid_chan = data[4] | data[5];
489+
}
490+
chan_mask = hi_mask | lo_mask;
491+
492+
if (invalid_chan) {
479493
dev_dbg(dev->class_dev, "invalid digital trigger channel\n");
480494
return -EINVAL;
481495
}

0 commit comments

Comments
 (0)