diff options
Diffstat (limited to 'net/ipv4/inet_diag.c')
-rw-r--r-- | net/ipv4/inet_diag.c | 45 |
1 files changed, 27 insertions, 18 deletions
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 570e61f9611f..535584c00f91 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -69,7 +69,8 @@ static inline void inet_diag_unlock_handler( | |||
69 | 69 | ||
70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
72 | u32 pid, u32 seq, u16 nlmsg_flags, | 72 | struct user_namespace *user_ns, |
73 | u32 portid, u32 seq, u16 nlmsg_flags, | ||
73 | const struct nlmsghdr *unlh) | 74 | const struct nlmsghdr *unlh) |
74 | { | 75 | { |
75 | const struct inet_sock *inet = inet_sk(sk); | 76 | const struct inet_sock *inet = inet_sk(sk); |
@@ -83,7 +84,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
83 | handler = inet_diag_table[req->sdiag_protocol]; | 84 | handler = inet_diag_table[req->sdiag_protocol]; |
84 | BUG_ON(handler == NULL); | 85 | BUG_ON(handler == NULL); |
85 | 86 | ||
86 | nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), | 87 | nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r), |
87 | nlmsg_flags); | 88 | nlmsg_flags); |
88 | if (!nlh) | 89 | if (!nlh) |
89 | return -EMSGSIZE; | 90 | return -EMSGSIZE; |
@@ -124,7 +125,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
124 | } | 125 | } |
125 | #endif | 126 | #endif |
126 | 127 | ||
127 | r->idiag_uid = sock_i_uid(sk); | 128 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
128 | r->idiag_inode = sock_i_ino(sk); | 129 | r->idiag_inode = sock_i_ino(sk); |
129 | 130 | ||
130 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { | 131 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { |
@@ -199,23 +200,24 @@ EXPORT_SYMBOL_GPL(inet_sk_diag_fill); | |||
199 | 200 | ||
200 | static int inet_csk_diag_fill(struct sock *sk, | 201 | static int inet_csk_diag_fill(struct sock *sk, |
201 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 202 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
202 | u32 pid, u32 seq, u16 nlmsg_flags, | 203 | struct user_namespace *user_ns, |
204 | u32 portid, u32 seq, u16 nlmsg_flags, | ||
203 | const struct nlmsghdr *unlh) | 205 | const struct nlmsghdr *unlh) |
204 | { | 206 | { |
205 | return inet_sk_diag_fill(sk, inet_csk(sk), | 207 | return inet_sk_diag_fill(sk, inet_csk(sk), |
206 | skb, req, pid, seq, nlmsg_flags, unlh); | 208 | skb, req, user_ns, portid, seq, nlmsg_flags, unlh); |
207 | } | 209 | } |
208 | 210 | ||
209 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | 211 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, |
210 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 212 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
211 | u32 pid, u32 seq, u16 nlmsg_flags, | 213 | u32 portid, u32 seq, u16 nlmsg_flags, |
212 | const struct nlmsghdr *unlh) | 214 | const struct nlmsghdr *unlh) |
213 | { | 215 | { |
214 | long tmo; | 216 | long tmo; |
215 | struct inet_diag_msg *r; | 217 | struct inet_diag_msg *r; |
216 | struct nlmsghdr *nlh; | 218 | struct nlmsghdr *nlh; |
217 | 219 | ||
218 | nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), | 220 | nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r), |
219 | nlmsg_flags); | 221 | nlmsg_flags); |
220 | if (!nlh) | 222 | if (!nlh) |
221 | return -EMSGSIZE; | 223 | return -EMSGSIZE; |
@@ -256,14 +258,16 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | |||
256 | } | 258 | } |
257 | 259 | ||
258 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | 260 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
259 | struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags, | 261 | struct inet_diag_req_v2 *r, |
262 | struct user_namespace *user_ns, | ||
263 | u32 portid, u32 seq, u16 nlmsg_flags, | ||
260 | const struct nlmsghdr *unlh) | 264 | const struct nlmsghdr *unlh) |
261 | { | 265 | { |
262 | if (sk->sk_state == TCP_TIME_WAIT) | 266 | if (sk->sk_state == TCP_TIME_WAIT) |
263 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, | 267 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, |
264 | skb, r, pid, seq, nlmsg_flags, | 268 | skb, r, portid, seq, nlmsg_flags, |
265 | unlh); | 269 | unlh); |
266 | return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh); | 270 | return inet_csk_diag_fill(sk, skb, r, user_ns, portid, seq, nlmsg_flags, unlh); |
267 | } | 271 | } |
268 | 272 | ||
269 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, | 273 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, |
@@ -311,14 +315,15 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s | |||
311 | } | 315 | } |
312 | 316 | ||
313 | err = sk_diag_fill(sk, rep, req, | 317 | err = sk_diag_fill(sk, rep, req, |
314 | NETLINK_CB(in_skb).pid, | 318 | sk_user_ns(NETLINK_CB(in_skb).ssk), |
319 | NETLINK_CB(in_skb).portid, | ||
315 | nlh->nlmsg_seq, 0, nlh); | 320 | nlh->nlmsg_seq, 0, nlh); |
316 | if (err < 0) { | 321 | if (err < 0) { |
317 | WARN_ON(err == -EMSGSIZE); | 322 | WARN_ON(err == -EMSGSIZE); |
318 | nlmsg_free(rep); | 323 | nlmsg_free(rep); |
319 | goto out; | 324 | goto out; |
320 | } | 325 | } |
321 | err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).pid, | 326 | err = netlink_unicast(net->diag_nlsk, rep, NETLINK_CB(in_skb).portid, |
322 | MSG_DONTWAIT); | 327 | MSG_DONTWAIT); |
323 | if (err > 0) | 328 | if (err > 0) |
324 | err = 0; | 329 | err = 0; |
@@ -551,7 +556,8 @@ static int inet_csk_diag_dump(struct sock *sk, | |||
551 | return 0; | 556 | return 0; |
552 | 557 | ||
553 | return inet_csk_diag_fill(sk, skb, r, | 558 | return inet_csk_diag_fill(sk, skb, r, |
554 | NETLINK_CB(cb->skb).pid, | 559 | sk_user_ns(NETLINK_CB(cb->skb).ssk), |
560 | NETLINK_CB(cb->skb).portid, | ||
555 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 561 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
556 | } | 562 | } |
557 | 563 | ||
@@ -586,12 +592,14 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, | |||
586 | } | 592 | } |
587 | 593 | ||
588 | return inet_twsk_diag_fill(tw, skb, r, | 594 | return inet_twsk_diag_fill(tw, skb, r, |
589 | NETLINK_CB(cb->skb).pid, | 595 | NETLINK_CB(cb->skb).portid, |
590 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 596 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
591 | } | 597 | } |
592 | 598 | ||
593 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | 599 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, |
594 | struct request_sock *req, u32 pid, u32 seq, | 600 | struct request_sock *req, |
601 | struct user_namespace *user_ns, | ||
602 | u32 portid, u32 seq, | ||
595 | const struct nlmsghdr *unlh) | 603 | const struct nlmsghdr *unlh) |
596 | { | 604 | { |
597 | const struct inet_request_sock *ireq = inet_rsk(req); | 605 | const struct inet_request_sock *ireq = inet_rsk(req); |
@@ -600,7 +608,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
600 | struct nlmsghdr *nlh; | 608 | struct nlmsghdr *nlh; |
601 | long tmo; | 609 | long tmo; |
602 | 610 | ||
603 | nlh = nlmsg_put(skb, pid, seq, unlh->nlmsg_type, sizeof(*r), | 611 | nlh = nlmsg_put(skb, portid, seq, unlh->nlmsg_type, sizeof(*r), |
604 | NLM_F_MULTI); | 612 | NLM_F_MULTI); |
605 | if (!nlh) | 613 | if (!nlh) |
606 | return -EMSGSIZE; | 614 | return -EMSGSIZE; |
@@ -625,7 +633,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
625 | r->idiag_expires = jiffies_to_msecs(tmo); | 633 | r->idiag_expires = jiffies_to_msecs(tmo); |
626 | r->idiag_rqueue = 0; | 634 | r->idiag_rqueue = 0; |
627 | r->idiag_wqueue = 0; | 635 | r->idiag_wqueue = 0; |
628 | r->idiag_uid = sock_i_uid(sk); | 636 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
629 | r->idiag_inode = 0; | 637 | r->idiag_inode = 0; |
630 | #if IS_ENABLED(CONFIG_IPV6) | 638 | #if IS_ENABLED(CONFIG_IPV6) |
631 | if (r->idiag_family == AF_INET6) { | 639 | if (r->idiag_family == AF_INET6) { |
@@ -702,7 +710,8 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | |||
702 | } | 710 | } |
703 | 711 | ||
704 | err = inet_diag_fill_req(skb, sk, req, | 712 | err = inet_diag_fill_req(skb, sk, req, |
705 | NETLINK_CB(cb->skb).pid, | 713 | sk_user_ns(NETLINK_CB(cb->skb).ssk), |
714 | NETLINK_CB(cb->skb).portid, | ||
706 | cb->nlh->nlmsg_seq, cb->nlh); | 715 | cb->nlh->nlmsg_seq, cb->nlh); |
707 | if (err < 0) { | 716 | if (err < 0) { |
708 | cb->args[3] = j + 1; | 717 | cb->args[3] = j + 1; |