Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] nl80211: Define policy for packet pattern attributes
From: Jouni Malinen @ 2017-10-03 20:21 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Peng Xu, Jouni Malinen

From: Peng Xu <pxu@qti.qualcomm.com>

Define a policy for packet pattern attributes in order to fix the
security vulnerability of buffer over read issue on
NL80211_PKTPAT_OFFSET (nla_get_u32() was used without checking the
attribute length).

Signed-off-by: Peng Xu <pxu@qti.qualcomm.com>
Signed-off-by: Jouni Malinen <jouni@qca.qualcomm.com>
---
 net/wireless/nl80211.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 90e212d..e99671f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -549,6 +549,14 @@ nl80211_nan_srf_policy[NL80211_NAN_SRF_ATTR_MAX + 1] = {
 	[NL80211_NAN_SRF_MAC_ADDRS] = { .type = NLA_NESTED },
 };
 
+/* policy for packet pattern attributes */
+static const struct nla_policy
+nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
+	[NL80211_PKTPAT_MASK] = { .type = NLA_BINARY, },
+	[NL80211_PKTPAT_PATTERN] = { .type = NLA_BINARY, },
+	[NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
+};
+
 static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
 				     struct netlink_callback *cb,
 				     struct cfg80211_registered_device **rdev,
@@ -10563,7 +10571,8 @@ static int nl80211_set_wowlan(struct sk_buff *skb, struct genl_info *info)
 			u8 *mask_pat;
 
 			nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
-					 NULL, info->extack);
+					 nl80211_packet_pattern_policy,
+					 info->extack);
 			err = -EINVAL;
 			if (!pat_tb[NL80211_PKTPAT_MASK] ||
 			    !pat_tb[NL80211_PKTPAT_PATTERN])
@@ -10812,7 +10821,8 @@ static int nl80211_parse_coalesce_rule(struct cfg80211_registered_device *rdev,
 			    rem) {
 		u8 *mask_pat;
 
-		nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat, NULL, NULL);
+		nla_parse_nested(pat_tb, MAX_NL80211_PKTPAT, pat,
+				 nl80211_packet_pattern_policy, NULL);
 		if (!pat_tb[NL80211_PKTPAT_MASK] ||
 		    !pat_tb[NL80211_PKTPAT_PATTERN])
 			return -EINVAL;
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH] mwifiex: Use put_unaligned_le32
From: kbuild test robot @ 2017-10-07  3:31 UTC (permalink / raw)
  To: Himanshu Jha
  Cc: kbuild-all, amitkarwar, nishants, gbhat, huxm, kvalo,
	linux-wireless, netdev, linux-kernel, Himanshu Jha
In-Reply-To: <1507141686-5178-1-git-send-email-himanshujha199640@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 12590 bytes --]

Hi Himanshu,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.14-rc3 next-20170929]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Himanshu-Jha/mwifiex-Use-put_unaligned_le32/20171007-095017
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: xtensa-allyesconfig (attached as .config)
compiler: xtensa-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=xtensa 

All errors (new ones prefixed by >>):

   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:6:19: error: redefinition of 'get_unaligned_be16'
    static inline u16 get_unaligned_be16(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:22:28: note: previous definition of 'get_unaligned_be16' was here
    static __always_inline u16 get_unaligned_be16(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:11:19: error: redefinition of 'get_unaligned_be32'
    static inline u32 get_unaligned_be32(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:27:28: note: previous definition of 'get_unaligned_be32' was here
    static __always_inline u32 get_unaligned_be32(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:16:19: error: redefinition of 'get_unaligned_be64'
    static inline u64 get_unaligned_be64(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:32:28: note: previous definition of 'get_unaligned_be64' was here
    static __always_inline u64 get_unaligned_be64(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:21:20: error: redefinition of 'put_unaligned_be16'
    static inline void put_unaligned_be16(u16 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:52:29: note: previous definition of 'put_unaligned_be16' was here
    static __always_inline void put_unaligned_be16(u16 val, void *p)
                                ^
   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:26:20: error: redefinition of 'put_unaligned_be32'
    static inline void put_unaligned_be32(u32 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:57:29: note: previous definition of 'put_unaligned_be32' was here
    static __always_inline void put_unaligned_be32(u32 val, void *p)
                                ^
   In file included from arch/xtensa/include/asm/unaligned.h:22:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_struct.h:31:20: error: redefinition of 'put_unaligned_be64'
    static inline void put_unaligned_be64(u64 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:62:29: note: previous definition of 'put_unaligned_be64' was here
    static __always_inline void put_unaligned_be64(u64 val, void *p)
                                ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:40:19: error: redefinition of 'get_unaligned_le16'
    static inline u16 get_unaligned_le16(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:7:28: note: previous definition of 'get_unaligned_le16' was here
    static __always_inline u16 get_unaligned_le16(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:45:19: error: redefinition of 'get_unaligned_le32'
    static inline u32 get_unaligned_le32(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:12:28: note: previous definition of 'get_unaligned_le32' was here
    static __always_inline u32 get_unaligned_le32(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:50:19: error: redefinition of 'get_unaligned_le64'
    static inline u64 get_unaligned_le64(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:17:28: note: previous definition of 'get_unaligned_le64' was here
    static __always_inline u64 get_unaligned_le64(const void *p)
                               ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:55:20: error: redefinition of 'put_unaligned_le16'
    static inline void put_unaligned_le16(u16 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:37:29: note: previous definition of 'put_unaligned_le16' was here
    static __always_inline void put_unaligned_le16(u16 val, void *p)
                                ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:60:20: error: redefinition of 'put_unaligned_le32'
    static inline void put_unaligned_le32(u32 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:42:29: note: previous definition of 'put_unaligned_le32' was here
    static __always_inline void put_unaligned_le32(u32 val, void *p)
                                ^
   In file included from arch/xtensa/include/asm/unaligned.h:23:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/le_byteshift.h:65:20: error: redefinition of 'put_unaligned_le64'
    static inline void put_unaligned_le64(u64 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:47:29: note: previous definition of 'put_unaligned_le64' was here
    static __always_inline void put_unaligned_le64(u64 val, void *p)
                                ^

vim +/put_unaligned_le32 +60 include/linux/unaligned/le_byteshift.h

064106a9 Harvey Harrison 2008-04-29  39  
064106a9 Harvey Harrison 2008-04-29 @40  static inline u16 get_unaligned_le16(const void *p)
064106a9 Harvey Harrison 2008-04-29  41  {
064106a9 Harvey Harrison 2008-04-29  42  	return __get_unaligned_le16((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29  43  }
064106a9 Harvey Harrison 2008-04-29  44  
064106a9 Harvey Harrison 2008-04-29 @45  static inline u32 get_unaligned_le32(const void *p)
064106a9 Harvey Harrison 2008-04-29  46  {
064106a9 Harvey Harrison 2008-04-29  47  	return __get_unaligned_le32((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29  48  }
064106a9 Harvey Harrison 2008-04-29  49  
064106a9 Harvey Harrison 2008-04-29 @50  static inline u64 get_unaligned_le64(const void *p)
064106a9 Harvey Harrison 2008-04-29  51  {
064106a9 Harvey Harrison 2008-04-29  52  	return __get_unaligned_le64((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29  53  }
064106a9 Harvey Harrison 2008-04-29  54  
064106a9 Harvey Harrison 2008-04-29 @55  static inline void put_unaligned_le16(u16 val, void *p)
064106a9 Harvey Harrison 2008-04-29  56  {
064106a9 Harvey Harrison 2008-04-29  57  	__put_unaligned_le16(val, p);
064106a9 Harvey Harrison 2008-04-29  58  }
064106a9 Harvey Harrison 2008-04-29  59  
064106a9 Harvey Harrison 2008-04-29 @60  static inline void put_unaligned_le32(u32 val, void *p)
064106a9 Harvey Harrison 2008-04-29  61  {
064106a9 Harvey Harrison 2008-04-29  62  	__put_unaligned_le32(val, p);
064106a9 Harvey Harrison 2008-04-29  63  }
064106a9 Harvey Harrison 2008-04-29  64  
064106a9 Harvey Harrison 2008-04-29 @65  static inline void put_unaligned_le64(u64 val, void *p)
064106a9 Harvey Harrison 2008-04-29  66  {
064106a9 Harvey Harrison 2008-04-29  67  	__put_unaligned_le64(val, p);
064106a9 Harvey Harrison 2008-04-29  68  }
064106a9 Harvey Harrison 2008-04-29  69  

:::::: The code at line 60 was first introduced by commit
:::::: 064106a91be5e76cb42c1ddf5d3871e3a1bd2a23 kernel: add common infrastructure for unaligned access

:::::: TO: Harvey Harrison <harvey.harrison@gmail.com>
:::::: CC: Linus Torvalds <torvalds@linux-foundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 51721 bytes --]

^ permalink raw reply

* Re: [PATCH] mwifiex: Use put_unaligned_le32
From: kbuild test robot @ 2017-10-07  5:17 UTC (permalink / raw)
  To: Himanshu Jha
  Cc: kbuild-all, amitkarwar, nishants, gbhat, huxm, kvalo,
	linux-wireless, netdev, linux-kernel, Himanshu Jha
In-Reply-To: <1507141686-5178-1-git-send-email-himanshujha199640@gmail.com>

[-- Attachment #1: Type: text/plain, Size: 12648 bytes --]

Hi Himanshu,

[auto build test ERROR on wireless-drivers-next/master]
[also build test ERROR on v4.14-rc3 next-20170929]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Himanshu-Jha/mwifiex-Use-put_unaligned_le32/20171007-095017
base:   https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/wireless-drivers-next.git master
config: openrisc-allyesconfig (attached as .config)
compiler: or1k-linux-gcc (GCC) 5.4.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=openrisc 

All errors (new ones prefixed by >>):

   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:6:19: error: redefinition of 'get_unaligned_be16'
    static inline u16 get_unaligned_be16(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:22:28: note: previous definition of 'get_unaligned_be16' was here
    static __always_inline u16 get_unaligned_be16(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:11:19: error: redefinition of 'get_unaligned_be32'
    static inline u32 get_unaligned_be32(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:27:28: note: previous definition of 'get_unaligned_be32' was here
    static __always_inline u32 get_unaligned_be32(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:16:19: error: redefinition of 'get_unaligned_be64'
    static inline u64 get_unaligned_be64(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:32:28: note: previous definition of 'get_unaligned_be64' was here
    static __always_inline u64 get_unaligned_be64(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:21:20: error: redefinition of 'put_unaligned_be16'
    static inline void put_unaligned_be16(u16 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:52:29: note: previous definition of 'put_unaligned_be16' was here
    static __always_inline void put_unaligned_be16(u16 val, void *p)
                                ^
   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:26:20: error: redefinition of 'put_unaligned_be32'
    static inline void put_unaligned_be32(u32 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:57:29: note: previous definition of 'put_unaligned_be32' was here
    static __always_inline void put_unaligned_be32(u32 val, void *p)
                                ^
   In file included from arch/openrisc/include/asm/unaligned.h:42:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
>> include/linux/unaligned/be_memmove.h:31:20: error: redefinition of 'put_unaligned_be64'
    static inline void put_unaligned_be64(u64 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:62:29: note: previous definition of 'put_unaligned_be64' was here
    static __always_inline void put_unaligned_be64(u64 val, void *p)
                                ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:40:19: error: redefinition of 'get_unaligned_le16'
    static inline u16 get_unaligned_le16(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:7:28: note: previous definition of 'get_unaligned_le16' was here
    static __always_inline u16 get_unaligned_le16(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:45:19: error: redefinition of 'get_unaligned_le32'
    static inline u32 get_unaligned_le32(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:12:28: note: previous definition of 'get_unaligned_le32' was here
    static __always_inline u32 get_unaligned_le32(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:50:19: error: redefinition of 'get_unaligned_le64'
    static inline u64 get_unaligned_le64(const void *p)
                      ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:17:28: note: previous definition of 'get_unaligned_le64' was here
    static __always_inline u64 get_unaligned_le64(const void *p)
                               ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:55:20: error: redefinition of 'put_unaligned_le16'
    static inline void put_unaligned_le16(u16 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:37:29: note: previous definition of 'put_unaligned_le16' was here
    static __always_inline void put_unaligned_le16(u16 val, void *p)
                                ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:60:20: error: redefinition of 'put_unaligned_le32'
    static inline void put_unaligned_le32(u32 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:42:29: note: previous definition of 'put_unaligned_le32' was here
    static __always_inline void put_unaligned_le32(u32 val, void *p)
                                ^
   In file included from arch/openrisc/include/asm/unaligned.h:43:0,
                    from include/linux/etherdevice.h:28,
                    from include/linux/ieee80211.h:22,
                    from drivers/net//wireless/marvell/mwifiex/decl.h:28,
                    from drivers/net//wireless/marvell/mwifiex/cmdevt.c:21:
   include/linux/unaligned/le_byteshift.h:65:20: error: redefinition of 'put_unaligned_le64'
    static inline void put_unaligned_le64(u64 val, void *p)
                       ^
   In file included from drivers/net//wireless/marvell/mwifiex/cmdevt.c:20:0:
   include/linux/unaligned/access_ok.h:47:29: note: previous definition of 'put_unaligned_le64' was here
    static __always_inline void put_unaligned_le64(u64 val, void *p)
                                ^

vim +/get_unaligned_be16 +6 include/linux/unaligned/be_memmove.h

064106a9 Harvey Harrison 2008-04-29   5  
064106a9 Harvey Harrison 2008-04-29  @6  static inline u16 get_unaligned_be16(const void *p)
064106a9 Harvey Harrison 2008-04-29   7  {
064106a9 Harvey Harrison 2008-04-29   8  	return __get_unaligned_memmove16((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29   9  }
064106a9 Harvey Harrison 2008-04-29  10  
064106a9 Harvey Harrison 2008-04-29 @11  static inline u32 get_unaligned_be32(const void *p)
064106a9 Harvey Harrison 2008-04-29  12  {
064106a9 Harvey Harrison 2008-04-29  13  	return __get_unaligned_memmove32((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29  14  }
064106a9 Harvey Harrison 2008-04-29  15  
064106a9 Harvey Harrison 2008-04-29 @16  static inline u64 get_unaligned_be64(const void *p)
064106a9 Harvey Harrison 2008-04-29  17  {
064106a9 Harvey Harrison 2008-04-29  18  	return __get_unaligned_memmove64((const u8 *)p);
064106a9 Harvey Harrison 2008-04-29  19  }
064106a9 Harvey Harrison 2008-04-29  20  
064106a9 Harvey Harrison 2008-04-29 @21  static inline void put_unaligned_be16(u16 val, void *p)
064106a9 Harvey Harrison 2008-04-29  22  {
064106a9 Harvey Harrison 2008-04-29  23  	__put_unaligned_memmove16(val, p);
064106a9 Harvey Harrison 2008-04-29  24  }
064106a9 Harvey Harrison 2008-04-29  25  
064106a9 Harvey Harrison 2008-04-29 @26  static inline void put_unaligned_be32(u32 val, void *p)
064106a9 Harvey Harrison 2008-04-29  27  {
064106a9 Harvey Harrison 2008-04-29  28  	__put_unaligned_memmove32(val, p);
064106a9 Harvey Harrison 2008-04-29  29  }
064106a9 Harvey Harrison 2008-04-29  30  
064106a9 Harvey Harrison 2008-04-29 @31  static inline void put_unaligned_be64(u64 val, void *p)
064106a9 Harvey Harrison 2008-04-29  32  {
064106a9 Harvey Harrison 2008-04-29  33  	__put_unaligned_memmove64(val, p);
064106a9 Harvey Harrison 2008-04-29  34  }
064106a9 Harvey Harrison 2008-04-29  35  

:::::: The code at line 6 was first introduced by commit
:::::: 064106a91be5e76cb42c1ddf5d3871e3a1bd2a23 kernel: add common infrastructure for unaligned access

:::::: TO: Harvey Harrison <harvey.harrison@gmail.com>
:::::: CC: Linus Torvalds <torvalds@linux-foundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 42911 bytes --]

^ permalink raw reply

* Linux wireless device driver tutorials.
From: Madhu K @ 2017-10-07  6:03 UTC (permalink / raw)
  To: linux-wireless

Hi All,

I am kernel newbie, I am trying to understand the linux wireless
architecture and wanted write some simple drivers. Please somebody
help me to get the documents related this?

Thanks & regards,
Madhu

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Toke Høiland-Jørgensen @ 2017-10-07 11:22 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless
In-Reply-To: <1507310319.19300.28.camel@sipsolutions.net>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Fri, 2017-10-06 at 16:29 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>> Johannes Berg <johannes@sipsolutions.net> writes:
>>=20
>> Well, calculating the duration from the rate and size is what ath9k
>> is currently doing, and that has all the information available to do
>> so (I did verify that the airtime was almost identical on the TX and
>> RX side for the same traffic).
>
> It's still iffy - with aggregation you might have a better idea of the
> total airtime, but not really see - in the higher layers - all the
> padding that comes between A-MPDUs etc. I think many drivers could do
> better by exposing the total airtime from the device/firmware, whereas
> exposing _all_ the little details that you need to calculate it post-
> facto will be really difficult, and make the calculation really hard.

Guess you are right that it will be difficult to get a completely
accurate number. But as David Lang notes, as long as we are off by the
same amount for all stations, that is fine - we're just interested in
relative numbers.

>> But yeah, I guess that is not necessarily the case for all drivers?
>> Maybe having a field that the driver can fill in is better (that also
>> has the nice property that a driver that doesn't supply any airtime
>> information won't get the scheduling; which is probably desirable).
>
> I think that'd be better, yes. Perhaps for some simple cases a helper
> function can be provided, but I'd want to actually know about those
> drivers before adding that.

Right, I'll add a field to rx_status instead that drivers can use.

>> You're right that it does nothing for one-way UDP, of course. But not
>> a lot of traffic is actually one-way (most is either TCP or something
>> like Quic that also has a feedback loop). So in most of our tests we
>> saw a pretty nice effect from TCP back-pressure.
>
> Yeah that makes some sense. I'm a bit concerned about pathological
> corner cases, you don't really know about the protocol used on top.
> Can a client starve itself by sending things? And perhaps, if it has a
> dumb higher layer protocol, it'll retransmit rather than back off, if
> it doesn't get the higher layer ACK?

I suppose a station that keeps sending flooding the airwaves (say, an
upstream CBR UDP flow with no feedback loop, at a rate higher than it
has bandwidth for) can lock itself out to some extent. I'll see if I can
get this to happen in my testbed with the ath9k code and report back on
what happens.

But for anything TCP-like with a feedback loop, the starvation will be
temporary as the lack of ACKs will cause the sender to eventually slow
down enough to get below its fair share.

>> Having a separate deficit for each AC level is a crude workaround for
>> this, which is what we went with for the initial version in ath9k;
>> and this patch is just a straight-forward port of that. But I guess
>> this is a good opportunity to figure out how to solve this properly;
>> I'll think about how to do that (ideas welcome!)...
>
> So ... no, I don't understand. You have a TXQ per _TID_, so splitting
> up this per _AC_ still doesn't make sense since you have two TXQs for
> each AC?

Yeah, but ath9k schedules all TIDs on the same AC together. So if
station A has two TIDs active and station B one, the scheduling order
will be A1, A2, B1, basically. This is fine as long as they are all on
the same AC and scheduled together (in which case A1 and A2 will just
share the same deficit).

But if there is only one TXQ active, every time that queue is scheduled,
the scheduler will loop until its deficit becomes positive (which is
generally good; that is how we make sure the scheduler is
work-conserving). However, if the deficit is shared with another
scheduling group (which in ath9k is another AC), the station in the
group by itself will not be limited to its fair share, because every
time it is scheduled by itself, its deficit is "reset".

Ideally, I would prefer the scheduling to be "two-pass": First, decide
which physical station to send to, then decide which TID on that station
to service. But because everything is done at the TID/TXQ level, that is
not quite trivial to achieve I think...

-Toke

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: add device tree binding for Allwinner XR819 SDIO Wi-Fi
From: Icenowy Zheng @ 2017-10-07 12:31 UTC (permalink / raw)
  To: linux-arm-kernel, Kalle Valo
  Cc: devicetree, Arend van Spriel, netdev, linux-wireless,
	linux-kernel, linux-sunxi, Rob Herring, Maxime Ripard,
	Chen-Yu Tsai
In-Reply-To: <878tgq5beu.fsf@codeaurora.org>



于 2017年10月5日 GMT+08:00 下午2:58:01, Kalle Valo <kvalo@codeaurora.org> 写到:
>Icenowy Zheng <icenowy@aosc.io> writes:
>
>> 于 2017年10月4日 GMT+08:00 下午6:11:45, Maxime Ripard
>> <maxime.ripard@free-electrons.com> 写到:
>>>On Wed, Oct 04, 2017 at 10:02:48AM +0000, Arend van Spriel wrote:
>>>> On 10/4/2017 11:03 AM, Icenowy Zheng wrote:
>>>> > 
>>>> > 
>>>> > 于 2017年10月4日 GMT+08:00 下午5:02:17, Kalle Valo
><kvalo@codeaurora.org>
>>>写到:
>>>> > > Icenowy Zheng <icenowy@aosc.io> writes:
>>>> > > 
>>>> > > > Allwinner XR819 is a SDIO Wi-Fi chip, which has the
>>>functionality to
>>>> > > use
>>>> > > > an out-of-band interrupt pin instead of SDIO in-band
>interrupt.
>>>> > > > 
>>>> > > > Add the device tree binding of this chip, in order to make it
>>>> > > possible
>>>> > > > to add this interrupt pin to device trees.
>>>> > > > 
>>>> > > > Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>>> > > > Acked-by: Rob Herring <robh@kernel.org>
>>>> > > > ---
>>>> > > > Changes in v3:
>>>> > > > - Renames the node name.
>>>> > > > - Adds ACK from Rob.
>>>> > > > Changes in v2:
>>>> > > > - Removed status property in example.
>>>> > > > - Added required property reg.
>>>> > > > 
>>>> > > >   .../bindings/net/wireless/allwinner,xr819.txt      | 38
>>>> > > ++++++++++++++++++++++
>>>> > > >   1 file changed, 38 insertions(+)
>>>> > > >   create mode 100644
>>>> > >
>>>Documentation/devicetree/bindings/net/wireless/allwinner,xr819.txt
>>>> > > 
>>>> > > Like I asked already last time, AFAICS there is no upstream
>xr819
>>>> > > wireless driver in drivers/net/wireless directory. Do we still
>>>accept
>>>> > > bindings like this for out-of-tree drivers?
>>>> > 
>>>> > See esp8089.
>>>> > 
>>>> > There's also no in-tree driver for it.
>>>> 
>>>> The question is whether we should. The above might be a precedent,
>>>but it
>>>> may not necessarily be the way to go. The commit message for
>esp8089
>>>seems
>>>> to hint that there is intent to have an in-tree driver:
>>>> 
>>>> """
>>>>     Note that at this point there only is an out of tree driver for
>>>this
>>>>     hardware, there is no clear timeline / path for merging this.
>>>Still
>>>>     I believe it would be good to specify the binding for this in
>>>tree
>>>>     now, so that any future migration to an in tree driver will not
>>>cause
>>>>     compatiblity issues.
>>>> 
>>>>     Cc: Icenowy Zheng <icenowy@aosc.xyz>
>>>>     Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>>     Signed-off-by: Rob Herring <robh@kernel.org>
>>>> """
>>>> 
>>>> Regardless the bindings are in principle independent of the kernel
>>>and just
>>>> describing hardware. I think there have been discussions to move
>the
>>>> bindings to their own repository, but apparently it was decided
>>>otherwise.
>>>
>>>Yeah, I guess especially how it could be merged with the cw1200
>driver
>>>would be very relevant to that commit log.
>>
>> The cw1200 driver seems to still have some legacy platform
>> data. Maybe they should also be convert to DT.
>> (Or maybe compatible = "allwinner,xr819" is enough, as
>> xr819 is a specified variant of cw1200 family)
>
>Ah, so the upstream cw1200 driver supports xr819? Has anyone tested
>that? Or does cw1200 more changes than just adding the DT support?

I think the cw1200 driver currently lacks maintain, and
the product is already discontinued by ST-E.

>
>-- 
>Kalle Valo
>
>_______________________________________________
>linux-arm-kernel mailing list
>linux-arm-kernel@lists.infradead.org
>http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply

* Re: [PATCH v3 1/2] dt-bindings: add device tree binding for Allwinner XR819 SDIO Wi-Fi
From: icenowy @ 2017-10-07 13:01 UTC (permalink / raw)
  To: Kalle Valo
  Cc: devicetree, Arend van Spriel, netdev, linux-wireless,
	linux-kernel, linux-sunxi, Rob Herring, Maxime Ripard,
	Chen-Yu Tsai, linux-arm-kernel
In-Reply-To: <878tgq5beu.fsf@codeaurora.org>

在 2017-10-05 14:58,Kalle Valo 写道:
> Icenowy Zheng <icenowy@aosc.io> writes:
> 
>> 于 2017年10月4日 GMT+08:00 下午6:11:45, Maxime Ripard
>> <maxime.ripard@free-electrons.com> 写到:
>>> On Wed, Oct 04, 2017 at 10:02:48AM +0000, Arend van Spriel wrote:
>>>> On 10/4/2017 11:03 AM, Icenowy Zheng wrote:
>>>> >
>>>> >
>>>> > 于 2017年10月4日 GMT+08:00 下午5:02:17, Kalle Valo <kvalo@codeaurora.org>
>>> 写到:
>>>> > > Icenowy Zheng <icenowy@aosc.io> writes:
>>>> > >
>>>> > > > Allwinner XR819 is a SDIO Wi-Fi chip, which has the
>>> functionality to
>>>> > > use
>>>> > > > an out-of-band interrupt pin instead of SDIO in-band interrupt.
>>>> > > >
>>>> > > > Add the device tree binding of this chip, in order to make it
>>>> > > possible
>>>> > > > to add this interrupt pin to device trees.
>>>> > > >
>>>> > > > Signed-off-by: Icenowy Zheng <icenowy@aosc.io>
>>>> > > > Acked-by: Rob Herring <robh@kernel.org>
>>>> > > > ---
>>>> > > > Changes in v3:
>>>> > > > - Renames the node name.
>>>> > > > - Adds ACK from Rob.
>>>> > > > Changes in v2:
>>>> > > > - Removed status property in example.
>>>> > > > - Added required property reg.
>>>> > > >
>>>> > > >   .../bindings/net/wireless/allwinner,xr819.txt      | 38
>>>> > > ++++++++++++++++++++++
>>>> > > >   1 file changed, 38 insertions(+)
>>>> > > >   create mode 100644
>>>> > >
>>> Documentation/devicetree/bindings/net/wireless/allwinner,xr819.txt
>>>> > >
>>>> > > Like I asked already last time, AFAICS there is no upstream xr819
>>>> > > wireless driver in drivers/net/wireless directory. Do we still
>>> accept
>>>> > > bindings like this for out-of-tree drivers?
>>>> >
>>>> > See esp8089.
>>>> >
>>>> > There's also no in-tree driver for it.
>>>> 
>>>> The question is whether we should. The above might be a precedent,
>>> but it
>>>> may not necessarily be the way to go. The commit message for esp8089
>>> seems
>>>> to hint that there is intent to have an in-tree driver:
>>>> 
>>>> """
>>>>     Note that at this point there only is an out of tree driver for
>>> this
>>>>     hardware, there is no clear timeline / path for merging this.
>>> Still
>>>>     I believe it would be good to specify the binding for this in
>>> tree
>>>>     now, so that any future migration to an in tree driver will not
>>> cause
>>>>     compatiblity issues.
>>>> 
>>>>     Cc: Icenowy Zheng <icenowy@aosc.xyz>
>>>>     Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>>>>     Signed-off-by: Rob Herring <robh@kernel.org>
>>>> """
>>>> 
>>>> Regardless the bindings are in principle independent of the kernel
>>> and just
>>>> describing hardware. I think there have been discussions to move the
>>>> bindings to their own repository, but apparently it was decided
>>> otherwise.
>>> 
>>> Yeah, I guess especially how it could be merged with the cw1200 
>>> driver
>>> would be very relevant to that commit log.
>> 
>> The cw1200 driver seems to still have some legacy platform
>> data. Maybe they should also be convert to DT.
>> (Or maybe compatible = "allwinner,xr819" is enough, as
>> xr819 is a specified variant of cw1200 family)
> 
> Ah, so the upstream cw1200 driver supports xr819? Has anyone tested
> that? Or does cw1200 more changes than just adding the DT support?

By doing some tests, XR819 is in the the CW1x60 family, which is not
yet well supported by cw1200 driver.

More work should be needed for support xr819 in cw1200 driver.

^ permalink raw reply

* Re: Linux wireless device driver tutorials.
From: Kalle Valo @ 2017-10-07 14:53 UTC (permalink / raw)
  To: Madhu K; +Cc: linux-wireless
In-Reply-To: <CAA2oCOkCdKeyioo=26BMj1spvxjHQ+vM4S+ZUSgxbF8qisAY=A@mail.gmail.com>

Madhu K <madhu.sk89@gmail.com> writes:

> I am kernel newbie, I am trying to understand the linux wireless
> architecture and wanted write some simple drivers. Please somebody
> help me to get the documents related this?

This is not about wireless but still I think a must read for anyone new
with kernel development:

https://lwn.net/Kernel/LDD3/

For wireless development take a look at simple drivers like wl1251 or
mac80211_hwsim and start studying how they work.

And of course you need to check the wiki:

https://wireless.wiki.kernel.org/

-- 
Kalle Valo

^ permalink raw reply

* Re: [PATCH] bcma: keep *config menu together
From: Randy Dunlap @ 2017-10-07 21:04 UTC (permalink / raw)
  To: LKML, linux-wireless; +Cc: Andrew Morton, Rafał Miłecki
In-Reply-To: <c4250321-0c2e-4f9c-7fea-aa1001d9c3a8@infradead.org>

On 09/27/17 13:01, Randy Dunlap wrote:
> From: Randy Dunlap <rdunlap@infradead.org>
> 
> Use "if BCMA"/"endif" around all Kconfig symbols so that they are
> kept together in *config menus instead of showing up in unexpected
> places. Also remove "depends on BCMA" since this is handled by the
> "if BCMA" addition.
> 
> Tested with ARCH={x86_64,MIPS} using make {n,menu,g,x}config.
> 
> Signed-off-by: Randy Dunlap <rdunlap@infradead.org>
> Cc: Rafał Miłecki <zajec5@gmail.com>

Rafał -- ping?

> ---
>  drivers/bcma/Kconfig |   18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> --- lnx-414-rc2.orig/drivers/bcma/Kconfig
> +++ lnx-414-rc2/drivers/bcma/Kconfig
> @@ -10,14 +10,15 @@ menuconfig BCMA
>  	  Bus driver for Broadcom specific Advanced Microcontroller Bus
>  	  Architecture.
>  
> +if BCMA
> +
>  # Support for Block-I/O. SELECT this from the driver that needs it.
>  config BCMA_BLOCKIO
>  	bool
> -	depends on BCMA
>  
>  config BCMA_HOST_PCI_POSSIBLE
>  	bool
> -	depends on BCMA && PCI = y
> +	depends on PCI = y
>  	default y
>  
>  config BCMA_HOST_PCI
> @@ -28,7 +29,6 @@ config BCMA_HOST_PCI
>  
>  config BCMA_HOST_SOC
>  	bool "Support for BCMA in a SoC"
> -	depends on BCMA
>  	help
>  	  Host interface for a Broadcom AIX bus directly mapped into
>  	  the memory. This only works with the Broadcom SoCs from the
> @@ -38,7 +38,7 @@ config BCMA_HOST_SOC
>  
>  config BCMA_DRIVER_PCI
>  	bool "BCMA Broadcom PCI core driver"
> -	depends on BCMA && PCI
> +	depends on PCI
>  	default y
>  	help
>  	  BCMA bus may have many versions of PCIe core. This driver
> @@ -54,13 +54,13 @@ config BCMA_DRIVER_PCI
>  
>  config BCMA_DRIVER_PCI_HOSTMODE
>  	bool "Driver for PCI core working in hostmode"
> -	depends on BCMA && MIPS && BCMA_DRIVER_PCI
> +	depends on MIPS && BCMA_DRIVER_PCI
>  	help
>  	  PCI core hostmode operation (external PCI bus).
>  
>  config BCMA_DRIVER_MIPS
>  	bool "BCMA Broadcom MIPS core driver"
> -	depends on BCMA && MIPS
> +	depends on MIPS
>  	help
>  	  Driver for the Broadcom MIPS core attached to Broadcom specific
>  	  Advanced Microcontroller Bus.
> @@ -91,7 +91,6 @@ config BCMA_NFLASH
>  
>  config BCMA_DRIVER_GMAC_CMN
>  	bool "BCMA Broadcom GBIT MAC COMMON core driver"
> -	depends on BCMA
>  	help
>  	  Driver for the Broadcom GBIT MAC COMMON core attached to Broadcom
>  	  specific Advanced Microcontroller Bus.
> @@ -100,7 +99,7 @@ config BCMA_DRIVER_GMAC_CMN
>  
>  config BCMA_DRIVER_GPIO
>  	bool "BCMA GPIO driver"
> -	depends on BCMA && GPIOLIB
> +	depends on GPIOLIB
>  	select GPIOLIB_IRQCHIP if BCMA_HOST_SOC
>  	help
>  	  Driver to provide access to the GPIO pins of the bcma bus.
> @@ -109,8 +108,9 @@ config BCMA_DRIVER_GPIO
>  
>  config BCMA_DEBUG
>  	bool "BCMA debugging"
> -	depends on BCMA
>  	help
>  	  This turns on additional debugging messages.
>  
>  	  If unsure, say N
> +
> +endif # BCMA
> 
> 
> 


-- 
~Randy

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Xiang Gao @ 2017-10-08  5:43 UTC (permalink / raw)
  To: Johannes Berg; +Cc: David S. Miller, linux-kernel, linux-wireless, netdev
In-Reply-To: <1506945898.25586.3.camel@sipsolutions.net>

Hi Johannes,

Thanks for your time on reviewing this. I will make changes following
your review. See details below.
By the way, I'm still struggling on how to run unit tests. It might
take time for me to make it run on my machine.

2017-10-02 8:04 GMT-04:00 Johannes Berg <johannes@sipsolutions.net>:
> Please use "v2" tag or so in the subject line, having the same patch
> again is really not helpful.
>
> The next should be v3, obviously.

Thanks for your patience to point this out. I will follow your instruction.

>
>> +++ b/net/mac80211/aead_api.c
>> @@ -1,7 +1,4 @@
>> -/*
>> - * Copyright 2014-2015, Qualcomm Atheros, Inc.
>> - *
>> - * This program is free software; you can redistribute it and/or
>> modify
>> +/* This program is free software; you can redistribute it and/or
>> modify
>
> I see no reason to make this change, why remove copyright?

Hmm... good question. The reason is, aes_ccm.c and aes_gcm.c was
almost exact copy of each other. But they have different copyright
information.
The copyright of aes_ccm.c was:

Copyright 2006, Devicescape Software, Inc.
Copyright 2003-2004, Instant802 Networks, Inc.

and the copyright of aes_gcm.c was:

Copyright 2014-2015, Qualcomm Atheros, Inc.

I just don't know how to write the copyright for the new aead_api.c,
so I does not put anything there.

These copyright information are still at aes_ccm.h and aes_gcm.h

What's your opinion on writing these copyright information? Do I write
all of them? like:

Copyright 2014-2015, Qualcomm Atheros, Inc.
Copyright 2006, Devicescape Software, Inc.
Copyright 2003-2004, Instant802 Networks, Inc.

>
>> +++ b/net/mac80211/wpa.c
>> @@ -464,7 +464,8 @@ static int ccmp_encrypt_skb(struct
>> ieee80211_tx_data *tx, struct sk_buff *skb,
>>       pos += IEEE80211_CCMP_HDR_LEN;
>>       ccmp_special_blocks(skb, pn, b_0, aad);
>>       return ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad,
>> pos, len,
>> -                                      skb_put(skb, mic_len),
>> mic_len);
>> +                                      skb_put(skb,
>> +                                              key->u.ccmp.tfm-
>> >authsize));
>>  }
>
> I see no reason for the change from mic_len to authsize here?

This was because I was planning to put it to crypto directory, then I
changed it to the same name as in other crypto api. Now that it will
goes to the mac80211, I think it is time to revert this change.

>
>> @@ -540,10 +541,11 @@ ieee80211_crypto_ccmp_decrypt(struct
>> ieee80211_rx_data *rx,
>>                       ccmp_special_blocks(skb, pn, b_0, aad);
>>
>>                       if (ieee80211_aes_ccm_decrypt(
>> -                                 key->u.ccmp.tfm, b_0, aad,
>> -                                 skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
>> -                                 data_len,
>> -                                 skb->data + skb->len - mic_len, mic_len))
>> +                             key->u.ccmp.tfm, b_0, aad,
>> +                             skb->data + hdrlen + IEEE80211_CCMP_HDR_LEN,
>> +                             data_len,
>> +                             skb->data + skb->len - key->u.ccmp.tfm->authsize
>> +                     ))
>>                               return RX_DROP_UNUSABLE;
>
> That's a really really strange way of writing this ...
>
> Please reformat.

OK, I will reformat it.

>
> johannes

^ permalink raw reply

* [PATCH] wcn36xx: Remove unnecessary rcu_read_unlock in wcn36xx_bss_info_changed
From: Jia-Ju Bai @ 2017-10-08 13:06 UTC (permalink / raw)
  To: k.eugene.e, kvalo
  Cc: wcn36xx, linux-wireless, netdev, linux-kernel, Jia-Ju Bai

No rcu_read_lock is called, but rcu_read_unlock is still called.
Thus rcu_read_unlock should be removed.

Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
---
 drivers/net/wireless/ath/wcn36xx/main.c |    1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 35bd50b..b83f01d 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -812,7 +812,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
 			if (!sta) {
 				wcn36xx_err("sta %pM is not found\n",
 					      bss_conf->bssid);
-				rcu_read_unlock();
 				goto out;
 			}
 			sta_priv = wcn36xx_sta_to_priv(sta);
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH 1/5] iwlwifi: mvm: do not print security error in monitor mode
From: Joe Perches @ 2017-10-08 15:59 UTC (permalink / raw)
  To: Luca Coelho, kvalo; +Cc: linux-wireless, Shaul Triebitz, Luca Coelho
In-Reply-To: <20170929120305.20551-2-luca@coelho.fi>

On Fri, 2017-09-29 at 15:03 +0300, Luca Coelho wrote:
> From: Shaul Triebitz <shaul.triebitz@intel.com>
> 
> In monitor mode we are not expected to decrypt encrypted
> packets (not having the keys).
> Hence we are expected to get an unknown rx security status.
> Keeping the print in monitor mode causes a print for each
> captured packet flooding the dmesg.
[]
> diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
[]
> @@ -1015,6 +1015,9 @@ struct iwl_mvm {
>  	bool drop_bcn_ap_mode;
>  
>  	struct delayed_work cs_tx_unblock_dwork;
> +
> +	/* does a monitor vif exist (only one can exist hence bool) */
> +	bool monitor_on;

It would be slightly more space efficient to move this above
	struct delayed_work cs_tx_unblock_dwork
adjacent to
	bool drop_bcn_ap_mode

^ permalink raw reply

* [PATCH] ath10k: spectral: Simplify error checking
From: Christos Gkekas @ 2017-10-08 19:30 UTC (permalink / raw)
  To: Kalle Valo, ath10k, linux-wireless, netdev, linux-kernel; +Cc: Christos Gkekas

Variable val is unsigned so checking whether it is less than zero is
redundant.

Signed-off-by: Christos Gkekas <chris.gekas@gmail.com>
---
 drivers/net/wireless/ath/ath10k/spectral.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index dd9cc09..1867937 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -403,10 +403,7 @@ static ssize_t write_file_spectral_count(struct file *file,
 		return -EFAULT;
 
 	buf[len] = '\0';
-	if (kstrtoul(buf, 0, &val))
-		return -EINVAL;
-
-	if (val < 0 || val > 255)
+	if (kstrtoul(buf, 0, &val) || val > 255)
 		return -EINVAL;
 
 	mutex_lock(&ar->conf_mutex);
-- 
2.7.4

^ permalink raw reply related

* [PATCH] ath9k: debug: Simplify error checking
From: Christos Gkekas @ 2017-10-08 21:29 UTC (permalink / raw)
  To: QCA ath9k Development, Kalle Valo, linux-wireless, netdev,
	linux-kernel
  Cc: Christos Gkekas

Variable val is unsigned so checking whether it is less than zero is
redundant.

Signed-off-by: Christos Gkekas <chris.gekas@gmail.com>
---
 drivers/net/wireless/ath/ath9k/debug.c | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 01fa301..3b93c23 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1164,10 +1164,7 @@ static ssize_t write_file_tpc(struct file *file, const char __user *user_buf,
 		return -EFAULT;
 
 	buf[len] = '\0';
-	if (kstrtoul(buf, 0, &val))
-		return -EINVAL;
-
-	if (val < 0 || val > 1)
+	if (kstrtoul(buf, 0, &val) || val > 1)
 		return -EINVAL;
 
 	tpc_enabled = !!val;
-- 
2.7.4

^ permalink raw reply related

* [BUG] ssb: Possible sleep-in-atomic bugs in ssb_pcmcia_read8
From: Jia-Ju Bai @ 2017-10-09  1:29 UTC (permalink / raw)
  To: gregkh, m, sudipm.mukherjee, akpm, johannes, dahinds
  Cc: linux-pcmcia, Linux Kernel Mailing List, linux-wireless

According to pcmcia.c, the driver may sleep under a spinlock.
The function call paths are:
ssb_pcmcia_read8 (acquire the spinlock)
   select_core_and_segment
     ssb_pcmcia_switch_segment
       ssb_pcmcia_cfg_write
         pcmcia_write_config_byte
           pcmcia_access_config (drivers/pcmcia/pcmcia_resource.c)
             mutex_lock --> may sleep

ssb_pcmcia_read8 (acquire the spinlock)
   select_core_and_segment
     ssb_pcmcia_switch_segment
       sssb_pcmcia_cfg_read
         pcmcia_read_config_byte
           pcmcia_access_config (drivers/pcmcia/pcmcia_resource.c)
             mutex_lock --> may sleep

A possible fix is to use spinlock instead of mutex lock in 
pcmcia_access_config in drivers/pcmcia/pcmcia_resource.c.

These bugs are found by my static analysis tool and my code review.


Thanks,
Jia-Ju Bai

^ permalink raw reply

* Re: [PATCH] mac80211: aead api to reduce redundancy
From: Johannes Berg @ 2017-10-09  7:09 UTC (permalink / raw)
  To: Xiang Gao; +Cc: David S. Miller, linux-kernel, linux-wireless, netdev
In-Reply-To: <CAMtaSwRU45ve71=H4C7cDQEHrkHg2=eMvXhYbe4HZGxsPRD+AQ@mail.gmail.com>

On Sun, 2017-10-08 at 01:43 -0400, Xiang Gao wrote:
> 
> By the way, I'm still struggling on how to run unit tests. It might
> take time for me to make it run on my machine.

I can run it easily, so don't worry about it too much. Running it is of
course much appreciated, but I don't really want to go and require that
right now, it takes a long time to run.

If you do want to set it up, I suggest the vm scripts (hostap
repository in tests/hwsim/vm/ - you can use the kernel .config there as
a base to compile a kernel and then just kick it off from there, but it
can take a while to run.

> Hmm... good question. The reason is, aes_ccm.c and aes_gcm.c was
> almost exact copy of each other. But they have different copyright
> information.
> The copyright of aes_ccm.c was:
> 
> Copyright 2006, Devicescape Software, Inc.
> Copyright 2003-2004, Instant802 Networks, Inc.
> 
> and the copyright of aes_gcm.c was:
> 
> Copyright 2014-2015, Qualcomm Atheros, Inc.
> 
> I just don't know how to write the copyright for the new aead_api.c,
> so I does not put anything there.

Heh, good point. Well, I guess we can pretend it wasn't already copied
before and just "keep" both.

johannes

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Johannes Berg @ 2017-10-09  7:15 UTC (permalink / raw)
  To: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless
In-Reply-To: <87infrqk28.fsf@toke.dk>

On Sat, 2017-10-07 at 13:22 +0200, Toke Høiland-Jørgensen wrote:

> Guess you are right that it will be difficult to get a completely
> accurate number. But as David Lang notes, as long as we are off by
> the same amount for all stations, that is fine - we're just
> interested in relative numbers.

That's not quite true though, you'd overestimate most on stations that
are using aggregation, assuming you take into account the whole frame
exchange sequence time. But maybe giving less than their fair share to
fast stations isn't really that much of a problem.

> > So ... no, I don't understand. You have a TXQ per _TID_, so
> > splitting up this per _AC_ still doesn't make sense since you have
> > two TXQs for each AC?
> 
> Yeah, but ath9k schedules all TIDs on the same AC together. So if
> station A has two TIDs active and station B one, the scheduling order
> will be A1, A2, B1, basically. This is fine as long as they are all
> on the same AC and scheduled together (in which case A1 and A2 will
> just share the same deficit).

Huh, I'm confused. Can you elaborate on this? How does it schedule two
TIDs for _different_ ACs then?

It seems to me that to actually get the right QoS behaviour you have to
schedule *stations*, and then while you're looking at a station, you
need to select the highest-priority TXQ that has data? Otherwise, don't
you end up doing fairness on a STA/AC rather than just on a STA, so
that a station that uses two ACs gets twice as much airtime as one
using just a single AC?

> But if there is only one TXQ active, every time that queue is
> scheduled, the scheduler will loop until its deficit becomes positive
> (which is generally good; that is how we make sure the scheduler is
> work-conserving). However, if the deficit is shared with another
> scheduling group (which in ath9k is another AC), the station in the
> group by itself will not be limited to its fair share, because every
> time it is scheduled by itself, its deficit is "reset".
> 
> Ideally, I would prefer the scheduling to be "two-pass": First,
> decide which physical station to send to, then decide which TID on
> that station to service. 

Yeah, that would make more sense.

> But because everything is done at the TID/TXQ level, that is not
> quite trivial to achieve I think...

Well you can group the TXQs, I guess. They all have a STA pointer, so
you could put a one- or two-bit "schedule color" field into each
station and if you find a TXQ with the same station color you just skip
it or something like that?

johannes

^ permalink raw reply

* pull-request: mac80211 2017-10-09
From: Johannes Berg @ 2017-10-09  7:40 UTC (permalink / raw)
  To: David Miller; +Cc: netdev, linux-wireless

Hi Dave,

The QCA folks found another netlink problem - we were missing validation
of some attributes. It's not super problematic since one can only read a
few bytes beyond the message (and that memory must exist), but here's the
fix for it.

I thought perhaps we can make nla_parse_nested() require a policy, but
given the two-stage validation/parsing in regular netlink that won't work.

Please pull and let me know if there's any problem.

Thanks,
johannes



The following changes since commit 9f775ead5e570e7e19015b9e4e2f3dd6e71a5935:

  l2tp: fix l2tp_eth module loading (2017-10-01 22:35:07 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211.git tags/mac80211-for-davem-2017-10-09

for you to fetch changes up to ad670233c9e1d5feb365d870e30083ef1b889177:

  nl80211: Define policy for packet pattern attributes (2017-10-04 14:39:21 +0200)

----------------------------------------------------------------
Just a single fix for a missing netlink attribute validation.

----------------------------------------------------------------
Peng Xu (1):
      nl80211: Define policy for packet pattern attributes

 net/wireless/nl80211.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

^ permalink raw reply

* Re: [Make-wifi-fast] [RFC] mac80211: Add airtime fairness accounting
From: David Lang @ 2017-10-09  7:50 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Toke Høiland-Jørgensen, make-wifi-fast, linux-wireless
In-Reply-To: <1507533328.26041.12.camel@sipsolutions.net>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 968 bytes --]

On Mon, 9 Oct 2017, Johannes Berg wrote:

> On Sat, 2017-10-07 at 13:22 +0200, Toke Høiland-Jørgensen wrote:
>
>> Guess you are right that it will be difficult to get a completely
>> accurate number. But as David Lang notes, as long as we are off by
>> the same amount for all stations, that is fine - we're just
>> interested in relative numbers.
>
> That's not quite true though, you'd overestimate most on stations that
> are using aggregation, assuming you take into account the whole frame
> exchange sequence time. But maybe giving less than their fair share to
> fast stations isn't really that much of a problem.

how much error does this introduce?
Compared to the stations using 802.11b, this is a trivial difference.

That's why I said perfect is the enemy of good enough. Yes, it would be ideal to 
get the airtime from the driver, but if the driver doesn't provide it, I think 
ignoring aggregation in the name of simplicity is 'good enough'

David Lang

^ permalink raw reply

* Re: [RFC] mac80211: Add airtime fairness accounting
From: Toke Høiland-Jørgensen @ 2017-10-09  9:42 UTC (permalink / raw)
  To: Johannes Berg, make-wifi-fast, linux-wireless
In-Reply-To: <1507533328.26041.12.camel@sipsolutions.net>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Sat, 2017-10-07 at 13:22 +0200, Toke H=C3=B8iland-J=C3=B8rgensen wrote:
>
>> Guess you are right that it will be difficult to get a completely
>> accurate number. But as David Lang notes, as long as we are off by
>> the same amount for all stations, that is fine - we're just
>> interested in relative numbers.
>
> That's not quite true though, you'd overestimate most on stations that
> are using aggregation, assuming you take into account the whole frame
> exchange sequence time. But maybe giving less than their fair share to
> fast stations isn't really that much of a problem.

Well, the padding and spacing between frames is at most 11 bytes (4-byte
delimiter, 4-byte FCS and 3-byte padding), which is ~0.7% of a
full-sized frame. I'm not too worried about errors on that scale, TBH.
Sure, it would be better to have it be accurate, but there are other
imperfections, especially on the RX side (we can't count
retransmissions, for instance, since the receiver obviously doesn't see
those).

>> > So ... no, I don't understand. You have a TXQ per _TID_, so
>> > splitting up this per _AC_ still doesn't make sense since you have
>> > two TXQs for each AC?
>>=20
>> Yeah, but ath9k schedules all TIDs on the same AC together. So if
>> station A has two TIDs active and station B one, the scheduling order
>> will be A1, A2, B1, basically. This is fine as long as they are all
>> on the same AC and scheduled together (in which case A1 and A2 will
>> just share the same deficit).
>
> Huh, I'm confused. Can you elaborate on this? How does it schedule two
> TIDs for _different_ ACs then?

There's a separate scheduling loop for each hardware queue (one per AC),
which only schedules all TXQs with that AC. The hardware will prioritise
higher ACs by dequeueing from the high-priority hardware queue first.

> It seems to me that to actually get the right QoS behaviour you have
> to schedule *stations*, and then while you're looking at a station,
> you need to select the highest-priority TXQ that has data? Otherwise,
> don't you end up doing fairness on a STA/AC rather than just on a STA,
> so that a station that uses two ACs gets twice as much airtime as one
> using just a single AC?

Yeah, that's what we have currently in ath9k. However, it's rare in
practice that a station transmits the same amount of data on all ACs
(for one, since the max aggregation size is smaller at the higher ACs
that becomes difficult). But you are quite right that this is something
that should be fixed :)

>> Ideally, I would prefer the scheduling to be "two-pass": First,
>> decide which physical station to send to, then decide which TID on
>> that station to service.=20
>
> Yeah, that would make more sense.
>
>> But because everything is done at the TID/TXQ level, that is not
>> quite trivial to achieve I think...
>
> Well you can group the TXQs, I guess. They all have a STA pointer, so
> you could put a one- or two-bit "schedule color" field into each
> station and if you find a TXQ with the same station color you just
> skip it or something like that?

Couldn't we add something like a get_next_txq(phy) function to mac80211
that the drivers can call to get the queue to pull packets from? That
way, responsibility for scheduling both stations and QoS levels falls to
mac80211, which makes it possible to do clever scheduling stuff without
having to re-implement it in every driver. Also, this function could
handle all the special TXQs for PS and non-data frames that you were
talking about in your other email?

Unless there's some reason I'm missing that the driver really needs to
schedule the TXQs, I think this would make a lot of sense?

-Toke

^ permalink raw reply

* [PATCH v2 0/4] built-in regulatory database
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless

Here's a new version of these patches, hopefully the final. I changed
the database format to make it smaller
 * dropping antenna gain limitation (never used in db.txt)
 * make CAC timeout in seconds, and optional
 * change length fields to u8
 * change n_rules field to u8
 * re-pack those flags that are used in db.txt

The whole database is now only about 3.4KB.

johannes

^ permalink raw reply

* [PATCH v2 3/4] cfg80211: reg: remove support for built-in regdb
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Parsing and building C structures from a regdb is no longer needed
since the "firmware" file (regulatory.db) can be linked into the
kernel image to achieve the same effect.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/networking/regulatory.txt |  22 +----
 net/wireless/Kconfig                    |  24 +----
 net/wireless/Makefile                   |   6 --
 net/wireless/db.txt                     |  17 ----
 net/wireless/genregdb.awk               | 158 --------------------------------
 net/wireless/reg.c                      |  39 --------
 net/wireless/regdb.h                    |  23 -----
 7 files changed, 3 insertions(+), 286 deletions(-)
 delete mode 100644 net/wireless/db.txt
 delete mode 100644 net/wireless/genregdb.awk
 delete mode 100644 net/wireless/regdb.h

diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index 46c8d8b1cc66..381e5b23d61d 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -200,23 +200,5 @@ Then in some part of your code after your wiphy has been registered:
 Statically compiled regulatory database
 ---------------------------------------
 
-In most situations the userland solution using CRDA as described
-above is the preferred solution.  However in some cases a set of
-rules built into the kernel itself may be desirable.  To account
-for this situation, a configuration option has been provided
-(i.e. CONFIG_CFG80211_INTERNAL_REGDB).  With this option enabled,
-the wireless database information contained in net/wireless/db.txt is
-used to generate a data structure encoded in net/wireless/regdb.c.
-That option also enables code in net/wireless/reg.c which queries
-the data in regdb.c as an alternative to using CRDA.
-
-The file net/wireless/db.txt should be kept up-to-date with the db.txt
-file available in the git repository here:
-
-    git://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git
-
-Again, most users in most situations should be using the CRDA package
-provided with their distribution, and in most other situations users
-should be building and using CRDA on their own rather than using
-this option.  If you are not absolutely sure that you should be using
-CONFIG_CFG80211_INTERNAL_REGDB then _DO_NOT_USE_IT_.
+When a database should be fixed into the kernel, it can be provided as a
+firmware file at build time that is then linked into the kernel.
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 24eec5516649..f050030055c5 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -140,30 +140,8 @@ config CFG80211_DEBUGFS
 
 	  If unsure, say N.
 
-config CFG80211_INTERNAL_REGDB
-	bool "use statically compiled regulatory rules database" if EXPERT
-	default n
-	depends on CFG80211
-	---help---
-	  This option generates an internal data structure representing
-	  the wireless regulatory rules described in net/wireless/db.txt
-	  and includes code to query that database. This is an alternative
-	  to using CRDA for defining regulatory rules for the kernel.
-
-	  Using this option requires some parsing of the db.txt at build time,
-	  the parser will be upkept with the latest wireless-regdb updates but
-	  older wireless-regdb formats will be ignored. The parser may later
-	  be replaced to avoid issues with conflicts on versions of
-	  wireless-regdb.
-
-	  For details see:
-
-	  http://wireless.kernel.org/en/developers/Regulatory
-
-	  Most distributions have a CRDA package. So if unsure, say N.
-
 config CFG80211_CRDA_SUPPORT
-	bool "support CRDA" if CFG80211_INTERNAL_REGDB
+	bool "support CRDA" if EXPERT
 	default y
 	depends on CFG80211
 	help
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index d06e5015751a..5f20dac5d8c6 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -14,11 +14,5 @@ cfg80211-y += mlme.o ibss.o sme.o chan.o ethtool.o mesh.o ap.o trace.o ocb.o
 cfg80211-$(CONFIG_OF) += of.o
 cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
-cfg80211-$(CONFIG_CFG80211_INTERNAL_REGDB) += regdb.o
 
 CFLAGS_trace.o := -I$(src)
-
-$(obj)/regdb.c: $(src)/db.txt $(src)/genregdb.awk
-	@$(AWK) -f $(srctree)/$(src)/genregdb.awk < $< > $@
-
-clean-files := regdb.c
diff --git a/net/wireless/db.txt b/net/wireless/db.txt
deleted file mode 100644
index a2fc3a09ccdc..000000000000
--- a/net/wireless/db.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-#
-# This file is a placeholder to prevent accidental build breakage if someone
-# enables CONFIG_CFG80211_INTERNAL_REGDB.  Almost no one actually needs to
-# enable that build option.
-#
-# You should be using CRDA instead.  It is even better if you use the CRDA
-# package provided by your distribution, since they will probably keep it
-# up-to-date on your behalf.
-#
-# If you _really_ intend to use CONFIG_CFG80211_INTERNAL_REGDB then you will
-# need to replace this file with one containing appropriately formatted
-# regulatory rules that cover the regulatory domains you will be using.  Your
-# best option is to extract the db.txt file from the wireless-regdb git
-# repository:
-#
-#   git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-regdb.git
-#
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk
deleted file mode 100644
index baf2426b555a..000000000000
--- a/net/wireless/genregdb.awk
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/awk -f
-#
-# genregdb.awk -- generate regdb.c from db.txt
-#
-# Actually, it reads from stdin (presumed to be db.txt) and writes
-# to stdout (presumed to be regdb.c), but close enough...
-#
-# Copyright 2009 John W. Linville <linville@tuxdriver.com>
-#
-# Permission to use, copy, modify, and/or distribute this software for any
-# purpose with or without fee is hereby granted, provided that the above
-# copyright notice and this permission notice appear in all copies.
-#
-# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
-# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
-# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
-# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
-# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
-# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-
-BEGIN {
-	active = 0
-	rules = 0;
-	print "/*"
-	print " * DO NOT EDIT -- file generated from data in db.txt"
-	print " */"
-	print ""
-	print "#include <linux/nl80211.h>"
-	print "#include <net/cfg80211.h>"
-	print "#include \"regdb.h\""
-	print ""
-	regdb = "const struct ieee80211_regdomain *reg_regdb[] = {\n"
-}
-
-function parse_country_head() {
-	country=$2
-	sub(/:/, "", country)
-	printf "static const struct ieee80211_regdomain regdom_%s = {\n", country
-	printf "\t.alpha2 = \"%s\",\n", country
-	if ($NF ~ /DFS-ETSI/)
-		printf "\t.dfs_region = NL80211_DFS_ETSI,\n"
-	else if ($NF ~ /DFS-FCC/)
-		printf "\t.dfs_region = NL80211_DFS_FCC,\n"
-	else if ($NF ~ /DFS-JP/)
-		printf "\t.dfs_region = NL80211_DFS_JP,\n"
-	printf "\t.reg_rules = {\n"
-	active = 1
-	regdb = regdb "\t&regdom_" country ",\n"
-}
-
-function parse_reg_rule()
-{
-	flag_starts_at = 7
-
-	start = $1
-	sub(/\(/, "", start)
-	end = $3
-	bw = $5
-	sub(/\),/, "", bw)
-	gain = 0
-	power = $6
-	# power might be in mW...
-	units = $7
-	dfs_cac = 0
-
-	sub(/\(/, "", power)
-	sub(/\),/, "", power)
-	sub(/\),/, "", units)
-	sub(/\)/, "", units)
-
-	if (units == "mW") {
-		flag_starts_at = 8
-		power = 10 * log(power)/log(10)
-		if ($8 ~ /[[:digit:]]/) {
-			flag_starts_at = 9
-			dfs_cac = $8
-		}
-	} else {
-		if ($7 ~ /[[:digit:]]/) {
-			flag_starts_at = 8
-			dfs_cac = $7
-		}
-	}
-	sub(/\(/, "", dfs_cac)
-	sub(/\),/, "", dfs_cac)
-	flagstr = ""
-	for (i=flag_starts_at; i<=NF; i++)
-		flagstr = flagstr $i
-	split(flagstr, flagarray, ",")
-	flags = ""
-	for (arg in flagarray) {
-		if (flagarray[arg] == "NO-OFDM") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_OFDM | "
-		} else if (flagarray[arg] == "NO-CCK") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_CCK | "
-		} else if (flagarray[arg] == "NO-INDOOR") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_INDOOR | "
-		} else if (flagarray[arg] == "NO-OUTDOOR") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_OUTDOOR | "
-		} else if (flagarray[arg] == "DFS") {
-			flags = flags "\n\t\t\tNL80211_RRF_DFS | "
-		} else if (flagarray[arg] == "PTP-ONLY") {
-			flags = flags "\n\t\t\tNL80211_RRF_PTP_ONLY | "
-		} else if (flagarray[arg] == "PTMP-ONLY") {
-			flags = flags "\n\t\t\tNL80211_RRF_PTMP_ONLY | "
-		} else if (flagarray[arg] == "PASSIVE-SCAN") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
-		} else if (flagarray[arg] == "NO-IBSS") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
-		} else if (flagarray[arg] == "NO-IR") {
-			flags = flags "\n\t\t\tNL80211_RRF_NO_IR | "
-		} else if (flagarray[arg] == "AUTO-BW") {
-			flags = flags "\n\t\t\tNL80211_RRF_AUTO_BW | "
-		}
-
-	}
-	flags = flags "0"
-	printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %.0f, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags
-	rules++
-}
-
-function print_tail_country()
-{
-	active = 0
-	printf "\t},\n"
-	printf "\t.n_reg_rules = %d\n", rules
-	printf "};\n\n"
-	rules = 0;
-}
-
-/^[ \t]*#/ {
-	# Ignore
-}
-
-!active && /^[ \t]*$/ {
-	# Ignore
-}
-
-!active && /country/ {
-	parse_country_head()
-}
-
-active && /^[ \t]*\(/ {
-	parse_reg_rule()
-}
-
-active && /^[ \t]*$/ {
-	print_tail_country()
-}
-
-END {
-	if (active)
-		print_tail_country()
-	print regdb "};"
-	print ""
-	print "int reg_regdb_size = ARRAY_SIZE(reg_regdb);"
-}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 6b444898919b..bcccd1a905ef 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -59,7 +59,6 @@
 #include "core.h"
 #include "reg.h"
 #include "rdev-ops.h"
-#include "regdb.h"
 #include "nl80211.h"
 
 /*
@@ -495,38 +494,6 @@ static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
 	return 0;
 }
 
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
-static int reg_query_builtin(const char *alpha2)
-{
-	const struct ieee80211_regdomain *regdom = NULL;
-	unsigned int i;
-
-	for (i = 0; i < reg_regdb_size; i++) {
-		if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
-			regdom = reg_copy_regd(reg_regdb[i]);
-			break;
-		}
-	}
-	if (!regdom)
-		return -ENODATA;
-
-	return reg_schedule_apply(regdom);
-}
-
-/* Feel free to add any other sanity checks here */
-static void reg_regdb_size_check(void)
-{
-	/* We should ideally BUILD_BUG_ON() but then random builds would fail */
-	WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it...");
-}
-#else
-static inline void reg_regdb_size_check(void) {}
-static inline int reg_query_builtin(const char *alpha2)
-{
-	return -ENODATA;
-}
-#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
-
 #ifdef CONFIG_CFG80211_CRDA_SUPPORT
 /* Max number of consecutive attempts to communicate with CRDA  */
 #define REG_MAX_CRDA_TIMEOUTS 10
@@ -887,10 +854,6 @@ int reg_reload_regdb(void)
 
 static bool reg_query_database(struct regulatory_request *request)
 {
-	/* query internal regulatory database (if it exists) */
-	if (reg_query_builtin(request->alpha2) == 0)
-		return true;
-
 	if (query_regdb_file(request->alpha2) == 0)
 		return true;
 
@@ -3582,8 +3545,6 @@ int __init regulatory_init(void)
 	spin_lock_init(&reg_pending_beacons_lock);
 	spin_lock_init(&reg_indoor_lock);
 
-	reg_regdb_size_check();
-
 	rcu_assign_pointer(cfg80211_regdomain, cfg80211_world_regdom);
 
 	user_alpha2[0] = '9';
diff --git a/net/wireless/regdb.h b/net/wireless/regdb.h
deleted file mode 100644
index 3279cfcefb0c..000000000000
--- a/net/wireless/regdb.h
+++ /dev/null
@@ -1,23 +0,0 @@
-#ifndef __REGDB_H__
-#define __REGDB_H__
-
-/*
- * Copyright 2009 John W. Linville <linville@tuxdriver.com>
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-extern const struct ieee80211_regdomain *reg_regdb[];
-extern int reg_regdb_size;
-
-#endif /* __REGDB_H__ */
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 4/4] cfg80211: implement regdb signature checking
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Currently CRDA implements the signature checking, and the previous
commits added the ability to load the whole regulatory database
into the kernel.

However, we really can't lose the signature checking, so implement
it in the kernel by loading a detached signature (regulatory.db.p7s)
and check it against built-in keys.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/wireless/Kconfig             |  30 ++++++++++
 net/wireless/Makefile            |  22 +++++++
 net/wireless/certs/sforshee.x509 | Bin 0 -> 680 bytes
 net/wireless/reg.c               | 121 ++++++++++++++++++++++++++++++++++++++-
 net/wireless/reg.h               |   8 +++
 5 files changed, 180 insertions(+), 1 deletion(-)
 create mode 100644 net/wireless/certs/sforshee.x509

diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index f050030055c5..da91bb547db3 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -83,6 +83,36 @@ config CFG80211_CERTIFICATION_ONUS
 	  you are a wireless researcher and are working in a controlled
 	  and approved environment by your local regulatory agency.
 
+config CFG80211_REQUIRE_SIGNED_REGDB
+	bool "require regdb signature" if CFG80211_CERTIFICATION_ONUS
+	default y
+	select SYSTEM_DATA_VERIFICATION
+	help
+	  Require that in addition to the "regulatory.db" file a
+	  "regulatory.db.p7s" can be loaded with a valid PKCS#7
+	  signature for the regulatory.db file made by one of the
+	  keys in the certs/ directory.
+
+config CFG80211_USE_KERNEL_REGDB_KEYS
+	bool "allow regdb keys shipped with the kernel" if CFG80211_CERTIFICATION_ONUS
+	default y
+	depends on CFG80211_REQUIRE_SIGNED_REGDB
+	help
+	  Allow the regulatory database to be signed by one of the keys for
+	  which certificates are part of the kernel sources
+	  (in net/wireless/certs/).
+
+	  This is currently only Seth Forshee's key, who is the regulatory
+	  database maintainer.
+
+config CFG80211_EXTRA_REGDB_KEYDIR
+	string "additional regdb key directory" if CFG80211_CERTIFICATION_ONUS
+	depends on CFG80211_REQUIRE_SIGNED_REGDB
+	help
+	  If selected, point to a directory with DER-encoded X.509
+	  certificates like in the kernel sources (net/wireless/certs/)
+	  that shall be accepted for a signed regulatory database.
+
 config CFG80211_REG_CELLULAR_HINTS
 	bool "cfg80211 regulatory support for cellular base station hints"
 	depends on CFG80211_CERTIFICATION_ONUS
diff --git a/net/wireless/Makefile b/net/wireless/Makefile
index 5f20dac5d8c6..219baea57e4e 100644
--- a/net/wireless/Makefile
+++ b/net/wireless/Makefile
@@ -16,3 +16,25 @@ cfg80211-$(CONFIG_CFG80211_DEBUGFS) += debugfs.o
 cfg80211-$(CONFIG_CFG80211_WEXT) += wext-compat.o wext-sme.o
 
 CFLAGS_trace.o := -I$(src)
+
+cfg80211-$(CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS) += shipped-certs.o
+ifneq ($(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR),)
+cfg80211-y += extra-certs.o
+endif
+
+$(obj)/shipped-certs.c: $(wildcard $(srctree)/$(src)/certs/*.x509)
+	@echo "  GEN     $@"
+	@echo '#include "reg.h"' > $@
+	@echo 'const u8 shipped_regdb_certs[] = {' >> $@
+	@for f in $^ ; do hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ ; done
+	@echo '};' >> $@
+	@echo 'unsigned int shipped_regdb_certs_len = sizeof(shipped_regdb_certs);' >> $@
+
+$(obj)/extra-certs.c: $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%) \
+		      $(wildcard $(CONFIG_CFG80211_EXTRA_REGDB_KEYDIR:"%"=%)/*.x509)
+	@echo "  GEN     $@"
+	@echo '#include "reg.h"' > $@
+	@echo 'const u8 extra_regdb_certs[] = {' >> $@
+	@for f in $^ ; do test -f $$f && hexdump -v -e '1/1 "0x%.2x," "\n"' < $$f >> $@ || true ; done
+	@echo '};' >> $@
+	@echo 'unsigned int extra_regdb_certs_len = sizeof(extra_regdb_certs);' >> $@
diff --git a/net/wireless/certs/sforshee.x509 b/net/wireless/certs/sforshee.x509
new file mode 100644
index 0000000000000000000000000000000000000000..c6f8f9d6b98839048822ebbe27ecb831614ccf3d
GIT binary patch
literal 680
zcmXqLVp?L*#Mr~c$*`&SzWchL=aw7rvT<s)d9;1!Wn|=LWiSvn6g1#xV-96u=HVz#
z%P%U<NKG|R5a%^CH#9IXGqf}@FgA^n;5RZfG&is`G=d6X*Ve?Sgls$`D+6;ABR>Ps
z1zb!`jEoFh9UjloXt8AeWO+SJ$I(J`P2JMwLe;tnH5qsF?QdR>w3uI$6?BMMOSdlV
zi`-_R0)^-+(~WEkyRD@;#6_|bkA!zm6O;L?a+RC&XNF+Q?^A(17hNT93Al9K{8zT}
zZ-TA_x5m^>y01EB?6?@F_#s&SBUAoMx7m~9H74+{G5eLFTo@kq?abx-wOTi&i(Oyu
zQg3}<RloFf!*K(%OTq8ntdV<e_|a_9oaAGv(e<jO84F)su49Oq6?a2H!l;~GQz%W&
ztoZqK7Dw}q8;i8REYwt}nO4cIec{Hv6FK&ie;<8U5hN%oUG?oz#?0rx-NafRA7A+F
z!6mn=50AtzNc(c@$p5LbOw5c7jL0Dbi~wK=F*39>-}=;a=<fO&7yY)&@jjD1cK%}*
z->vvvRoQQq5|7x<;&pS~YD#Y&_6&F5Z@hi_o39R~2i%lCEQp;`DZKFij>Y=beQfq8
zwmr$x_+%2JY;Sbn*;@WJ=R-@}i!U>_Zs%4CQ>mTLxstDKo_X|~T&9~nCjzn_MSd1z
zd$q}FYs9}@7aPN+-fyz#i1@bZh+cP;`je$EmYhnDSyPmLIA8d%u4(1<uIFE`C>nTO
z{kHgKW!NWvf$y~!0w?Rc|ETrmY6%tMs`ay$*Vg}|u{qP^VMD|2N9%W9Gx#VQ(ylyn
seju}tYb{f1@#??lr<~!nO89FdqAzB=Qc?bNz{Y;&cMH;1idBjL01XcsegFUf

literal 0
HcmV?d00001

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index bcccd1a905ef..6f2728137749 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -53,6 +53,7 @@
 #include <linux/ctype.h>
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
+#include <linux/verification.h>
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <net/cfg80211.h>
@@ -660,6 +661,115 @@ static bool valid_country(const u8 *data, unsigned int size,
 	return true;
 }
 
+#ifdef CONFIG_CFG80211_REQUIRE_SIGNED_REGDB
+static struct key *builtin_regdb_keys;
+
+static void __init load_keys_from_buffer(const u8 *p, unsigned int buflen)
+{
+	const u8 *end = p + buflen;
+	size_t plen;
+	key_ref_t key;
+
+	while (p < end) {
+		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
+		 * than 256 bytes in size.
+		 */
+		if (end - p < 4)
+			goto dodgy_cert;
+		if (p[0] != 0x30 &&
+		    p[1] != 0x82)
+			goto dodgy_cert;
+		plen = (p[2] << 8) | p[3];
+		plen += 4;
+		if (plen > end - p)
+			goto dodgy_cert;
+
+		key = key_create_or_update(make_key_ref(builtin_regdb_keys, 1),
+					   "asymmetric", NULL, p, plen,
+					   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+					    KEY_USR_VIEW | KEY_USR_READ),
+					   KEY_ALLOC_NOT_IN_QUOTA |
+					   KEY_ALLOC_BUILT_IN |
+					   KEY_ALLOC_BYPASS_RESTRICTION);
+		if (IS_ERR(key)) {
+			pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
+			       PTR_ERR(key));
+		} else {
+			pr_notice("Loaded X.509 cert '%s'\n",
+				  key_ref_to_ptr(key)->description);
+			key_ref_put(key);
+		}
+		p += plen;
+	}
+
+	return;
+
+dodgy_cert:
+	pr_err("Problem parsing in-kernel X.509 certificate list\n");
+}
+
+static int __init load_builtin_regdb_keys(void)
+{
+	builtin_regdb_keys =
+		keyring_alloc(".builtin_regdb_keys",
+			      KUIDT_INIT(0), KGIDT_INIT(0), current_cred(),
+			      ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+			      KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH),
+			      KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+	if (IS_ERR(builtin_regdb_keys))
+		return PTR_ERR(builtin_regdb_keys);
+
+	pr_notice("Loading compiled-in X.509 certificates for regulatory database\n");
+
+#ifdef CONFIG_CFG80211_USE_KERNEL_REGDB_KEYS
+	load_keys_from_buffer(shipped_regdb_certs, shipped_regdb_certs_len);
+#endif
+#ifdef CFG80211_EXTRA_REGDB_KEYDIR
+	if (CONFIG_CFG80211_EXTRA_REGDB_KEYDIR[0] != '\0')
+		load_keys_from_buffer(extra_regdb_certs, extra_regdb_certs_len);
+#endif
+
+	return 0;
+}
+
+static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
+{
+	const struct firmware *sig;
+	bool result;
+
+	if (request_firmware(&sig, "regulatory.db.p7s", &reg_pdev->dev))
+		return false;
+
+	result = verify_pkcs7_signature(data, size, sig->data, sig->size,
+					builtin_regdb_keys,
+					VERIFYING_UNSPECIFIED_SIGNATURE,
+					NULL, NULL) == 0;
+
+	release_firmware(sig);
+
+	return result;
+}
+
+static void free_regdb_keyring(void)
+{
+	key_put(builtin_regdb_keys);
+}
+#else
+static int load_builtin_regdb_keys(void)
+{
+	return 0;
+}
+
+static bool regdb_has_valid_signature(const u8 *data, unsigned int size)
+{
+	return true;
+}
+
+static void free_regdb_keyring(void)
+{
+}
+#endif /* CONFIG_CFG80211_REQUIRE_SIGNED_REGDB */
+
 static bool valid_regdb(const u8 *data, unsigned int size)
 {
 	const struct fwdb_header *hdr = (void *)data;
@@ -674,6 +784,9 @@ static bool valid_regdb(const u8 *data, unsigned int size)
 	if (hdr->version != cpu_to_be32(FWDB_VERSION))
 		return false;
 
+	if (!regdb_has_valid_signature(data, size))
+		return false;
+
 	country = &hdr->country[0];
 	while ((u8 *)(country + 1) <= data + size) {
 		if (!country->coll_ptr)
@@ -775,7 +888,7 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
 		if (fwregdb_attempts-- == 0)
 			set_error = -ENODATA;
 	} else if (!valid_regdb(fw->data, fw->size)) {
-		pr_info("loaded regulatory.db is malformed\n");
+		pr_info("loaded regulatory.db is malformed or signature is missing/invalid\n");
 		set_error = -EINVAL;
 	}
 
@@ -3537,6 +3650,10 @@ int __init regulatory_init(void)
 {
 	int err = 0;
 
+	err = load_builtin_regdb_keys();
+	if (err)
+		return err;
+
 	reg_pdev = platform_device_register_simple("regulatory", 0, NULL, 0);
 	if (IS_ERR(reg_pdev))
 		return PTR_ERR(reg_pdev);
@@ -3613,4 +3730,6 @@ void regulatory_exit(void)
 
 	if (!IS_ERR_OR_NULL(regdb))
 		kfree(regdb);
+
+	free_regdb_keyring();
 }
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 9529c522611a..9ceeb5f3a7cb 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -1,5 +1,8 @@
 #ifndef __NET_WIRELESS_REG_H
 #define __NET_WIRELESS_REG_H
+
+#include <net/cfg80211.h>
+
 /*
  * Copyright 2008-2011	Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  *
@@ -185,4 +188,9 @@ bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
  */
 int reg_reload_regdb(void);
 
+extern const u8 shipped_regdb_certs[];
+extern unsigned int shipped_regdb_certs_len;
+extern const u8 extra_regdb_certs[];
+extern unsigned int extra_regdb_certs_len;
+
 #endif  /* __NET_WIRELESS_REG_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 2/4] cfg80211: support reloading regulatory database
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

If the regulatory database is loaded, and then updated, it may
be necessary to reload it. Add an nl80211 command to do this.

Note that this just reloads the database, it doesn't re-apply
the rules from it immediately.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/uapi/linux/nl80211.h |  4 +++
 net/wireless/nl80211.c       | 11 ++++++
 net/wireless/reg.c           | 80 +++++++++++++++++++++++++++++++++-----------
 net/wireless/reg.h           |  6 ++++
 4 files changed, 81 insertions(+), 20 deletions(-)

diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 95832ce03a44..f882fe1f9709 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -990,6 +990,8 @@
  *	&NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
  *	&NL80211_CMD_DISCONNECT should be indicated instead.
  *
+ * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1194,6 +1196,8 @@ enum nl80211_commands {
 
 	NL80211_CMD_PORT_AUTHORIZED,
 
+	NL80211_CMD_RELOAD_REGDB,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5129342151e6..67a03f2885a4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5678,6 +5678,11 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
 	}
 }
 
+static int nl80211_reload_regdb(struct sk_buff *skb, struct genl_info *info)
+{
+	return reg_reload_regdb();
+}
+
 static int nl80211_get_mesh_config(struct sk_buff *skb,
 				   struct genl_info *info)
 {
@@ -12708,6 +12713,12 @@ static const struct genl_ops nl80211_ops[] = {
 		.policy = nl80211_policy,
 		.flags = GENL_ADMIN_PERM,
 	},
+	{
+		.cmd = NL80211_CMD_RELOAD_REGDB,
+		.doit = nl80211_reload_regdb,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+	},
 	{
 		.cmd = NL80211_CMD_GET_MESH_CONFIG,
 		.doit = nl80211_get_mesh_config,
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3187a941b7bf..6b444898919b 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -782,6 +782,8 @@ static int query_regdb(const char *alpha2)
 	const struct fwdb_header *hdr = regdb;
 	const struct fwdb_country *country;
 
+	ASSERT_RTNL();
+
 	if (IS_ERR(regdb))
 		return PTR_ERR(regdb);
 
@@ -797,42 +799,48 @@ static int query_regdb(const char *alpha2)
 
 static void regdb_fw_cb(const struct firmware *fw, void *context)
 {
+	int set_error = 0;
+	bool restore = true;
 	void *db;
 
 	if (!fw) {
 		pr_info("failed to load regulatory.db\n");
 		if (fwregdb_attempts-- == 0)
-			regdb = ERR_PTR(-ENODATA);
-		goto restore;
-	}
-
-	if (!valid_regdb(fw->data, fw->size)) {
+			set_error = -ENODATA;
+	} else if (!valid_regdb(fw->data, fw->size)) {
 		pr_info("loaded regulatory.db is malformed\n");
-		release_firmware(fw);
-		regdb = ERR_PTR(-EINVAL);
-		goto restore;
+		set_error = -EINVAL;
 	}
 
-	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
-	release_firmware(fw);
+	rtnl_lock();
+	if (WARN_ON(regdb && !IS_ERR(regdb))) {
+		/* just restore and free new db */
+	} else if (set_error) {
+		regdb = ERR_PTR(set_error);
+	} else if (fw) {
+		db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+		if (db) {
+			regdb = db;
+			restore = context && query_regdb(context);
+		} else {
+			restore = true;
+		}
+	}
 
-	if (!db)
-		goto restore;
-	regdb = db;
+	if (restore)
+		restore_regulatory_settings(true);
 
-	if (query_regdb(context))
-		goto restore;
-	goto free;
- restore:
-	rtnl_lock();
-	restore_regulatory_settings(true);
 	rtnl_unlock();
- free:
+
 	kfree(context);
+
+	release_firmware(fw);
 }
 
 static int query_regdb_file(const char *alpha2)
 {
+	ASSERT_RTNL();
+
 	if (regdb)
 		return query_regdb(alpha2);
 
@@ -845,6 +853,38 @@ static int query_regdb_file(const char *alpha2)
 				       (void *)alpha2, regdb_fw_cb);
 }
 
+int reg_reload_regdb(void)
+{
+	const struct firmware *fw;
+	void *db;
+	int err;
+
+	err = request_firmware(&fw, "regulatory.db", &reg_pdev->dev);
+	if (err)
+		return err;
+
+	if (!valid_regdb(fw->data, fw->size)) {
+		err = -ENODATA;
+		goto out;
+	}
+
+	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+	if (!db) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	rtnl_lock();
+	if (!IS_ERR_OR_NULL(regdb))
+		kfree(regdb);
+	regdb = db;
+	rtnl_unlock();
+
+ out:
+	release_firmware(fw);
+	return err;
+}
+
 static bool reg_query_database(struct regulatory_request *request)
 {
 	/* query internal regulatory database (if it exists) */
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index ca7fedf2e7a1..9529c522611a 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -179,4 +179,10 @@ void regulatory_propagate_dfs_state(struct wiphy *wiphy,
  * @wiphy2 - wiphy it's dfs_region to be checked against that of wiphy1
  */
 bool reg_dfs_domain_same(struct wiphy *wiphy1, struct wiphy *wiphy2);
+
+/**
+ * reg_reload_regdb - reload the regulatory.db firmware file
+ */
+int reg_reload_regdb(void);
+
 #endif  /* __NET_WIRELESS_REG_H */
-- 
2.14.2

^ permalink raw reply related

* [PATCH v2 1/4] cfg80211: support loading regulatory database as firmware file
From: Johannes Berg @ 2017-10-09  9:50 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20171009095018.5289-1-johannes@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

As the current regulatory database is only about 4k big, and already
difficult to extend, we decided that overall it would be better to
get rid of the complications with CRDA and load the database into the
kernel directly, but in a new format that is extensible.

The new file format can be extended since it carries a length field
on all the structs that need to be extensible.

In order to be able to request firmware when the module initializes,
move cfg80211 from subsys_initcall() to the later fs_initcall(); the
firmware loader is at the same level but linked earlier, so it can
be called from there. Otherwise, when both the firmware loader and
cfg80211 are built-in, the request will crash the kernel. We also
need to be before device_initcall() so that cfg80211 is available
for devices when they initialize.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/networking/regulatory.txt |   8 +
 net/wireless/Kconfig                    |   4 +-
 net/wireless/core.c                     |   2 +-
 net/wireless/reg.c                      | 296 +++++++++++++++++++++++++++++---
 4 files changed, 286 insertions(+), 24 deletions(-)

diff --git a/Documentation/networking/regulatory.txt b/Documentation/networking/regulatory.txt
index 7818b5fe448b..46c8d8b1cc66 100644
--- a/Documentation/networking/regulatory.txt
+++ b/Documentation/networking/regulatory.txt
@@ -19,6 +19,14 @@ core regulatory domain all wireless devices should adhere to.
 How to get regulatory domains to the kernel
 -------------------------------------------
 
+When the regulatory domain is first set up, the kernel will request a
+database file (regulatory.db) containing all the regulatory rules. It
+will then use that database when it needs to look up the rules for a
+given country.
+
+How to get regulatory domains to the kernel (old CRDA solution)
+---------------------------------------------------------------
+
 Userspace gets a regulatory domain in the kernel by having
 a userspace agent build it and send it via nl80211. Only
 expected regulatory domains will be respected by the kernel.
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig
index 6c606120abfe..24eec5516649 100644
--- a/net/wireless/Kconfig
+++ b/net/wireless/Kconfig
@@ -19,6 +19,7 @@ config WEXT_PRIV
 config CFG80211
 	tristate "cfg80211 - wireless configuration API"
 	depends on RFKILL || !RFKILL
+	select FW_LOADER
 	---help---
 	  cfg80211 is the Linux wireless LAN (802.11) configuration API.
 	  Enable this if you have a wireless device.
@@ -167,7 +168,8 @@ config CFG80211_CRDA_SUPPORT
 	depends on CFG80211
 	help
 	  You should enable this option unless you know for sure you have no
-	  need for it, for example when using internal regdb (above.)
+	  need for it, for example when using internal regdb (above) or the
+	  database loaded as a firmware file.
 
 	  If unsure, say Y.
 
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 7b33e8c366bc..fdde0d98fde1 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1384,7 +1384,7 @@ static int __init cfg80211_init(void)
 out_fail_pernet:
 	return err;
 }
-subsys_initcall(cfg80211_init);
+fs_initcall(cfg80211_init);
 
 static void __exit cfg80211_exit(void)
 {
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 6e94f6934a0e..3187a941b7bf 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -54,6 +54,7 @@
 #include <linux/nl80211.h>
 #include <linux/platform_device.h>
 #include <linux/moduleparam.h>
+#include <linux/firmware.h>
 #include <net/cfg80211.h>
 #include "core.h"
 #include "reg.h"
@@ -100,7 +101,7 @@ static struct regulatory_request core_request_world = {
 static struct regulatory_request __rcu *last_request =
 	(void __force __rcu *)&core_request_world;
 
-/* To trigger userspace events */
+/* To trigger userspace events and load firmware */
 static struct platform_device *reg_pdev;
 
 /*
@@ -443,7 +444,6 @@ reg_copy_regd(const struct ieee80211_regdomain *src_regd)
 	return regd;
 }
 
-#ifdef CONFIG_CFG80211_INTERNAL_REGDB
 struct reg_regdb_apply_request {
 	struct list_head list;
 	const struct ieee80211_regdomain *regdom;
@@ -475,41 +475,44 @@ static void reg_regdb_apply(struct work_struct *work)
 
 static DECLARE_WORK(reg_regdb_work, reg_regdb_apply);
 
-static int reg_query_builtin(const char *alpha2)
+static int reg_schedule_apply(const struct ieee80211_regdomain *regdom)
 {
-	const struct ieee80211_regdomain *regdom = NULL;
 	struct reg_regdb_apply_request *request;
-	unsigned int i;
-
-	for (i = 0; i < reg_regdb_size; i++) {
-		if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
-			regdom = reg_regdb[i];
-			break;
-		}
-	}
-
-	if (!regdom)
-		return -ENODATA;
 
 	request = kzalloc(sizeof(struct reg_regdb_apply_request), GFP_KERNEL);
-	if (!request)
-		return -ENOMEM;
-
-	request->regdom = reg_copy_regd(regdom);
-	if (IS_ERR_OR_NULL(request->regdom)) {
-		kfree(request);
+	if (!request) {
+		kfree(regdom);
 		return -ENOMEM;
 	}
 
+	request->regdom = regdom;
+
 	mutex_lock(&reg_regdb_apply_mutex);
 	list_add_tail(&request->list, &reg_regdb_apply_list);
 	mutex_unlock(&reg_regdb_apply_mutex);
 
 	schedule_work(&reg_regdb_work);
-
 	return 0;
 }
 
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+static int reg_query_builtin(const char *alpha2)
+{
+	const struct ieee80211_regdomain *regdom = NULL;
+	unsigned int i;
+
+	for (i = 0; i < reg_regdb_size; i++) {
+		if (alpha2_equal(alpha2, reg_regdb[i]->alpha2)) {
+			regdom = reg_copy_regd(reg_regdb[i]);
+			break;
+		}
+	}
+	if (!regdom)
+		return -ENODATA;
+
+	return reg_schedule_apply(regdom);
+}
+
 /* Feel free to add any other sanity checks here */
 static void reg_regdb_size_check(void)
 {
@@ -599,12 +602,258 @@ static inline int call_crda(const char *alpha2)
 }
 #endif /* CONFIG_CFG80211_CRDA_SUPPORT */
 
+/* code to directly load a firmware database through request_firmware */
+static const struct fwdb_header *regdb;
+static unsigned int fwregdb_attempts = 10;
+
+struct fwdb_country {
+	u8 alpha2[2];
+	__be16 coll_ptr;
+	/* this struct cannot be extended */
+} __packed __aligned(4);
+
+struct fwdb_collection {
+	u8 len;
+	u8 n_rules;
+	u8 dfs_region;
+	/* no optional data yet */
+	/* aligned to 2, then followed by __be16 array of rule pointers */
+} __packed __aligned(4);
+
+enum fwdb_flags {
+	FWDB_FLAG_NO_OFDM	= BIT(0),
+	FWDB_FLAG_NO_OUTDOOR	= BIT(1),
+	FWDB_FLAG_DFS		= BIT(2),
+	FWDB_FLAG_NO_IR		= BIT(3),
+	FWDB_FLAG_AUTO_BW	= BIT(4),
+};
+
+struct fwdb_rule {
+	u8 len;
+	u8 flags;
+	__be16 max_eirp;
+	__be32 start, end, max_bw;
+	/* start of optional data */
+	__be16 cac_timeout;
+} __packed __aligned(4);
+
+#define FWDB_MAGIC 0x52474442
+#define FWDB_VERSION 20
+
+struct fwdb_header {
+	__be32 magic;
+	__be32 version;
+	struct fwdb_country country[];
+} __packed __aligned(4);
+
+static bool valid_rule(const u8 *data, unsigned int size, u16 rule_ptr)
+{
+	struct fwdb_rule *rule = (void *)(data + (rule_ptr << 2));
+
+	if ((u8 *)rule + sizeof(rule->len) > data + size)
+		return false;
+
+	/* mandatory fields */
+	if (rule->len < offsetofend(struct fwdb_rule, max_bw))
+		return false;
+
+	return true;
+}
+
+static bool valid_country(const u8 *data, unsigned int size,
+			  const struct fwdb_country *country)
+{
+	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+	struct fwdb_collection *coll = (void *)(data + ptr);
+	__be16 *rules_ptr;
+	unsigned int i;
+
+	/* make sure we can read len/n_rules */
+	if ((u8 *)coll + offsetofend(typeof(*coll), n_rules) > data + size)
+		return false;
+
+	/* make sure base struct and all rules fit */
+	if ((u8 *)coll + ALIGN(coll->len, 2) +
+	    (coll->n_rules * 2) > data + size)
+		return false;
+
+	/* mandatory fields must exist */
+	if (coll->len < offsetofend(struct fwdb_collection, dfs_region))
+		return false;
+
+	rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+
+	for (i = 0; i < coll->n_rules; i++) {
+		u16 rule_ptr = be16_to_cpu(rules_ptr[i]);
+
+		if (!valid_rule(data, size, rule_ptr))
+			return false;
+	}
+
+	return true;
+}
+
+static bool valid_regdb(const u8 *data, unsigned int size)
+{
+	const struct fwdb_header *hdr = (void *)data;
+	const struct fwdb_country *country;
+
+	if (size < sizeof(*hdr))
+		return false;
+
+	if (hdr->magic != cpu_to_be32(FWDB_MAGIC))
+		return false;
+
+	if (hdr->version != cpu_to_be32(FWDB_VERSION))
+		return false;
+
+	country = &hdr->country[0];
+	while ((u8 *)(country + 1) <= data + size) {
+		if (!country->coll_ptr)
+			break;
+		if (!valid_country(data, size, country))
+			return false;
+		country++;
+	}
+
+	return true;
+}
+
+static int regdb_query_country(const struct fwdb_header *db,
+			       const struct fwdb_country *country)
+{
+	unsigned int ptr = be16_to_cpu(country->coll_ptr) << 2;
+	struct fwdb_collection *coll = (void *)((u8 *)db + ptr);
+	struct ieee80211_regdomain *regdom;
+	unsigned int size_of_regd;
+	unsigned int i;
+
+	size_of_regd =
+		sizeof(struct ieee80211_regdomain) +
+		coll->n_rules * sizeof(struct ieee80211_reg_rule);
+
+	regdom = kzalloc(size_of_regd, GFP_KERNEL);
+	if (!regdom)
+		return -ENOMEM;
+
+	regdom->n_reg_rules = coll->n_rules;
+	regdom->alpha2[0] = country->alpha2[0];
+	regdom->alpha2[1] = country->alpha2[1];
+	regdom->dfs_region = coll->dfs_region;
+
+	for (i = 0; i < regdom->n_reg_rules; i++) {
+		__be16 *rules_ptr = (void *)((u8 *)coll + ALIGN(coll->len, 2));
+		unsigned int rule_ptr = be16_to_cpu(rules_ptr[i]) << 2;
+		struct fwdb_rule *rule = (void *)((u8 *)db + rule_ptr);
+		struct ieee80211_reg_rule *rrule = &regdom->reg_rules[i];
+
+		rrule->freq_range.start_freq_khz = be32_to_cpu(rule->start);
+		rrule->freq_range.end_freq_khz = be32_to_cpu(rule->end);
+		rrule->freq_range.max_bandwidth_khz = be32_to_cpu(rule->max_bw);
+
+		rrule->power_rule.max_antenna_gain = 0;
+		rrule->power_rule.max_eirp = be16_to_cpu(rule->max_eirp);
+
+		rrule->flags = 0;
+		if (rule->flags & FWDB_FLAG_NO_OFDM)
+			rrule->flags |= NL80211_RRF_NO_OFDM;
+		if (rule->flags & FWDB_FLAG_NO_OUTDOOR)
+			rrule->flags |= NL80211_RRF_NO_OUTDOOR;
+		if (rule->flags & FWDB_FLAG_DFS)
+			rrule->flags |= NL80211_RRF_DFS;
+		if (rule->flags & FWDB_FLAG_NO_IR)
+			rrule->flags |= NL80211_RRF_NO_IR;
+		if (rule->flags & FWDB_FLAG_AUTO_BW)
+			rrule->flags |= NL80211_RRF_AUTO_BW;
+
+		rrule->dfs_cac_ms = 0;
+
+		/* handle optional data */
+		if (rule->len >= offsetofend(struct fwdb_rule, cac_timeout))
+			rrule->dfs_cac_ms =
+				1000 * be16_to_cpu(rule->cac_timeout);
+	}
+
+	return reg_schedule_apply(regdom);
+}
+
+static int query_regdb(const char *alpha2)
+{
+	const struct fwdb_header *hdr = regdb;
+	const struct fwdb_country *country;
+
+	if (IS_ERR(regdb))
+		return PTR_ERR(regdb);
+
+	country = &hdr->country[0];
+	while (country->coll_ptr) {
+		if (alpha2_equal(alpha2, country->alpha2))
+			return regdb_query_country(regdb, country);
+		country++;
+	}
+
+	return -ENODATA;
+}
+
+static void regdb_fw_cb(const struct firmware *fw, void *context)
+{
+	void *db;
+
+	if (!fw) {
+		pr_info("failed to load regulatory.db\n");
+		if (fwregdb_attempts-- == 0)
+			regdb = ERR_PTR(-ENODATA);
+		goto restore;
+	}
+
+	if (!valid_regdb(fw->data, fw->size)) {
+		pr_info("loaded regulatory.db is malformed\n");
+		release_firmware(fw);
+		regdb = ERR_PTR(-EINVAL);
+		goto restore;
+	}
+
+	db = kmemdup(fw->data, fw->size, GFP_KERNEL);
+	release_firmware(fw);
+
+	if (!db)
+		goto restore;
+	regdb = db;
+
+	if (query_regdb(context))
+		goto restore;
+	goto free;
+ restore:
+	rtnl_lock();
+	restore_regulatory_settings(true);
+	rtnl_unlock();
+ free:
+	kfree(context);
+}
+
+static int query_regdb_file(const char *alpha2)
+{
+	if (regdb)
+		return query_regdb(alpha2);
+
+	alpha2 = kmemdup(alpha2, 2, GFP_KERNEL);
+	if (!alpha2)
+		return -ENOMEM;
+
+	return request_firmware_nowait(THIS_MODULE, true, "regulatory.db",
+				       &reg_pdev->dev, GFP_KERNEL,
+				       (void *)alpha2, regdb_fw_cb);
+}
+
 static bool reg_query_database(struct regulatory_request *request)
 {
 	/* query internal regulatory database (if it exists) */
 	if (reg_query_builtin(request->alpha2) == 0)
 		return true;
 
+	if (query_regdb_file(request->alpha2) == 0)
+		return true;
+
 	if (call_crda(request->alpha2) == 0)
 		return true;
 
@@ -3360,4 +3609,7 @@ void regulatory_exit(void)
 		list_del(&reg_request->list);
 		kfree(reg_request);
 	}
+
+	if (!IS_ERR_OR_NULL(regdb))
+		kfree(regdb);
 }
-- 
2.14.2

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox