[2/2,WIP,nf-next] nft: implement the nf_tables_api changes to add osf signatures in nft

Message ID 20180712103414.2501-2-ffmancera@riseup.net
State RFC
Delegated to: Pablo Neira
Headers show
Series
  • Untitled series #55124
Related show

Commit Message

Fernando Fernandez Mancera July 12, 2018, 10:34 a.m.
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 <ffmancera@riseup.net>
---
 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(-)

Comments

Florian Westphal July 12, 2018, 11:03 a.m. | #1
Fernando Fernandez Mancera <ffmancera@riseup.net> wrote:
> +extern struct list_head nft_osf_fingers[2];

How is this going to be used?

I find it weird to see this in netfilter core.

> +	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]);
> +

This is missing input validation.
I see no nla_policy for OSF_ATTR_FINGER.

Userspace could have placed anything from 0 to 0xffff bytes.

+	memcpy(&kf->finger, f, sizeof(struct nf_osf_user_finger));

Probably should use
nla_memdup() + an nla_plolicy struct entry.

Or nla_memdup() plus manual checking of nla_len() vs. expected/sane
values?

> +	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);

Hmm.  So there can't be any duplicate entries in first place.

So I really wonder how this is going to be used or why
all of this code can't live in nft_osf.c .

I mean, we are adding this to core nftables api, and i think this is
something that should only be done if it can't be specific to particular
expression for some reason.

> +	list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) {
> +		if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger)))
> +			continue;

list_for_each_entry_safe?

--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Fernando Fernandez Mancera July 12, 2018, 11:37 a.m. | #2
On 07/12/2018 01:27 PM, Florian Westphal wrote:
> Fernando Fernandez Mancera <ffmancera@riseup.net> wrote:
>>>> +	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);
>>>
>>> Hmm.  So there can't be any duplicate entries in first place.
>>>
>>> So I really wonder how this is going to be used or why
>>> all of this code can't live in nft_osf.c .
>>>
>>> I mean, we are adding this to core nftables api, and i think this is
>>> something that should only be done if it can't be specific to particular
>>> expression for some reason.
>>
>> Can we load/unload pf.os signatures from nft_osf.c at the expression init?
>> If we can do it, then maybe all this code can live in nft_osf.c.
> 
> I'd like to see how this is used from grammar point of view first.
> What does a rule look like?

A rule will contain a string (the OS we want to match) and two u8 
(loglevel and ttl).

> 
> Are the osf signatures global, tied to table, tied to expression?
> 

OSF signatures should be load at the osf expression init if I am not 
wrong, and that only happens once. If we add more rules using osf they 
should use the already loaded signatures.

>>>> +	list_for_each_entry(sf, &nft_osf_fingers[!!f->df], finger_entry) {
>>>> +		if (memcmp(&sf->finger, f, sizeof(struct nf_osf_user_finger)))
>>>> +			continue;
>>>
>>> list_for_each_entry_safe?
>>
>> I think it is not necessary and isn't used in xt_osf module, but we can use
>> it if recommended.
> 
> xt_osf use looks buggy too...  I don't see it holding rcu read lock, so
> once kfree_rcu() is invoked sf ->next pointer can already reside in
> free'd memory.
> 

Okey then let's use list_for_each_entry_safe. Will fix xt_osf too.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso July 12, 2018, 2:04 p.m. | #3
On Thu, Jul 12, 2018 at 01:03:00PM +0200, Florian Westphal wrote:
> Fernando Fernandez Mancera <ffmancera@riseup.net> wrote:
> > +extern struct list_head nft_osf_fingers[2];
> 
> How is this going to be used?
> 
> I find it weird to see this in netfilter core.

We can also place it as a struct nft_object_ops, but we'll need some
infrastructure to define singleton objects, ie. allow to add only one
single instance of the 'osf' fingerprints object that can be used the
rule.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Florian Westphal July 12, 2018, 2:27 p.m. | #4
Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> On Thu, Jul 12, 2018 at 01:03:00PM +0200, Florian Westphal wrote:
> > Fernando Fernandez Mancera <ffmancera@riseup.net> wrote:
> > > +extern struct list_head nft_osf_fingers[2];
> > 
> > How is this going to be used?
> > 
> > I find it weird to see this in netfilter core.
> 
> We can also place it as a struct nft_object_ops, but we'll need some
> infrastructure to define singleton objects, ie. allow to add only one
> single instance of the 'osf' fingerprints object that can be used the
> rule.

Why so complicated?
Where is this file coming from?
Do we even need a file?
Why/how does user care?

I get feeling we only have this nfnl_osf tool because iptables
uapi is smelly and can't do any better.

So again, how does this look like from user point of view?

Is it something that is going to be shipped with nft itself?
Is it something coming from external source?
What is this osf nft version going to be?

A statement?
An expression?

If so, what does it return?
Name of os found in a register?
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Florian Westphal July 12, 2018, 4:27 p.m. | #5
Florian Westphal <fw@strlen.de> wrote:
> Pablo Neira Ayuso <pablo@netfilter.org> wrote:
> > On Thu, Jul 12, 2018 at 01:03:00PM +0200, Florian Westphal wrote:
> > > Fernando Fernandez Mancera <ffmancera@riseup.net> wrote:
> > > > +extern struct list_head nft_osf_fingers[2];
> > > 
> > > How is this going to be used?
> > > 
> > > I find it weird to see this in netfilter core.
> > 
> > We can also place it as a struct nft_object_ops, but we'll need some
> > infrastructure to define singleton objects, ie. allow to add only one
> > single instance of the 'osf' fingerprints object that can be used the
> > rule.
> 
> Why so complicated?
[..]

I did not intend to be negative.

I am trying to review this but I have a hard time giving
feedback because I do not understand what the end result is
supposed to do, what service(s) it provides, etc.

It would be good if intended usage could be illustrated
with a few examples, it might make most of my questions obsolete.
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso July 12, 2018, 8:18 p.m. | #6
On Thu, Jul 12, 2018 at 12:34:14PM +0200, Fernando Fernandez Mancera wrote:
> 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 <ffmancera@riseup.net>
> ---
>  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 <linux/types.h>
> +#include <linux/ip.h>
> +#include <linux/tcp.h>
>  
>  #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 <linux/netfilter.h>
>  #include <linux/netfilter/nfnetlink.h>
>  #include <linux/netfilter/nf_tables.h>
> +#include <linux/netfilter/nf_osf.h>
>  #include <net/netfilter/nf_flow_table.h>
>  #include <net/netfilter/nf_tables_core.h>
>  #include <net/netfilter/nf_tables.h>
> @@ -26,6 +27,7 @@
>  static LIST_HEAD(nf_tables_expressions);
>  static LIST_HEAD(nf_tables_objects);
>  static LIST_HEAD(nf_tables_flowtables);
> +

Por favor, evita este ruido en los parche.

>  static u64 table_handle;
>  
>  enum {
> @@ -5851,6 +5853,8 @@ static int nf_tables_flowtable_event(struct notifier_block *this,
>  	return NOTIFY_DONE;
>  }
>  
> +
> +

Estas dos líneas nuevas es también ruido, no pertenecen a este
problema.

>  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);
> +

De nuevo línea innecesaria.

Intenta ser meticuloso con lo que presentas, pues da la sensación a
quien lo envías que no eres cuidadoso con los detalles...

>  	return 0;
>  }
>  
> -- 
> 2.18.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Pablo Neira Ayuso July 12, 2018, 8:19 p.m. | #7
Hi,

I'm sorry for this email in Spanish, I forgot to trim off Cc when
reviewing some cosmestic stuff.

On Thu, Jul 12, 2018 at 10:18:32PM +0200, Pablo Neira Ayuso wrote:
> On Thu, Jul 12, 2018 at 12:34:14PM +0200, Fernando Fernandez Mancera wrote:
> > 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 <ffmancera@riseup.net>
> > ---
> >  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 <linux/types.h>
> > +#include <linux/ip.h>
> > +#include <linux/tcp.h>
> >  
> >  #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 <linux/netfilter.h>
> >  #include <linux/netfilter/nfnetlink.h>
> >  #include <linux/netfilter/nf_tables.h>
> > +#include <linux/netfilter/nf_osf.h>
> >  #include <net/netfilter/nf_flow_table.h>
> >  #include <net/netfilter/nf_tables_core.h>
> >  #include <net/netfilter/nf_tables.h>
> > @@ -26,6 +27,7 @@
> >  static LIST_HEAD(nf_tables_expressions);
> >  static LIST_HEAD(nf_tables_objects);
> >  static LIST_HEAD(nf_tables_flowtables);
> > +
> 
> Por favor, evita este ruido en los parche.
> 
> >  static u64 table_handle;
> >  
> >  enum {
> > @@ -5851,6 +5853,8 @@ static int nf_tables_flowtable_event(struct notifier_block *this,
> >  	return NOTIFY_DONE;
> >  }
> >  
> > +
> > +
> 
> Estas dos líneas nuevas es también ruido, no pertenecen a este
> problema.
> 
> >  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);
> > +
> 
> De nuevo línea innecesaria.
> 
> Intenta ser meticuloso con lo que presentas, pues da la sensación a
> quien lo envías que no eres cuidadoso con los detalles...
> 
> >  	return 0;
> >  }
> >  
> > -- 
> > 2.18.0
> > 
> > --
> > To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Patch

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 <linux/types.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
 
 #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 <linux/netfilter.h>
 #include <linux/netfilter/nfnetlink.h>
 #include <linux/netfilter/nf_tables.h>
+#include <linux/netfilter/nf_osf.h>
 #include <net/netfilter/nf_flow_table.h>
 #include <net/netfilter/nf_tables_core.h>
 #include <net/netfilter/nf_tables.h>
@@ -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;
 }