lkml.org 
[lkml]   [2016]   [Nov]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 035/152] tty/vt/keyboard: fix OOB access in do_compute_shiftstate()
    3.2.84-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Dmitry Torokhov <dmitry.torokhov@gmail.com>

    commit 510cccb5b0c8868a2b302a0ab524da7912da648b upstream.

    The size of individual keymap in drivers/tty/vt/keyboard.c is NR_KEYS,
    which is currently 256, whereas number of keys/buttons in input device (and
    therefor in key_down) is much larger - KEY_CNT - 768, and that can cause
    out-of-bound access when we do

    sym = U(key_maps[0][k]);

    with large 'k'.

    To fix it we should not attempt iterating beyond smaller of NR_KEYS and
    KEY_CNT.

    Also while at it let's switch to for_each_set_bit() instead of open-coding
    it.

    Reported-by: Sasha Levin <sasha.levin@oracle.com>
    Reviewed-by: Guenter Roeck <linux@roeck-us.net>
    Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/tty/vt/keyboard.c | 30 +++++++++---------------------
    1 file changed, 9 insertions(+), 21 deletions(-)

    --- a/drivers/tty/vt/keyboard.c
    +++ b/drivers/tty/vt/keyboard.c
    @@ -386,34 +386,22 @@ static void to_utf8(struct vc_data *vc,
    */
    void compute_shiftstate(void)
    {
    - unsigned int i, j, k, sym, val;
    + unsigned int k, sym, val;

    shift_state = 0;
    memset(shift_down, 0, sizeof(shift_down));

    - for (i = 0; i < ARRAY_SIZE(key_down); i++) {
    -
    - if (!key_down[i])
    + for_each_set_bit(k, key_down, min(NR_KEYS, KEY_CNT)) {
    + sym = U(key_maps[0][k]);
    + if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
    continue;

    - k = i * BITS_PER_LONG;
    -
    - for (j = 0; j < BITS_PER_LONG; j++, k++) {
    -
    - if (!test_bit(k, key_down))
    - continue;
    -
    - sym = U(key_maps[0][k]);
    - if (KTYP(sym) != KT_SHIFT && KTYP(sym) != KT_SLOCK)
    - continue;
    -
    - val = KVAL(sym);
    - if (val == KVAL(K_CAPSSHIFT))
    - val = KVAL(K_SHIFT);
    + val = KVAL(sym);
    + if (val == KVAL(K_CAPSSHIFT))
    + val = KVAL(K_SHIFT);

    - shift_down[val]++;
    - shift_state |= (1 << val);
    - }
    + shift_down[val]++;
    + shift_state |= BIT(val);
    }
    }

    \
     
     \ /
      Last update: 2016-11-14 04:12    [W:4.112 / U:0.124 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site