Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Lorenzo Colitti and committed by
David S. Miller
d545caca 74f13c80

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