diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2012-05-24 19:58:08 -0400 |
|---|---|---|
| committer | Eric W. Biederman <ebiederm@xmission.com> | 2012-08-15 00:55:20 -0400 |
| commit | d06ca9564350184a19b5aae9ac150f1b1306de29 (patch) | |
| tree | a6f5e39232911fe0582690f223390997a84f0b86 | |
| parent | c336d148adc4181f31741ae066df41429be64b67 (diff) | |
userns: Teach inet_diag to work with user namespaces
Compute the user namespace of the socket that we are replying to
and translate the kuids of reported sockets into that user namespace.
Cc: Andrew Vagin <avagin@openvz.org>
Acked-by: David S. Miller <davem@davemloft.net>
Acked-by: Pavel Emelyanov <xemul@parallels.com>
Acked-by: Serge Hallyn <serge.hallyn@canonical.com>
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
| -rw-r--r-- | include/linux/inet_diag.h | 1 | ||||
| -rw-r--r-- | init/Kconfig | 1 | ||||
| -rw-r--r-- | net/ipv4/inet_diag.c | 21 | ||||
| -rw-r--r-- | net/ipv4/udp_diag.c | 5 |
4 files changed, 20 insertions, 8 deletions
diff --git a/include/linux/inet_diag.h b/include/linux/inet_diag.h index f1362b5447fc..e788c186ed3a 100644 --- a/include/linux/inet_diag.h +++ b/include/linux/inet_diag.h | |||
| @@ -159,6 +159,7 @@ struct inet_diag_handler { | |||
| 159 | struct inet_connection_sock; | 159 | struct inet_connection_sock; |
| 160 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 160 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
| 161 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 161 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
| 162 | struct user_namespace *user_ns, | ||
| 162 | u32 pid, u32 seq, u16 nlmsg_flags, | 163 | u32 pid, u32 seq, u16 nlmsg_flags, |
| 163 | const struct nlmsghdr *unlh); | 164 | const struct nlmsghdr *unlh); |
| 164 | void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, | 165 | void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb, |
diff --git a/init/Kconfig b/init/Kconfig index 8447e0ca4186..07435e0c3a4b 100644 --- a/init/Kconfig +++ b/init/Kconfig | |||
| @@ -950,7 +950,6 @@ config UIDGID_CONVERTED | |||
| 950 | depends on NETFILTER_NETLINK_LOG = n | 950 | depends on NETFILTER_NETLINK_LOG = n |
| 951 | depends on AF_RXRPC = n | 951 | depends on AF_RXRPC = n |
| 952 | depends on NET_KEY = n | 952 | depends on NET_KEY = n |
| 953 | depends on INET_DIAG = n | ||
| 954 | depends on DNS_RESOLVER = n | 953 | depends on DNS_RESOLVER = n |
| 955 | 954 | ||
| 956 | # Filesystems | 955 | # Filesystems |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 570e61f9611f..8bc005b1435f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
| @@ -69,6 +69,7 @@ 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 | struct user_namespace *user_ns, | ||
| 72 | u32 pid, u32 seq, u16 nlmsg_flags, | 73 | u32 pid, u32 seq, u16 nlmsg_flags, |
| 73 | const struct nlmsghdr *unlh) | 74 | const struct nlmsghdr *unlh) |
| 74 | { | 75 | { |
| @@ -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,11 +200,12 @@ 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, |
| 203 | struct user_namespace *user_ns, | ||
| 202 | u32 pid, u32 seq, u16 nlmsg_flags, | 204 | u32 pid, 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, pid, 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, |
| @@ -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 pid, 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, pid, 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, pid, 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,6 +315,7 @@ 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, |
| 318 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
| 314 | NETLINK_CB(in_skb).pid, | 319 | NETLINK_CB(in_skb).pid, |
| 315 | nlh->nlmsg_seq, 0, nlh); | 320 | nlh->nlmsg_seq, 0, nlh); |
| 316 | if (err < 0) { | 321 | if (err < 0) { |
| @@ -551,6 +556,7 @@ 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, |
| 559 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
| 554 | NETLINK_CB(cb->skb).pid, | 560 | NETLINK_CB(cb->skb).pid, |
| 555 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 561 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
| 556 | } | 562 | } |
| @@ -591,7 +597,9 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, | |||
| 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 pid, 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); |
| @@ -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,6 +710,7 @@ 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, |
| 713 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
| 705 | NETLINK_CB(cb->skb).pid, | 714 | NETLINK_CB(cb->skb).pid, |
| 706 | cb->nlh->nlmsg_seq, cb->nlh); | 715 | cb->nlh->nlmsg_seq, cb->nlh); |
| 707 | if (err < 0) { | 716 | if (err < 0) { |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 16d0960062be..d2f336ea82ca 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
| @@ -24,7 +24,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, | |||
| 24 | if (!inet_diag_bc_sk(bc, sk)) | 24 | if (!inet_diag_bc_sk(bc, sk)) |
| 25 | return 0; | 25 | return 0; |
| 26 | 26 | ||
| 27 | return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid, | 27 | return inet_sk_diag_fill(sk, NULL, skb, req, |
| 28 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
| 29 | NETLINK_CB(cb->skb).pid, | ||
| 28 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 30 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
| 29 | } | 31 | } |
| 30 | 32 | ||
| @@ -69,6 +71,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
| 69 | goto out; | 71 | goto out; |
| 70 | 72 | ||
| 71 | err = inet_sk_diag_fill(sk, NULL, rep, req, | 73 | err = inet_sk_diag_fill(sk, NULL, rep, req, |
| 74 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
| 72 | NETLINK_CB(in_skb).pid, | 75 | NETLINK_CB(in_skb).pid, |
| 73 | nlh->nlmsg_seq, 0, nlh); | 76 | nlh->nlmsg_seq, 0, nlh); |
| 74 | if (err < 0) { | 77 | if (err < 0) { |
