Skip to content

Commit

Permalink
userns: Teach inet_diag to work with user namespaces
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Eric W. Biederman committed Aug 15, 2012
1 parent c336d14 commit d06ca95
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 8 deletions.
1 change: 1 addition & 0 deletions include/linux/inet_diag.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 0 additions & 1 deletion init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 15 additions & 6 deletions net/ipv4/inet_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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))) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down
5 changes: 4 additions & 1 deletion net/ipv4/udp_diag.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit d06ca95

Please sign in to comment.