Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eeeb172d authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by Amit Pundir
Browse files

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 a52e95abf772 ("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.

[backport of net-next d545caca827b65aab557a9e9dcdcf1e5a3823c2d]

Change-Id: I78b842ee68162df542ad43b8fd5ab21856ddd248
Tested: https://android-review.googlesource.com/270210


Signed-off-by: default avatarLorenzo Colitti <lorenzo@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e0ba1a8a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -36,7 +36,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
			      struct user_namespace *user_ns,
			      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,
		struct netlink_callback *cb, struct inet_diag_req_v2 *r,
		struct nlattr *bc);
+7 −1
Original line number Diff line number Diff line
@@ -118,9 +118,15 @@ enum {
	INET_DIAG_SKMEMINFO,
	INET_DIAG_SHUTDOWN,
	INET_DIAG_DCTCPINFO,
	INET_DIAG_PROTOCOL,  /* response attribute only */
	INET_DIAG_SKV6ONLY,
	INET_DIAG_LOCALS,
	INET_DIAG_PEERS,
	INET_DIAG_PAD,
	INET_DIAG_MARK,
};

#define INET_DIAG_MAX INET_DIAG_DCTCPINFO
#define INET_DIAG_MAX INET_DIAG_MARK

/* INET_DIAG_MEM */

+21 −10
Original line number Diff line number Diff line
@@ -91,7 +91,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
			      struct user_namespace *user_ns,		      	
			      u32 portid, u32 seq, u16 nlmsg_flags,
			      const struct nlmsghdr *unlh)
			      const struct nlmsghdr *unlh, bool net_admin)
{
	const struct inet_sock *inet = inet_sk(sk);
	struct inet_diag_msg *r;
@@ -152,6 +152,9 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
	}
#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_inode = sock_i_ino(sk);

@@ -231,10 +234,12 @@ static int inet_csk_diag_fill(struct sock *sk,
			      struct sk_buff *skb, struct inet_diag_req_v2 *req,
			      struct user_namespace *user_ns,
			      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, user_ns, portid, seq, nlmsg_flags, unlh);
			skb, req, user_ns, portid, seq, nlmsg_flags, unlh,
			net_admin);
}

static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -294,14 +299,14 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
			struct inet_diag_req_v2 *r,
			struct user_namespace *user_ns,
			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)
		return inet_twsk_diag_fill(inet_twsk(sk), skb, r, portid, seq,
					   nlmsg_flags, unlh);

	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,
@@ -370,7 +375,8 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
	err = sk_diag_fill(sk, rep, req,
			   sk_user_ns(NETLINK_CB(in_skb).sk),
			   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) {
		WARN_ON(err == -EMSGSIZE);
		nlmsg_free(rep);
@@ -721,7 +727,8 @@ static int inet_csk_diag_dump(struct sock *sk,
			      struct sk_buff *skb,
			      struct netlink_callback *cb,
			      struct inet_diag_req_v2 *r,
			      const struct nlattr *bc)
			      const struct nlattr *bc,
			      bool net_admin)
{
	if (!inet_diag_bc_sk(bc, sk))
		return 0;
@@ -729,7 +736,8 @@ static int inet_csk_diag_dump(struct sock *sk,
	return inet_csk_diag_fill(sk, skb, r,
				  sk_user_ns(NETLINK_CB(cb->skb).sk),
				  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 inet_twsk_diag_dump(struct sock *sk,
@@ -934,6 +942,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
	int i, num;
	int s_i, s_num;
	struct net *net = sock_net(skb->sk);
	bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);

	s_i = cb->args[1];
	s_num = num = cb->args[2];
@@ -974,7 +983,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
				    cb->args[3] > 0)
					goto syn_recv;

				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);
					goto done;
				}
@@ -1046,7 +1056,8 @@ skip_listen_ht:
			if (sk->sk_state == TCP_TIME_WAIT)
				res = inet_twsk_diag_dump(sk, skb, cb, r, bc);
			else
				res = inet_csk_diag_dump(sk, skb, cb, r, bc);
				res = inet_csk_diag_dump(sk, skb, cb, r, bc,
							 net_admin);
			if (res < 0) {
				spin_unlock_bh(lock);
				goto done;
+6 −4
Original line number Diff line number Diff line
@@ -19,7 +19,7 @@

static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
		struct netlink_callback *cb, struct inet_diag_req_v2 *req,
		struct nlattr *bc)
		struct nlattr *bc, bool net_admin)
{
	if (!inet_diag_bc_sk(bc, sk))
		return 0;
@@ -27,7 +27,7 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
	return inet_sk_diag_fill(sk, NULL, skb, req,
			sk_user_ns(NETLINK_CB(cb->skb).sk),
			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,
@@ -73,7 +73,8 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
	err = inet_sk_diag_fill(sk, NULL, rep, req,
			   sk_user_ns(NETLINK_CB(in_skb).sk),
			   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) {
		WARN_ON(err == -EMSGSIZE);
		kfree_skb(rep);
@@ -95,6 +96,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
{
	int num, s_num, slot, s_slot;
	struct net *net = sock_net(skb->sk);
	bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);

	s_slot = cb->args[0];
	num = s_num = cb->args[1];
@@ -129,7 +131,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb, struct netlin
			    r->id.idiag_dport)
				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);
				goto done;
			}