Received: by 2002:ac0:a5a6:0:0:0:0:0 with SMTP id m35-v6csp1333124imm; Wed, 19 Sep 2018 16:47:03 -0700 (PDT) X-Google-Smtp-Source: ANB0VdbOaOdpMQoQtHaSe/e/UihZDh4m0Bl9uzPOmflnFq6W7+F6UdgTqOq6O13vJKweVwwnRbvN X-Received: by 2002:a62:7a01:: with SMTP id v1-v6mr38047775pfc.153.1537400823798; Wed, 19 Sep 2018 16:47:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1537400823; cv=none; d=google.com; s=arc-20160816; b=jMfOJGzEkKxAQhAqJYe0S6QN9g03m2wudyWYQxXjsDoSrw04D+AB6AXogctNn6RU3o QBR6uq1TtzhsyIQAWKHUHv/Mqvd+Vwo1HxBX5frky7J42wrOP+dLpb5sq2KvF1ZQX0mb hjhkUM5idwvS676/h/mgiybUygBGEMekN0QB0WVEBlMCeJ6JUWI51DY0IbyGCITs3XQj n1g+54AikHK6lJQnmeiC6vKUsdHJYpPlrt906DtnevVK4ZjRL566B6zUcP5e/HVeN8T2 3od88Eiyoz+eJmZbrcSq0VAsA1WDZuZaIt4Qo78lnAV6b1VXIeWdve9GSxiwA8hTsfpD fOuA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :message-id:date:subject:to:from:dkim-signature; bh=1ZkCy9BDjKtS+RtDTCXwFfQMhHVf0s2rtMCS0C9ZKTc=; b=YSlpA/+PS8zSlmNC34LRlxU8UDBpdRQYH2i5VhpLh+oKhflfSEpYklTxsrvyHkBkJL BLobbKnYIk+EfIp6JZoStMbwKLyHCpPq8ZyCMyhXkfV9Z12pqafiE8wYQz1iiFcxUXwv /35yqpGvh0FViMwVRjFURyq2c+oo0Kjv37EAsDY+Lg/1Nn3U05RdNP7Nup1zPwi+BbaE QLdE4UMMX6XNqyuCWHUyntwLaP9yaO4fBIEOsFHVt/wuGK7qQkJTzoWtXB8QSv3qrAXF yPoiDPbGBxR+wJCSBaRJYEvrOIac3VAZnvg5K8N09vNG0y6nxZyfoPm/YGbf3ZpmRimc yahQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@googlemail.com header.s=20161025 header.b=qncYjeD8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id cb14-v6si24460723plb.178.2018.09.19.16.46.19; Wed, 19 Sep 2018 16:47:03 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@googlemail.com header.s=20161025 header.b=qncYjeD8; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=googlemail.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732819AbeITEyb (ORCPT + 99 others); Thu, 20 Sep 2018 00:54:31 -0400 Received: from mail-wm1-f67.google.com ([209.85.128.67]:56143 "EHLO mail-wm1-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725755AbeITEyb (ORCPT ); Thu, 20 Sep 2018 00:54:31 -0400 Received: by mail-wm1-f67.google.com with SMTP id f21-v6so7920509wmc.5; Wed, 19 Sep 2018 16:14:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=20161025; h=from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=1ZkCy9BDjKtS+RtDTCXwFfQMhHVf0s2rtMCS0C9ZKTc=; b=qncYjeD8FZGbSTLhN78K/QFFXz4HevM01GxhpGYSUhR2u9pW67sqyxy7Cfpdiok6Ky zdw3DyypyOTahqSZMnjVdxTArc2lAnTgruQHOEawnJV3Fsw1AsHMoZUm4LtDx1vB75Ty Z7w1A3xpUelKiIRvxwHgSNz943hBqvSwRIEau2pfcjjr3FzhGffDVc0gQU0kl4/4DQT5 93jvyMCfzVzhYnG275twK0ubpRsK+k38uv5cxEB21dBye2LB1sm8dFxJPCRj+x+gJ3aD eaEaDGK89dKNlbRozymMu2fAPrMMZcHbd21PRfVPI2NuWqg5coHT1XcrQ+InTQTG12Fh hnTQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:mime-version :content-transfer-encoding; bh=1ZkCy9BDjKtS+RtDTCXwFfQMhHVf0s2rtMCS0C9ZKTc=; b=I2OrHzlOA7TLzDG0Btx0UpgLpw+sp/9BaxJx0SIzSJvBb/B0v3w7+LQqUpEbUD3z0e A9ufNZz+/r7v7x429OXEdchDoDd1r4YfFsmZnVZzfQP6UK0bVShKsx+uwRZwOimdbV3Q YSfdd7J8yVJrqbZUrgGji2xv+4A95PzJ5g/Y/43Z45efuN4nGlv1nz5qdquqSBa4w9Lv ebZlrZdy6p+EgGAAuX0Oe8eb9LXd2bhmg6v4h1ml4BmfjAEArgrrazBSjOKdKn1kBjfC t+qEL1EYeUz2Q7q48wq+haUAC1y41JM88+2NnEsWSiwip4q5//w2xK7EtKpHFiOttfFm oNyA== X-Gm-Message-State: APzg51A0qO8FEMmn7h6vi8qqhHGUwBBEvr6cj/bmBat0tLmufKCY9z3U kYOfoliQ96NzVoS/dHpiG+94siLfnMk= X-Received: by 2002:a1c:d98a:: with SMTP id q132-v6mr117391wmg.78.1537398855558; Wed, 19 Sep 2018 16:14:15 -0700 (PDT) Received: from desktopdebian.localdomain (x4dba2007.dyn.telefonica.de. [77.186.32.7]) by smtp.gmail.com with ESMTPSA id d12-v6sm23398624wru.36.2018.09.19.16.14.14 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 19 Sep 2018 16:14:15 -0700 (PDT) From: =?UTF-8?q?Christian=20G=C3=B6ttsche?= To: pablo@netfilter.org, kadlec@blackhole.kfki.hu, fw@strlen.de, davem@davemloft.net, netfilter-devel@vger.kernel.org, coreteam@netfilter.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, paul@paul-moore.com, sds@tycho.nsa.gov, eparis@parisplace.org, jmorris@namei.org, serge@hallyn.com, selinux@tycho.nsa.gov, linux-security-module@vger.kernel.org Subject: [PATCH] netfilter: nf_tables: add SECMARK support Date: Thu, 20 Sep 2018 01:14:02 +0200 Message-Id: <20180919231402.4482-1-cgzones@googlemail.com> X-Mailer: git-send-email 2.19.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add the ability to set the security context of packets within the nf_tables framework. Add a nft_object for holding security contexts in the kernel and manipulating packets on the wire. The contexts are kept as strings and are evaluated to security identifiers at runtime (packet arrival), so that the nft_objects do not need to be refreshed after security changes. The maximum security context length is set to 256. Based on v4.18.6 Signed-off-by: Christian Göttsche --- include/net/netfilter/nf_tables_core.h | 4 + include/uapi/linux/netfilter/nf_tables.h | 18 ++++- net/netfilter/nf_tables_core.c | 28 ++++++- net/netfilter/nft_meta.c | 95 ++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 5 deletions(-) diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h index a0513450..0d1f3b96 100644 --- a/include/net/netfilter/nf_tables_core.h +++ b/include/net/netfilter/nf_tables_core.h @@ -16,6 +16,10 @@ extern struct nft_expr_type nft_meta_type; extern struct nft_expr_type nft_rt_type; extern struct nft_expr_type nft_exthdr_type; +#ifdef CONFIG_NETWORK_SECMARK +extern struct nft_object_type nft_secmark_obj_type; +#endif + int nf_tables_core_module_init(void); void nf_tables_core_module_exit(void); diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h index 89438e68..f1527962 100644 --- a/include/uapi/linux/netfilter/nf_tables.h +++ b/include/uapi/linux/netfilter/nf_tables.h @@ -1169,6 +1169,21 @@ enum nft_quota_attributes { }; #define NFTA_QUOTA_MAX (__NFTA_QUOTA_MAX - 1) +/** + * enum nft_secmark_attributes - nf_tables secmark object netlink attributes + * + * @NFTA_SECMARK_CTX: security context (NLA_STRING) + */ +enum nft_secmark_attributes { + NFTA_SECMARK_UNSPEC, + NFTA_SECMARK_CTX, + __NFTA_SECMARK_MAX, +}; +#define NFTA_SECMARK_MAX (__NFTA_SECMARK_MAX - 1) + +/* Max security context length */ +#define NFT_SECMARK_CTX_MAXLEN 256 + /** * enum nft_reject_types - nf_tables reject expression reject types * @@ -1398,7 +1413,8 @@ enum nft_ct_helper_attributes { #define NFT_OBJECT_CT_HELPER 3 #define NFT_OBJECT_LIMIT 4 #define NFT_OBJECT_CONNLIMIT 5 -#define __NFT_OBJECT_MAX 6 +#define NFT_OBJECT_SECMARK 6 +#define __NFT_OBJECT_MAX 7 #define NFT_OBJECT_MAX (__NFT_OBJECT_MAX - 1) /** diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 8de912ca..d59ebba0 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c @@ -235,12 +235,24 @@ static struct nft_expr_type *nft_basic_types[] = { &nft_exthdr_type, }; +static struct nft_object_type *nft_basic_objects[] = { +#ifdef CONFIG_NETWORK_SECMARK + &nft_secmark_obj_type, +#endif +}; + int __init nf_tables_core_module_init(void) { - int err, i; + int err, i, j = 0; + + for (i = 0; i < ARRAY_SIZE(nft_basic_objects); i++) { + err = nft_register_obj(nft_basic_objects[i]); + if (err) + goto err; + } - for (i = 0; i < ARRAY_SIZE(nft_basic_types); i++) { - err = nft_register_expr(nft_basic_types[i]); + for (j = 0; j < ARRAY_SIZE(nft_basic_types); j++) { + err = nft_register_expr(nft_basic_types[j]); if (err) goto err; } @@ -248,8 +260,12 @@ int __init nf_tables_core_module_init(void) return 0; err: + while (j-- > 0) + nft_unregister_expr(nft_basic_types[j]); + while (i-- > 0) - nft_unregister_expr(nft_basic_types[i]); + nft_unregister_obj(nft_basic_objects[i]); + return err; } @@ -260,4 +276,8 @@ void nf_tables_core_module_exit(void) i = ARRAY_SIZE(nft_basic_types); while (i-- > 0) nft_unregister_expr(nft_basic_types[i]); + + i = ARRAY_SIZE(nft_basic_objects); + while (i-- > 0) + nft_unregister_obj(nft_basic_objects[i]); } diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c index 1105a23b..26b79a3c 100644 --- a/net/netfilter/nft_meta.c +++ b/net/netfilter/nft_meta.c @@ -540,3 +540,98 @@ struct nft_expr_type nft_meta_type __read_mostly = { .maxattr = NFTA_META_MAX, .owner = THIS_MODULE, }; + +#ifdef CONFIG_NETWORK_SECMARK + +struct nft_secmark { + char ctx[NFT_SECMARK_CTX_MAXLEN]; + int len; +}; + +static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = { + [NFTA_SECMARK_CTX] = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN }, +}; + + +static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs, const struct nft_pktinfo *pkt) +{ + const struct nft_secmark *priv = nft_obj_data(obj); + struct sk_buff *skb = pkt->skb; + int err; + u32 secid = 0; + + /* skip if packet has already a secmark */ + if (skb->secmark) + return; + + err = security_secctx_to_secid(priv->ctx, priv->len, &secid); + if (err) { + if (err == -EINVAL) + pr_notice_ratelimited("invalid security context \'%s\'\n", priv->ctx); + else + pr_notice_ratelimited("unable to convert security context \'%s\': %d\n", priv->ctx, -err); + return; + } + + if (!secid) { + pr_notice_ratelimited("unable to map security context \'%s\'\n", priv->ctx); + return; + } + + err = security_secmark_relabel_packet(secid); + if (err) { + pr_notice_ratelimited("unable to obtain relabeling permission: %d\n", -err); + return; + } + + skb->secmark = secid; +} + + +static int nft_secmark_obj_init(const struct nft_ctx *ctx, const struct nlattr * const tb[], struct nft_object *obj) +{ + struct nft_secmark *priv = nft_obj_data(obj); + + if (tb[NFTA_SECMARK_CTX] == NULL) + return -EINVAL; + + nla_strlcpy(priv->ctx, tb[NFTA_SECMARK_CTX], NFT_SECMARK_CTX_MAXLEN); + priv->len = strlen(priv->ctx); + + security_secmark_refcount_inc(); + + return 0; +} + +static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj, bool reset) +{ + const struct nft_secmark *priv = nft_obj_data(obj); + + if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx)) + return -1; + + return 0; +} + +static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj) +{ + security_secmark_refcount_dec(); +} + +static const struct nft_object_ops nft_secmark_obj_ops = { + .type = &nft_secmark_obj_type, + .size = sizeof(struct nft_secmark), + .init = nft_secmark_obj_init, + .eval = nft_secmark_obj_eval, + .dump = nft_secmark_obj_dump, + .destroy = nft_secmark_obj_destroy, +}; +struct nft_object_type nft_secmark_obj_type __read_mostly = { + .type = NFT_OBJECT_SECMARK, + .ops = &nft_secmark_obj_ops, + .maxattr = NFTA_SECMARK_MAX, + .policy = nft_secmark_policy, + .owner = THIS_MODULE, +}; + +#endif /* CONFIG_NETWORK_SECMARK */ -- 2.19.0