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: I0c9708aae5ab8dfa296b8a1e6aecceb2a382415a Tested: https://android-review.googlesource.com/270210 Signed-off-by: Lorenzo Colitti <lorenzo@google.com> Signed-off-by: David S. Miller <davem@davemloft.net> Git-commit: 37249459aab0efae6ee7e11d12fc8f790dd32ebc Git-repo: https://android.googlesource.com/kernel/common.git Signed-off-by: Srinivasarao P <spathi@codeaurora.org>
This commit is contained in:
parent
e567849255
commit
85c311cf8d
|
@ -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);
|
||||
|
|
|
@ -117,9 +117,16 @@ enum {
|
|||
INET_DIAG_TCLASS,
|
||||
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_SHUTDOWN
|
||||
#define INET_DIAG_MAX INET_DIAG_MARK
|
||||
|
||||
|
||||
/* INET_DIAG_MEM */
|
||||
|
|
|
@ -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,11 @@ 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,
|
||||
|
@ -297,13 +301,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((struct inet_timewait_sock *)sk,
|
||||
skb, r, portid, seq, nlmsg_flags,
|
||||
unlh);
|
||||
return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, nlmsg_flags, unlh);
|
||||
return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, nlmsg_flags,
|
||||
unlh, net_admin);
|
||||
}
|
||||
|
||||
struct sock *inet_diag_find_one_icsk(struct net *net,
|
||||
|
@ -376,7 +381,9 @@ 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,
|
||||
ns_capable(sock_net(in_skb->sk)->user_ns,
|
||||
CAP_NET_ADMIN));
|
||||
if (err < 0) {
|
||||
WARN_ON(err == -EMSGSIZE);
|
||||
nlmsg_free(rep);
|
||||
|
@ -731,7 +738,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;
|
||||
|
@ -739,7 +747,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 inet_timewait_sock *tw,
|
||||
|
@ -944,6 +953,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 = ns_capable(net->user_ns, CAP_NET_ADMIN);
|
||||
|
||||
s_i = cb->args[1];
|
||||
s_num = num = cb->args[2];
|
||||
|
@ -984,7 +994,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;
|
||||
}
|
||||
|
@ -1051,7 +1062,8 @@ skip_listen_ht:
|
|||
if (r->id.idiag_dport != inet->inet_dport &&
|
||||
r->id.idiag_dport)
|
||||
goto next_normal;
|
||||
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(lock);
|
||||
goto done;
|
||||
}
|
||||
|
|
|
@ -20,7 +20,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;
|
||||
|
@ -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,
|
||||
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,
|
||||
|
@ -74,7 +74,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,
|
||||
ns_capable(net->user_ns, CAP_NET_ADMIN));
|
||||
if (err < 0) {
|
||||
WARN_ON(err == -EMSGSIZE);
|
||||
kfree_skb(rep);
|
||||
|
@ -96,6 +97,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 = ns_capable(net->user_ns, CAP_NET_ADMIN);
|
||||
|
||||
s_slot = cb->args[0];
|
||||
num = s_num = cb->args[1];
|
||||
|
@ -130,7 +132,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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue