mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	net: inet: diag: expose the socket mark to privileged processes.
This adds the capability for a process that has CAP_NET_ADMIN on
a socket to see the socket mark in socket dumps.
Commit a52e95abf7 ("net: diag: allow socket bytecode filters to
match socket marks") recently gave privileged processes the
ability to filter socket dumps based on mark. This patch is
complementary: it ensures that the mark is also passed to
userspace in the socket's netlink attributes.  It is useful for
tools like ss which display information about sockets.
Tested: https://android-review.googlesource.com/270210
Signed-off-by: Lorenzo Colitti <lorenzo@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									74f13c80e2
								
							
						
					
					
						commit
						d545caca82
					
				
					 5 changed files with 56 additions and 28 deletions
				
			
		| 
						 | 
					@ -37,7 +37,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 | 
				
			||||||
		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 | 
							      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 | 
				
			||||||
		      struct user_namespace *user_ns,
 | 
							      struct user_namespace *user_ns,
 | 
				
			||||||
		      u32 pid, u32 seq, u16 nlmsg_flags,
 | 
							      u32 pid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
		      const struct nlmsghdr *unlh);
 | 
							      const struct nlmsghdr *unlh, bool net_admin);
 | 
				
			||||||
void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
 | 
					void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
 | 
				
			||||||
			 struct netlink_callback *cb,
 | 
								 struct netlink_callback *cb,
 | 
				
			||||||
			 const struct inet_diag_req_v2 *r,
 | 
								 const struct inet_diag_req_v2 *r,
 | 
				
			||||||
| 
						 | 
					@ -56,7 +56,7 @@ void inet_diag_msg_common_fill(struct inet_diag_msg *r, struct sock *sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 | 
					int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			     struct inet_diag_msg *r, int ext,
 | 
								     struct inet_diag_msg *r, int ext,
 | 
				
			||||||
			     struct user_namespace *user_ns);
 | 
								     struct user_namespace *user_ns, bool net_admin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int  inet_diag_register(const struct inet_diag_handler *handler);
 | 
					extern int  inet_diag_register(const struct inet_diag_handler *handler);
 | 
				
			||||||
extern void inet_diag_unregister(const struct inet_diag_handler *handler);
 | 
					extern void inet_diag_unregister(const struct inet_diag_handler *handler);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,6 +123,7 @@ enum {
 | 
				
			||||||
	INET_DIAG_LOCALS,
 | 
						INET_DIAG_LOCALS,
 | 
				
			||||||
	INET_DIAG_PEERS,
 | 
						INET_DIAG_PEERS,
 | 
				
			||||||
	INET_DIAG_PAD,
 | 
						INET_DIAG_PAD,
 | 
				
			||||||
 | 
						INET_DIAG_MARK,
 | 
				
			||||||
	__INET_DIAG_MAX,
 | 
						__INET_DIAG_MAX,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,6 +99,7 @@ static size_t inet_sk_attr_size(void)
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
 | 
							+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_TOS */
 | 
							+ nla_total_size(1) /* INET_DIAG_TOS */
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_TCLASS */
 | 
							+ nla_total_size(1) /* INET_DIAG_TCLASS */
 | 
				
			||||||
 | 
							+ nla_total_size(4) /* INET_DIAG_MARK */
 | 
				
			||||||
		+ nla_total_size(sizeof(struct inet_diag_meminfo))
 | 
							+ nla_total_size(sizeof(struct inet_diag_meminfo))
 | 
				
			||||||
		+ nla_total_size(sizeof(struct inet_diag_msg))
 | 
							+ nla_total_size(sizeof(struct inet_diag_msg))
 | 
				
			||||||
		+ nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
 | 
							+ nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
 | 
				
			||||||
| 
						 | 
					@ -109,7 +110,8 @@ static size_t inet_sk_attr_size(void)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 | 
					int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			     struct inet_diag_msg *r, int ext,
 | 
								     struct inet_diag_msg *r, int ext,
 | 
				
			||||||
			     struct user_namespace *user_ns)
 | 
								     struct user_namespace *user_ns,
 | 
				
			||||||
 | 
								     bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct inet_sock *inet = inet_sk(sk);
 | 
						const struct inet_sock *inet = inet_sk(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -136,6 +138,9 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
 | 
				
			||||||
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
 | 
						r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
 | 
				
			||||||
	r->idiag_inode = sock_i_ino(sk);
 | 
						r->idiag_inode = sock_i_ino(sk);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -149,7 +154,8 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 | 
				
			||||||
		      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 | 
							      struct sk_buff *skb, const struct inet_diag_req_v2 *req,
 | 
				
			||||||
		      struct user_namespace *user_ns,
 | 
							      struct user_namespace *user_ns,
 | 
				
			||||||
		      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
							      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
		      const struct nlmsghdr *unlh)
 | 
							      const struct nlmsghdr *unlh,
 | 
				
			||||||
 | 
							      bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	const struct tcp_congestion_ops *ca_ops;
 | 
						const struct tcp_congestion_ops *ca_ops;
 | 
				
			||||||
	const struct inet_diag_handler *handler;
 | 
						const struct inet_diag_handler *handler;
 | 
				
			||||||
| 
						 | 
					@ -175,7 +181,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
 | 
				
			||||||
	r->idiag_timer = 0;
 | 
						r->idiag_timer = 0;
 | 
				
			||||||
	r->idiag_retrans = 0;
 | 
						r->idiag_retrans = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns))
 | 
						if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
 | 
				
			||||||
		goto errout;
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
 | 
						if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
 | 
				
			||||||
| 
						 | 
					@ -274,10 +280,11 @@ static int inet_csk_diag_fill(struct sock *sk,
 | 
				
			||||||
			      const struct inet_diag_req_v2 *req,
 | 
								      const struct inet_diag_req_v2 *req,
 | 
				
			||||||
			      struct user_namespace *user_ns,
 | 
								      struct user_namespace *user_ns,
 | 
				
			||||||
			      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
								      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
			      const struct nlmsghdr *unlh)
 | 
								      const struct nlmsghdr *unlh,
 | 
				
			||||||
 | 
								      bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return inet_sk_diag_fill(sk, inet_csk(sk), skb, req,
 | 
						return inet_sk_diag_fill(sk, inet_csk(sk), skb, req, user_ns,
 | 
				
			||||||
				 user_ns, portid, seq, nlmsg_flags, unlh);
 | 
									 portid, seq, nlmsg_flags, unlh, net_admin);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int inet_twsk_diag_fill(struct sock *sk,
 | 
					static int inet_twsk_diag_fill(struct sock *sk,
 | 
				
			||||||
| 
						 | 
					@ -319,8 +326,9 @@ static int inet_twsk_diag_fill(struct sock *sk,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
					static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
								      u32 portid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
			      const struct nlmsghdr *unlh)
 | 
								      const struct nlmsghdr *unlh, bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct request_sock *reqsk = inet_reqsk(sk);
 | 
				
			||||||
	struct inet_diag_msg *r;
 | 
						struct inet_diag_msg *r;
 | 
				
			||||||
	struct nlmsghdr *nlh;
 | 
						struct nlmsghdr *nlh;
 | 
				
			||||||
	long tmo;
 | 
						long tmo;
 | 
				
			||||||
| 
						 | 
					@ -334,7 +342,7 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	inet_diag_msg_common_fill(r, sk);
 | 
						inet_diag_msg_common_fill(r, sk);
 | 
				
			||||||
	r->idiag_state = TCP_SYN_RECV;
 | 
						r->idiag_state = TCP_SYN_RECV;
 | 
				
			||||||
	r->idiag_timer = 1;
 | 
						r->idiag_timer = 1;
 | 
				
			||||||
	r->idiag_retrans = inet_reqsk(sk)->num_retrans;
 | 
						r->idiag_retrans = reqsk->num_retrans;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
 | 
						BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
 | 
				
			||||||
		     offsetof(struct sock, sk_cookie));
 | 
							     offsetof(struct sock, sk_cookie));
 | 
				
			||||||
| 
						 | 
					@ -346,6 +354,10 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	r->idiag_uid	= 0;
 | 
						r->idiag_uid	= 0;
 | 
				
			||||||
	r->idiag_inode	= 0;
 | 
						r->idiag_inode	= 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (net_admin && nla_put_u32(skb, INET_DIAG_MARK,
 | 
				
			||||||
 | 
									     inet_rsk(reqsk)->ir_mark))
 | 
				
			||||||
 | 
							return -EMSGSIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	nlmsg_end(skb, nlh);
 | 
						nlmsg_end(skb, nlh);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -354,7 +366,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			const struct inet_diag_req_v2 *r,
 | 
								const struct inet_diag_req_v2 *r,
 | 
				
			||||||
			struct user_namespace *user_ns,
 | 
								struct user_namespace *user_ns,
 | 
				
			||||||
			u32 portid, u32 seq, u16 nlmsg_flags,
 | 
								u32 portid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
			const struct nlmsghdr *unlh)
 | 
								const struct nlmsghdr *unlh, bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (sk->sk_state == TCP_TIME_WAIT)
 | 
						if (sk->sk_state == TCP_TIME_WAIT)
 | 
				
			||||||
		return inet_twsk_diag_fill(sk, skb, portid, seq,
 | 
							return inet_twsk_diag_fill(sk, skb, portid, seq,
 | 
				
			||||||
| 
						 | 
					@ -362,10 +374,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sk->sk_state == TCP_NEW_SYN_RECV)
 | 
						if (sk->sk_state == TCP_NEW_SYN_RECV)
 | 
				
			||||||
		return inet_req_diag_fill(sk, skb, portid, seq,
 | 
							return inet_req_diag_fill(sk, skb, portid, seq,
 | 
				
			||||||
					  nlmsg_flags, unlh);
 | 
										  nlmsg_flags, unlh, net_admin);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
 | 
						return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
 | 
				
			||||||
				  nlmsg_flags, unlh);
 | 
									  nlmsg_flags, unlh, net_admin);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sock *inet_diag_find_one_icsk(struct net *net,
 | 
					struct sock *inet_diag_find_one_icsk(struct net *net,
 | 
				
			||||||
| 
						 | 
					@ -435,7 +447,8 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
 | 
				
			||||||
	err = sk_diag_fill(sk, rep, req,
 | 
						err = sk_diag_fill(sk, rep, req,
 | 
				
			||||||
			   sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
								   sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
				
			||||||
			   NETLINK_CB(in_skb).portid,
 | 
								   NETLINK_CB(in_skb).portid,
 | 
				
			||||||
			   nlh->nlmsg_seq, 0, nlh);
 | 
								   nlh->nlmsg_seq, 0, nlh,
 | 
				
			||||||
 | 
								   netlink_net_capable(in_skb, CAP_NET_ADMIN));
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		WARN_ON(err == -EMSGSIZE);
 | 
							WARN_ON(err == -EMSGSIZE);
 | 
				
			||||||
		nlmsg_free(rep);
 | 
							nlmsg_free(rep);
 | 
				
			||||||
| 
						 | 
					@ -796,7 +809,8 @@ static int inet_csk_diag_dump(struct sock *sk,
 | 
				
			||||||
			      struct sk_buff *skb,
 | 
								      struct sk_buff *skb,
 | 
				
			||||||
			      struct netlink_callback *cb,
 | 
								      struct netlink_callback *cb,
 | 
				
			||||||
			      const struct inet_diag_req_v2 *r,
 | 
								      const struct inet_diag_req_v2 *r,
 | 
				
			||||||
			      const struct nlattr *bc)
 | 
								      const struct nlattr *bc,
 | 
				
			||||||
 | 
								      bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!inet_diag_bc_sk(bc, sk))
 | 
						if (!inet_diag_bc_sk(bc, sk))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -804,7 +818,8 @@ static int inet_csk_diag_dump(struct sock *sk,
 | 
				
			||||||
	return inet_csk_diag_fill(sk, skb, r,
 | 
						return inet_csk_diag_fill(sk, skb, r,
 | 
				
			||||||
				  sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
									  sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
				  NETLINK_CB(cb->skb).portid,
 | 
									  NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
				  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 | 
									  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh,
 | 
				
			||||||
 | 
									  net_admin);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void twsk_build_assert(void)
 | 
					static void twsk_build_assert(void)
 | 
				
			||||||
| 
						 | 
					@ -840,6 +855,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 | 
				
			||||||
	struct net *net = sock_net(skb->sk);
 | 
						struct net *net = sock_net(skb->sk);
 | 
				
			||||||
	int i, num, s_i, s_num;
 | 
						int i, num, s_i, s_num;
 | 
				
			||||||
	u32 idiag_states = r->idiag_states;
 | 
						u32 idiag_states = r->idiag_states;
 | 
				
			||||||
 | 
						bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (idiag_states & TCPF_SYN_RECV)
 | 
						if (idiag_states & TCPF_SYN_RECV)
 | 
				
			||||||
		idiag_states |= TCPF_NEW_SYN_RECV;
 | 
							idiag_states |= TCPF_NEW_SYN_RECV;
 | 
				
			||||||
| 
						 | 
					@ -880,7 +896,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 | 
				
			||||||
				    cb->args[3] > 0)
 | 
									    cb->args[3] > 0)
 | 
				
			||||||
					goto next_listen;
 | 
										goto next_listen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) {
 | 
									if (inet_csk_diag_dump(sk, skb, cb, r,
 | 
				
			||||||
 | 
											       bc, net_admin) < 0) {
 | 
				
			||||||
					spin_unlock_bh(&ilb->lock);
 | 
										spin_unlock_bh(&ilb->lock);
 | 
				
			||||||
					goto done;
 | 
										goto done;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
| 
						 | 
					@ -948,7 +965,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
 | 
				
			||||||
					   sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
										   sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
					   NETLINK_CB(cb->skb).portid,
 | 
										   NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
					   cb->nlh->nlmsg_seq, NLM_F_MULTI,
 | 
										   cb->nlh->nlmsg_seq, NLM_F_MULTI,
 | 
				
			||||||
					   cb->nlh);
 | 
										   cb->nlh, net_admin);
 | 
				
			||||||
			if (res < 0) {
 | 
								if (res < 0) {
 | 
				
			||||||
				spin_unlock_bh(lock);
 | 
									spin_unlock_bh(lock);
 | 
				
			||||||
				goto done;
 | 
									goto done;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@
 | 
				
			||||||
static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
 | 
					static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
			struct netlink_callback *cb,
 | 
								struct netlink_callback *cb,
 | 
				
			||||||
			const struct inet_diag_req_v2 *req,
 | 
								const struct inet_diag_req_v2 *req,
 | 
				
			||||||
			struct nlattr *bc)
 | 
								struct nlattr *bc, bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (!inet_diag_bc_sk(bc, sk))
 | 
						if (!inet_diag_bc_sk(bc, sk))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
 | 
				
			||||||
	return inet_sk_diag_fill(sk, NULL, skb, req,
 | 
						return inet_sk_diag_fill(sk, NULL, skb, req,
 | 
				
			||||||
			sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
								sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
			NETLINK_CB(cb->skb).portid,
 | 
								NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
			cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 | 
								cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh, net_admin);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 | 
					static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 | 
				
			||||||
| 
						 | 
					@ -76,7 +76,8 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
 | 
				
			||||||
	err = inet_sk_diag_fill(sk, NULL, rep, req,
 | 
						err = inet_sk_diag_fill(sk, NULL, rep, req,
 | 
				
			||||||
			   sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
								   sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
				
			||||||
			   NETLINK_CB(in_skb).portid,
 | 
								   NETLINK_CB(in_skb).portid,
 | 
				
			||||||
			   nlh->nlmsg_seq, 0, nlh);
 | 
								   nlh->nlmsg_seq, 0, nlh,
 | 
				
			||||||
 | 
								   netlink_net_capable(in_skb, CAP_NET_ADMIN));
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		WARN_ON(err == -EMSGSIZE);
 | 
							WARN_ON(err == -EMSGSIZE);
 | 
				
			||||||
		kfree_skb(rep);
 | 
							kfree_skb(rep);
 | 
				
			||||||
| 
						 | 
					@ -97,6 +98,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb,
 | 
				
			||||||
		     struct netlink_callback *cb,
 | 
							     struct netlink_callback *cb,
 | 
				
			||||||
		     const struct inet_diag_req_v2 *r, struct nlattr *bc)
 | 
							     const struct inet_diag_req_v2 *r, struct nlattr *bc)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
 | 
				
			||||||
	struct net *net = sock_net(skb->sk);
 | 
						struct net *net = sock_net(skb->sk);
 | 
				
			||||||
	int num, s_num, slot, s_slot;
 | 
						int num, s_num, slot, s_slot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -132,7 +134,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb,
 | 
				
			||||||
			    r->id.idiag_dport)
 | 
								    r->id.idiag_dport)
 | 
				
			||||||
				goto next;
 | 
									goto next;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (sk_diag_dump(sk, skb, cb, r, bc) < 0) {
 | 
								if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0) {
 | 
				
			||||||
				spin_unlock_bh(&hslot->lock);
 | 
									spin_unlock_bh(&hslot->lock);
 | 
				
			||||||
				goto done;
 | 
									goto done;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,7 +106,8 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc,
 | 
				
			||||||
			       const struct inet_diag_req_v2 *req,
 | 
								       const struct inet_diag_req_v2 *req,
 | 
				
			||||||
			       struct user_namespace *user_ns,
 | 
								       struct user_namespace *user_ns,
 | 
				
			||||||
			       int portid, u32 seq, u16 nlmsg_flags,
 | 
								       int portid, u32 seq, u16 nlmsg_flags,
 | 
				
			||||||
			       const struct nlmsghdr *unlh)
 | 
								       const struct nlmsghdr *unlh,
 | 
				
			||||||
 | 
								       bool net_admin)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sctp_endpoint *ep = sctp_sk(sk)->ep;
 | 
						struct sctp_endpoint *ep = sctp_sk(sk)->ep;
 | 
				
			||||||
	struct list_head *addr_list;
 | 
						struct list_head *addr_list;
 | 
				
			||||||
| 
						 | 
					@ -133,7 +134,7 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc,
 | 
				
			||||||
		r->idiag_retrans = 0;
 | 
							r->idiag_retrans = 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns))
 | 
						if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
 | 
				
			||||||
		goto errout;
 | 
							goto errout;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) {
 | 
						if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) {
 | 
				
			||||||
| 
						 | 
					@ -203,6 +204,7 @@ struct sctp_comm_param {
 | 
				
			||||||
	struct netlink_callback *cb;
 | 
						struct netlink_callback *cb;
 | 
				
			||||||
	const struct inet_diag_req_v2 *r;
 | 
						const struct inet_diag_req_v2 *r;
 | 
				
			||||||
	const struct nlmsghdr *nlh;
 | 
						const struct nlmsghdr *nlh;
 | 
				
			||||||
 | 
						bool net_admin;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static size_t inet_assoc_attr_size(struct sctp_association *asoc)
 | 
					static size_t inet_assoc_attr_size(struct sctp_association *asoc)
 | 
				
			||||||
| 
						 | 
					@ -219,6 +221,7 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
 | 
							+ nla_total_size(1) /* INET_DIAG_SHUTDOWN */
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_TOS */
 | 
							+ nla_total_size(1) /* INET_DIAG_TOS */
 | 
				
			||||||
		+ nla_total_size(1) /* INET_DIAG_TCLASS */
 | 
							+ nla_total_size(1) /* INET_DIAG_TCLASS */
 | 
				
			||||||
 | 
							+ nla_total_size(4) /* INET_DIAG_MARK */
 | 
				
			||||||
		+ nla_total_size(addrlen * asoc->peer.transport_count)
 | 
							+ nla_total_size(addrlen * asoc->peer.transport_count)
 | 
				
			||||||
		+ nla_total_size(addrlen * addrcnt)
 | 
							+ nla_total_size(addrlen * addrcnt)
 | 
				
			||||||
		+ nla_total_size(sizeof(struct inet_diag_meminfo))
 | 
							+ nla_total_size(sizeof(struct inet_diag_meminfo))
 | 
				
			||||||
| 
						 | 
					@ -256,7 +259,8 @@ static int sctp_tsp_dump_one(struct sctp_transport *tsp, void *p)
 | 
				
			||||||
	err = inet_sctp_diag_fill(sk, assoc, rep, req,
 | 
						err = inet_sctp_diag_fill(sk, assoc, rep, req,
 | 
				
			||||||
				  sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
									  sk_user_ns(NETLINK_CB(in_skb).sk),
 | 
				
			||||||
				  NETLINK_CB(in_skb).portid,
 | 
									  NETLINK_CB(in_skb).portid,
 | 
				
			||||||
				  nlh->nlmsg_seq, 0, nlh);
 | 
									  nlh->nlmsg_seq, 0, nlh,
 | 
				
			||||||
 | 
									  commp->net_admin);
 | 
				
			||||||
	release_sock(sk);
 | 
						release_sock(sk);
 | 
				
			||||||
	if (err < 0) {
 | 
						if (err < 0) {
 | 
				
			||||||
		WARN_ON(err == -EMSGSIZE);
 | 
							WARN_ON(err == -EMSGSIZE);
 | 
				
			||||||
| 
						 | 
					@ -310,7 +314,8 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p)
 | 
				
			||||||
					sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
										sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
					NETLINK_CB(cb->skb).portid,
 | 
										NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
					cb->nlh->nlmsg_seq,
 | 
										cb->nlh->nlmsg_seq,
 | 
				
			||||||
					NLM_F_MULTI, cb->nlh) < 0) {
 | 
										NLM_F_MULTI, cb->nlh,
 | 
				
			||||||
 | 
										commp->net_admin) < 0) {
 | 
				
			||||||
			cb->args[3] = 1;
 | 
								cb->args[3] = 1;
 | 
				
			||||||
			err = 2;
 | 
								err = 2;
 | 
				
			||||||
			goto release;
 | 
								goto release;
 | 
				
			||||||
| 
						 | 
					@ -320,7 +325,8 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p)
 | 
				
			||||||
		if (inet_sctp_diag_fill(sk, assoc, skb, r,
 | 
							if (inet_sctp_diag_fill(sk, assoc, skb, r,
 | 
				
			||||||
					sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
										sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
					NETLINK_CB(cb->skb).portid,
 | 
										NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
					cb->nlh->nlmsg_seq, 0, cb->nlh) < 0) {
 | 
										cb->nlh->nlmsg_seq, 0, cb->nlh,
 | 
				
			||||||
 | 
										commp->net_admin) < 0) {
 | 
				
			||||||
			err = 2;
 | 
								err = 2;
 | 
				
			||||||
			goto release;
 | 
								goto release;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -375,7 +381,7 @@ static int sctp_ep_dump(struct sctp_endpoint *ep, void *p)
 | 
				
			||||||
				sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
									sk_user_ns(NETLINK_CB(cb->skb).sk),
 | 
				
			||||||
				NETLINK_CB(cb->skb).portid,
 | 
									NETLINK_CB(cb->skb).portid,
 | 
				
			||||||
				cb->nlh->nlmsg_seq, NLM_F_MULTI,
 | 
									cb->nlh->nlmsg_seq, NLM_F_MULTI,
 | 
				
			||||||
				cb->nlh) < 0) {
 | 
									cb->nlh, commp->net_admin) < 0) {
 | 
				
			||||||
		err = 2;
 | 
							err = 2;
 | 
				
			||||||
		goto out;
 | 
							goto out;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -412,6 +418,7 @@ static int sctp_diag_dump_one(struct sk_buff *in_skb,
 | 
				
			||||||
		.skb = in_skb,
 | 
							.skb = in_skb,
 | 
				
			||||||
		.r = req,
 | 
							.r = req,
 | 
				
			||||||
		.nlh = nlh,
 | 
							.nlh = nlh,
 | 
				
			||||||
 | 
							.net_admin = netlink_net_capable(in_skb, CAP_NET_ADMIN),
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (req->sdiag_family == AF_INET) {
 | 
						if (req->sdiag_family == AF_INET) {
 | 
				
			||||||
| 
						 | 
					@ -447,6 +454,7 @@ static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
 | 
				
			||||||
		.skb = skb,
 | 
							.skb = skb,
 | 
				
			||||||
		.cb = cb,
 | 
							.cb = cb,
 | 
				
			||||||
		.r = r,
 | 
							.r = r,
 | 
				
			||||||
 | 
							.net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN),
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* eps hashtable dumps
 | 
						/* eps hashtable dumps
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue