mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Add a new socket option, NETLINK_DUMP_STRICT_CHK, that userspace can use via setsockopt to request strict checking of headers and attributes on dump requests. To get dump features such as kernel side filtering based on data in the header or attributes appended to the dump request, userspace must call setsockopt() for NETLINK_DUMP_STRICT_CHK and a non-zero value. Since the netlink sock and its flags are private to the af_netlink code, the strict checking flag is passed to dump handlers via a flag in the netlink_callback struct. For old userspace on new kernel there is no impact as all of the data checks in later patches are wrapped in a check on the new strict flag. For new userspace on old kernel, the setsockopt will fail and even if new userspace sets data in the headers and appended attributes the kernel will silently ignore it. Moving forward when the setsockopt succeeds, the new userspace on old kernel means the dump request can pass an attribute the kernel does not understand. The dump will then fail as the older kernel does not understand it. New userspace on new kernel setting the socket option gets the benefit of the improved data dump. Kernel side the NETLINK_DUMP_STRICT_CHK uapi is converted to a generic NETLINK_F_STRICT_CHK flag which can potentially be leveraged for tighter checking on the NEW, DEL, and SET commands. Signed-off-by: David Ahern <dsahern@gmail.com> Acked-by: Christian Brauner <christian@brauner.io> Signed-off-by: David S. Miller <davem@davemloft.net>
		
			
				
	
	
		
			74 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
	
		
			1.8 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* SPDX-License-Identifier: GPL-2.0 */
 | 
						|
#ifndef _AF_NETLINK_H
 | 
						|
#define _AF_NETLINK_H
 | 
						|
 | 
						|
#include <linux/rhashtable.h>
 | 
						|
#include <linux/atomic.h>
 | 
						|
#include <linux/workqueue.h>
 | 
						|
#include <net/sock.h>
 | 
						|
 | 
						|
/* flags */
 | 
						|
#define NETLINK_F_KERNEL_SOCKET		0x1
 | 
						|
#define NETLINK_F_RECV_PKTINFO		0x2
 | 
						|
#define NETLINK_F_BROADCAST_SEND_ERROR	0x4
 | 
						|
#define NETLINK_F_RECV_NO_ENOBUFS	0x8
 | 
						|
#define NETLINK_F_LISTEN_ALL_NSID	0x10
 | 
						|
#define NETLINK_F_CAP_ACK		0x20
 | 
						|
#define NETLINK_F_EXT_ACK		0x40
 | 
						|
#define NETLINK_F_STRICT_CHK		0x80
 | 
						|
 | 
						|
#define NLGRPSZ(x)	(ALIGN(x, sizeof(unsigned long) * 8) / 8)
 | 
						|
#define NLGRPLONGS(x)	(NLGRPSZ(x)/sizeof(unsigned long))
 | 
						|
 | 
						|
struct netlink_sock {
 | 
						|
	/* struct sock has to be the first member of netlink_sock */
 | 
						|
	struct sock		sk;
 | 
						|
	u32			portid;
 | 
						|
	u32			dst_portid;
 | 
						|
	u32			dst_group;
 | 
						|
	u32			flags;
 | 
						|
	u32			subscriptions;
 | 
						|
	u32			ngroups;
 | 
						|
	unsigned long		*groups;
 | 
						|
	unsigned long		state;
 | 
						|
	size_t			max_recvmsg_len;
 | 
						|
	wait_queue_head_t	wait;
 | 
						|
	bool			bound;
 | 
						|
	bool			cb_running;
 | 
						|
	int			dump_done_errno;
 | 
						|
	struct netlink_callback	cb;
 | 
						|
	struct mutex		*cb_mutex;
 | 
						|
	struct mutex		cb_def_mutex;
 | 
						|
	void			(*netlink_rcv)(struct sk_buff *skb);
 | 
						|
	int			(*netlink_bind)(struct net *net, int group);
 | 
						|
	void			(*netlink_unbind)(struct net *net, int group);
 | 
						|
	struct module		*module;
 | 
						|
 | 
						|
	struct rhash_head	node;
 | 
						|
	struct rcu_head		rcu;
 | 
						|
	struct work_struct	work;
 | 
						|
};
 | 
						|
 | 
						|
static inline struct netlink_sock *nlk_sk(struct sock *sk)
 | 
						|
{
 | 
						|
	return container_of(sk, struct netlink_sock, sk);
 | 
						|
}
 | 
						|
 | 
						|
struct netlink_table {
 | 
						|
	struct rhashtable	hash;
 | 
						|
	struct hlist_head	mc_list;
 | 
						|
	struct listeners __rcu	*listeners;
 | 
						|
	unsigned int		flags;
 | 
						|
	unsigned int		groups;
 | 
						|
	struct mutex		*cb_mutex;
 | 
						|
	struct module		*module;
 | 
						|
	int			(*bind)(struct net *net, int group);
 | 
						|
	void			(*unbind)(struct net *net, int group);
 | 
						|
	bool			(*compare)(struct net *net, struct sock *sock);
 | 
						|
	int			registered;
 | 
						|
};
 | 
						|
 | 
						|
extern struct netlink_table *nl_table;
 | 
						|
extern rwlock_t nl_table_lock;
 | 
						|
 | 
						|
#endif
 |