[PATCH net-next RFC] netlink: Add compare function for netlink_table

Serge Hallyn serge.hallyn at ubuntu.com
Thu Jun 6 20:26:40 UTC 2013


Quoting Gao feng (gaofeng at cn.fujitsu.com):
> As we know, netlink sockets are private resource of
> net namespace, they can communicate with each other
> only when they in the same net namespace. this works
> well until we try to add namespace support for other
> subsystems which use netlink.
> 
> Don't like ipv4 and route table.., it is not suited to
> make these subsytems belong to net namespace, Such as
> audit and crypto subsystems,they are more suitable to
> user namespace.
> 
> So we must have the ability to make the netlink sockets
> in same user namespace can communicate with each other.
> 
> This patch adds a new function pointer "compare" for
> netlink_table, we can decide if the netlink sockets can
> communicate with each other through this netlink_table
> self-defined compare function.
> 
> The behavior isn't changed if we don't provide the compare
> function for netlink_table.
> 
> Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>

Hi,

I'm looking at that set right now.  So far all looks good to me.
I expect to send a blanket ack for the set, but since you've sent
this patch separately:

Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>

> ---
> Actually I already send a patchset to add namespace support
> for audit subsystem [1]. this patch is a part of the patchset.
> I think it's better to send this patch out separately, since
> some people may have comments on this one. I need to know what's
> the idea of network guy.
> 
> [1] http://lwn.net/Articles/549546/
> 
>  include/linux/netlink.h  |  1 +
>  net/netlink/af_netlink.c | 33 +++++++++++++++++++++++++--------
>  net/netlink/af_netlink.h |  1 +
>  3 files changed, 27 insertions(+), 8 deletions(-)
> 
> diff --git a/include/linux/netlink.h b/include/linux/netlink.h
> index 6358da5..f78b430 100644
> --- a/include/linux/netlink.h
> +++ b/include/linux/netlink.h
> @@ -46,6 +46,7 @@ struct netlink_kernel_cfg {
>  	void		(*input)(struct sk_buff *skb);
>  	struct mutex	*cb_mutex;
>  	void		(*bind)(int group);
> +	bool		(*compare)(struct net *net, struct sock *sk);
>  };
>  
>  extern struct sock *__netlink_kernel_create(struct net *net, int unit,
> diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
> index 12ac6b4..e399877 100644
> --- a/net/netlink/af_netlink.c
> +++ b/net/netlink/af_netlink.c
> @@ -854,16 +854,23 @@ netlink_unlock_table(void)
>  		wake_up(&nl_table_wait);
>  }
>  
> +static bool netlink_compare(struct net *net, struct sock *sk)
> +{
> +	return net_eq(sock_net(sk), net);
> +}
> +
>  static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid)
>  {
> -	struct nl_portid_hash *hash = &nl_table[protocol].hash;
> +	struct netlink_table *table = &nl_table[protocol];
> +	struct nl_portid_hash *hash = &table->hash;
>  	struct hlist_head *head;
>  	struct sock *sk;
>  
>  	read_lock(&nl_table_lock);
>  	head = nl_portid_hashfn(hash, portid);
>  	sk_for_each(sk, head) {
> -		if (net_eq(sock_net(sk), net) && (nlk_sk(sk)->portid == portid)) {
> +		if (table->compare(net, sk) &&
> +		    (nlk_sk(sk)->portid == portid)) {
>  			sock_hold(sk);
>  			goto found;
>  		}
> @@ -976,7 +983,8 @@ netlink_update_listeners(struct sock *sk)
>  
>  static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
>  {
> -	struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash;
> +	struct netlink_table *table = &nl_table[sk->sk_protocol];
> +	struct nl_portid_hash *hash = &table->hash;
>  	struct hlist_head *head;
>  	int err = -EADDRINUSE;
>  	struct sock *osk;
> @@ -986,7 +994,8 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid)
>  	head = nl_portid_hashfn(hash, portid);
>  	len = 0;
>  	sk_for_each(osk, head) {
> -		if (net_eq(sock_net(osk), net) && (nlk_sk(osk)->portid == portid))
> +		if (table->compare(net, osk) &&
> +		    (nlk_sk(osk)->portid == portid))
>  			break;
>  		len++;
>  	}
> @@ -1161,6 +1170,7 @@ static int netlink_release(struct socket *sock)
>  			kfree_rcu(old, rcu);
>  			nl_table[sk->sk_protocol].module = NULL;
>  			nl_table[sk->sk_protocol].bind = NULL;
> +			nl_table[sk->sk_protocol].compare = NULL;
>  			nl_table[sk->sk_protocol].flags = 0;
>  			nl_table[sk->sk_protocol].registered = 0;
>  		}
> @@ -1183,7 +1193,8 @@ static int netlink_autobind(struct socket *sock)
>  {
>  	struct sock *sk = sock->sk;
>  	struct net *net = sock_net(sk);
> -	struct nl_portid_hash *hash = &nl_table[sk->sk_protocol].hash;
> +	struct netlink_table *table = &nl_table[sk->sk_protocol];
> +	struct nl_portid_hash *hash = &table->hash;
>  	struct hlist_head *head;
>  	struct sock *osk;
>  	s32 portid = task_tgid_vnr(current);
> @@ -1195,7 +1206,7 @@ retry:
>  	netlink_table_grab();
>  	head = nl_portid_hashfn(hash, portid);
>  	sk_for_each(osk, head) {
> -		if (!net_eq(sock_net(osk), net))
> +		if (!table->compare(net, osk))
>  			continue;
>  		if (nlk_sk(osk)->portid == portid) {
>  			/* Bind collision, search negative portid values. */
> @@ -2282,9 +2293,12 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
>  		rcu_assign_pointer(nl_table[unit].listeners, listeners);
>  		nl_table[unit].cb_mutex = cb_mutex;
>  		nl_table[unit].module = module;
> +		nl_table[unit].compare = netlink_compare;
>  		if (cfg) {
>  			nl_table[unit].bind = cfg->bind;
>  			nl_table[unit].flags = cfg->flags;
> +			if (cfg->compare)
> +				nl_table[unit].compare = cfg->compare;
>  		}
>  		nl_table[unit].registered = 1;
>  	} else {
> @@ -2707,6 +2721,7 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>  {
>  	struct sock *s;
>  	struct nl_seq_iter *iter;
> +	struct net *net;
>  	int i, j;
>  
>  	++*pos;
> @@ -2714,11 +2729,12 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>  	if (v == SEQ_START_TOKEN)
>  		return netlink_seq_socket_idx(seq, 0);
>  
> +	net = seq_file_net(seq);
>  	iter = seq->private;
>  	s = v;
>  	do {
>  		s = sk_next(s);
> -	} while (s && sock_net(s) != seq_file_net(seq));
> +	} while (s && !nl_table[s->sk_protocol].compare(net, s));
>  	if (s)
>  		return s;
>  
> @@ -2730,7 +2746,8 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos)
>  
>  		for (; j <= hash->mask; j++) {
>  			s = sk_head(&hash->table[j]);
> -			while (s && sock_net(s) != seq_file_net(seq))
> +
> +			while (s && !nl_table[s->sk_protocol].compare(net, s))
>  				s = sk_next(s);
>  			if (s) {
>  				iter->link = i;
> diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
> index ed85222..eaa88d1 100644
> --- a/net/netlink/af_netlink.h
> +++ b/net/netlink/af_netlink.h
> @@ -73,6 +73,7 @@ struct netlink_table {
>  	struct mutex		*cb_mutex;
>  	struct module		*module;
>  	void			(*bind)(int group);
> +	bool			(*compare)(struct net *net, struct sock *sock);
>  	int			registered;
>  };
>  
> -- 
> 1.8.1.4
> 
> _______________________________________________
> Containers mailing list
> Containers at lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/containers




More information about the Linux-audit mailing list