Skip to content

Commit

Permalink
staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
Browse files Browse the repository at this point in the history
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: <[email protected]> radcolor#4.0+: ef75e14a6c93: staging: comedi: verify array index is correct before using it
Cc: <[email protected]> radcolor#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]>
  • Loading branch information
ian-abbott authored and gregkh committed Jul 31, 2020
1 parent 6bc939f commit 1763572
Showing 1 changed file with 19 additions and 5 deletions.
24 changes: 19 additions & 5 deletions drivers/staging/comedi/drivers/addi_apci_1500.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,21 +461,35 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
struct apci1500_private *devpriv = dev->private;
unsigned int trig = data[1];
unsigned int shift = data[3];
unsigned int hi_mask = data[4] << shift;
unsigned int lo_mask = data[5] << shift;
unsigned int chan_mask = hi_mask | lo_mask;
unsigned int old_mask = (1 << shift) - 1;
unsigned int hi_mask;
unsigned int lo_mask;
unsigned int chan_mask;
unsigned int old_mask;
unsigned int pm;
unsigned int pt;
unsigned int pp;
unsigned int invalid_chan;

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

if (chan_mask > 0xffff) {
if (shift <= 16) {
hi_mask = data[4] << shift;
lo_mask = data[5] << shift;
old_mask = (1U << shift) - 1;
invalid_chan = (data[4] | data[5]) >> (16 - shift);
} else {
hi_mask = 0;
lo_mask = 0;
old_mask = 0xffff;
invalid_chan = data[4] | data[5];
}
chan_mask = hi_mask | lo_mask;

if (invalid_chan) {
dev_dbg(dev->class_dev, "invalid digital trigger channel\n");
return -EINVAL;
}
Expand Down

0 comments on commit 1763572

Please sign in to comment.