mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 11:19:37 +00:00
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:a8c66b684e
("staging: comedi: addi_apci_1500: rewrite the subdevice support functions") Cc: <stable@vger.kernel.org> #4.0+:ef75e14a6c
: staging: comedi: verify array index is correct before using it Cc: <stable@vger.kernel.org> #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>
This commit is contained in:
parent
0bd0db42a0
commit
fc846e9db6
1 changed files with 19 additions and 5 deletions
|
@ -452,13 +452,14 @@ 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,
|
||||
|
@ -466,7 +467,20 @@ static int apci1500_di_cfg_trig(struct comedi_device *dev,
|
|||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue