aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLorenzo Colitti <lorenzo@google.com>2016-09-07 11:42:25 -0400
committerDavid S. Miller <davem@davemloft.net>2016-09-08 19:13:09 -0400
commitd545caca827b65aab557a9e9dcdcf1e5a3823c2d (patch)
tree1ec87b39e2490acc3f435d650d6ddc6e594300cf
parent74f13c80e210ff5a9e7b13b9853d8a866972f385 (diff)
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. Tested: https://android-review.googlesource.com/270210 Signed-off-by: Lorenzo Colitti <lorenzo@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/inet_diag.h4
-rw-r--r--include/uapi/linux/inet_diag.h1
-rw-r--r--net/ipv4/inet_diag.c49
-rw-r--r--net/ipv4/udp_diag.c10
-rw-r--r--net/sctp/sctp_diag.c20
5 files changed, 56 insertions, 28 deletions
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h
index feb04ea20f11..65da430e260f 100644
--- a/include/linux/inet_diag.h
+++ b/include/linux/inet_diag.h
@@ -37,7 +37,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
37 struct sk_buff *skb, const struct inet_diag_req_v2 *req, 37 struct sk_buff *skb, const struct inet_diag_req_v2 *req,
38 struct user_namespace *user_ns, 38 struct user_namespace *user_ns,
39 u32 pid, u32 seq, u16 nlmsg_flags, 39 u32 pid, u32 seq, u16 nlmsg_flags,
40 const struct nlmsghdr *unlh); 40 const struct nlmsghdr *unlh, bool net_admin);
41void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, 41void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
42 struct netlink_callback *cb, 42 struct netlink_callback *cb,
43 const struct inet_diag_req_v2 *r, 43 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 56
57int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, 57int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
58 struct inet_diag_msg *r, int ext, 58 struct inet_diag_msg *r, int ext,
59 struct user_namespace *user_ns); 59 struct user_namespace *user_ns, bool net_admin);
60 60
61extern int inet_diag_register(const struct inet_diag_handler *handler); 61extern int inet_diag_register(const struct inet_diag_handler *handler);
62extern void inet_diag_unregister(const struct inet_diag_handler *handler); 62extern void inet_diag_unregister(const struct inet_diag_handler *handler);
diff --git a/include/uapi/linux/inet_diag.h b/include/uapi/linux/inet_diag.h
index 5581206a08ae..b5c366f87b3e 100644
--- a/include/uapi/linux/inet_diag.h
+++ b/include/uapi/linux/inet_diag.h
@@ -123,6 +123,7 @@ enum {
123 INET_DIAG_LOCALS, 123 INET_DIAG_LOCALS,
124 INET_DIAG_PEERS, 124 INET_DIAG_PEERS,
125 INET_DIAG_PAD, 125 INET_DIAG_PAD,
126 INET_DIAG_MARK,
126 __INET_DIAG_MAX, 127 __INET_DIAG_MAX,
127}; 128};
128 129
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index abfbe492ebfe..e4d16fc5bbb3 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -99,6 +99,7 @@ static size_t inet_sk_attr_size(void)
99 + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ 99 + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
100 + nla_total_size(1) /* INET_DIAG_TOS */ 100 + nla_total_size(1) /* INET_DIAG_TOS */
101 + nla_total_size(1) /* INET_DIAG_TCLASS */ 101 + nla_total_size(1) /* INET_DIAG_TCLASS */
102 + nla_total_size(4) /* INET_DIAG_MARK */
102 + nla_total_size(sizeof(struct inet_diag_meminfo)) 103 + nla_total_size(sizeof(struct inet_diag_meminfo))
103 + nla_total_size(sizeof(struct inet_diag_msg)) 104 + nla_total_size(sizeof(struct inet_diag_msg))
104 + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) 105 + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -109,7 +110,8 @@ static size_t inet_sk_attr_size(void)
109 110
110int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb, 111int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
111 struct inet_diag_msg *r, int ext, 112 struct inet_diag_msg *r, int ext,
112 struct user_namespace *user_ns) 113 struct user_namespace *user_ns,
114 bool net_admin)
113{ 115{
114 const struct inet_sock *inet = inet_sk(sk); 116 const struct inet_sock *inet = inet_sk(sk);
115 117
@@ -136,6 +138,9 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
136 } 138 }
137#endif 139#endif
138 140
141 if (net_admin && nla_put_u32(skb, INET_DIAG_MARK, sk->sk_mark))
142 goto errout;
143
139 r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); 144 r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
140 r->idiag_inode = sock_i_ino(sk); 145 r->idiag_inode = sock_i_ino(sk);
141 146
@@ -149,7 +154,8 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
149 struct sk_buff *skb, const struct inet_diag_req_v2 *req, 154 struct sk_buff *skb, const struct inet_diag_req_v2 *req,
150 struct user_namespace *user_ns, 155 struct user_namespace *user_ns,
151 u32 portid, u32 seq, u16 nlmsg_flags, 156 u32 portid, u32 seq, u16 nlmsg_flags,
152 const struct nlmsghdr *unlh) 157 const struct nlmsghdr *unlh,
158 bool net_admin)
153{ 159{
154 const struct tcp_congestion_ops *ca_ops; 160 const struct tcp_congestion_ops *ca_ops;
155 const struct inet_diag_handler *handler; 161 const struct inet_diag_handler *handler;
@@ -175,7 +181,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
175 r->idiag_timer = 0; 181 r->idiag_timer = 0;
176 r->idiag_retrans = 0; 182 r->idiag_retrans = 0;
177 183
178 if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns)) 184 if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
179 goto errout; 185 goto errout;
180 186
181 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { 187 if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
@@ -274,10 +280,11 @@ static int inet_csk_diag_fill(struct sock *sk,
274 const struct inet_diag_req_v2 *req, 280 const struct inet_diag_req_v2 *req,
275 struct user_namespace *user_ns, 281 struct user_namespace *user_ns,
276 u32 portid, u32 seq, u16 nlmsg_flags, 282 u32 portid, u32 seq, u16 nlmsg_flags,
277 const struct nlmsghdr *unlh) 283 const struct nlmsghdr *unlh,
284 bool net_admin)
278{ 285{
279 return inet_sk_diag_fill(sk, inet_csk(sk), skb, req, 286 return inet_sk_diag_fill(sk, inet_csk(sk), skb, req, user_ns,
280 user_ns, portid, seq, nlmsg_flags, unlh); 287 portid, seq, nlmsg_flags, unlh, net_admin);
281} 288}
282 289
283static int inet_twsk_diag_fill(struct sock *sk, 290static int inet_twsk_diag_fill(struct sock *sk,
@@ -319,8 +326,9 @@ static int inet_twsk_diag_fill(struct sock *sk,
319 326
320static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb, 327static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
321 u32 portid, u32 seq, u16 nlmsg_flags, 328 u32 portid, u32 seq, u16 nlmsg_flags,
322 const struct nlmsghdr *unlh) 329 const struct nlmsghdr *unlh, bool net_admin)
323{ 330{
331 struct request_sock *reqsk = inet_reqsk(sk);
324 struct inet_diag_msg *r; 332 struct inet_diag_msg *r;
325 struct nlmsghdr *nlh; 333 struct nlmsghdr *nlh;
326 long tmo; 334 long tmo;
@@ -334,7 +342,7 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
334 inet_diag_msg_common_fill(r, sk); 342 inet_diag_msg_common_fill(r, sk);
335 r->idiag_state = TCP_SYN_RECV; 343 r->idiag_state = TCP_SYN_RECV;
336 r->idiag_timer = 1; 344 r->idiag_timer = 1;
337 r->idiag_retrans = inet_reqsk(sk)->num_retrans; 345 r->idiag_retrans = reqsk->num_retrans;
338 346
339 BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) != 347 BUILD_BUG_ON(offsetof(struct inet_request_sock, ir_cookie) !=
340 offsetof(struct sock, sk_cookie)); 348 offsetof(struct sock, sk_cookie));
@@ -346,6 +354,10 @@ static int inet_req_diag_fill(struct sock *sk, struct sk_buff *skb,
346 r->idiag_uid = 0; 354 r->idiag_uid = 0;
347 r->idiag_inode = 0; 355 r->idiag_inode = 0;
348 356
357 if (net_admin && nla_put_u32(skb, INET_DIAG_MARK,
358 inet_rsk(reqsk)->ir_mark))
359 return -EMSGSIZE;
360
349 nlmsg_end(skb, nlh); 361 nlmsg_end(skb, nlh);
350 return 0; 362 return 0;
351} 363}
@@ -354,7 +366,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
354 const struct inet_diag_req_v2 *r, 366 const struct inet_diag_req_v2 *r,
355 struct user_namespace *user_ns, 367 struct user_namespace *user_ns,
356 u32 portid, u32 seq, u16 nlmsg_flags, 368 u32 portid, u32 seq, u16 nlmsg_flags,
357 const struct nlmsghdr *unlh) 369 const struct nlmsghdr *unlh, bool net_admin)
358{ 370{
359 if (sk->sk_state == TCP_TIME_WAIT) 371 if (sk->sk_state == TCP_TIME_WAIT)
360 return inet_twsk_diag_fill(sk, skb, portid, seq, 372 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 374
363 if (sk->sk_state == TCP_NEW_SYN_RECV) 375 if (sk->sk_state == TCP_NEW_SYN_RECV)
364 return inet_req_diag_fill(sk, skb, portid, seq, 376 return inet_req_diag_fill(sk, skb, portid, seq,
365 nlmsg_flags, unlh); 377 nlmsg_flags, unlh, net_admin);
366 378
367 return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, 379 return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq,
368 nlmsg_flags, unlh); 380 nlmsg_flags, unlh, net_admin);
369} 381}
370 382
371struct sock *inet_diag_find_one_icsk(struct net *net, 383struct sock *inet_diag_find_one_icsk(struct net *net,
@@ -435,7 +447,8 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo,
435 err = sk_diag_fill(sk, rep, req, 447 err = sk_diag_fill(sk, rep, req,
436 sk_user_ns(NETLINK_CB(in_skb).sk), 448 sk_user_ns(NETLINK_CB(in_skb).sk),
437 NETLINK_CB(in_skb).portid, 449 NETLINK_CB(in_skb).portid,
438 nlh->nlmsg_seq, 0, nlh); 450 nlh->nlmsg_seq, 0, nlh,
451 netlink_net_capable(in_skb, CAP_NET_ADMIN));
439 if (err < 0) { 452 if (err < 0) {
440 WARN_ON(err == -EMSGSIZE); 453 WARN_ON(err == -EMSGSIZE);
441 nlmsg_free(rep); 454 nlmsg_free(rep);
@@ -796,7 +809,8 @@ static int inet_csk_diag_dump(struct sock *sk,
796 struct sk_buff *skb, 809 struct sk_buff *skb,
797 struct netlink_callback *cb, 810 struct netlink_callback *cb,
798 const struct inet_diag_req_v2 *r, 811 const struct inet_diag_req_v2 *r,
799 const struct nlattr *bc) 812 const struct nlattr *bc,
813 bool net_admin)
800{ 814{
801 if (!inet_diag_bc_sk(bc, sk)) 815 if (!inet_diag_bc_sk(bc, sk))
802 return 0; 816 return 0;
@@ -804,7 +818,8 @@ static int inet_csk_diag_dump(struct sock *sk,
804 return inet_csk_diag_fill(sk, skb, r, 818 return inet_csk_diag_fill(sk, skb, r,
805 sk_user_ns(NETLINK_CB(cb->skb).sk), 819 sk_user_ns(NETLINK_CB(cb->skb).sk),
806 NETLINK_CB(cb->skb).portid, 820 NETLINK_CB(cb->skb).portid,
807 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); 821 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh,
822 net_admin);
808} 823}
809 824
810static void twsk_build_assert(void) 825static void twsk_build_assert(void)
@@ -840,6 +855,7 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
840 struct net *net = sock_net(skb->sk); 855 struct net *net = sock_net(skb->sk);
841 int i, num, s_i, s_num; 856 int i, num, s_i, s_num;
842 u32 idiag_states = r->idiag_states; 857 u32 idiag_states = r->idiag_states;
858 bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
843 859
844 if (idiag_states & TCPF_SYN_RECV) 860 if (idiag_states & TCPF_SYN_RECV)
845 idiag_states |= TCPF_NEW_SYN_RECV; 861 idiag_states |= TCPF_NEW_SYN_RECV;
@@ -880,7 +896,8 @@ void inet_diag_dump_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *skb,
880 cb->args[3] > 0) 896 cb->args[3] > 0)
881 goto next_listen; 897 goto next_listen;
882 898
883 if (inet_csk_diag_dump(sk, skb, cb, r, bc) < 0) { 899 if (inet_csk_diag_dump(sk, skb, cb, r,
900 bc, net_admin) < 0) {
884 spin_unlock_bh(&ilb->lock); 901 spin_unlock_bh(&ilb->lock);
885 goto done; 902 goto done;
886 } 903 }
@@ -948,7 +965,7 @@ skip_listen_ht:
948 sk_user_ns(NETLINK_CB(cb->skb).sk), 965 sk_user_ns(NETLINK_CB(cb->skb).sk),
949 NETLINK_CB(cb->skb).portid, 966 NETLINK_CB(cb->skb).portid,
950 cb->nlh->nlmsg_seq, NLM_F_MULTI, 967 cb->nlh->nlmsg_seq, NLM_F_MULTI,
951 cb->nlh); 968 cb->nlh, net_admin);
952 if (res < 0) { 969 if (res < 0) {
953 spin_unlock_bh(lock); 970 spin_unlock_bh(lock);
954 goto done; 971 goto done;
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c
index 58b79c0c0d69..9a89c10a55f0 100644
--- a/net/ipv4/udp_diag.c
+++ b/net/ipv4/udp_diag.c
@@ -20,7 +20,7 @@
20static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, 20static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
21 struct netlink_callback *cb, 21 struct netlink_callback *cb,
22 const struct inet_diag_req_v2 *req, 22 const struct inet_diag_req_v2 *req,
23 struct nlattr *bc) 23 struct nlattr *bc, bool net_admin)
24{ 24{
25 if (!inet_diag_bc_sk(bc, sk)) 25 if (!inet_diag_bc_sk(bc, sk))
26 return 0; 26 return 0;
@@ -28,7 +28,7 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
28 return inet_sk_diag_fill(sk, NULL, skb, req, 28 return inet_sk_diag_fill(sk, NULL, skb, req,
29 sk_user_ns(NETLINK_CB(cb->skb).sk), 29 sk_user_ns(NETLINK_CB(cb->skb).sk),
30 NETLINK_CB(cb->skb).portid, 30 NETLINK_CB(cb->skb).portid,
31 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); 31 cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh, net_admin);
32} 32}
33 33
34static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, 34static 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 err = inet_sk_diag_fill(sk, NULL, rep, req, 76 err = inet_sk_diag_fill(sk, NULL, rep, req,
77 sk_user_ns(NETLINK_CB(in_skb).sk), 77 sk_user_ns(NETLINK_CB(in_skb).sk),
78 NETLINK_CB(in_skb).portid, 78 NETLINK_CB(in_skb).portid,
79 nlh->nlmsg_seq, 0, nlh); 79 nlh->nlmsg_seq, 0, nlh,
80 netlink_net_capable(in_skb, CAP_NET_ADMIN));
80 if (err < 0) { 81 if (err < 0) {
81 WARN_ON(err == -EMSGSIZE); 82 WARN_ON(err == -EMSGSIZE);
82 kfree_skb(rep); 83 kfree_skb(rep);
@@ -97,6 +98,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb,
97 struct netlink_callback *cb, 98 struct netlink_callback *cb,
98 const struct inet_diag_req_v2 *r, struct nlattr *bc) 99 const struct inet_diag_req_v2 *r, struct nlattr *bc)
99{ 100{
101 bool net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN);
100 struct net *net = sock_net(skb->sk); 102 struct net *net = sock_net(skb->sk);
101 int num, s_num, slot, s_slot; 103 int num, s_num, slot, s_slot;
102 104
@@ -132,7 +134,7 @@ static void udp_dump(struct udp_table *table, struct sk_buff *skb,
132 r->id.idiag_dport) 134 r->id.idiag_dport)
133 goto next; 135 goto next;
134 136
135 if (sk_diag_dump(sk, skb, cb, r, bc) < 0) { 137 if (sk_diag_dump(sk, skb, cb, r, bc, net_admin) < 0) {
136 spin_unlock_bh(&hslot->lock); 138 spin_unlock_bh(&hslot->lock);
137 goto done; 139 goto done;
138 } 140 }
diff --git a/net/sctp/sctp_diag.c b/net/sctp/sctp_diag.c
index f3508aa75815..807158e32f5f 100644
--- a/net/sctp/sctp_diag.c
+++ b/net/sctp/sctp_diag.c
@@ -106,7 +106,8 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc,
106 const struct inet_diag_req_v2 *req, 106 const struct inet_diag_req_v2 *req,
107 struct user_namespace *user_ns, 107 struct user_namespace *user_ns,
108 int portid, u32 seq, u16 nlmsg_flags, 108 int portid, u32 seq, u16 nlmsg_flags,
109 const struct nlmsghdr *unlh) 109 const struct nlmsghdr *unlh,
110 bool net_admin)
110{ 111{
111 struct sctp_endpoint *ep = sctp_sk(sk)->ep; 112 struct sctp_endpoint *ep = sctp_sk(sk)->ep;
112 struct list_head *addr_list; 113 struct list_head *addr_list;
@@ -133,7 +134,7 @@ static int inet_sctp_diag_fill(struct sock *sk, struct sctp_association *asoc,
133 r->idiag_retrans = 0; 134 r->idiag_retrans = 0;
134 } 135 }
135 136
136 if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns)) 137 if (inet_diag_msg_attrs_fill(sk, skb, r, ext, user_ns, net_admin))
137 goto errout; 138 goto errout;
138 139
139 if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) { 140 if (ext & (1 << (INET_DIAG_SKMEMINFO - 1))) {
@@ -203,6 +204,7 @@ struct sctp_comm_param {
203 struct netlink_callback *cb; 204 struct netlink_callback *cb;
204 const struct inet_diag_req_v2 *r; 205 const struct inet_diag_req_v2 *r;
205 const struct nlmsghdr *nlh; 206 const struct nlmsghdr *nlh;
207 bool net_admin;
206}; 208};
207 209
208static size_t inet_assoc_attr_size(struct sctp_association *asoc) 210static 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 + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ 221 + nla_total_size(1) /* INET_DIAG_SHUTDOWN */
220 + nla_total_size(1) /* INET_DIAG_TOS */ 222 + nla_total_size(1) /* INET_DIAG_TOS */
221 + nla_total_size(1) /* INET_DIAG_TCLASS */ 223 + nla_total_size(1) /* INET_DIAG_TCLASS */
224 + nla_total_size(4) /* INET_DIAG_MARK */
222 + nla_total_size(addrlen * asoc->peer.transport_count) 225 + nla_total_size(addrlen * asoc->peer.transport_count)
223 + nla_total_size(addrlen * addrcnt) 226 + nla_total_size(addrlen * addrcnt)
224 + nla_total_size(sizeof(struct inet_diag_meminfo)) 227 + 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 err = inet_sctp_diag_fill(sk, assoc, rep, req, 259 err = inet_sctp_diag_fill(sk, assoc, rep, req,
257 sk_user_ns(NETLINK_CB(in_skb).sk), 260 sk_user_ns(NETLINK_CB(in_skb).sk),
258 NETLINK_CB(in_skb).portid, 261 NETLINK_CB(in_skb).portid,
259 nlh->nlmsg_seq, 0, nlh); 262 nlh->nlmsg_seq, 0, nlh,
263 commp->net_admin);
260 release_sock(sk); 264 release_sock(sk);
261 if (err < 0) { 265 if (err < 0) {
262 WARN_ON(err == -EMSGSIZE); 266 WARN_ON(err == -EMSGSIZE);
@@ -310,7 +314,8 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p)
310 sk_user_ns(NETLINK_CB(cb->skb).sk), 314 sk_user_ns(NETLINK_CB(cb->skb).sk),
311 NETLINK_CB(cb->skb).portid, 315 NETLINK_CB(cb->skb).portid,
312 cb->nlh->nlmsg_seq, 316 cb->nlh->nlmsg_seq,
313 NLM_F_MULTI, cb->nlh) < 0) { 317 NLM_F_MULTI, cb->nlh,
318 commp->net_admin) < 0) {
314 cb->args[3] = 1; 319 cb->args[3] = 1;
315 err = 2; 320 err = 2;
316 goto release; 321 goto release;
@@ -320,7 +325,8 @@ static int sctp_tsp_dump(struct sctp_transport *tsp, void *p)
320 if (inet_sctp_diag_fill(sk, assoc, skb, r, 325 if (inet_sctp_diag_fill(sk, assoc, skb, r,
321 sk_user_ns(NETLINK_CB(cb->skb).sk), 326 sk_user_ns(NETLINK_CB(cb->skb).sk),
322 NETLINK_CB(cb->skb).portid, 327 NETLINK_CB(cb->skb).portid,
323 cb->nlh->nlmsg_seq, 0, cb->nlh) < 0) { 328 cb->nlh->nlmsg_seq, 0, cb->nlh,
329 commp->net_admin) < 0) {
324 err = 2; 330 err = 2;
325 goto release; 331 goto release;
326 } 332 }
@@ -375,7 +381,7 @@ static int sctp_ep_dump(struct sctp_endpoint *ep, void *p)
375 sk_user_ns(NETLINK_CB(cb->skb).sk), 381 sk_user_ns(NETLINK_CB(cb->skb).sk),
376 NETLINK_CB(cb->skb).portid, 382 NETLINK_CB(cb->skb).portid,
377 cb->nlh->nlmsg_seq, NLM_F_MULTI, 383 cb->nlh->nlmsg_seq, NLM_F_MULTI,
378 cb->nlh) < 0) { 384 cb->nlh, commp->net_admin) < 0) {
379 err = 2; 385 err = 2;
380 goto out; 386 goto out;
381 } 387 }
@@ -412,6 +418,7 @@ static int sctp_diag_dump_one(struct sk_buff *in_skb,
412 .skb = in_skb, 418 .skb = in_skb,
413 .r = req, 419 .r = req,
414 .nlh = nlh, 420 .nlh = nlh,
421 .net_admin = netlink_net_capable(in_skb, CAP_NET_ADMIN),
415 }; 422 };
416 423
417 if (req->sdiag_family == AF_INET) { 424 if (req->sdiag_family == AF_INET) {
@@ -447,6 +454,7 @@ static void sctp_diag_dump(struct sk_buff *skb, struct netlink_callback *cb,
447 .skb = skb, 454 .skb = skb,
448 .cb = cb, 455 .cb = cb,
449 .r = r, 456 .r = r,
457 .net_admin = netlink_net_capable(cb->skb, CAP_NET_ADMIN),
450 }; 458 };
451 459
452 /* eps hashtable dumps 460 /* eps hashtable dumps