From patchwork Tue Sep 24 07:59:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: You-Sheng Yang X-Patchwork-Id: 1166423 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46ctsl3Rqyz9sP7; Tue, 24 Sep 2019 18:00:43 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1iCfkU-0007af-26; Tue, 24 Sep 2019 08:00:38 +0000 Received: from mail-pf1-f193.google.com ([209.85.210.193]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1iCfk4-0007Ig-7s for kernel-team@lists.ubuntu.com; Tue, 24 Sep 2019 08:00:12 +0000 Received: by mail-pf1-f193.google.com with SMTP id y22so832528pfr.3 for ; Tue, 24 Sep 2019 01:00:12 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=e78Z3bUSotHW+yFmJoR5EDSzBsaaMAI95XpYob6IW/M=; b=Ox3y37lULPeDUKQBEUtalzOYy6sDIxWM+sZYkQo4uRb2nQdPvxhh6cmvo05A7ERaul ThaGBgSPBRWutpRfRlY4g/MLOZjKPfxtRYErBVRm5/snyneVStfuIT9GIjrxWUKYoFZE R3FLGFDbw+jnq+P6IKXCTtx1/s/KB0auyHat0IBKDFZqW8gDdWMrYpx+3DkZpsbe0MCb YKOVdbzbfycH6FqdlT+rWbt/VmGUBgcbhK0xBh+E57UsZQRNiCnBAnqmJGQ4dVykV8mc uBZfzPxdAd030Icv4LFk84m1N9Qcn3de5l1vowrRSGwoLmg4OYJ2T4kpUA/g0MyYfajX lVjA== X-Gm-Message-State: APjAAAWd2eR5iYZy711zuknkhKK1G9POJWF42no2hdANXxfL2yjWg8m8 rphiT1mCQuFIaYHRYQUcXCmGItMH X-Google-Smtp-Source: APXvYqyOV//RuMrczt7vqC2o/vh/RyKP2NfJcMQ49JMwq/4Lwnc7H2qBMx/Z9xdrXjIjkSqOtOLV0w== X-Received: by 2002:a63:c148:: with SMTP id p8mr1881713pgi.282.1569312010134; Tue, 24 Sep 2019 01:00:10 -0700 (PDT) Received: from localhost.localdomain (61-220-137-37.HINET-IP.hinet.net. [61.220.137.37]) by smtp.gmail.com with ESMTPSA id g202sm1359780pfb.155.2019.09.24.01.00.08 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 24 Sep 2019 01:00:09 -0700 (PDT) From: You-Sheng Yang To: kernel-team@lists.ubuntu.com Subject: [PATCH 01/21][SRU][OEM-OSP1-B] cfg80211: add and use strongly typed element iteration macros Date: Tue, 24 Sep 2019 15:59:27 +0800 Message-Id: <20190924075947.33954-2-vicamo.yang@canonical.com> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190924075947.33954-1-vicamo.yang@canonical.com> References: <20190924075947.33954-1-vicamo.yang@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Johannes Berg BugLink: https://bugs.launchpad.net/bugs/1845138 Rather than always iterating elements from frames with pure u8 pointers, add a type "struct element" that encapsulates the id/datalen/data format of them. Then, add the element iteration macros * for_each_element * for_each_element_id * for_each_element_extid which take, as their first 'argument', such a structure and iterate through a given u8 array interpreting it as elements. While at it and since we'll need it, also add * for_each_subelement * for_each_subelement_id * for_each_subelement_extid which instead of taking data/length just take an outer element and use its data/datalen. Also add for_each_element_completed() to determine if any of the loops above completed, i.e. it was able to parse all of the elements successfully and no data remained. Use for_each_element_id() in cfg80211_find_ie_match() as the first user of this. Signed-off-by: Johannes Berg (cherry picked from commit 0f3b07f027f87a38ebe5c436490095df762819be) Signed-off-by: You-Sheng Yang --- include/linux/ieee80211.h | 53 +++++++++++++++++++++++++++++++++++++++ net/wireless/scan.c | 14 +++++------ 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index 9f761e6bf5de9..f89f7d74325f1 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -3253,4 +3253,57 @@ static inline bool ieee80211_action_contains_tpc(struct sk_buff *skb) return true; } +struct element { + u8 id; + u8 datalen; + u8 data[]; +}; + +/* element iteration helpers */ +#define for_each_element(element, _data, _datalen) \ + for (element = (void *)(_data); \ + (u8 *)(_data) + (_datalen) - (u8 *)element >= \ + sizeof(*element) && \ + (u8 *)(_data) + (_datalen) - (u8 *)element >= \ + sizeof(*element) + element->datalen; \ + element = (void *)(element->data + element->datalen)) + +#define for_each_element_id(element, _id, data, datalen) \ + for_each_element(element, data, datalen) \ + if (element->id == (_id)) + +#define for_each_element_extid(element, extid, data, datalen) \ + for_each_element(element, data, datalen) \ + if (element->id == WLAN_EID_EXTENSION && \ + element->datalen > 0 && \ + element->data[0] == (extid)) + +#define for_each_subelement(sub, element) \ + for_each_element(sub, (element)->data, (element)->datalen) + +#define for_each_subelement_id(sub, id, element) \ + for_each_element_id(sub, id, (element)->data, (element)->datalen) + +#define for_each_subelement_extid(sub, extid, element) \ + for_each_element_extid(sub, extid, (element)->data, (element)->datalen) + +/** + * for_each_element_completed - determine if element parsing consumed all data + * @element: element pointer after for_each_element() or friends + * @data: same data pointer as passed to for_each_element() or friends + * @datalen: same data length as passed to for_each_element() or friends + * + * This function returns %true if all the data was parsed or considered + * while walking the elements. Only use this if your for_each_element() + * loop cannot be broken out of, otherwise it always returns %false. + * + * If some data was malformed, this returns %false since the last parsed + * element will not fill the whole remaining data. + */ +static inline bool for_each_element_completed(const struct element *element, + const void *data, size_t datalen) +{ + return (u8 *)element == (u8 *)data + datalen; +} + #endif /* LINUX_IEEE80211_H */ diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 5123667f4569a..c7f64bb9c581a 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -484,6 +484,8 @@ const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, const u8 *match, int match_len, int match_offset) { + const struct element *elem; + /* match_offset can't be smaller than 2, unless match_len is * zero, in which case match_offset must be zero as well. */ @@ -491,14 +493,10 @@ const u8 *cfg80211_find_ie_match(u8 eid, const u8 *ies, int len, (!match_len && match_offset))) return NULL; - while (len >= 2 && len >= ies[1] + 2) { - if ((ies[0] == eid) && - (ies[1] + 2 >= match_offset + match_len) && - !memcmp(ies + match_offset, match, match_len)) - return ies; - - len -= ies[1] + 2; - ies += ies[1] + 2; + for_each_element_id(elem, eid, ies, len) { + if (elem->datalen >= match_offset - 2 + match_len && + !memcmp(elem->data + match_offset - 2, match, match_len)) + return (void *)elem; } return NULL;