On 9/19/2018 4:14 PM, Christian Göttsche wrote: > 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 <cgzones@xxxxxxxxxxxxxx> I've only had a cursory look at your patch, but how is it different from what's in xt_SECMARK.c ? > --- > 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 */