userns: Teach inet_diag to work with user namespaces
authorEric W. Biederman <ebiederm@xmission.com>
Thu, 24 May 2012 23:58:08 +0000 (17:58 -0600)
committerEric W. Biederman <ebiederm@xmission.com>
Wed, 15 Aug 2012 04:55:20 +0000 (21:55 -0700)
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>
include/linux/inet_diag.h
init/Kconfig
net/ipv4/inet_diag.c
net/ipv4/udp_diag.c

index f1362b5447fcbcf6935e49aec748675562eb0b12..e788c186ed3a85a933b0ce219d4f6b8b8bb84e88 100644 (file)
@@ -159,6 +159,7 @@ struct inet_diag_handler {
 struct inet_connection_sock;
 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
+                             struct user_namespace *user_ns,
                              u32 pid, u32 seq, u16 nlmsg_flags,
                              const struct nlmsghdr *unlh);
 void inet_diag_dump_icsk(struct inet_hashinfo *h, struct sk_buff *skb,
index 8447e0ca418607e97f29678beddb8a52943ad2d1..07435e0c3a4bb5dd01bfa1e079589f93dad7fa7e 100644 (file)
@@ -950,7 +950,6 @@ config UIDGID_CONVERTED
        depends on NETFILTER_NETLINK_LOG = n
        depends on AF_RXRPC = n
        depends on NET_KEY = n
-       depends on INET_DIAG = n
        depends on DNS_RESOLVER = n
 
        # Filesystems
index 570e61f9611fe9f62bf3513afc9a5abb365544b7..8bc005b1435f5109269a6057ad96d7c9985574d5 100644 (file)
@@ -69,6 +69,7 @@ static inline void inet_diag_unlock_handler(
 
 int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
+                             struct user_namespace *user_ns,                   
                              u32 pid, u32 seq, u16 nlmsg_flags,
                              const struct nlmsghdr *unlh)
 {
@@ -124,7 +125,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
        }
 #endif
 
-       r->idiag_uid = sock_i_uid(sk);
+       r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
        r->idiag_inode = sock_i_ino(sk);
 
        if (ext & (1 << (INET_DIAG_MEMINFO - 1))) {
@@ -199,11 +200,12 @@ EXPORT_SYMBOL_GPL(inet_sk_diag_fill);
 
 static int inet_csk_diag_fill(struct sock *sk,
                              struct sk_buff *skb, struct inet_diag_req_v2 *req,
+                             struct user_namespace *user_ns,
                              u32 pid, u32 seq, u16 nlmsg_flags,
                              const struct nlmsghdr *unlh)
 {
        return inet_sk_diag_fill(sk, inet_csk(sk),
-                       skb, req, pid, seq, nlmsg_flags, unlh);
+                       skb, req, user_ns, pid, seq, nlmsg_flags, unlh);
 }
 
 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,
 }
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
-                       struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags,
+                       struct inet_diag_req_v2 *r,
+                       struct user_namespace *user_ns,
+                       u32 pid, u32 seq, u16 nlmsg_flags,
                        const struct nlmsghdr *unlh)
 {
        if (sk->sk_state == TCP_TIME_WAIT)
                return inet_twsk_diag_fill((struct inet_timewait_sock *)sk,
                                           skb, r, pid, seq, nlmsg_flags,
                                           unlh);
-       return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh);
+       return inet_csk_diag_fill(sk, skb, r, user_ns, pid, seq, nlmsg_flags, unlh);
 }
 
 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
        }
 
        err = sk_diag_fill(sk, rep, req,
+                          sk_user_ns(NETLINK_CB(in_skb).ssk),
                           NETLINK_CB(in_skb).pid,
                           nlh->nlmsg_seq, 0, nlh);
        if (err < 0) {
@@ -551,6 +556,7 @@ static int inet_csk_diag_dump(struct sock *sk,
                return 0;
 
        return inet_csk_diag_fill(sk, skb, r,
+                                 sk_user_ns(NETLINK_CB(cb->skb).ssk),
                                  NETLINK_CB(cb->skb).pid,
                                  cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 }
@@ -591,7 +597,9 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw,
 }
 
 static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk,
-                             struct request_sock *req, u32 pid, u32 seq,
+                             struct request_sock *req,
+                             struct user_namespace *user_ns,
+                             u32 pid, u32 seq,
                              const struct nlmsghdr *unlh)
 {
        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,
        r->idiag_expires = jiffies_to_msecs(tmo);
        r->idiag_rqueue = 0;
        r->idiag_wqueue = 0;
-       r->idiag_uid = sock_i_uid(sk);
+       r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk));
        r->idiag_inode = 0;
 #if IS_ENABLED(CONFIG_IPV6)
        if (r->idiag_family == AF_INET6) {
@@ -702,6 +710,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk,
                        }
 
                        err = inet_diag_fill_req(skb, sk, req,
+                                              sk_user_ns(NETLINK_CB(cb->skb).ssk),
                                               NETLINK_CB(cb->skb).pid,
                                               cb->nlh->nlmsg_seq, cb->nlh);
                        if (err < 0) {
index 16d0960062be9a5fd0bb8c031e224c04595313c2..d2f336ea82caa98cefdc6e84540fa784ea6703b7 100644 (file)
@@ -24,7 +24,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb,
        if (!inet_diag_bc_sk(bc, sk))
                return 0;
 
-       return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid,
+       return inet_sk_diag_fill(sk, NULL, skb, req,
+                       sk_user_ns(NETLINK_CB(cb->skb).ssk),
+                       NETLINK_CB(cb->skb).pid,
                        cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh);
 }
 
@@ -69,6 +71,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb,
                goto out;
 
        err = inet_sk_diag_fill(sk, NULL, rep, req,
+                          sk_user_ns(NETLINK_CB(in_skb).ssk),
                           NETLINK_CB(in_skb).pid,
                           nlh->nlmsg_seq, 0, nlh);
        if (err < 0) {