Commit d545caca authored by Lorenzo Colitti's avatar Lorenzo Colitti Committed by David S. Miller

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 a52e95ab ("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/270210Signed-off-by: default avatarLorenzo Colitti <lorenzo@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 74f13c80
...@@ -37,7 +37,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, ...@@ -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); ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 @@ ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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 { ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment