From patchwork Tue Jul 3 18:26:26 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Denis Kenzior X-Patchwork-Id: 10504975 X-Patchwork-Delegate: johannes@sipsolutions.net Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 1E3BB6035E for ; Tue, 3 Jul 2018 18:26:48 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 4B10E28A42 for ; Tue, 3 Jul 2018 18:26:47 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 3C25228A53; Tue, 3 Jul 2018 18:26:47 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 92FB328A42 for ; Tue, 3 Jul 2018 18:26:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S934464AbeGCS0p (ORCPT ); Tue, 3 Jul 2018 14:26:45 -0400 Received: from mail-oi0-f65.google.com ([209.85.218.65]:33324 "EHLO mail-oi0-f65.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S934004AbeGCS0n (ORCPT ); Tue, 3 Jul 2018 14:26:43 -0400 Received: by mail-oi0-f65.google.com with SMTP id c6-v6so5786732oiy.0 for ; Tue, 03 Jul 2018 11:26:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id; bh=+1S/EbSp1m7VjV3WAlbG6eQzb4b/ZGsANBOpGwkyvv0=; b=r/BAy/OIFYX7LKEFTuQAm573doF/lpvAyZjAnjaODPlsg39j/e39SgrudRu+Nl1mvJ Jq5qoxVKqtmSZDf5Q4K9dMTV0PF5pDmD2a6slC6M8b0kUcWGLJ+DxFCSUyAtcntQZ4LQ fFMvvo3vRv8HGWPQqbjXz093BP2g62pAMZrBj4Yg+KWO+T9c364VMUmFTSLmO4u0J2lr Tes4n4v2wdrkoL/1bE6lD12WyX1L0KL1+QLUnmHHcJCgP+UHe4qg2HCA0DeLNg2EGzOP GdfqkUOi4/2RENqCkr4wLM5fdRHX4UociIFByDO43Wl6TeEzrc0KmQdK8M8V9vFrE6s9 PdzQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=+1S/EbSp1m7VjV3WAlbG6eQzb4b/ZGsANBOpGwkyvv0=; b=QBXqCHs6si8oJ7SsGaOkMY6LolMKljJucPHexNsVg87d1uV/MIAWsvTz8H1OjvtPdW IP8bXKYepSIPLXVMy9MIwOmI0Qx1f+MkE7lZ2jn67ubw/aC3mgUxkwwcYF89tPn/4eio H8H7RWyhSoJIQqUKphIVaPguVS8d+2muQOY5y/CEPeX5vjz+db0mOF7HjdhfJoNdeTub Cz50cXq/P4+f5HOVDl51tM4JAjH9liNb/qPNwAtoFnJnvrzSqDerJ/irHD+Ie6w0qrYl VYX8XXJc0MR6qVdlXcaC2cq3/IaEqLK3mzxAhGGrtAZp0L6jGJzoyyOW0rZlEbB7bCYO umMQ== X-Gm-Message-State: APt69E17+3TsZZYrL7Z3p7kMKF6eJa2EVqlkBWGvdKrqxYDzxAq+oRK5 QvfnhCOQPSLwb92wDZQyBg0= X-Google-Smtp-Source: AAOMgpehFktljWdA6GPoAIvDkyLPIhU1EugFEe/t2wp3joH/Cnw2mjN89phsKPEcWWYS0/tlItzZUw== X-Received: by 2002:aca:728f:: with SMTP id p137-v6mr23112987oic.335.1530642403233; Tue, 03 Jul 2018 11:26:43 -0700 (PDT) Received: from localhost.localdomain (cpe-70-114-247-242.austin.res.rr.com. [70.114.247.242]) by smtp.gmail.com with ESMTPSA id c2-v6sm693796oia.53.2018.07.03.11.26.42 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 03 Jul 2018 11:26:42 -0700 (PDT) From: Denis Kenzior To: johannes@sipsolutions.net, linux-wireless@vger.kernel.org Cc: Denis Kenzior Subject: [PATCH] nl80211/mac80211: Fix cfg80211_rx_control_port Date: Tue, 3 Jul 2018 13:26:26 -0500 Message-Id: <20180703182626.26782-1-denkenz@gmail.com> X-Mailer: git-send-email 2.13.5 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP The current implementation of cfg80211_rx_control_port assumed that the caller could provide a contiguous region of memory for the control port frame to be sent up to userspace. Unfortunately, many drivers produce non-linear skbs, especially for data frames. This resulted in userspace getting notified of control port frames with correct metadata (from address, port, etc) yet garbage / nonsense contents, resulting in bad handshakes, disconnections, etc. mac80211 linearizes skbs containing management frames. But it didn't seem worthwhile to do this for control port frames. Thus the signature of cfg80211_rx_control_port was changed to take the skb directly. nl80211 then takes care of obtaining control port frame data directly from the (linear | non-linear) skb. The caller is still responsible for freeing the skb, cfg80211_rx_control_port does not take ownership of it. Signed-off-by: Denis Kenzior --- include/net/cfg80211.h | 11 +++++------ net/mac80211/rx.c | 5 +---- net/wireless/nl80211.c | 24 +++++++++++++++--------- net/wireless/trace.h | 26 +++++++++++++++++--------- 4 files changed, 38 insertions(+), 28 deletions(-) diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 9ba1f289c439..94842c2a2f73 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -5937,10 +5937,10 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, /** * cfg80211_rx_control_port - notification about a received control port frame * @dev: The device the frame matched to - * @buf: control port frame - * @len: length of the frame data - * @addr: The peer from which the frame was received - * @proto: frame protocol, typically PAE or Pre-authentication + * @skb: The skbuf with the control port frame. It is assumed that the skbuf + * is 802.3 formatted (with 802.3 header). The skb can be non-linear. This + * function does not take ownership of the skb, so the caller is responsible + * for any cleanup. * @unencrypted: Whether the frame was received unencrypted * * This function is used to inform userspace about a received control port @@ -5953,8 +5953,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, * Return: %true if the frame was passed to userspace */ bool cfg80211_rx_control_port(struct net_device *dev, - const u8 *buf, size_t len, - const u8 *addr, u16 proto, bool unencrypted); + struct sk_buff *skb, bool unencrypted); /** * cfg80211_cqm_rssi_notify - connection quality monitoring rssi event diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index a16ba568e2a3..64742f2765c4 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -2370,11 +2370,8 @@ static void ieee80211_deliver_skb_to_local_stack(struct sk_buff *skb, sdata->control_port_over_nl80211)) { struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); bool noencrypt = status->flag & RX_FLAG_DECRYPTED; - struct ethhdr *ehdr = eth_hdr(skb); - cfg80211_rx_control_port(dev, skb->data, skb->len, - ehdr->h_source, - be16_to_cpu(skb->protocol), noencrypt); + cfg80211_rx_control_port(dev, skb, noencrypt); dev_kfree_skb(skb); } else { /* deliver to local stack */ diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 8db59129c095..b75a0144c0a5 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -15036,20 +15036,24 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, EXPORT_SYMBOL(cfg80211_mgmt_tx_status); static int __nl80211_rx_control_port(struct net_device *dev, - const u8 *buf, size_t len, - const u8 *addr, u16 proto, + struct sk_buff *skb, bool unencrypted, gfp_t gfp) { struct wireless_dev *wdev = dev->ieee80211_ptr; struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + struct ethhdr *ehdr = eth_hdr(skb); + const u8 *addr = ehdr->h_source; + u16 proto = be16_to_cpu(skb->protocol); struct sk_buff *msg; void *hdr; + struct nlattr *frame; + u32 nlportid = READ_ONCE(wdev->conn_owner_nlportid); if (!nlportid) return -ENOENT; - msg = nlmsg_new(100 + len, gfp); + msg = nlmsg_new(100 + skb->len, gfp); if (!msg) return -ENOMEM; @@ -15063,13 +15067,17 @@ static int __nl80211_rx_control_port(struct net_device *dev, nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || nla_put_u64_64bit(msg, NL80211_ATTR_WDEV, wdev_id(wdev), NL80211_ATTR_PAD) || - nla_put(msg, NL80211_ATTR_FRAME, len, buf) || nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, addr) || nla_put_u16(msg, NL80211_ATTR_CONTROL_PORT_ETHERTYPE, proto) || (unencrypted && nla_put_flag(msg, NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT))) goto nla_put_failure; + frame = nla_reserve(msg, NL80211_ATTR_FRAME, skb->len); + if (!frame) + goto nla_put_failure; + + skb_copy_bits(skb, 0, nla_data(frame), skb->len); genlmsg_end(msg, hdr); return genlmsg_unicast(wiphy_net(&rdev->wiphy), msg, nlportid); @@ -15080,14 +15088,12 @@ static int __nl80211_rx_control_port(struct net_device *dev, } bool cfg80211_rx_control_port(struct net_device *dev, - const u8 *buf, size_t len, - const u8 *addr, u16 proto, bool unencrypted) + struct sk_buff *skb, bool unencrypted) { int ret; - trace_cfg80211_rx_control_port(dev, buf, len, addr, proto, unencrypted); - ret = __nl80211_rx_control_port(dev, buf, len, addr, proto, - unencrypted, GFP_ATOMIC); + trace_cfg80211_rx_control_port(dev, skb, unencrypted); + ret = __nl80211_rx_control_port(dev, skb, unencrypted, GFP_ATOMIC); trace_cfg80211_return_bool(ret == 0); return ret == 0; } diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 2b417a2fe63f..e18a8b0176e2 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2627,24 +2627,32 @@ TRACE_EVENT(cfg80211_mgmt_tx_status, ); TRACE_EVENT(cfg80211_rx_control_port, - TP_PROTO(struct net_device *netdev, const u8 *buf, size_t len, - const u8 *addr, u16 proto, bool unencrypted), - TP_ARGS(netdev, buf, len, addr, proto, unencrypted), + TP_PROTO(struct net_device *netdev, struct sk_buff *skb, + bool unencrypted), + TP_ARGS(netdev, skb, unencrypted), TP_STRUCT__entry( NETDEV_ENTRY - MAC_ENTRY(addr) + __field(const void *, skbaddr) + __field(int, len) + MAC_ENTRY(from) __field(u16, proto) __field(bool, unencrypted) ), TP_fast_assign( NETDEV_ASSIGN; - MAC_ASSIGN(addr, addr); - __entry->proto = proto; + __entry->skbaddr = skb; + __entry->len = skb->len; + do { + struct ethhdr *ehdr = eth_hdr(skb); + memcpy(__entry->from, ehdr->h_source, ETH_ALEN); + } while (0); + __entry->proto = be16_to_cpu(skb->protocol); __entry->unencrypted = unencrypted; ), - TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT " proto: 0x%x, unencrypted: %s", - NETDEV_PR_ARG, MAC_PR_ARG(addr), - __entry->proto, BOOL_TO_STR(__entry->unencrypted)) + TP_printk(NETDEV_PR_FMT ", skbaddr=%p, len=%d, " MAC_PR_FMT ", proto: 0x%x, unencrypted: %s", + NETDEV_PR_ARG, __entry->skbaddr, __entry->len, + MAC_PR_ARG(from), __entry->proto, + BOOL_TO_STR(__entry->unencrypted)) ); TRACE_EVENT(cfg80211_cqm_rssi_notify,