lkml.org 
[lkml]   [2019]   [Mar]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 4.9 73/87] Bluetooth: Verify that l2cap_get_conf_opt provides large enough buffer
    Date
    From: Marcel Holtmann <marcel@holtmann.org>

    [ Upstream commit 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 ]

    The function l2cap_get_conf_opt will return L2CAP_CONF_OPT_SIZE + opt->len
    as length value. The opt->len however is in control over the remote user
    and can be used by an attacker to gain access beyond the bounds of the
    actual packet.

    To prevent any potential leak of heap memory, it is enough to check that
    the resulting len calculation after calling l2cap_get_conf_opt is not
    below zero. A well formed packet will always return >= 0 here and will
    end with the length value being zero after the last option has been
    parsed. In case of malformed packets messing with the opt->len field the
    length value will become negative. If that is the case, then just abort
    and ignore the option.

    In case an attacker uses a too short opt->len value, then garbage will
    be parsed, but that is protected by the unknown option handling and also
    the option parameter size checks.

    Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
    Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/bluetooth/l2cap_core.c | 6 ++++++
    1 file changed, 6 insertions(+)

    diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
    index 1fc23cb4a3e0..bf7a2846a85f 100644
    --- a/net/bluetooth/l2cap_core.c
    +++ b/net/bluetooth/l2cap_core.c
    @@ -3326,6 +3326,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data

    while (len >= L2CAP_CONF_OPT_SIZE) {
    len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
    + if (len < 0)
    + break;

    hint = type & L2CAP_CONF_HINT;
    type &= L2CAP_CONF_MASK;
    @@ -3537,6 +3539,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,

    while (len >= L2CAP_CONF_OPT_SIZE) {
    len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
    + if (len < 0)
    + break;

    switch (type) {
    case L2CAP_CONF_MTU:
    @@ -3717,6 +3721,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)

    while (len >= L2CAP_CONF_OPT_SIZE) {
    len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
    + if (len < 0)
    + break;

    switch (type) {
    case L2CAP_CONF_RFC:
    --
    2.19.1
    \
     
     \ /
      Last update: 2019-03-27 19:40    [W:4.031 / U:0.048 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site