lkml.org 
[lkml]   [2020]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.7 149/179] staging: comedi: addi_apci_1500: check INSN_CONFIG_DIGITAL_TRIG shift
    Date
    From: Ian Abbott <abbotti@mev.co.uk>

    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: a8c66b684efaf ("staging: comedi: addi_apci_1500: rewrite the subdevice support functions")
    Cc: <stable@vger.kernel.org> #4.0+: ef75e14a6c93: 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>

    ---
    drivers/staging/comedi/drivers/addi_apci_1500.c | 24 +++++++++++++++++++-----
    1 file changed, 19 insertions(+), 5 deletions(-)

    --- a/drivers/staging/comedi/drivers/addi_apci_1500.c
    +++ b/drivers/staging/comedi/drivers/addi_apci_1500.c
    @@ -452,13 +452,14 @@ static int apci1500_di_cfg_trig(struct c
    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 c
    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;
    }

    \
     
     \ /
      Last update: 2020-07-27 16:26    [W:4.160 / U:0.144 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site