Message ID | 20190219104856.29208-2-kai.heng.feng@canonical.com |
---|---|
State | New |
Headers | show |
Series | CVE-2019-3459 - Heap address infoleak in use of l2cap_get_conf_opt | expand |
On 2019-02-19 18:48:56, Kai-Heng Feng wrote: > From: Marcel Holtmann <marcel@holtmann.org> > > 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. > > CVE-2019-3459 > > 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> > (cherry picked from commit 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 linux-next) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> I don't love the fact that these bluetooth fixes are still sitting in linux-next and haven't landed in Linus' tree yet but they've been sitting in linux-next for a while and I don't spot any reports of breakage. I think we should go ahead and pull these in at this time. Acked-by: Tyler Hicks <tyhicks@canonical.com> Tyler > --- > 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 d17a4736e47c..6c873dc549b0 100644 > --- a/net/bluetooth/l2cap_core.c > +++ b/net/bluetooth/l2cap_core.c > @@ -3336,6 +3336,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; > @@ -3547,6 +3549,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: > @@ -3727,6 +3731,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.17.1 > > > -- > kernel-team mailing list > kernel-team@lists.ubuntu.com > https://lists.ubuntu.com/mailman/listinfo/kernel-team
On 19.02.19 11:48, Kai-Heng Feng wrote: > From: Marcel Holtmann <marcel@holtmann.org> > > 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. > > CVE-2019-3459 > > 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> > (cherry picked from commit 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 linux-next) > Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com> > --- Applied to trusty,xenial,bionic,cosmic/master-next. Thanks. -Stefan > 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 d17a4736e47c..6c873dc549b0 100644 > --- a/net/bluetooth/l2cap_core.c > +++ b/net/bluetooth/l2cap_core.c > @@ -3336,6 +3336,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; > @@ -3547,6 +3549,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: > @@ -3727,6 +3731,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: >
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index d17a4736e47c..6c873dc549b0 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3336,6 +3336,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; @@ -3547,6 +3549,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: @@ -3727,6 +3731,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: