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>
This commit is contained in:
Eric W. Biederman 2014-04-23 14:26:25 -07:00 коммит произвёл David S. Miller
Родитель 5187cd055b
Коммит a53b72c83a
3 изменённых файлов: 9 добавлений и 4 удалений

Просмотреть файл

@ -23,7 +23,7 @@ int sock_diag_check_cookie(void *sk, __u32 *cookie);
void sock_diag_save_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_meminfo(struct sock *sk, struct sk_buff *skb, int attr);
int sock_diag_put_filterinfo(struct sock *sk, int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
struct sk_buff *skb, int attrtype); struct sk_buff *skb, int attrtype);
#endif #endif

Просмотреть файл

@ -49,7 +49,7 @@ int sock_diag_put_meminfo(struct sock *sk, struct sk_buff *skb, int attrtype)
} }
EXPORT_SYMBOL_GPL(sock_diag_put_meminfo); EXPORT_SYMBOL_GPL(sock_diag_put_meminfo);
int sock_diag_put_filterinfo(struct sock *sk, int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk,
struct sk_buff *skb, int attrtype) struct sk_buff *skb, int attrtype)
{ {
struct sock_fprog_kern *fprog; struct sock_fprog_kern *fprog;
@ -58,7 +58,7 @@ int sock_diag_put_filterinfo(struct sock *sk,
unsigned int flen; unsigned int flen;
int err = 0; int err = 0;
if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) { if (!may_report_filterinfo) {
nla_reserve(skb, attrtype, 0); nla_reserve(skb, attrtype, 0);
return 0; return 0;
} }

Просмотреть файл

@ -128,6 +128,7 @@ static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb)
static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
struct packet_diag_req *req, struct packet_diag_req *req,
bool may_report_filterinfo,
struct user_namespace *user_ns, struct user_namespace *user_ns,
u32 portid, u32 seq, u32 flags, int sk_ino) u32 portid, u32 seq, u32 flags, int sk_ino)
{ {
@ -172,7 +173,8 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
goto out_nlmsg_trim; goto out_nlmsg_trim;
if ((req->pdiag_show & PACKET_SHOW_FILTER) && if ((req->pdiag_show & PACKET_SHOW_FILTER) &&
sock_diag_put_filterinfo(sk, skb, PACKET_DIAG_FILTER)) sock_diag_put_filterinfo(may_report_filterinfo, sk, skb,
PACKET_DIAG_FILTER))
goto out_nlmsg_trim; goto out_nlmsg_trim;
return nlmsg_end(skb, nlh); return nlmsg_end(skb, nlh);
@ -188,9 +190,11 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
struct packet_diag_req *req; struct packet_diag_req *req;
struct net *net; struct net *net;
struct sock *sk; struct sock *sk;
bool may_report_filterinfo;
net = sock_net(skb->sk); net = sock_net(skb->sk);
req = nlmsg_data(cb->nlh); req = nlmsg_data(cb->nlh);
may_report_filterinfo = ns_capable(net->user_ns, CAP_NET_ADMIN);
mutex_lock(&net->packet.sklist_lock); mutex_lock(&net->packet.sklist_lock);
sk_for_each(sk, &net->packet.sklist) { sk_for_each(sk, &net->packet.sklist) {
@ -200,6 +204,7 @@ static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)
goto next; goto next;
if (sk_diag_fill(sk, skb, req, if (sk_diag_fill(sk, skb, req,
may_report_filterinfo,
sk_user_ns(NETLINK_CB(cb->skb).sk), sk_user_ns(NETLINK_CB(cb->skb).sk),
NETLINK_CB(cb->skb).portid, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh->nlmsg_seq, NLM_F_MULTI,