aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChristian Göttsche <cgzones@googlemail.com>2018-09-23 14:26:15 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2018-09-28 08:28:29 -0400
commitfb961945457f5177072c968aa38fee910ab893b9 (patch)
treedb7a9801ea060e236514626f4296ec8a378c8ad0 /net
parent097f95d319f817e651bd51f8846aced92a55a6a1 (diff)
netfilter: nf_tables: add SECMARK support
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. Convert the security context strings at rule addition time to security identifiers. This is the same behavior like in xt_SECMARK and offers better performance than computing it per packet. Set the maximum security context length to 256. Signed-off-by: Christian Göttsche <cgzones@googlemail.com> Acked-by: Florian Westphal <fw@strlen.de> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_tables_core.c28
-rw-r--r--net/netfilter/nft_meta.c108
2 files changed, 132 insertions, 4 deletions
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c
index ffd5c0f9412b..3fbce3b9c5ec 100644
--- a/net/netfilter/nf_tables_core.c
+++ b/net/netfilter/nf_tables_core.c
@@ -249,12 +249,24 @@ static struct nft_expr_type *nft_basic_types[] = {
249 &nft_exthdr_type, 249 &nft_exthdr_type,
250}; 250};
251 251
252static struct nft_object_type *nft_basic_objects[] = {
253#ifdef CONFIG_NETWORK_SECMARK
254 &nft_secmark_obj_type,
255#endif
256};
257
252int __init nf_tables_core_module_init(void) 258int __init nf_tables_core_module_init(void)
253{ 259{
254 int err, i; 260 int err, i, j = 0;
261
262 for (i = 0; i < ARRAY_SIZE(nft_basic_objects); i++) {
263 err = nft_register_obj(nft_basic_objects[i]);
264 if (err)
265 goto err;
266 }
255 267
256 for (i = 0; i < ARRAY_SIZE(nft_basic_types); i++) { 268 for (j = 0; j < ARRAY_SIZE(nft_basic_types); j++) {
257 err = nft_register_expr(nft_basic_types[i]); 269 err = nft_register_expr(nft_basic_types[j]);
258 if (err) 270 if (err)
259 goto err; 271 goto err;
260 } 272 }
@@ -262,8 +274,12 @@ int __init nf_tables_core_module_init(void)
262 return 0; 274 return 0;
263 275
264err: 276err:
277 while (j-- > 0)
278 nft_unregister_expr(nft_basic_types[j]);
279
265 while (i-- > 0) 280 while (i-- > 0)
266 nft_unregister_expr(nft_basic_types[i]); 281 nft_unregister_obj(nft_basic_objects[i]);
282
267 return err; 283 return err;
268} 284}
269 285
@@ -274,4 +290,8 @@ void nf_tables_core_module_exit(void)
274 i = ARRAY_SIZE(nft_basic_types); 290 i = ARRAY_SIZE(nft_basic_types);
275 while (i-- > 0) 291 while (i-- > 0)
276 nft_unregister_expr(nft_basic_types[i]); 292 nft_unregister_expr(nft_basic_types[i]);
293
294 i = ARRAY_SIZE(nft_basic_objects);
295 while (i-- > 0)
296 nft_unregister_obj(nft_basic_objects[i]);
277} 297}
diff --git a/net/netfilter/nft_meta.c b/net/netfilter/nft_meta.c
index 297fe7d97c18..91fd6e677ad7 100644
--- a/net/netfilter/nft_meta.c
+++ b/net/netfilter/nft_meta.c
@@ -543,3 +543,111 @@ struct nft_expr_type nft_meta_type __read_mostly = {
543 .maxattr = NFTA_META_MAX, 543 .maxattr = NFTA_META_MAX,
544 .owner = THIS_MODULE, 544 .owner = THIS_MODULE,
545}; 545};
546
547#ifdef CONFIG_NETWORK_SECMARK
548struct nft_secmark {
549 u32 secid;
550 char *ctx;
551};
552
553static const struct nla_policy nft_secmark_policy[NFTA_SECMARK_MAX + 1] = {
554 [NFTA_SECMARK_CTX] = { .type = NLA_STRING, .len = NFT_SECMARK_CTX_MAXLEN },
555};
556
557static int nft_secmark_compute_secid(struct nft_secmark *priv)
558{
559 u32 tmp_secid = 0;
560 int err;
561
562 err = security_secctx_to_secid(priv->ctx, strlen(priv->ctx), &tmp_secid);
563 if (err)
564 return err;
565
566 if (!tmp_secid)
567 return -ENOENT;
568
569 err = security_secmark_relabel_packet(tmp_secid);
570 if (err)
571 return err;
572
573 priv->secid = tmp_secid;
574 return 0;
575}
576
577static void nft_secmark_obj_eval(struct nft_object *obj, struct nft_regs *regs,
578 const struct nft_pktinfo *pkt)
579{
580 const struct nft_secmark *priv = nft_obj_data(obj);
581 struct sk_buff *skb = pkt->skb;
582
583 skb->secmark = priv->secid;
584}
585
586static int nft_secmark_obj_init(const struct nft_ctx *ctx,
587 const struct nlattr * const tb[],
588 struct nft_object *obj)
589{
590 struct nft_secmark *priv = nft_obj_data(obj);
591 int err;
592
593 if (tb[NFTA_SECMARK_CTX] == NULL)
594 return -EINVAL;
595
596 priv->ctx = nla_strdup(tb[NFTA_SECMARK_CTX], GFP_KERNEL);
597 if (!priv->ctx)
598 return -ENOMEM;
599
600 err = nft_secmark_compute_secid(priv);
601 if (err) {
602 kfree(priv->ctx);
603 return err;
604 }
605
606 security_secmark_refcount_inc();
607
608 return 0;
609}
610
611static int nft_secmark_obj_dump(struct sk_buff *skb, struct nft_object *obj,
612 bool reset)
613{
614 struct nft_secmark *priv = nft_obj_data(obj);
615 int err;
616
617 if (nla_put_string(skb, NFTA_SECMARK_CTX, priv->ctx))
618 return -1;
619
620 if (reset) {
621 err = nft_secmark_compute_secid(priv);
622 if (err)
623 return err;
624 }
625
626 return 0;
627}
628
629static void nft_secmark_obj_destroy(const struct nft_ctx *ctx, struct nft_object *obj)
630{
631 struct nft_secmark *priv = nft_obj_data(obj);
632
633 security_secmark_refcount_dec();
634
635 kfree(priv->ctx);
636}
637
638static const struct nft_object_ops nft_secmark_obj_ops = {
639 .type = &nft_secmark_obj_type,
640 .size = sizeof(struct nft_secmark),
641 .init = nft_secmark_obj_init,
642 .eval = nft_secmark_obj_eval,
643 .dump = nft_secmark_obj_dump,
644 .destroy = nft_secmark_obj_destroy,
645};
646struct nft_object_type nft_secmark_obj_type __read_mostly = {
647 .type = NFT_OBJECT_SECMARK,
648 .ops = &nft_secmark_obj_ops,
649 .maxattr = NFTA_SECMARK_MAX,
650 .policy = nft_secmark_policy,
651 .owner = THIS_MODULE,
652};
653#endif /* CONFIG_NETWORK_SECMARK */