lkml.org 
[lkml]   [2024]   [Mar]   [29]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 6.8 58/68] wifi: cfg80211: check A-MSDU format more carefully
    Date
    From: Johannes Berg <johannes.berg@intel.com>

    [ Upstream commit 9ad7974856926129f190ffbe3beea78460b3b7cc ]

    If it looks like there's another subframe in the A-MSDU
    but the header isn't fully there, we can end up reading
    data out of bounds, only to discard later. Make this a
    bit more careful and check if the subframe header can
    even be present.

    Reported-by: syzbot+d050d437fe47d479d210@syzkaller.appspotmail.com
    Link: https://msgid.link/20240226203405.a731e2c95e38.I82ce7d8c0cc8970ce29d0a39fdc07f1ffc425be4@changeid
    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    net/wireless/util.c | 14 ++++++++++----
    1 file changed, 10 insertions(+), 4 deletions(-)

    diff --git a/net/wireless/util.c b/net/wireless/util.c
    index d1ce3bee27973..b9d15f369378b 100644
    --- a/net/wireless/util.c
    +++ b/net/wireless/util.c
    @@ -791,15 +791,19 @@ ieee80211_amsdu_subframe_length(void *field, u8 mesh_flags, u8 hdr_type)

    bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
    {
    - int offset = 0, remaining, subframe_len, padding;
    + int offset = 0, subframe_len, padding;

    for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
    + int remaining = skb->len - offset;
    struct {
    __be16 len;
    u8 mesh_flags;
    } hdr;
    u16 len;

    + if (sizeof(hdr) > remaining)
    + return false;
    +
    if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
    return false;

    @@ -807,7 +811,6 @@ bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
    mesh_hdr);
    subframe_len = sizeof(struct ethhdr) + len;
    padding = (4 - subframe_len) & 0x3;
    - remaining = skb->len - offset;

    if (subframe_len > remaining)
    return false;
    @@ -825,7 +828,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
    {
    unsigned int hlen = ALIGN(extra_headroom, 4);
    struct sk_buff *frame = NULL;
    - int offset = 0, remaining;
    + int offset = 0;
    struct {
    struct ethhdr eth;
    uint8_t flags;
    @@ -839,10 +842,14 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
    copy_len = sizeof(hdr);

    while (!last) {
    + int remaining = skb->len - offset;
    unsigned int subframe_len;
    int len, mesh_len = 0;
    u8 padding;

    + if (copy_len > remaining)
    + goto purge;
    +
    skb_copy_bits(skb, offset, &hdr, copy_len);
    if (iftype == NL80211_IFTYPE_MESH_POINT)
    mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
    @@ -852,7 +859,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
    padding = (4 - subframe_len) & 0x3;

    /* the last MSDU has no padding */
    - remaining = skb->len - offset;
    if (subframe_len > remaining)
    goto purge;
    /* mitigate A-MSDU aggregation injection attacks */
    --
    2.43.0

    \
     
     \ /
      Last update: 2024-05-27 16:15    [W:4.445 / U:0.064 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site