From patchwork Tue Oct 2 19:32:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10624003 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A1EC51926 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 962A0285B0 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8AC48285B3; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0F560285B7 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726418AbeJCCR3 (ORCPT ); Tue, 2 Oct 2018 22:17:29 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48344 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726274AbeJCCR3 (ORCPT ); Tue, 2 Oct 2018 22:17:29 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPG-0004o0-Nt; Tue, 02 Oct 2018 21:32:30 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 1/6] backports: rename magic functions for netlink parsing Date: Tue, 2 Oct 2018 21:32:10 +0200 Message-Id: <20181002193215.399-1-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg Make all the magic variable argument calls inlines and rename them so we can override them more easily later. Signed-off-by: Johannes Berg --- backport/backport-include/net/netlink.h | 100 +++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 35 deletions(-) diff --git a/backport/backport-include/net/netlink.h b/backport/backport-include/net/netlink.h index 37c899b07b1d..7775bc8295c3 100644 --- a/backport/backport-include/net/netlink.h +++ b/backport/backport-include/net/netlink.h @@ -7,70 +7,100 @@ #if LINUX_VERSION_IS_LESS(4,12,0) #include -static inline int nla_validate5(const struct nlattr *head, - int len, int maxtype, - const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nla_validate5(const struct nlattr *head, + int len, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) { return nla_validate(head, len, maxtype, policy); } -#define nla_validate4 nla_validate +static inline int _nla_validate4(const struct nlattr *head, + int len, int maxtype, + const struct nla_policy *policy) +{ + return nla_validate(head, len, maxtype, policy); +} +#undef nla_validate #define nla_validate(...) \ - macro_dispatcher(nla_validate, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nla_validate, __VA_ARGS__)(__VA_ARGS__) -static inline int nla_parse6(struct nlattr **tb, int maxtype, - const struct nlattr *head, - int len, const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nla_parse6(struct nlattr **tb, int maxtype, + const struct nlattr *head, + int len, const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nla_parse(tb, maxtype, head, len, policy); +} +static inline int _nla_parse5(struct nlattr **tb, int maxtype, + const struct nlattr *head, + int len, const struct nla_policy *policy) { return nla_parse(tb, maxtype, head, len, policy); } -#define nla_parse5(...) nla_parse(__VA_ARGS__) #define nla_parse(...) \ - macro_dispatcher(nla_parse, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nla_parse, __VA_ARGS__)(__VA_ARGS__) -static inline int nlmsg_parse6(const struct nlmsghdr *nlh, int hdrlen, - struct nlattr *tb[], int maxtype, - const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nlmsg_parse6(const struct nlmsghdr *nlh, int hdrlen, + struct nlattr *tb[], int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy); +} +static inline int _nlmsg_parse5(const struct nlmsghdr *nlh, int hdrlen, + struct nlattr *tb[], int maxtype, + const struct nla_policy *policy) { return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy); } -#define nlmsg_parse5 nlmsg_parse #define nlmsg_parse(...) \ - macro_dispatcher(nlmsg_parse, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nlmsg_parse, __VA_ARGS__)(__VA_ARGS__) -static inline int nlmsg_validate5(const struct nlmsghdr *nlh, - int hdrlen, int maxtype, - const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nlmsg_validate5(const struct nlmsghdr *nlh, + int hdrlen, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nlmsg_validate(nlh, hdrlen, maxtype, policy); +} +static inline int _nlmsg_validate4(const struct nlmsghdr *nlh, + int hdrlen, int maxtype, + const struct nla_policy *policy) { return nlmsg_validate(nlh, hdrlen, maxtype, policy); } -#define nlmsg_validate4 nlmsg_validate #define nlmsg_validate(...) \ - macro_dispatcher(nlmsg_validate, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nlmsg_validate, __VA_ARGS__)(__VA_ARGS__) -static inline int nla_parse_nested5(struct nlattr *tb[], int maxtype, - const struct nlattr *nla, - const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nla_parse_nested5(struct nlattr *tb[], int maxtype, + const struct nlattr *nla, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nla_parse_nested(tb, maxtype, nla, policy); +} +static inline int _nla_parse_nested4(struct nlattr *tb[], int maxtype, + const struct nlattr *nla, + const struct nla_policy *policy) { return nla_parse_nested(tb, maxtype, nla, policy); } -#define nla_parse_nested4 nla_parse_nested #define nla_parse_nested(...) \ - macro_dispatcher(nla_parse_nested, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nla_parse_nested, __VA_ARGS__)(__VA_ARGS__) -static inline int nla_validate_nested4(const struct nlattr *start, int maxtype, - const struct nla_policy *policy, - struct netlink_ext_ack *extack) +static inline int _nla_validate_nested4(const struct nlattr *start, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nla_validate_nested(start, maxtype, policy); +} +static inline int _nla_validate_nested3(const struct nlattr *start, int maxtype, + const struct nla_policy *policy) { return nla_validate_nested(start, maxtype, policy); } -#define nla_validate_nested3 nla_validate_nested #define nla_validate_nested(...) \ - macro_dispatcher(nla_validate_nested, __VA_ARGS__)(__VA_ARGS__) + macro_dispatcher(_nla_validate_nested, __VA_ARGS__)(__VA_ARGS__) #endif /* LINUX_VERSION_IS_LESS(4,12,0) */ #if LINUX_VERSION_IS_LESS(3,7,0) From patchwork Tue Oct 2 19:32:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10623999 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 3B81F14BD for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 283BA285B0 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1BE6D285BD; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BED33285B0 for ; Tue, 2 Oct 2018 19:32:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726647AbeJCCR2 (ORCPT ); Tue, 2 Oct 2018 22:17:28 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48348 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726365AbeJCCR2 (ORCPT ); Tue, 2 Oct 2018 22:17:28 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPH-0004o0-5R; Tue, 02 Oct 2018 21:32:31 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 2/6] backports: fix genlmsg_nlhdr() backport Date: Tue, 2 Oct 2018 21:32:11 +0200 Message-Id: <20181002193215.399-2-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20181002193215.399-1-johannes@sipsolutions.net> References: <20181002193215.399-1-johannes@sipsolutions.net> Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg Since 4.15 this no longer takes a family argument, so add that to the backports instead of trying to work around the family argument having changed type. Signed-off-by: Johannes Berg --- backport/backport-include/net/genetlink.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/backport/backport-include/net/genetlink.h b/backport/backport-include/net/genetlink.h index dfbacbf40723..d80d979ac423 100644 --- a/backport/backport-include/net/genetlink.h +++ b/backport/backport-include/net/genetlink.h @@ -60,6 +60,14 @@ static inline void *genl_info_userhdr(struct genl_info *info) #endif #if LINUX_VERSION_IS_LESS(4,15,0) +#define genlmsg_nlhdr LINUX_BACKPORT(genlmsg_nlhdr) +static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr) +{ + return (struct nlmsghdr *)((char *)user_hdr - + GENL_HDRLEN - + NLMSG_HDRLEN); +} + #ifndef genl_dump_check_consistent static inline void backport_genl_dump_check_consistent(struct netlink_callback *cb, @@ -153,8 +161,6 @@ extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, (_fam)->mcgrps[_group].id, _info->nlhdr, _flags) #define genlmsg_put(_skb, _pid, _seq, _fam, _flags, _cmd) \ genlmsg_put(_skb, _pid, _seq, &(_fam)->family, _flags, _cmd) -#define genlmsg_nlhdr(_hdr, _fam) \ - genlmsg_nlhdr(_hdr, &(_fam)->family) #ifndef genlmsg_put_reply /* might already be there from _info override above */ #define genlmsg_put_reply(_skb, _info, _fam, _flags, _cmd) \ From patchwork Tue Oct 2 19:32:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10624001 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6893615E8 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5D64B285B0 for ; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 52510285B6; Tue, 2 Oct 2018 19:32:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E2210285B3 for ; Tue, 2 Oct 2018 19:32:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726649AbeJCCR3 (ORCPT ); Tue, 2 Oct 2018 22:17:29 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48352 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726418AbeJCCR2 (ORCPT ); Tue, 2 Oct 2018 22:17:28 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPH-0004o0-Jv; Tue, 02 Oct 2018 21:32:31 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 3/6] backports: add copy-list.hwsim Date: Tue, 2 Oct 2018 21:32:12 +0200 Message-Id: <20181002193215.399-3-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20181002193215.399-1-johannes@sipsolutions.net> References: <20181002193215.399-1-johannes@sipsolutions.net> Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg This is can be useful for minimal testing. Signed-off-by: Johannes Berg --- copy-list.hwsim | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 copy-list.hwsim diff --git a/copy-list.hwsim b/copy-list.hwsim new file mode 100644 index 000000000000..c56f0bcb915c --- /dev/null +++ b/copy-list.hwsim @@ -0,0 +1,91 @@ +# +# This file specifies which sources are copied from the kernel +# into the backports package. +# +# Directories must end with a slash (e.g. "net/wireless/") and +# are then copied with all their contents. +# +# It is also possible to rename while copying, to do so list +# old name -> new name +# Note that in this case the spaces are needed: " -> " +# + +COPYING +MAINTAINERS +include/linux/unaligned/ +include/linux/hashtable.h +include/linux/fixp-arith.h +include/linux/crc32poly.h + +# This just defines some macros, simply take it +include/linux/bitfield.h +include/linux/average.h +include/linux/overflow.h + +# crypto_memneq +crypto/memneq.c -> compat/memneq.c + +# 802.11 +drivers/net/wireless/Kconfig +drivers/net/wireless/Makefile + +include/linux/wireless.h +include/uapi/linux/wireless.h +include/linux/ieee80211.h +include/linux/pci_ids.h +include/uapi/linux/pci_regs.h +include/linux/mmc/sdio_ids.h +include/linux/ath9k_platform.h +include/linux/wl12xx.h +include/linux/rndis.h +include/linux/bcm47xx_wdt.h +include/linux/usb/usbnet.h +include/linux/usb/cdc.h +include/uapi/linux/usb/cdc.h +include/uapi/linux/usb/cdc-wdm.h +include/linux/usb/cdc_ncm.h +include/linux/usb/cdc-wdm.h +include/linux/usb/rndis_host.h +include/linux/spi/libertas_spi.h +include/linux/platform_data/brcmfmac.h +include/linux/platform_data/net-cw1200.h +include/uapi/linux/nl80211.h +include/net/rsi_91x.h + +include/net/cfg80211.h +include/net/cfg80211-wext.h +include/net/ieee80211_radiotap.h +include/net/lib80211.h +include/net/mac80211.h +include/net/regulatory.h +include/net/codel.h +include/net/codel_impl.h +include/net/codel_qdisc.h +include/net/fq.h +include/net/fq_impl.h + +# signature verification code +include/linux/asn1.h +include/linux/asn1_ber_bytecode.h +include/linux/oid_registry.h +lib/build_OID_registry -> compat/build_OID_registry +crypto/asymmetric_keys/pkcs7_parser.c -> compat/verification/pkcs7_parser.c +crypto/asymmetric_keys/pkcs7_parser.h -> compat/verification/pkcs7_parser.h +crypto/asymmetric_keys/pkcs7_trust.c -> compat/verification/pkcs7_trust.c +crypto/asymmetric_keys/pkcs7_verify.c -> compat/verification/pkcs7_verify.c +crypto/asymmetric_keys/x509_cert_parser.c -> compat/verification/x509_cert_parser.c +crypto/asymmetric_keys/x509_parser.h -> compat/verification/x509_parser.h +crypto/asymmetric_keys/x509_public_key.c -> compat/verification/x509_public_key.c + +net/Makefile +net/Kconfig +net/wireless/ +net/mac80211/ +# MPLS labels, checked on skb->protocol on the +# respective 802 family, only ethernet seems to use +# this right now, see 960d97f95 +include/linux/mpls.h +include/uapi/linux/mpls.h + +drivers/net/wireless/mac80211_hwsim.c +drivers/net/wireless/mac80211_hwsim.h From patchwork Tue Oct 2 19:32:13 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10624007 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 2BE6E15E8 for ; Tue, 2 Oct 2018 19:32:38 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F0EC285B0 for ; Tue, 2 Oct 2018 19:32:38 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 131B3285B6; Tue, 2 Oct 2018 19:32:38 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D99E4285B0 for ; Tue, 2 Oct 2018 19:32:36 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726365AbeJCCRc (ORCPT ); Tue, 2 Oct 2018 22:17:32 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48356 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726503AbeJCCRb (ORCPT ); Tue, 2 Oct 2018 22:17:31 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPI-0004o0-20; Tue, 02 Oct 2018 21:32:32 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 4/6] backports: backport most of improved netlink policy validation Date: Tue, 2 Oct 2018 21:32:13 +0200 Message-Id: <20181002193215.399-4-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20181002193215.399-1-johannes@sipsolutions.net> References: <20181002193215.399-1-johannes@sipsolutions.net> Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg Signed-off-by: Johannes Berg --- backport/backport-include/linux/netlink.h | 19 ++ backport/backport-include/net/netlink.h | 185 ++++++++++++++- backport/compat/Makefile | 1 + backport/compat/backport-4.20.c | 379 ++++++++++++++++++++++++++++++ 4 files changed, 572 insertions(+), 12 deletions(-) create mode 100644 backport/compat/backport-4.20.c diff --git a/backport/backport-include/linux/netlink.h b/backport/backport-include/linux/netlink.h index 468a12d15dbe..366c9e27e8c2 100644 --- a/backport/backport-include/linux/netlink.h +++ b/backport/backport-include/linux/netlink.h @@ -3,6 +3,13 @@ #include_next #include +#if LINUX_VERSION_IS_LESS(4,14,0) +struct nla_bitfield32 { + __u32 value; + __u32 selector; +}; +#endif + #if LINUX_VERSION_IS_LESS(4,12,0) #define NETLINK_MAX_COOKIE_LEN 20 @@ -23,6 +30,18 @@ struct netlink_ext_ack { } while (0) #endif +#ifndef NL_SET_ERR_MSG_ATTR +#define NL_SET_ERR_MSG_ATTR(extack, attr, msg) do { \ + static const char __msg[] = msg; \ + struct netlink_ext_ack *__extack = (extack); \ + \ + if (__extack) { \ + __extack->_msg = __msg; \ + __extack->bad_attr = (attr); \ + } \ +} while (0) +#endif + /* this is for patches we apply */ #if LINUX_VERSION_IS_LESS(3,7,0) #define netlink_notify_portid(__notify) (__notify->pid) diff --git a/backport/backport-include/net/netlink.h b/backport/backport-include/net/netlink.h index 7775bc8295c3..4af73631115e 100644 --- a/backport/backport-include/net/netlink.h +++ b/backport/backport-include/net/netlink.h @@ -4,6 +4,162 @@ #include #include +#if LINUX_VERSION_IS_LESS(4,20,0) +/* can't backport using the enum - need to override */ +#define NLA_UNSPEC 0 +#define NLA_U8 1 +#define NLA_U16 2 +#define NLA_U32 3 +#define NLA_U64 4 +#define NLA_STRING 5 +#define NLA_FLAG 6 +#define NLA_MSECS 7 +#define NLA_NESTED 8 +#define NLA_NESTED_ARRAY 9 +#define NLA_NUL_STRING 10 +#define NLA_BINARY 11 +#define NLA_S8 12 +#define NLA_S16 13 +#define NLA_S32 14 +#define NLA_S64 15 +#define NLA_BITFIELD32 16 +#define NLA_REJECT 17 +#define NLA_EXACT_LEN 18 +#define NLA_EXACT_LEN_WARN 19 +#define __NLA_TYPE_MAX 20 +#define NLA_TYPE_MAX (__NLA_TYPE_MAX - 1) + +enum nla_policy_validation { + NLA_VALIDATE_NONE, + NLA_VALIDATE_RANGE, + NLA_VALIDATE_MIN, + NLA_VALIDATE_MAX, + NLA_VALIDATE_FUNCTION, +}; + +struct backport_nla_policy { + u8 type; + u8 validation_type; + u16 len; + union { + const void *validation_data; + struct { + s16 min, max; + }; + int (*validate)(const struct nlattr *attr, + struct netlink_ext_ack *extack); + }; +}; +#define nla_policy backport_nla_policy + +#define NLA_POLICY_EXACT_LEN(_len) { .type = NLA_EXACT_LEN, .len = _len } +#define NLA_POLICY_EXACT_LEN_WARN(_len) { .type = NLA_EXACT_LEN_WARN, \ + .len = _len } + +#define NLA_POLICY_ETH_ADDR NLA_POLICY_EXACT_LEN(ETH_ALEN) +#define NLA_POLICY_ETH_ADDR_COMPAT NLA_POLICY_EXACT_LEN_WARN(ETH_ALEN) + +#define NLA_POLICY_NESTED(maxattr, policy) \ + { .type = NLA_NESTED, .validation_data = policy, .len = maxattr } +#define NLA_POLICY_NESTED_ARRAY(maxattr, policy) \ + { .type = NLA_NESTED_ARRAY, .validation_data = policy, .len = maxattr } + +#define __NLA_ENSURE(condition) (sizeof(char[1 - 2*!(condition)]) - 1) +#define NLA_ENSURE_INT_TYPE(tp) \ + (__NLA_ENSURE(tp == NLA_S8 || tp == NLA_U8 || \ + tp == NLA_S16 || tp == NLA_U16 || \ + tp == NLA_S32 || tp == NLA_U32 || \ + tp == NLA_S64 || tp == NLA_U64) + tp) +#define NLA_ENSURE_NO_VALIDATION_PTR(tp) \ + (__NLA_ENSURE(tp != NLA_BITFIELD32 && \ + tp != NLA_REJECT && \ + tp != NLA_NESTED && \ + tp != NLA_NESTED_ARRAY) + tp) + +#define NLA_POLICY_RANGE(tp, _min, _max) { \ + .type = NLA_ENSURE_INT_TYPE(tp), \ + .validation_type = NLA_VALIDATE_RANGE, \ + .min = _min, \ + .max = _max \ +} + +#define NLA_POLICY_MIN(tp, _min) { \ + .type = NLA_ENSURE_INT_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MIN, \ + .min = _min, \ +} + +#define NLA_POLICY_MAX(tp, _max) { \ + .type = NLA_ENSURE_INT_TYPE(tp), \ + .validation_type = NLA_VALIDATE_MAX, \ + .max = _max, \ +} + +#define NLA_POLICY_VALIDATE_FN(tp, fn, ...) { \ + .type = NLA_ENSURE_NO_VALIDATION_PTR(tp), \ + .validation_type = NLA_VALIDATE_FUNCTION, \ + .validate = fn, \ + .len = __VA_ARGS__ + 0, \ +} + +#define nla_validate LINUX_BACKPORT(nla_validate) +int nla_validate(const struct nlattr *head, int len, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack); +#define nla_parse LINUX_BACKPORT(nla_parse) +int nla_parse(struct nlattr **tb, int maxtype, const struct nlattr *head, + int len, const struct nla_policy *policy, + struct netlink_ext_ack *extack); +#define nla_policy_len LINUX_BACKPORT(nla_policy_len) +int nla_policy_len(const struct nla_policy *, int); + +#define nlmsg_parse LINUX_BACKPORT(nlmsg_parse) +static inline int nlmsg_parse(const struct nlmsghdr *nlh, int hdrlen, + struct nlattr *tb[], int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) + return -EINVAL; + + return nla_parse(tb, maxtype, nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), policy, extack); +} + +#define nlmsg_validate LINUX_BACKPORT(nlmsg_validate) +static inline int nlmsg_validate(const struct nlmsghdr *nlh, + int hdrlen, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen)) + return -EINVAL; + + return nla_validate(nlmsg_attrdata(nlh, hdrlen), + nlmsg_attrlen(nlh, hdrlen), maxtype, policy, + extack); +} + +#define nla_parse_nested LINUX_BACKPORT(nla_parse_nested) +static inline int nla_parse_nested(struct nlattr *tb[], int maxtype, + const struct nlattr *nla, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nla_parse(tb, maxtype, nla_data(nla), nla_len(nla), policy, + extack); +} + +#define nla_validate_nested LINUX_BACKPORT(nla_validate_nested) +static inline int nla_validate_nested(const struct nlattr *start, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + return nla_validate(nla_data(start), nla_len(start), maxtype, policy, + extack); +} +#endif /* < 4.20 */ + #if LINUX_VERSION_IS_LESS(4,12,0) #include @@ -12,13 +168,13 @@ static inline int _nla_validate5(const struct nlattr *head, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nla_validate(head, len, maxtype, policy); + return nla_validate(head, len, maxtype, policy, extack); } static inline int _nla_validate4(const struct nlattr *head, int len, int maxtype, const struct nla_policy *policy) { - return nla_validate(head, len, maxtype, policy); + return nla_validate(head, len, maxtype, policy, NULL); } #undef nla_validate #define nla_validate(...) \ @@ -29,14 +185,15 @@ static inline int _nla_parse6(struct nlattr **tb, int maxtype, int len, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nla_parse(tb, maxtype, head, len, policy); + return nla_parse(tb, maxtype, head, len, policy, extack); } static inline int _nla_parse5(struct nlattr **tb, int maxtype, const struct nlattr *head, int len, const struct nla_policy *policy) { - return nla_parse(tb, maxtype, head, len, policy); + return nla_parse(tb, maxtype, head, len, policy, NULL); } +#undef nla_parse #define nla_parse(...) \ macro_dispatcher(_nla_parse, __VA_ARGS__)(__VA_ARGS__) @@ -45,14 +202,15 @@ static inline int _nlmsg_parse6(const struct nlmsghdr *nlh, int hdrlen, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy); + return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy, extack); } static inline int _nlmsg_parse5(const struct nlmsghdr *nlh, int hdrlen, struct nlattr *tb[], int maxtype, const struct nla_policy *policy) { - return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy); + return nlmsg_parse(nlh, hdrlen, tb, maxtype, policy, NULL); } +#undef nlmsg_parse #define nlmsg_parse(...) \ macro_dispatcher(_nlmsg_parse, __VA_ARGS__)(__VA_ARGS__) @@ -61,14 +219,15 @@ static inline int _nlmsg_validate5(const struct nlmsghdr *nlh, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nlmsg_validate(nlh, hdrlen, maxtype, policy); + return nlmsg_validate(nlh, hdrlen, maxtype, policy, extack); } static inline int _nlmsg_validate4(const struct nlmsghdr *nlh, int hdrlen, int maxtype, const struct nla_policy *policy) { - return nlmsg_validate(nlh, hdrlen, maxtype, policy); + return nlmsg_validate(nlh, hdrlen, maxtype, policy, NULL); } +#undef nlmsg_validate #define nlmsg_validate(...) \ macro_dispatcher(_nlmsg_validate, __VA_ARGS__)(__VA_ARGS__) @@ -77,14 +236,15 @@ static inline int _nla_parse_nested5(struct nlattr *tb[], int maxtype, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nla_parse_nested(tb, maxtype, nla, policy); + return nla_parse_nested(tb, maxtype, nla, policy, extack); } static inline int _nla_parse_nested4(struct nlattr *tb[], int maxtype, const struct nlattr *nla, const struct nla_policy *policy) { - return nla_parse_nested(tb, maxtype, nla, policy); + return nla_parse_nested(tb, maxtype, nla, policy, NULL); } +#undef nla_parse_nested #define nla_parse_nested(...) \ macro_dispatcher(_nla_parse_nested, __VA_ARGS__)(__VA_ARGS__) @@ -92,13 +252,14 @@ static inline int _nla_validate_nested4(const struct nlattr *start, int maxtype, const struct nla_policy *policy, struct netlink_ext_ack *extack) { - return nla_validate_nested(start, maxtype, policy); + return nla_validate_nested(start, maxtype, policy, extack); } static inline int _nla_validate_nested3(const struct nlattr *start, int maxtype, const struct nla_policy *policy) { - return nla_validate_nested(start, maxtype, policy); + return nla_validate_nested(start, maxtype, policy, NULL); } +#undef nla_validate_nested #define nla_validate_nested(...) \ macro_dispatcher(_nla_validate_nested, __VA_ARGS__)(__VA_ARGS__) #endif /* LINUX_VERSION_IS_LESS(4,12,0) */ diff --git a/backport/compat/Makefile b/backport/compat/Makefile index f5b1886e2d8e..ff6c7e658380 100644 --- a/backport/compat/Makefile +++ b/backport/compat/Makefile @@ -38,6 +38,7 @@ compat-$(CPTCFG_KERNEL_4_8) += backport-4.8.o compat-$(CPTCFG_KERNEL_4_10) += backport-4.10.o compat-$(CPTCFG_KERNEL_4_12) += backport-4.12.o compat-$(CPTCFG_KERNEL_4_18) += backport-4.18.o +compat-$(CPTCFG_KERNEL_4_20) += backport-4.20.o compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o diff --git a/backport/compat/backport-4.20.c b/backport/compat/backport-4.20.c new file mode 100644 index 000000000000..e26f3b52fbbe --- /dev/null +++ b/backport/compat/backport-4.20.c @@ -0,0 +1,379 @@ +/* + * Copyright (C) 2018 Intel Corporation + * + * Backport functionality introduced in Linux 4.20. + * This is basically upstream lib/nlattr.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include + +static const u8 nla_attr_len[NLA_TYPE_MAX+1] = { + [NLA_U8] = sizeof(u8), + [NLA_U16] = sizeof(u16), + [NLA_U32] = sizeof(u32), + [NLA_U64] = sizeof(u64), + [NLA_S8] = sizeof(s8), + [NLA_S16] = sizeof(s16), + [NLA_S32] = sizeof(s32), + [NLA_S64] = sizeof(s64), +}; + +static const u8 nla_attr_minlen[NLA_TYPE_MAX+1] = { + [NLA_U8] = sizeof(u8), + [NLA_U16] = sizeof(u16), + [NLA_U32] = sizeof(u32), + [NLA_U64] = sizeof(u64), + [NLA_MSECS] = sizeof(u64), + [NLA_NESTED] = NLA_HDRLEN, + [NLA_S8] = sizeof(s8), + [NLA_S16] = sizeof(s16), + [NLA_S32] = sizeof(s32), + [NLA_S64] = sizeof(s64), +}; + +static int validate_nla_bitfield32(const struct nlattr *nla, + const u32 *valid_flags_mask) +{ + const struct nla_bitfield32 *bf = nla_data(nla); + + if (!valid_flags_mask) + return -EINVAL; + + /*disallow invalid bit selector */ + if (bf->selector & ~*valid_flags_mask) + return -EINVAL; + + /*disallow invalid bit values */ + if (bf->value & ~*valid_flags_mask) + return -EINVAL; + + /*disallow valid bit values that are not selected*/ + if (bf->value & ~bf->selector) + return -EINVAL; + + return 0; +} + +static int nla_validate_array(const struct nlattr *head, int len, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + const struct nlattr *entry; + int rem; + + nla_for_each_attr(entry, head, len, rem) { + int ret; + + if (nla_len(entry) == 0) + continue; + + if (nla_len(entry) < NLA_HDRLEN) { + NL_SET_ERR_MSG_ATTR(extack, entry, + "Array element too short"); + return -ERANGE; + } + + ret = nla_validate(nla_data(entry), nla_len(entry), + maxtype, policy, extack); + if (ret < 0) + return ret; + } + + return 0; +} + +static int nla_validate_int_range(const struct nla_policy *pt, + const struct nlattr *nla, + struct netlink_ext_ack *extack) +{ + bool validate_min, validate_max; + s64 value; + + validate_min = pt->validation_type == NLA_VALIDATE_RANGE || + pt->validation_type == NLA_VALIDATE_MIN; + validate_max = pt->validation_type == NLA_VALIDATE_RANGE || + pt->validation_type == NLA_VALIDATE_MAX; + + switch (pt->type) { + case NLA_U8: + value = nla_get_u8(nla); + break; + case NLA_U16: + value = nla_get_u16(nla); + break; + case NLA_U32: + value = nla_get_u32(nla); + break; + case NLA_S8: + value = nla_get_s8(nla); + break; + case NLA_S16: + value = nla_get_s16(nla); + break; + case NLA_S32: + value = nla_get_s32(nla); + break; + case NLA_S64: + value = nla_get_s64(nla); + break; + case NLA_U64: + /* treat this one specially, since it may not fit into s64 */ + if ((validate_min && nla_get_u64(nla) < pt->min) || + (validate_max && nla_get_u64(nla) > pt->max)) { + NL_SET_ERR_MSG_ATTR(extack, nla, + "integer out of range"); + return -ERANGE; + } + return 0; + default: + WARN_ON(1); + return -EINVAL; + } + + if ((validate_min && value < pt->min) || + (validate_max && value > pt->max)) { + NL_SET_ERR_MSG_ATTR(extack, nla, + "integer out of range"); + return -ERANGE; + } + + return 0; +} + +static int validate_nla(const struct nlattr *nla, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + const struct nla_policy *pt; + int minlen = 0, attrlen = nla_len(nla), type = nla_type(nla); + int err = -ERANGE; + + if (type <= 0 || type > maxtype) + return 0; + + pt = &policy[type]; + + BUG_ON(pt->type > NLA_TYPE_MAX); + + if ((nla_attr_len[pt->type] && attrlen != nla_attr_len[pt->type]) || + (pt->type == NLA_EXACT_LEN_WARN && attrlen != pt->len)) { + pr_warn_ratelimited("netlink: '%s': attribute type %d has an invalid length.\n", + current->comm, type); + } + + switch (pt->type) { + case NLA_EXACT_LEN: + if (attrlen != pt->len) + goto out_err; + break; + + case NLA_REJECT: + if (extack && pt->validation_data) { + NL_SET_BAD_ATTR(extack, nla); + extack->_msg = pt->validation_data; + return -EINVAL; + } + err = -EINVAL; + goto out_err; + + case NLA_FLAG: + if (attrlen > 0) + goto out_err; + break; + + case NLA_BITFIELD32: + if (attrlen != sizeof(struct nla_bitfield32)) + goto out_err; + + err = validate_nla_bitfield32(nla, pt->validation_data); + if (err) + goto out_err; + break; + + case NLA_NUL_STRING: + if (pt->len) + minlen = min_t(int, attrlen, pt->len + 1); + else + minlen = attrlen; + + if (!minlen || memchr(nla_data(nla), '\0', minlen) == NULL) { + err = -EINVAL; + goto out_err; + } + /* fall through */ + + case NLA_STRING: + if (attrlen < 1) + goto out_err; + + if (pt->len) { + char *buf = nla_data(nla); + + if (buf[attrlen - 1] == '\0') + attrlen--; + + if (attrlen > pt->len) + goto out_err; + } + break; + + case NLA_BINARY: + if (pt->len && attrlen > pt->len) + goto out_err; + break; + + case NLA_NESTED: + /* a nested attributes is allowed to be empty; if its not, + * it must have a size of at least NLA_HDRLEN. + */ + if (attrlen == 0) + break; + if (attrlen < NLA_HDRLEN) + goto out_err; + if (pt->validation_data) { + err = nla_validate(nla_data(nla), nla_len(nla), pt->len, + pt->validation_data, extack); + if (err < 0) { + /* + * return directly to preserve the inner + * error message/attribute pointer + */ + return err; + } + } + break; + case NLA_NESTED_ARRAY: + /* a nested array attribute is allowed to be empty; if its not, + * it must have a size of at least NLA_HDRLEN. + */ + if (attrlen == 0) + break; + if (attrlen < NLA_HDRLEN) + goto out_err; + if (pt->validation_data) { + int err; + + err = nla_validate_array(nla_data(nla), nla_len(nla), + pt->len, pt->validation_data, + extack); + if (err < 0) { + /* + * return directly to preserve the inner + * error message/attribute pointer + */ + return err; + } + } + break; + default: + if (pt->len) + minlen = pt->len; + else if (pt->type != NLA_UNSPEC) + minlen = nla_attr_minlen[pt->type]; + + if (attrlen < minlen) + goto out_err; + } + + /* further validation */ + switch (pt->validation_type) { + case NLA_VALIDATE_NONE: + /* nothing to do */ + break; + case NLA_VALIDATE_RANGE: + case NLA_VALIDATE_MIN: + case NLA_VALIDATE_MAX: + err = nla_validate_int_range(pt, nla, extack); + if (err) + return err; + break; + case NLA_VALIDATE_FUNCTION: + if (pt->validate) { + err = pt->validate(nla, extack); + if (err) + return err; + } + break; + } + + return 0; +out_err: + NL_SET_ERR_MSG_ATTR(extack, nla, "Attribute failed policy validation"); + return err; +} + +int backport_nla_validate(const struct nlattr *head, int len, int maxtype, + const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + const struct nlattr *nla; + int rem; + + nla_for_each_attr(nla, head, len, rem) { + int err = validate_nla(nla, maxtype, policy, extack); + + if (err < 0) + return err; + } + + return 0; +} +EXPORT_SYMBOL_GPL(backport_nla_validate); + +int backport_nla_policy_len(const struct nla_policy *p, int n) +{ + int i, len = 0; + + for (i = 0; i < n; i++, p++) { + if (p->len) + len += nla_total_size(p->len); + else if (nla_attr_len[p->type]) + len += nla_total_size(nla_attr_len[p->type]); + else if (nla_attr_minlen[p->type]) + len += nla_total_size(nla_attr_minlen[p->type]); + } + + return len; +} +EXPORT_SYMBOL_GPL(backport_nla_policy_len); + +int backport_nla_parse(struct nlattr **tb, int maxtype, + const struct nlattr *head, + int len, const struct nla_policy *policy, + struct netlink_ext_ack *extack) +{ + const struct nlattr *nla; + int rem; + + memset(tb, 0, sizeof(struct nlattr *) * (maxtype + 1)); + + nla_for_each_attr(nla, head, len, rem) { + u16 type = nla_type(nla); + + if (type > 0 && type <= maxtype) { + if (policy) { + int err = validate_nla(nla, maxtype, policy, + extack); + + if (err < 0) + return err; + } + + tb[type] = (struct nlattr *)nla; + } + } + + if (unlikely(rem > 0)) + pr_warn_ratelimited("netlink: %d bytes leftover after parsing attributes in process `%s'.\n", + rem, current->comm); + + return 0; +} +EXPORT_SYMBOL(backport_nla_parse); From patchwork Tue Oct 2 19:32:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10624005 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7EE1015E8 for ; Tue, 2 Oct 2018 19:32:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 73C0E285B0 for ; Tue, 2 Oct 2018 19:32:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6877C285B6; Tue, 2 Oct 2018 19:32:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 23DC7285B0 for ; Tue, 2 Oct 2018 19:32:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726695AbeJCCRa (ORCPT ); Tue, 2 Oct 2018 22:17:30 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48360 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726365AbeJCCRa (ORCPT ); Tue, 2 Oct 2018 22:17:30 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPI-0004o0-HN; Tue, 02 Oct 2018 21:32:32 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 5/6] backports: add __skb_peek() Date: Tue, 2 Oct 2018 21:32:14 +0200 Message-Id: <20181002193215.399-5-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20181002193215.399-1-johannes@sipsolutions.net> References: <20181002193215.399-1-johannes@sipsolutions.net> Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg New API slated to show up in 4.20. Signed-off-by: Johannes Berg --- backport/backport-include/linux/skbuff.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/backport/backport-include/linux/skbuff.h b/backport/backport-include/linux/skbuff.h index 61133c4277cc..44b2a5de0478 100644 --- a/backport/backport-include/linux/skbuff.h +++ b/backport/backport-include/linux/skbuff.h @@ -382,4 +382,11 @@ static inline void skb_put_u8(struct sk_buff *skb, u8 val) } #endif +#if LINUX_VERSION_IS_LESS(4,20,0) +static inline struct sk_buff *__skb_peek(const struct sk_buff_head *list_) +{ + return list_->next; +} +#endif + #endif /* __BACKPORT_SKBUFF_H */ From patchwork Tue Oct 2 19:32:15 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Johannes Berg X-Patchwork-Id: 10624009 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 9163714BD for ; Tue, 2 Oct 2018 19:32:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 7E489285B0 for ; Tue, 2 Oct 2018 19:32:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 7289B285B6; Tue, 2 Oct 2018 19:32:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E84BC285B0 for ; Tue, 2 Oct 2018 19:32:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726503AbeJCCRf (ORCPT ); Tue, 2 Oct 2018 22:17:35 -0400 Received: from s3.sipsolutions.net ([144.76.43.62]:48364 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726274AbeJCCRe (ORCPT ); Tue, 2 Oct 2018 22:17:34 -0400 Received: by sipsolutions.net with esmtpsa (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.91) (envelope-from ) id 1g7QPI-0004o0-VC; Tue, 02 Oct 2018 21:32:33 +0200 From: Johannes Berg To: backports@vger.kernel.org Cc: Johannes Berg Subject: [PATCH v2 6/6] backports: genetlink: update completely Date: Tue, 2 Oct 2018 21:32:15 +0200 Message-Id: <20181002193215.399-6-johannes@sipsolutions.net> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20181002193215.399-1-johannes@sipsolutions.net> References: <20181002193215.399-1-johannes@sipsolutions.net> Sender: backports-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: backports@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Johannes Berg Replace all the different nested versions of generic netlink backport with a single one, covering from < 3.13 all the way to the upcoming netlink policy improvements in 4.20. Signed-off-by: Johannes Berg --- backport/backport-include/linux/netlink.h | 2 +- backport/backport-include/net/genetlink.h | 238 ++++++----------- backport/compat/Makefile | 3 +- backport/compat/backport-3.13.c | 66 ----- backport/compat/backport-4.12.c | 274 ------------------- backport/compat/backport-genetlink.c | 429 ++++++++++++++++++++++++++++++ backport/compat/compat-3.3.c | 13 - 7 files changed, 513 insertions(+), 512 deletions(-) delete mode 100644 backport/compat/backport-4.12.c create mode 100644 backport/compat/backport-genetlink.c diff --git a/backport/backport-include/linux/netlink.h b/backport/backport-include/linux/netlink.h index 366c9e27e8c2..f956a76966f3 100644 --- a/backport/backport-include/linux/netlink.h +++ b/backport/backport-include/linux/netlink.h @@ -20,7 +20,7 @@ struct netlink_ext_ack { u8 cookie_len; /* backport only field */ - void *__bp_genl_real_ops; + void *__bp_doit; }; #define NL_SET_ERR_MSG(extack, msg) do { \ diff --git a/backport/backport-include/net/genetlink.h b/backport/backport-include/net/genetlink.h index d80d979ac423..84011e72644e 100644 --- a/backport/backport-include/net/genetlink.h +++ b/backport/backport-include/net/genetlink.h @@ -15,18 +15,14 @@ static inline void *__bp_genl_info_userhdr(struct genl_info *info) } #if LINUX_VERSION_IS_LESS(4,12,0) -#define GENL_SET_ERR_MSG(info, msg) do { } while (0) +#define GENL_SET_ERR_MSG(info, msg) NL_SET_ERR_MSG(genl_info_extack(info), msg) static inline int genl_err_attr(struct genl_info *info, int err, struct nlattr *attr) { -#if LINUX_VERSION_IS_GEQ(4,12,0) - info->extack->bad_attr = attr; -#endif - return err; } -#endif +#endif /* < 4.12 */ /* this is for patches we apply */ static inline struct netlink_ext_ack *genl_info_extack(struct genl_info *info) @@ -51,12 +47,24 @@ static inline void *genl_info_userhdr(struct genl_info *info) #define genl_info_snd_portid(__genl_info) (__genl_info->snd_portid) #endif +#if LINUX_VERSION_IS_LESS(3,13,0) +#define __genl_const +#else /* < 3.13 */ +#define __genl_const const +#endif /* < 3.13 */ + #ifndef GENLMSG_DEFAULT_SIZE #define GENLMSG_DEFAULT_SIZE (NLMSG_DEFAULT_SIZE - GENL_HDRLEN) #endif #if LINUX_VERSION_IS_LESS(3,1,0) -#define genl_dump_check_consistent(cb, user_hdr) +#define genl_dump_check_consistent(cb, user_hdr) do { } while (0) +#endif + +#if LINUX_VERSION_IS_LESS(4,10,0) +#define __genl_ro_after_init +#else +#define __genl_ro_after_init __ro_after_init #endif #if LINUX_VERSION_IS_LESS(4,15,0) @@ -83,148 +91,87 @@ void backport_genl_dump_check_consistent(struct netlink_callback *cb, #endif #endif /* LINUX_VERSION_IS_LESS(4,15,0) */ -#if LINUX_VERSION_IS_LESS(3,13,0) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) -static inline int __real_genl_register_family(struct genl_family *family) +#if LINUX_VERSION_IS_LESS(4,20,0) +static inline int +__real_backport_genl_register_family(struct genl_family *family) { return genl_register_family(family); } - -/* Needed for the mcgrps pointer */ -struct backport_genl_family { - struct genl_family family; - - unsigned int id, hdrsize, version, maxattr; - char name[GENL_NAMSIZ]; - bool netnsok; - bool parallel_ops; - - struct nlattr **attrbuf; - - int (*pre_doit)(struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); - - void (*post_doit)(struct genl_ops *ops, struct sk_buff *skb, - struct genl_info *info); - - struct genl_multicast_group *mcgrps; - struct genl_ops *ops; - unsigned int n_mcgrps, n_ops; - - struct module *module; -}; -#define genl_family LINUX_BACKPORT(genl_family) - -int __backport_genl_register_family(struct genl_family *family); - -#define genl_register_family LINUX_BACKPORT(genl_register_family) static inline int -genl_register_family(struct genl_family *family) +__real_backport_genl_unregister_family(struct genl_family *family) { - family->module = THIS_MODULE; - return __backport_genl_register_family(family); + return genl_unregister_family(family); } -#define _genl_register_family_with_ops_grps \ - _backport_genl_register_family_with_ops_grps -static inline int -_genl_register_family_with_ops_grps(struct genl_family *family, - struct genl_ops *ops, size_t n_ops, - struct genl_multicast_group *mcgrps, - size_t n_mcgrps) -{ - family->ops = ops; - family->n_ops = n_ops; - family->mcgrps = mcgrps; - family->n_mcgrps = n_mcgrps; - return genl_register_family(family); -} +struct backport_genl_family { + struct genl_family family; + const struct genl_ops * copy_ops; + + /* copied */ + int id; /* private */ + unsigned int hdrsize; + char name[GENL_NAMSIZ]; + unsigned int version; + unsigned int maxattr; + bool netnsok; + bool parallel_ops; + int (*pre_doit)(__genl_const struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info); + void (*post_doit)(__genl_const struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info); +/* + * unsupported! + int (*mcast_bind)(struct net *net, int group); + void (*mcast_unbind)(struct net *net, int group); + */ + struct nlattr ** attrbuf; /* private */ + __genl_const struct genl_ops * ops; + __genl_const struct genl_multicast_group *mcgrps; + unsigned int n_ops; + unsigned int n_mcgrps; + struct module *module; +}; +#undef genl_family +#define genl_family backport_genl_family -#define genl_register_family_with_ops(family, ops) \ - _genl_register_family_with_ops_grps((family), \ - (ops), ARRAY_SIZE(ops), \ - NULL, 0) -#define genl_register_family_with_ops_groups(family, ops, grps) \ - _genl_register_family_with_ops_grps((family), \ - (ops), ARRAY_SIZE(ops), \ - (grps), ARRAY_SIZE(grps)) +#define genl_register_family backport_genl_register_family +int genl_register_family(struct genl_family *family); #define genl_unregister_family backport_genl_unregister_family -int genl_unregister_family(struct genl_family *family); +int backport_genl_unregister_family(struct genl_family *family); -#if LINUX_VERSION_IS_LESS(3,3,0) -extern void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, - u32 group, struct nlmsghdr *nlh, gfp_t flags); -#endif -#define genl_notify(_fam, _skb, _info, _group, _flags) \ - genl_notify(_skb, genl_info_net(_info), \ - genl_info_snd_portid(_info), \ - (_fam)->mcgrps[_group].id, _info->nlhdr, _flags) -#define genlmsg_put(_skb, _pid, _seq, _fam, _flags, _cmd) \ - genlmsg_put(_skb, _pid, _seq, &(_fam)->family, _flags, _cmd) +#define genl_notify LINUX_BACKPORT(genl_notify) +void genl_notify(const struct genl_family *family, struct sk_buff *skb, + struct genl_info *info, u32 group, gfp_t flags); + +#define genlmsg_put LINUX_BACKPORT(genlmsg_put) +void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, + const struct genl_family *family, int flags, u8 cmd); + +#define genlmsg_put_reply LINUX_BACKPORT(genlmsg_put_reply) +void *genlmsg_put_reply(struct sk_buff *skb, + struct genl_info *info, + const struct genl_family *family, + int flags, u8 cmd); -#ifndef genlmsg_put_reply /* might already be there from _info override above */ -#define genlmsg_put_reply(_skb, _info, _fam, _flags, _cmd) \ - genlmsg_put_reply(_skb, _info, &(_fam)->family, _flags, _cmd) -#endif #define genlmsg_multicast_netns LINUX_BACKPORT(genlmsg_multicast_netns) -static inline int genlmsg_multicast_netns(struct genl_family *family, - struct net *net, struct sk_buff *skb, - u32 portid, unsigned int group, - gfp_t flags) -{ - if (WARN_ON_ONCE(group >= family->n_mcgrps)) - return -EINVAL; - group = family->mcgrps[group].id; - return nlmsg_multicast( - net->genl_sock, - skb, portid, group, flags); -} +int genlmsg_multicast_netns(const struct genl_family *family, + struct net *net, struct sk_buff *skb, + u32 portid, unsigned int group, + gfp_t flags); + #define genlmsg_multicast LINUX_BACKPORT(genlmsg_multicast) -static inline int genlmsg_multicast(struct genl_family *family, - struct sk_buff *skb, u32 portid, - unsigned int group, gfp_t flags) -{ - if (WARN_ON_ONCE(group >= family->n_mcgrps)) - return -EINVAL; - group = family->mcgrps[group].id; - return nlmsg_multicast( - init_net.genl_sock, - skb, portid, group, flags); -} -static inline int -backport_genlmsg_multicast_allns(struct genl_family *family, - struct sk_buff *skb, u32 portid, - unsigned int group, gfp_t flags) -{ - if (WARN_ON_ONCE(group >= family->n_mcgrps)) - return -EINVAL; - group = family->mcgrps[group].id; - return genlmsg_multicast_allns(skb, portid, group, flags); -} -#define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns) +int genlmsg_multicast(const struct genl_family *family, + struct sk_buff *skb, u32 portid, + unsigned int group, gfp_t flags); -#define __genl_const -#else /* < 3.13 */ -#define __genl_const const -#if LINUX_VERSION_IS_LESS(4,4,0) -#define genl_notify(_fam, _skb, _info, _group, _flags) \ - genl_notify(_fam, _skb, genl_info_net(_info), \ - genl_info_snd_portid(_info), \ - _group, _info->nlhdr, _flags) -#endif /* < 4.4 */ -#endif /* < 3.13 */ +#define genlmsg_multicast_allns LINUX_BACKPORT(genlmsg_multicast_allns) +int backport_genlmsg_multicast_allns(const struct genl_family *family, + struct sk_buff *skb, u32 portid, + unsigned int group, gfp_t flags); -#if LINUX_VERSION_IS_LESS(4,10,0) -/** - * genl_family_attrbuf - return family's attrbuf - * @family: the family - * - * Return the family's attrbuf, while validating that it's - * actually valid to access it. - * - * You cannot use this function with a family that has parallel_ops - * and you can only use it within (pre/post) doit/dumpit callbacks. - */ #define genl_family_attrbuf LINUX_BACKPORT(genl_family_attrbuf) static inline struct nlattr **genl_family_attrbuf(struct genl_family *family) { @@ -232,29 +179,6 @@ static inline struct nlattr **genl_family_attrbuf(struct genl_family *family) return family->attrbuf; } - -#define __genl_ro_after_init -#else -#define __genl_ro_after_init __ro_after_init -#endif - -#if LINUX_VERSION_IS_LESS(4,12,0) -static inline int -__real_bp_extack_genl_register_family(struct genl_family *family) -{ - return genl_register_family(family); -} -static inline int -__real_bp_extack_genl_unregister_family(struct genl_family *family) -{ - return genl_unregister_family(family); -} -int bp_extack_genl_register_family(struct genl_family *family); -int bp_extack_genl_unregister_family(struct genl_family *family); -#undef genl_register_family -#define genl_register_family bp_extack_genl_register_family -#undef genl_unregister_family -#define genl_unregister_family bp_extack_genl_unregister_family -#endif +#endif /* LINUX_VERSION_IS_LESS(4,20,0) */ #endif /* __BACKPORT_NET_GENETLINK_H */ diff --git a/backport/compat/Makefile b/backport/compat/Makefile index ff6c7e658380..fdc68c8b4600 100644 --- a/backport/compat/Makefile +++ b/backport/compat/Makefile @@ -36,10 +36,11 @@ compat-$(CPTCFG_KERNEL_4_6) += backport-4.6.o compat-$(CPTCFG_KERNEL_4_7) += backport-4.7.o compat-$(CPTCFG_KERNEL_4_8) += backport-4.8.o compat-$(CPTCFG_KERNEL_4_10) += backport-4.10.o -compat-$(CPTCFG_KERNEL_4_12) += backport-4.12.o compat-$(CPTCFG_KERNEL_4_18) += backport-4.18.o compat-$(CPTCFG_KERNEL_4_20) += backport-4.20.o +compat-$(CPTCFG_KERNEL_4_20) += backport-genetlink.o + compat-$(CPTCFG_BPAUTO_CRYPTO_SKCIPHER) += crypto-skcipher.o compat-$(CPTCFG_BPAUTO_BUILD_SYSTEM_DATA_VERIFICATION) += verification/verify.o diff --git a/backport/compat/backport-3.13.c b/backport/compat/backport-3.13.c index c33a04432ddc..2b61711d233d 100644 --- a/backport/compat/backport-3.13.c +++ b/backport/compat/backport-3.13.c @@ -11,78 +11,12 @@ */ #include #include -#include #include #include #include #include #include -/************* generic netlink backport *****************/ -#if RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) - -#undef genl_register_family -#undef genl_unregister_family - -int __backport_genl_register_family(struct genl_family *family) -{ - int i, ret; - -#define __copy(_field) family->family._field = family->_field - __copy(id); - __copy(hdrsize); - __copy(version); - __copy(maxattr); - strncpy(family->family.name, family->name, sizeof(family->family.name)); - __copy(netnsok); - __copy(pre_doit); - __copy(post_doit); -#if LINUX_VERSION_IS_GEQ(3,10,0) - __copy(parallel_ops); -#endif -#if LINUX_VERSION_IS_GEQ(3,11,0) - __copy(module); -#endif -#undef __copy - - ret = genl_register_family(&family->family); - if (ret < 0) - return ret; - - family->attrbuf = family->family.attrbuf; - family->id = family->family.id; - - for (i = 0; i < family->n_ops; i++) { - ret = genl_register_ops(&family->family, &family->ops[i]); - if (ret < 0) - goto error; - } - - for (i = 0; i < family->n_mcgrps; i++) { - ret = genl_register_mc_group(&family->family, - &family->mcgrps[i]); - if (ret) - goto error; - } - - return 0; - - error: - backport_genl_unregister_family(family); - return ret; -} -EXPORT_SYMBOL_GPL(__backport_genl_register_family); - -int backport_genl_unregister_family(struct genl_family *family) -{ - int err; - err = genl_unregister_family(&family->family); - return err; -} -EXPORT_SYMBOL_GPL(backport_genl_unregister_family); - -#endif /* RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) */ - #ifdef __BACKPORT_NET_GET_RANDOM_ONCE struct __net_random_once_work { struct work_struct work; diff --git a/backport/compat/backport-4.12.c b/backport/compat/backport-4.12.c deleted file mode 100644 index 5fc8c10cb8d8..000000000000 --- a/backport/compat/backport-4.12.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * Copyright 2017 Intel Deutschland GmbH - */ -#include -#include - -enum nlmsgerr_attrs { - NLMSGERR_ATTR_UNUSED, - NLMSGERR_ATTR_MSG, - NLMSGERR_ATTR_OFFS, - NLMSGERR_ATTR_COOKIE, - __NLMSGERR_ATTR_MAX, - NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 -}; - -#define NLM_F_CAPPED 0x100 /* request was capped */ -#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ - -struct bp_extack_genl_family { - struct genl_family family; - struct genl_family *real_family; - struct list_head list; - - struct genl_ops ops[]; -}; - -static LIST_HEAD(copies_list); -static DEFINE_MUTEX(copies_mutex); - -static const struct nla_policy extack_dummy_policy[1] = {}; - -static struct bp_extack_genl_family *get_copy(__genl_const struct genl_ops *op) -{ - do { - op--; - } while (op->policy != extack_dummy_policy); - - return container_of(op, struct bp_extack_genl_family, ops[0]); -} - -static int extack_pre_doit(__genl_const struct genl_ops *ops, - struct sk_buff *skb, - struct genl_info *info) -{ - struct netlink_ext_ack *extack = kzalloc(sizeof(*extack), GFP_KERNEL); - struct bp_extack_genl_family *copy = get_copy(ops); - struct genl_ops *real_ops; - int err; - - __bp_genl_info_userhdr_set(info, extack); - - if (!extack) { - __bp_genl_info_userhdr_set(info, ERR_PTR(-ENOMEM)); - return -ENOMEM; - } - - real_ops = (void *)©->real_family->ops[ops - ©->ops[1]]; - extack->__bp_genl_real_ops = real_ops; - - if (copy->real_family->pre_doit) - err = copy->real_family->pre_doit(real_ops, skb, info); - else - err = 0; - - if (err) { - __bp_genl_info_userhdr_set(info, ERR_PTR(err)); - kfree(extack); - } - - return err; -} - -static void extack_netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, - int err, const struct netlink_ext_ack *extack) -{ - struct sk_buff *skb; - struct nlmsghdr *rep; - struct nlmsgerr *errmsg; - size_t payload = sizeof(*errmsg); - size_t tlvlen = 0; - unsigned int flags = 0; - /* backports assumes everyone supports this - libnl does so it's true */ - bool nlk_has_extack = true; - - /* Error messages get the original request appened, unless the user - * requests to cap the error message, and get extra error data if - * requested. - * (ignored in backports) - */ - if (nlk_has_extack && extack && extack->_msg) - tlvlen += nla_total_size(strlen(extack->_msg) + 1); - - if (err) { - if (1) - payload += nlmsg_len(nlh); - else - flags |= NLM_F_CAPPED; - if (nlk_has_extack && extack && extack->bad_attr) - tlvlen += nla_total_size(sizeof(u32)); - } else { - flags |= NLM_F_CAPPED; - - if (nlk_has_extack && extack && extack->cookie_len) - tlvlen += nla_total_size(extack->cookie_len); - } - - if (tlvlen) - flags |= NLM_F_ACK_TLVS; - - skb = nlmsg_new(payload + tlvlen, GFP_KERNEL); - if (!skb) { - NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; - NETLINK_CB(in_skb).sk->sk_error_report(NETLINK_CB(in_skb).sk); - return; - } - - rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, - NLMSG_ERROR, payload, flags); - errmsg = nlmsg_data(rep); - errmsg->error = err; - memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); - - if (nlk_has_extack && extack) { - if (extack->_msg) { - WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, - extack->_msg)); - } - if (err) { - if (extack->bad_attr && - !WARN_ON((u8 *)extack->bad_attr < in_skb->data || - (u8 *)extack->bad_attr >= in_skb->data + - in_skb->len)) - WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, - (u8 *)extack->bad_attr - - in_skb->data)); - } else { - if (extack->cookie_len) - WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE, - extack->cookie_len, - extack->cookie)); - } - } - - nlmsg_end(skb, rep); - - netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT); -} - -static int extack_doit(struct sk_buff *skb, struct genl_info *info) -{ - struct genl_ops *real_ops; - int err; - - /* older kernels have a bug here */ - if (IS_ERR(__bp_genl_info_userhdr(info))) { - extack_netlink_ack(skb, info->nlhdr, - PTR_ERR(__bp_genl_info_userhdr(info)), - genl_info_extack(info)); - goto out; - } - - real_ops = genl_info_extack(info)->__bp_genl_real_ops; - err = real_ops->doit(skb, info); - - if (err == -EINTR) - return err; - - if (info->nlhdr->nlmsg_flags & NLM_F_ACK || err) - extack_netlink_ack(skb, info->nlhdr, err, - genl_info_extack(info)); - -out: - /* suppress sending ACK from normal netlink code */ - info->nlhdr->nlmsg_flags &= ~NLM_F_ACK; - return 0; -} - -static void extack_post_doit(__genl_const struct genl_ops *ops, - struct sk_buff *skb, - struct genl_info *info) -{ - void (*post_doit)(__genl_const struct genl_ops *ops, - struct sk_buff *skb, - struct genl_info *info); - - post_doit = get_copy(ops)->real_family->post_doit; - - if (post_doit) - post_doit(ops, skb, info); - kfree(__bp_genl_info_userhdr(info)); -} - -int bp_extack_genl_register_family(struct genl_family *family) -{ - unsigned int size = sizeof(struct bp_extack_genl_family) + - sizeof(family->ops[0]) * (family->n_ops + 1); - struct bp_extack_genl_family *copy; - int i, err; - - copy = kzalloc(size, GFP_KERNEL); - if (!copy) - return -ENOMEM; - - copy->family = *family; - copy->real_family = family; - copy->family.ops = ©->ops[1]; - - for (i = 0; i < family->n_ops; i++) { - copy->ops[i + 1] = family->ops[i]; - if (family->ops[i].doit) - copy->ops[i + 1].doit = extack_doit; - } - - copy->ops[0].policy = extack_dummy_policy; - - copy->family.pre_doit = extack_pre_doit; - copy->family.post_doit = extack_post_doit; - - err = __real_bp_extack_genl_register_family(©->family); - if (err) { - kfree(copy); - return err; - } - - /* copy this since the family might access it directly */ - family->id = copy->family.id; - family->attrbuf = copy->family.attrbuf; - -#if LINUX_VERSION_IS_LESS(3,13,0) && RHEL_RELEASE_CODE < RHEL_RELEASE_VERSION(7,0) - /* family ID from the original family struct will be used when building - * genl messages (sent as nlmsg_type), so the new id should be updated - * in the original (older kernel format) family struct too - */ - family->family.id = copy->family.id; -#endif - -#if LINUX_VERSION_IS_GEQ(3,13,0) - family->mcgrp_offset = copy->family.mcgrp_offset; -#endif - - mutex_lock(&copies_mutex); - list_add_tail(©->list, &copies_list); - mutex_unlock(&copies_mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(bp_extack_genl_register_family); - -int bp_extack_genl_unregister_family(struct genl_family *family) -{ - struct bp_extack_genl_family *tmp, *copy = NULL; - int err; - - mutex_lock(&copies_mutex); - list_for_each_entry(tmp, &copies_list, list) { - if (tmp->real_family == family) { - copy = tmp; - break; - } - } - if (copy) - list_del(©->list); - mutex_unlock(&copies_mutex); - - if (!copy) - return -ENOENT; - - err = __real_bp_extack_genl_unregister_family(©->family); - WARN_ON(err); - kfree(copy); - - return 0; -} -EXPORT_SYMBOL_GPL(bp_extack_genl_unregister_family); diff --git a/backport/compat/backport-genetlink.c b/backport/compat/backport-genetlink.c new file mode 100644 index 000000000000..cc70cd73d0c0 --- /dev/null +++ b/backport/compat/backport-genetlink.c @@ -0,0 +1,429 @@ +/* + * Copyright 2017 Intel Deutschland GmbH + * Copyright (C) 2018 Intel Corporation + * + * Backport functionality introduced in Linux 4.20. + * Much of this is based on upstream lib/nlattr.c. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include + +static const struct genl_family *find_family_real_ops(__genl_const struct genl_ops **ops) +{ + const struct genl_family *family; + const struct genl_ops *tmp_ops = *ops; + + /* find the family ... */ + while (tmp_ops->doit || tmp_ops->dumpit) + tmp_ops++; + family = (void *)tmp_ops->done; + + /* cast to suppress const warning */ + *ops = (void *)(family->ops + (*ops - family->copy_ops)); + + return family; +} + +#if LINUX_VERSION_IS_LESS(4,12,0) +enum nlmsgerr_attrs { + NLMSGERR_ATTR_UNUSED, + NLMSGERR_ATTR_MSG, + NLMSGERR_ATTR_OFFS, + NLMSGERR_ATTR_COOKIE, + __NLMSGERR_ATTR_MAX, + NLMSGERR_ATTR_MAX = __NLMSGERR_ATTR_MAX - 1 +}; + +#define NLM_F_CAPPED 0x100 /* request was capped */ +#define NLM_F_ACK_TLVS 0x200 /* extended ACK TVLs were included */ + +static void extack_netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, + int err, const struct netlink_ext_ack *extack) +{ + struct sk_buff *skb; + struct nlmsghdr *rep; + struct nlmsgerr *errmsg; + size_t payload = sizeof(*errmsg); + size_t tlvlen = 0; + unsigned int flags = 0; + /* backports assumes everyone supports this - libnl does so it's true */ + bool nlk_has_extack = true; + + /* Error messages get the original request appened, unless the user + * requests to cap the error message, and get extra error data if + * requested. + * (ignored in backports) + */ + if (nlk_has_extack && extack && extack->_msg) + tlvlen += nla_total_size(strlen(extack->_msg) + 1); + + if (err) { + if (1) + payload += nlmsg_len(nlh); + else + flags |= NLM_F_CAPPED; + if (nlk_has_extack && extack && extack->bad_attr) + tlvlen += nla_total_size(sizeof(u32)); + } else { + flags |= NLM_F_CAPPED; + + if (nlk_has_extack && extack && extack->cookie_len) + tlvlen += nla_total_size(extack->cookie_len); + } + + if (tlvlen) + flags |= NLM_F_ACK_TLVS; + + skb = nlmsg_new(payload + tlvlen, GFP_KERNEL); + if (!skb) { + NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; + NETLINK_CB(in_skb).sk->sk_error_report(NETLINK_CB(in_skb).sk); + return; + } + + rep = __nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, + NLMSG_ERROR, payload, flags); + errmsg = nlmsg_data(rep); + errmsg->error = err; + memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) ? nlh->nlmsg_len : sizeof(*nlh)); + + if (nlk_has_extack && extack) { + if (extack->_msg) { + WARN_ON(nla_put_string(skb, NLMSGERR_ATTR_MSG, + extack->_msg)); + } + if (err) { + if (extack->bad_attr && + !WARN_ON((u8 *)extack->bad_attr < in_skb->data || + (u8 *)extack->bad_attr >= in_skb->data + + in_skb->len)) + WARN_ON(nla_put_u32(skb, NLMSGERR_ATTR_OFFS, + (u8 *)extack->bad_attr - + in_skb->data)); + } else { + if (extack->cookie_len) + WARN_ON(nla_put(skb, NLMSGERR_ATTR_COOKIE, + extack->cookie_len, + extack->cookie)); + } + } + + nlmsg_end(skb, rep); + + netlink_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid, MSG_DONTWAIT); +} + +static int extack_doit(struct sk_buff *skb, struct genl_info *info) +{ + int (*doit)(struct sk_buff *, struct genl_info *); + int err; + + doit = genl_info_extack(info)->__bp_doit; + + /* signal from our pre_doit to not do anything */ + if (!doit) + return 0; + + err = doit(skb, info); + + if (err == -EINTR) + return err; + + if (info->nlhdr->nlmsg_flags & NLM_F_ACK || err) + extack_netlink_ack(skb, info->nlhdr, err, + genl_info_extack(info)); + + /* suppress sending ACK from normal netlink code */ + info->nlhdr->nlmsg_flags &= ~NLM_F_ACK; + return 0; +} +#endif /* LINUX_VERSION_IS_LESS(4,12,0) */ + +static int backport_pre_doit(__genl_const struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info) +{ + const struct genl_family *family = find_family_real_ops(&ops); + int err; +#if LINUX_VERSION_IS_LESS(4,12,0) + struct netlink_ext_ack *extack = kzalloc(sizeof(*extack), GFP_KERNEL); + + __bp_genl_info_userhdr_set(info, extack); + + if (!extack) { + err = -ENOMEM; + goto err; + } + + extack->__bp_doit = ops->doit; +#else + struct netlink_ext_ack *extack = info->extack; +#endif + + err = nlmsg_validate(info->nlhdr, GENL_HDRLEN + family->hdrsize, + family->maxattr, ops->policy, extack); + if (!err) + err = family->pre_doit(ops, skb, info); + +#if LINUX_VERSION_IS_LESS(4,12,0) +err: + if (err) { + /* signal to do nothing */ + extack->__bp_doit = NULL; + + extack_netlink_ack(skb, info->nlhdr, err, extack); + + /* suppress sending ACK from normal netlink code */ + info->nlhdr->nlmsg_flags &= ~NLM_F_ACK; + + /* extack will be freed in post_doit as usual */ + + return 0; + } +#endif + + return err; +} + +static void backport_post_doit(__genl_const struct genl_ops *ops, + struct sk_buff *skb, + struct genl_info *info) +{ + const struct genl_family *family = find_family_real_ops(&ops); + +#if LINUX_VERSION_IS_LESS(4,12,0) + if (genl_info_extack(info)->__bp_doit) +#else + if (1) +#endif + family->post_doit(ops, skb, info); + +#if LINUX_VERSION_IS_LESS(4,12,0) + kfree(__bp_genl_info_userhdr(info)); +#endif +} + +int backport_genl_register_family(struct genl_family *family) +{ + struct genl_ops *ops; + int err, i; + +#define COPY(memb) family->family.memb = family->memb +#define BACK(memb) family->memb = family->family.memb + + /* we append one entry to the ops to find our family pointer ... */ + ops = kzalloc(sizeof(*ops) * (family->n_ops + 1), GFP_KERNEL); + memcpy(ops, family->ops, sizeof(*ops) * family->n_ops); + /* + * Remove policy to skip validation as the struct nla_policy + * memory layout isn't compatible with the old version + */ + for (i = 0; i < family->n_ops; i++) { + ops[i].policy = NULL; +#if LINUX_VERSION_IS_LESS(4,12,0) + if (ops[i].doit) + ops[i].doit = extack_doit; +#endif + } + /* keep doit/dumpit NULL - that's invalid */ + ops[family->n_ops].done = (void *)family; + + COPY(id); + memcpy(family->family.name, family->name, sizeof(family->name)); + COPY(hdrsize); + COPY(version); + COPY(maxattr); + COPY(netnsok); +#if LINUX_VERSION_IS_GEQ(3,10,0) + COPY(parallel_ops); +#endif + family->family.pre_doit = backport_pre_doit; + family->family.post_doit = backport_post_doit; + /* attrbuf is output only */ + family->copy_ops = ops; +#if LINUX_VERSION_IS_GEQ(3,13,0) + family->family.ops = ops; + COPY(mcgrps); + COPY(n_ops); + COPY(n_mcgrps); +#endif +#if LINUX_VERSION_IS_GEQ(3,11,0) + COPY(module); +#endif + + err = __real_backport_genl_register_family(&family->family); + + BACK(id); + BACK(attrbuf); + + if (err) + return err; + +#if LINUX_VERSION_IS_GEQ(3,13,0) || RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,0) + return 0; +#else + for (i = 0; i < family->n_ops; i++) { + err = genl_register_ops(&family->family, ops + i); + if (err < 0) + goto error; + } + + for (i = 0; i < family->n_mcgrps; i++) { + err = genl_register_mc_group(&family->family, + &family->mcgrps[i]); + if (err) + goto error; + } + + return 0; + error: + genl_unregister_family(family); + return err; +#endif /* LINUX_VERSION_IS_GEQ(3,13,0) || RHEL_RELEASE_CODE >= RHEL_RELEASE_VERSION(7,0) */ +} +EXPORT_SYMBOL_GPL(backport_genl_register_family); + +int backport_genl_unregister_family(struct genl_family *family) +{ + return __real_backport_genl_unregister_family(&family->family); +} +EXPORT_SYMBOL_GPL(backport_genl_unregister_family); + +#define INVALID_GROUP 0xffffffff + +static u32 __backport_genl_group(const struct genl_family *family, + u32 group) +{ + if (WARN_ON_ONCE(group >= family->n_mcgrps)) + return INVALID_GROUP; +#if LINUX_VERSION_IS_LESS(3,13,0) + return family->mcgrps[group].id; +#else + return family->family.mcgrp_offset + group; +#endif +} + +void genl_notify(const struct genl_family *family, struct sk_buff *skb, + struct genl_info *info, u32 group, gfp_t flags) +{ + struct net *net = genl_info_net(info); + struct sock *sk = net->genl_sock; + int report = 0; + + if (info->nlhdr) + report = nlmsg_report(info->nlhdr); + + group = __backport_genl_group(family, group); + if (group == INVALID_GROUP) + return; + nlmsg_notify(sk, skb, info->snd_portid, group, report, flags); +} +EXPORT_SYMBOL_GPL(genl_notify); + +void *genlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, + const struct genl_family *family, int flags, u8 cmd) +{ + struct nlmsghdr *nlh; + struct genlmsghdr *hdr; + + nlh = nlmsg_put(skb, portid, seq, family->id, GENL_HDRLEN + + family->hdrsize, flags); + if (nlh == NULL) + return NULL; + + hdr = nlmsg_data(nlh); + hdr->cmd = cmd; + hdr->version = family->version; + hdr->reserved = 0; + + return (char *) hdr + GENL_HDRLEN; +} +EXPORT_SYMBOL_GPL(genlmsg_put); + +void *genlmsg_put_reply(struct sk_buff *skb, + struct genl_info *info, + const struct genl_family *family, + int flags, u8 cmd) +{ + return genlmsg_put(skb, info->snd_portid, info->snd_seq, family, + flags, cmd); +} +EXPORT_SYMBOL_GPL(genlmsg_put_reply); + +int genlmsg_multicast_netns(const struct genl_family *family, + struct net *net, struct sk_buff *skb, + u32 portid, unsigned int group, + gfp_t flags) +{ + group = __backport_genl_group(family, group); + if (group == INVALID_GROUP) + return -EINVAL; + return nlmsg_multicast(net->genl_sock, skb, portid, group, flags); +} +EXPORT_SYMBOL_GPL(genlmsg_multicast_netns); + +int genlmsg_multicast(const struct genl_family *family, + struct sk_buff *skb, u32 portid, + unsigned int group, gfp_t flags) +{ + return genlmsg_multicast_netns(family, &init_net, skb, + portid, group, flags); +} +EXPORT_SYMBOL_GPL(genlmsg_multicast); + +static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group, + gfp_t flags) +{ + struct sk_buff *tmp; + struct net *net, *prev = NULL; + bool delivered = false; + int err; + + for_each_net_rcu(net) { + if (prev) { + tmp = skb_clone(skb, flags); + if (!tmp) { + err = -ENOMEM; + goto error; + } + err = nlmsg_multicast(prev->genl_sock, tmp, + portid, group, flags); + if (!err) + delivered = true; + else if (err != -ESRCH) + goto error; + } + + prev = net; + } + + err = nlmsg_multicast(prev->genl_sock, skb, portid, group, flags); + if (!err) + delivered = true; + else if (err != -ESRCH) + return err; + return delivered ? 0 : -ESRCH; + error: + kfree_skb(skb); + return err; +} + +int backport_genlmsg_multicast_allns(const struct genl_family *family, + struct sk_buff *skb, u32 portid, + unsigned int group, gfp_t flags) +{ + group = __backport_genl_group(family, group); + if (group == INVALID_GROUP) + return -EINVAL; + return genlmsg_mcast(skb, portid, group, flags); +} +EXPORT_SYMBOL_GPL(backport_genlmsg_multicast_allns); diff --git a/backport/compat/compat-3.3.c b/backport/compat/compat-3.3.c index c064f09d9abe..1185a5d2d4e0 100644 --- a/backport/compat/compat-3.3.c +++ b/backport/compat/compat-3.3.c @@ -224,16 +224,3 @@ void backport_destroy_workqueue(struct workqueue_struct *wq) spin_unlock(&wq_name_lock); } EXPORT_SYMBOL_GPL(backport_destroy_workqueue); - -void genl_notify(struct sk_buff *skb, struct net *net, u32 pid, u32 group, - struct nlmsghdr *nlh, gfp_t flags) -{ - struct sock *sk = net->genl_sock; - int report = 0; - - if (nlh) - report = nlmsg_report(nlh); - - nlmsg_notify(sk, skb, pid, group, report, flags); -} -EXPORT_SYMBOL_GPL(genl_notify);