diff options
author | David S. Miller <davem@davemloft.net> | 2013-04-29 13:22:07 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-04-29 13:22:07 -0400 |
commit | 13ccf043ce85b64802a57bd3e47ca1505b6bf275 (patch) | |
tree | 16093300e9da78c1c3e272283ae4886d7b3984e8 | |
parent | fdd5f43a1b53a844d04c6eda2cbdbe044b629ae7 (diff) | |
parent | e8d9612c181b1a68ba5f71384629343466f1bd13 (diff) |
Merge branch 'pktdiag'
Nicolas Dichtel says:
====================
The goal of this patchset is to be able to get all infos exported via the
/proc/net/packet and also beeing able to get filter associated to af_packet
sockets.
As usual, the patch against iproute2 will be sent once the patches are included
and net-next merged. I can send it on demand.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/sock_diag.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/packet_diag.h | 5 | ||||
-rw-r--r-- | net/core/sock_diag.c | 33 | ||||
-rw-r--r-- | net/packet/diag.c | 27 |
4 files changed, 63 insertions, 5 deletions
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 @@ | |||
1 | #ifndef __SOCK_DIAG_H__ | 1 | #ifndef __SOCK_DIAG_H__ |
2 | #define __SOCK_DIAG_H__ | 2 | #define __SOCK_DIAG_H__ |
3 | 3 | ||
4 | #include <linux/user_namespace.h> | ||
4 | #include <uapi/linux/sock_diag.h> | 5 | #include <uapi/linux/sock_diag.h> |
5 | 6 | ||
6 | struct sk_buff; | 7 | struct sk_buff; |
@@ -22,5 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie); | |||
22 | void sock_diag_save_cookie(void *sk, __u32 *cookie); | 23 | void sock_diag_save_cookie(void *sk, __u32 *cookie); |
23 | 24 | ||
24 | int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); | 25 | int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attr); |
26 | int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, | ||
27 | struct sk_buff *skb, int attrtype); | ||
25 | 28 | ||
26 | #endif | 29 | #endif |
diff --git a/include/uapi/linux/packet_diag.h b/include/uapi/linux/packet_diag.h index afafd703ad92..b2cc0cd9c4d9 100644 --- a/include/uapi/linux/packet_diag.h +++ b/include/uapi/linux/packet_diag.h | |||
@@ -16,6 +16,8 @@ struct packet_diag_req { | |||
16 | #define PACKET_SHOW_MCLIST 0x00000002 /* A set of packet_diag_mclist-s */ | 16 | #define PACKET_SHOW_MCLIST 0x00000002 /* A set of packet_diag_mclist-s */ |
17 | #define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */ | 17 | #define PACKET_SHOW_RING_CFG 0x00000004 /* Rings configuration parameters */ |
18 | #define PACKET_SHOW_FANOUT 0x00000008 | 18 | #define PACKET_SHOW_FANOUT 0x00000008 |
19 | #define PACKET_SHOW_MEMINFO 0x00000010 | ||
20 | #define PACKET_SHOW_FILTER 0x00000020 | ||
19 | 21 | ||
20 | struct packet_diag_msg { | 22 | struct packet_diag_msg { |
21 | __u8 pdiag_family; | 23 | __u8 pdiag_family; |
@@ -32,6 +34,9 @@ enum { | |||
32 | PACKET_DIAG_RX_RING, | 34 | PACKET_DIAG_RX_RING, |
33 | PACKET_DIAG_TX_RING, | 35 | PACKET_DIAG_TX_RING, |
34 | PACKET_DIAG_FANOUT, | 36 | PACKET_DIAG_FANOUT, |
37 | PACKET_DIAG_UID, | ||
38 | PACKET_DIAG_MEMINFO, | ||
39 | PACKET_DIAG_FILTER, | ||
35 | 40 | ||
36 | __PACKET_DIAG_MAX, | 41 | __PACKET_DIAG_MAX, |
37 | }; | 42 | }; |
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) | |||
49 | } | 49 | } |
50 | EXPORT_SYMBOL_GPL(sock_diag_put_meminfo); | 50 | EXPORT_SYMBOL_GPL(sock_diag_put_meminfo); |
51 | 51 | ||
52 | int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, | ||
53 | struct sk_buff *skb, int attrtype) | ||
54 | { | ||
55 | struct nlattr *attr; | ||
56 | struct sk_filter *filter; | ||
57 | unsigned int len; | ||
58 | int err = 0; | ||
59 | |||
60 | if (!ns_capable(user_ns, CAP_NET_ADMIN)) { | ||
61 | nla_reserve(skb, attrtype, 0); | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | rcu_read_lock(); | ||
66 | |||
67 | filter = rcu_dereference(sk->sk_filter); | ||
68 | len = filter ? filter->len * sizeof(struct sock_filter) : 0; | ||
69 | |||
70 | attr = nla_reserve(skb, attrtype, len); | ||
71 | if (attr == NULL) { | ||
72 | err = -EMSGSIZE; | ||
73 | goto out; | ||
74 | } | ||
75 | |||
76 | if (filter) | ||
77 | memcpy(nla_data(attr), filter->insns, len); | ||
78 | |||
79 | out: | ||
80 | rcu_read_unlock(); | ||
81 | return err; | ||
82 | } | ||
83 | EXPORT_SYMBOL(sock_diag_put_filterinfo); | ||
84 | |||
52 | void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) | 85 | void sock_diag_register_inet_compat(int (*fn)(struct sk_buff *skb, struct nlmsghdr *nlh)) |
53 | { | 86 | { |
54 | mutex_lock(&sock_diag_table_mutex); | 87 | mutex_lock(&sock_diag_table_mutex); |
diff --git a/net/packet/diag.c b/net/packet/diag.c index d3fcd1ebef7e..a9584a2f6d69 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) | |||
125 | return ret; | 125 | return ret; |
126 | } | 126 | } |
127 | 127 | ||
128 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, | 128 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
129 | u32 portid, u32 seq, u32 flags, int sk_ino) | 129 | struct packet_diag_req *req, |
130 | struct user_namespace *user_ns, | ||
131 | u32 portid, u32 seq, u32 flags, int sk_ino) | ||
130 | { | 132 | { |
131 | struct nlmsghdr *nlh; | 133 | struct nlmsghdr *nlh; |
132 | struct packet_diag_msg *rp; | 134 | struct packet_diag_msg *rp; |
@@ -147,6 +149,11 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag | |||
147 | pdiag_put_info(po, skb)) | 149 | pdiag_put_info(po, skb)) |
148 | goto out_nlmsg_trim; | 150 | goto out_nlmsg_trim; |
149 | 151 | ||
152 | if ((req->pdiag_show & PACKET_SHOW_INFO) && | ||
153 | nla_put_u32(skb, PACKET_DIAG_UID, | ||
154 | from_kuid_munged(user_ns, sock_i_uid(sk)))) | ||
155 | goto out_nlmsg_trim; | ||
156 | |||
150 | if ((req->pdiag_show & PACKET_SHOW_MCLIST) && | 157 | if ((req->pdiag_show & PACKET_SHOW_MCLIST) && |
151 | pdiag_put_mclist(po, skb)) | 158 | pdiag_put_mclist(po, skb)) |
152 | goto out_nlmsg_trim; | 159 | goto out_nlmsg_trim; |
@@ -159,6 +166,14 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag | |||
159 | pdiag_put_fanout(po, skb)) | 166 | pdiag_put_fanout(po, skb)) |
160 | goto out_nlmsg_trim; | 167 | goto out_nlmsg_trim; |
161 | 168 | ||
169 | if ((req->pdiag_show & PACKET_SHOW_MEMINFO) && | ||
170 | sock_diag_put_meminfo(sk, skb, PACKET_DIAG_MEMINFO)) | ||
171 | goto out_nlmsg_trim; | ||
172 | |||
173 | if ((req->pdiag_show & PACKET_SHOW_FILTER) && | ||
174 | sock_diag_put_filterinfo(user_ns, sk, skb, PACKET_DIAG_FILTER)) | ||
175 | goto out_nlmsg_trim; | ||
176 | |||
162 | return nlmsg_end(skb, nlh); | 177 | return nlmsg_end(skb, nlh); |
163 | 178 | ||
164 | out_nlmsg_trim: | 179 | out_nlmsg_trim: |
@@ -183,9 +198,11 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
183 | if (num < s_num) | 198 | if (num < s_num) |
184 | goto next; | 199 | goto next; |
185 | 200 | ||
186 | if (sk_diag_fill(sk, skb, req, NETLINK_CB(cb->skb).portid, | 201 | if (sk_diag_fill(sk, skb, req, |
187 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 202 | sk_user_ns(NETLINK_CB(cb->skb).sk), |
188 | sock_i_ino(sk)) < 0) | 203 | NETLINK_CB(cb->skb).portid, |
204 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
205 | sock_i_ino(sk)) < 0) | ||
189 | goto done; | 206 | goto done; |
190 | next: | 207 | next: |
191 | num++; | 208 | num++; |