diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2014-04-23 17:26:25 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2014-04-24 13:44:53 -0400 |
| commit | a53b72c83a4216f2eb883ed45a0cbce014b8e62d (patch) | |
| tree | e5a7f73a70a53c3485f3147de60f7c77b1ab7f4f | |
| parent | 5187cd055b6e81fc6526109456f8b20623148d5f (diff) | |
net: Move the permission check in sock_diag_put_filterinfo to packet_diag_dump
The permission check in sock_diag_put_filterinfo is wrong, and it is so removed
from it's sources it is not clear why it is wrong. Move the computation
into packet_diag_dump and pass a bool of the result into sock_diag_filterinfo.
This does not yet correct the capability check but instead simply moves it to make
it clear what is going on.
Reported-by: Andy Lutomirski <luto@amacapital.net>
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
| -rw-r--r-- | include/linux/sock_diag.h | 2 | ||||
| -rw-r--r-- | net/core/sock_diag.c | 4 | ||||
| -rw-r--r-- | net/packet/diag.c | 7 |
3 files changed, 9 insertions, 4 deletions
diff --git a/include/linux/sock_diag.h b/include/linux/sock_diag.h index 302ab805b0bb..46cca4c06848 100644 --- a/include/linux/sock_diag.h +++ b/include/linux/sock_diag.h | |||
| @@ -23,7 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie); | |||
| 23 | void sock_diag_save_cookie(void *sk, __u32 *cookie); | 23 | void sock_diag_save_cookie(void *sk, __u32 *cookie); |
| 24 | 24 | ||
| 25 | 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 sock *sk, | 26 | int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk, |
| 27 | struct sk_buff *skb, int attrtype); | 27 | struct sk_buff *skb, int attrtype); |
| 28 | 28 | ||
| 29 | #endif | 29 | #endif |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index 9deb6abd6cf6..a4216a4c9572 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
| @@ -49,7 +49,7 @@ 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 sock *sk, | 52 | int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk, |
| 53 | struct sk_buff *skb, int attrtype) | 53 | struct sk_buff *skb, int attrtype) |
| 54 | { | 54 | { |
| 55 | struct sock_fprog_kern *fprog; | 55 | struct sock_fprog_kern *fprog; |
| @@ -58,7 +58,7 @@ int sock_diag_put_filterinfo(struct sock *sk, | |||
| 58 | unsigned int flen; | 58 | unsigned int flen; |
| 59 | int err = 0; | 59 | int err = 0; |
| 60 | 60 | ||
| 61 | if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { | 61 | if (!may_report_filterinfo) { |
| 62 | nla_reserve(skb, attrtype, 0); | 62 | nla_reserve(skb, attrtype, 0); |
| 63 | return 0; | 63 | return 0; |
| 64 | } | 64 | } |
diff --git a/net/packet/diag.c b/net/packet/diag.c index 435ff99ba8c7..b34d0de24091 100644 --- a/net/packet/diag.c +++ b/net/packet/diag.c | |||
| @@ -128,6 +128,7 @@ static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb) | |||
| 128 | 128 | ||
| 129 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | 129 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
| 130 | struct packet_diag_req *req, | 130 | struct packet_diag_req *req, |
| 131 | bool may_report_filterinfo, | ||
| 131 | struct user_namespace *user_ns, | 132 | struct user_namespace *user_ns, |
| 132 | u32 portid, u32 seq, u32 flags, int sk_ino) | 133 | u32 portid, u32 seq, u32 flags, int sk_ino) |
| 133 | { | 134 | { |
| @@ -172,7 +173,8 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | |||
| 172 | goto out_nlmsg_trim; | 173 | goto out_nlmsg_trim; |
| 173 | 174 | ||
| 174 | if ((req->pdiag_show & PACKET_SHOW_FILTER) && | 175 | if ((req->pdiag_show & PACKET_SHOW_FILTER) && |
| 175 | sock_diag_put_filterinfo(sk, skb, PACKET_DIAG_FILTER)) | 176 | sock_diag_put_filterinfo(may_report_filterinfo, sk, skb, |
| 177 | PACKET_DIAG_FILTER)) | ||
| 176 | goto out_nlmsg_trim; | 178 | goto out_nlmsg_trim; |
| 177 | 179 | ||
| 178 | return nlmsg_end(skb, nlh); | 180 | return nlmsg_end(skb, nlh); |
| @@ -188,9 +190,11 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 188 | struct packet_diag_req *req; | 190 | struct packet_diag_req *req; |
| 189 | struct net *net; | 191 | struct net *net; |
| 190 | struct sock *sk; | 192 | struct sock *sk; |
| 193 | bool may_report_filterinfo; | ||
| 191 | 194 | ||
| 192 | net = sock_net(skb->sk); | 195 | net = sock_net(skb->sk); |
| 193 | req = nlmsg_data(cb->nlh); | 196 | req = nlmsg_data(cb->nlh); |
| 197 | may_report_filterinfo = ns_capable(net->user_ns, CAP_NET_ADMIN); | ||
| 194 | 198 | ||
| 195 | mutex_lock(&net->packet.sklist_lock); | 199 | mutex_lock(&net->packet.sklist_lock); |
| 196 | sk_for_each(sk, &net->packet.sklist) { | 200 | sk_for_each(sk, &net->packet.sklist) { |
| @@ -200,6 +204,7 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 200 | goto next; | 204 | goto next; |
| 201 | 205 | ||
| 202 | if (sk_diag_fill(sk, skb, req, | 206 | if (sk_diag_fill(sk, skb, req, |
| 207 | may_report_filterinfo, | ||
| 203 | sk_user_ns(NETLINK_CB(cb->skb).sk), | 208 | sk_user_ns(NETLINK_CB(cb->skb).sk), |
| 204 | NETLINK_CB(cb->skb).portid, | 209 | NETLINK_CB(cb->skb).portid, |
| 205 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 210 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
