From 626419038a3e4a1f61119a4af08d01415961eb4e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 25 Apr 2013 06:53:52 +0000 Subject: [PATCH 1/3] packet_diag: disclose uid value This value is disclosed via /proc/net/packet but not via netlink messages. The goal is to have the same level of information. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/packet_diag.h | 1 + net/packet/diag.c | 19 ++++++++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h index afafd703ad92..84f83a47b6f6 100644 --- a/include/uapi/linux/packet_diag.h +++ b/include/uapi/linux/packet_diag.h @@ -32,6 +32,7 @@ enum { PACKET_DIAG_RX_RING, PACKET_DIAG_TX_RING, PACKET_DIAG_FANOUT, + PACKET_DIAG_UID, __PACKET_DIAG_MAX, }; diff --git a/net/packet/diag.c b/net/packet/diag.c index d3fcd1ebef7e..04c8219a2d06 100644 --- a/net/packet/diag.c +++ b/net/packet/diag.c @@ -125,8 +125,10 @@ static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb) return ret; } -static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, - u32 portid, u32 seq, u32 flags, int sk_ino) +static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, + struct packet_diag_req *req, + struct user_namespace *user_ns, + u32 portid, u32 seq, u32 flags, int sk_ino) { struct nlmsghdr *nlh; struct packet_diag_msg *rp; @@ -147,6 +149,11 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag pdiag_put_info(po, skb)) goto out_nlmsg_trim; + if ((req->pdiag_show & PACKET_SHOW_INFO) && + nla_put_u32(skb, PACKET_DIAG_UID, + from_kuid_munged(user_ns, sock_i_uid(sk)))) + goto out_nlmsg_trim; + if ((req->pdiag_show & PACKET_SHOW_MCLIST) && pdiag_put_mclist(po, skb)) goto out_nlmsg_trim; @@ -183,9 +190,11 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) if (num < s_num) goto next; - if (sk_diag_fill(sk, skb, req, NETLINK_CB(cb->skb).portid, - cb->nlh->nlmsg_seq, NLM_F_MULTI, - sock_i_ino(sk)) < 0) + if (sk_diag_fill(sk, skb, req, + sk_user_ns(NETLINK_CB(cb->skb).sk), + NETLINK_CB(cb->skb).portid, + cb->nlh->nlmsg_seq, NLM_F_MULTI, + sock_i_ino(sk)) < 0) goto done; next: num++; From 76d0eeb1a1579453cfd7c4da22004d4b34187ab4 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 25 Apr 2013 06:53:53 +0000 Subject: [PATCH 2/3] packet_diag: disclose meminfo values sk_rmem_alloc is disclosed via /proc/net/packet but not via netlink messages. The goal is to have the same level of information. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/uapi/linux/packet_diag.h | 2 ++ net/packet/diag.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h index 84f83a47b6f6..c0802c18c8ad 100644 --- a/include/uapi/linux/packet_diag.h +++ b/include/uapi/linux/packet_diag.h @@ -16,6 +16,7 @@ struct packet_diag_req { #define PACKET_SHOW_MCLIST 0x00000002 /* A set of packet_diag_mclist-s */ #define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */ #define PACKET_SHOW_FANOUT 0x00000008 +#define PACKET_SHOW_MEMINFO 0x00000010 struct packet_diag_msg { __u8 pdiag_family; @@ -33,6 +34,7 @@ enum { PACKET_DIAG_TX_RING, PACKET_DIAG_FANOUT, PACKET_DIAG_UID, + PACKET_DIAG_MEMINFO, __PACKET_DIAG_MAX, }; diff --git a/net/packet/diag.c b/net/packet/diag.c index 04c8219a2d06..822fe9b33a49 100644 --- a/net/packet/diag.c +++ b/net/packet/diag.c @@ -166,6 +166,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, pdiag_put_fanout(po, skb)) goto out_nlmsg_trim; + if ((req->pdiag_show & PACKET_SHOW_MEMINFO) && + sock_diag_put_meminfo(sk, skb, PACKET_DIAG_MEMINFO)) + goto out_nlmsg_trim; + return nlmsg_end(skb, nlh); out_nlmsg_trim: From e8d9612c181b1a68ba5f71384629343466f1bd13 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Thu, 25 Apr 2013 06:53:54 +0000 Subject: [PATCH 3/3] sock_diag: allow to dump bpf filters This patch allows to dump BPF filters attached to a socket with SO_ATTACH_FILTER. Note that we check CAP_SYS_ADMIN before allowing to dump this info. For now, only AF_PACKET sockets use this feature. Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- include/linux/sock_diag.h | 3 +++ include/uapi/linux/packet_diag.h | 2 ++ net/core/sock_diag.c | 33 ++++++++++++++++++++++++++++++++ net/packet/diag.c | 4 ++++ 4 files changed, 42 insertions(+) diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index e8d702e0fd89..54f91d35e5fd 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h @@ -1,6 +1,7 @@ #ifndef __SOCK_DIAG_H__ #define __SOCK_DIAG_H__ +#include #include struct sk_buff; @@ -22,5 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie); void sock_diag_save_cookie(void *sk, __u32 *cookie); int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); +int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, + struct sk_buff *skb, int attrtype); #endif diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h index c0802c18c8ad..b2cc0cd9c4d9 100644 --- a/include/uapi/linux/packet_diag.h +++ b/include/uapi/linux/packet_diag.h @@ -17,6 +17,7 @@ struct packet_diag_req { #define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */ #define PACKET_SHOW_FANOUT 0x00000008 #define PACKET_SHOW_MEMINFO 0x00000010 +#define PACKET_SHOW_FILTER 0x00000020 struct packet_diag_msg { __u8 pdiag_family; @@ -35,6 +36,7 @@ enum { PACKET_DIAG_FANOUT, PACKET_DIAG_UID, PACKET_DIAG_MEMINFO, + PACKET_DIAG_FILTER, __PACKET_DIAG_MAX, }; diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index a29e90cf36b7..d5bef0b0f639 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -49,6 +49,39 @@ int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attrtype) } EXPORT_SYMBOL_GPL(sock_diag_put_meminfo); +int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, + struct sk_buff *skb, int attrtype) +{ + struct nlattr *attr; + struct sk_filter *filter; + unsigned int len; + int err = 0; + + if (!ns_capable(user_ns, CAP_NET_ADMIN)) { + nla_reserve(skb, attrtype, 0); + return 0; + } + + rcu_read_lock(); + + filter = rcu_dereference(sk->sk_filter); + len = filter ? filter->len * sizeof(struct sock_filter) : 0; + + attr = nla_reserve(skb, attrtype, len); + if (attr == NULL) { + err = -EMSGSIZE; + goto out; + } + + if (filter) + memcpy(nla_data(attr), filter->insns, len); + +out: + rcu_read_unlock(); + return err; +} +EXPORT_SYMBOL(sock_diag_put_filterinfo); + void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) { mutex_lock(&sock_diag_table_mutex); diff --git a/net/packet/diag.c b/net/packet/diag.c index 822fe9b33a49..a9584a2f6d69 100644 --- a/net/packet/diag.c +++ b/net/packet/diag.c @@ -170,6 +170,10 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, sock_diag_put_meminfo(sk, skb, PACKET_DIAG_MEMINFO)) goto out_nlmsg_trim; + if ((req->pdiag_show & PACKET_SHOW_FILTER) && + sock_diag_put_filterinfo(user_ns, sk, skb, PACKET_DIAG_FILTER)) + goto out_nlmsg_trim; + return nlmsg_end(skb, nlh); out_nlmsg_trim: