From patchwork Thu Jul 12 10:34:14 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Fernando F. Mancera" X-Patchwork-Id: 942899 X-Patchwork-Delegate: pablo@netfilter.org Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netfilter-devel-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=riseup.net Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=riseup.net header.i=@riseup.net header.b="BJ26CeAD"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 41RC3r6S6Cz9s01 for ; Thu, 12 Jul 2018 20:34:32 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726518AbeGLKn0 (ORCPT ); Thu, 12 Jul 2018 06:43:26 -0400 Received: from mx1.riseup.net ([198.252.153.129]:40517 "EHLO mx1.riseup.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726453AbeGLKn0 (ORCPT ); Thu, 12 Jul 2018 06:43:26 -0400 Received: from piha.riseup.net (piha-pn.riseup.net [10.0.1.163]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client CN "*.riseup.net", Issuer "COMODO RSA Domain Validation Secure Server CA" (verified OK)) by mx1.riseup.net (Postfix) with ESMTPS id DB02C1A0BBB for ; Thu, 12 Jul 2018 03:34:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=riseup.net; s=squak; t=1531391668; bh=iW3JT42UoYbiKMFslGSYeIBjO+u4rzxQ3KUmnmxX90Y=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=BJ26CeAD2xqCLSmRfB96rqgE4SsuyfImyLBqYdgJ3XsQQNbvDZbJ+U9jxm2VhjNXV OXGrSP3HZSPIHVwrUOTdWuY+DsZvV8V0zRtKUBK8KlxU2mrhvn8Tvkp24KScVwiJJ/ zQUFwxlhbB6IHDokrVpXu3Kg8fR5140W+7Au7pP0= X-Riseup-User-ID: B0E5B2C425270E6693F17539CA7B9CBC0B0B62D41A28B2A7FAA64F8F6A2B0398 Received: from [127.0.0.1] (localhost [127.0.0.1]) by piha.riseup.net with ESMTPSA id 0DDCD2E1C0; Thu, 12 Jul 2018 03:34:27 -0700 (PDT) From: Fernando Fernandez Mancera To: netfilter-devel@vger.kernel.org Cc: Fernando Fernandez Mancera Subject: [PATCH 2/2 WIP nf-next] nft: implement the nf_tables_api changes to add osf signatures in nft Date: Thu, 12 Jul 2018 12:34:14 +0200 Message-Id: <20180712103414.2501-2-ffmancera@riseup.net> In-Reply-To: <20180712103414.2501-1-ffmancera@riseup.net> References: <20180712103414.2501-1-ffmancera@riseup.net> Sender: netfilter-devel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netfilter-devel@vger.kernel.org Added _ADD and _REMOVE commands to nf_tables_api.c in order to use the nf_tables interface to add 'osf' signatures in nft. Signed-off-by: Fernando Fernandez Mancera --- include/net/netfilter/nf_tables_core.h | 2 + include/uapi/linux/netfilter/nf_osf.h | 8 ++ include/uapi/linux/netfilter/nf_tables.h | 14 +++ include/uapi/linux/netfilter/xt_osf.h | 7 +- net/netfilter/nf_tables_api.c | 110 +++++++++++++++++++++++ net/netfilter/nft_osf.c | 1 + 6 files changed, 136 insertions(+), 6 deletions(-) diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index e0c0c2558ec4..ee7eabc8d3e1 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -65,4 +65,6 @@ extern const struct nft_expr_ops nft_payload_fast_ops; extern struct static_key_false nft_counters_enabled; extern struct static_key_false nft_trace_enabled; +extern struct list_head nft_osf_fingers[2]; + #endif /* _NET_NF_TABLES_CORE_H */ diff --git a/include/uapi/linux/netfilter/nf_osf.h b/include/uapi/linux/netfilter/nf_osf.h index 79882b2f7f8e..35352c1cd994 100644 --- a/include/uapi/linux/netfilter/nf_osf.h +++ b/include/uapi/linux/netfilter/nf_osf.h @@ -2,6 +2,8 @@ #define _NF_OSF_H #include +#include +#include #define MAXGENRELEN 32 @@ -90,4 +92,10 @@ enum iana_options { OSFOPT_EMPTY = 255, }; +enum nf_osf_attr_type { + OSF_ATTR_UNSPEC, + OSF_ATTR_FINGER, + OSF_ATTR_MAX, +}; + #endif /* _NF_OSF_H */ diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index c9bf74b94f37..beffa2010b20 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -9,6 +9,8 @@ #define NFT_OBJ_MAXNAMELEN NFT_NAME_MAXLEN #define NFT_USERDATA_MAXLEN 256 +#define OSF_GENRE_SIZE 32 + /** * enum nft_registers - nf_tables registers * @@ -122,6 +124,8 @@ enum nf_tables_msg_types { NFT_MSG_NEWFLOWTABLE, NFT_MSG_GETFLOWTABLE, NFT_MSG_DELFLOWTABLE, + NFT_MSG_NEWOSF, + NFT_MSG_DELOSF, NFT_MSG_MAX, }; @@ -1461,6 +1465,16 @@ enum nft_flowtable_hook_attributes { }; #define NFTA_FLOWTABLE_HOOK_MAX (__NFTA_FLOWTABLE_HOOK_MAX - 1) +enum nft_osf_attributes { + NFTA_OSF_UNSPEC, + NFTA_OSF_GENRE, + NFTA_OSF_FLAGS, + NFTA_OSF_LOGLEVEL, + NFTA_OSF_TTL, + __NFTA_OSF_MAX, +}; +#define NFTA_OSF_MAX (__NFTA_OSF_MAX - 1) + /** * enum nft_device_attributes - nf_tables device netlink attributes * diff --git a/include/uapi/linux/netfilter/xt_osf.h b/include/uapi/linux/netfilter/xt_osf.h index 2f5d4e6d0434..b7c0f93fe9d4 100644 --- a/include/uapi/linux/netfilter/xt_osf.h +++ b/include/uapi/linux/netfilter/xt_osf.h @@ -51,6 +51,7 @@ #define xt_osf_finger nf_osf_finger #define xt_osf_nlmsg nf_osf_nlmsg +#define xt_osf_attr_type nf_osf_attr_type /* * Add/remove fingerprint from the kernel. */ @@ -60,10 +61,4 @@ enum xt_osf_msg_types { OSF_MSG_MAX, }; -enum xt_osf_attr_type { - OSF_ATTR_UNSPEC, - OSF_ATTR_FINGER, - OSF_ATTR_MAX, -}; - #endif /* _XT_OSF_H */ diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index ca4c4d994ddb..1783d8ef658c 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -26,6 +27,7 @@ static LIST_HEAD(nf_tables_expressions); static LIST_HEAD(nf_tables_objects); static LIST_HEAD(nf_tables_flowtables); + static u64 table_handle; enum { @@ -5851,6 +5853,8 @@ static int nf_tables_flowtable_event(struct notifier_block *this, return NOTIFY_DONE; } + + static struct notifier_block nf_tables_flowtable_notifier = { .notifier_call = nf_tables_flowtable_event, }; @@ -5908,6 +5912,102 @@ static int nf_tables_getgen(struct net *net, struct sock *nlsk, return err; } +struct list_head nft_osf_fingers[2]; +EXPORT_SYMBOL_GPL(nft_osf_fingers); + +static int nf_tables_newosf(struct net *net, struct sock *ctnl, + struct sk_buff *skb, const struct nlmsghdr *nlh, + const struct nlattr * const osf_attrs[], + struct netlink_ext_ack *extack) +{ + struct nf_osf_user_finger *f; + struct nf_osf_finger *kf = NULL, *sf; + int err = 0; + int i = 0; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + if (!(nlh->nlmsg_flags & NLM_F_CREATE)) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + kf = kmalloc(sizeof(struct nf_osf_finger), GFP_KERNEL); + if (!kf) + return -ENOMEM; + + for (i = 0; i < ARRAY_SIZE(nft_osf_fingers); ++i) + INIT_LIST_HEAD(&nft_osf_fingers[i]); + + memcpy(&kf->finger, f, sizeof(struct nf_osf_user_finger)); + + list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger))) + continue; + + kfree(kf); + kf = NULL; + + if (nlh->nlmsg_flags & NLM_F_EXCL) + err = -EEXIST; + break; + } + + /* + * We are protected by nfnl mutex. + */ + if (kf) + list_add_tail_rcu(&kf->finger_entry, &nft_osf_fingers[!!f->df]); + + return err; +} + +static int nf_tables_delosf(struct net *net, struct sock *ctnl, + struct sk_buff *skb, + const struct nlmsghdr *nlh, + const struct nlattr * const osf_attrs[], + struct netlink_ext_ack *extack) +{ + struct nf_osf_user_finger *f; + struct nf_osf_finger *sf; + int err = -ENOENT; + + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + + if (!osf_attrs[OSF_ATTR_FINGER]) + return -EINVAL; + + f = nla_data(osf_attrs[OSF_ATTR_FINGER]); + + list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) { + if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger))) + continue; + + /* + * We are protected by nfnl mutex. + */ + list_del_rcu(&sf->finger_entry); + kfree_rcu(sf, rcu_head); + + err = 0; + break; + } + + return err; +} + +static const struct nla_policy nft_osf_policy[NFTA_OSF_MAX + 1] = { + [NFTA_OSF_GENRE] = { .type = NLA_STRING, .len = OSF_GENRE_SIZE }, + [NFTA_OSF_FLAGS] = { .type = NLA_U32 }, + [NFTA_OSF_LOGLEVEL] = { .type = NLA_U32 }, + [NFTA_OSF_TTL] = { .type = NLA_U32 }, +}; + static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { [NFT_MSG_NEWTABLE] = { .call_batch = nf_tables_newtable, @@ -6022,6 +6122,16 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .attr_count = NFTA_FLOWTABLE_MAX, .policy = nft_flowtable_policy, }, + [NFT_MSG_NEWOSF] = { + .call_batch = nf_tables_newosf, + .attr_count = NFTA_OSF_MAX, + .policy = nft_osf_policy, + }, + [NFT_MSG_DELOSF] = { + .call_batch = nf_tables_delosf, + .attr_count = NFTA_OSF_MAX, + .policy = nft_osf_policy, + }, }; static int nf_tables_validate(struct net *net) diff --git a/net/netfilter/nft_osf.c b/net/netfilter/nft_osf.c index 30c503f2bf53..cf8a38b052ad 100644 --- a/net/netfilter/nft_osf.c +++ b/net/netfilter/nft_osf.c @@ -54,6 +54,7 @@ static int nft_osf_init(const struct nft_ctx *ctx, return -EINVAL; priv->ttl = ntohl(nla_get_be32(tb[NFTA_OSF_TTL])); priv->len = strlen(priv->genre); + return 0; }