@@ -166,9 +166,10 @@ struct netlink_skb_parms {
struct ucred creds; /* Skb credentials */
__u32 pid;
__u32 dst_group;
+ __u32 flags;
struct sock *ssk;
};
-
+#define NETLINK_SKB_DST 0x8 /* Dst set in sendto or sendmsg */
#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
@@ -603,7 +603,9 @@ retry:
bool __netlink_ns_capable(const struct netlink_skb_parms *nsp,
struct user_namespace *user_ns, int cap)
{
- return sk_ns_capable(nsp->ssk, user_ns, cap);
+ return ((nsp->flags & NETLINK_SKB_DST) ||
+ file_ns_capable(nsp->ssk->sk_socket->file, user_ns, cap)) &&
+ ns_capable(user_ns, cap);
}
EXPORT_SYMBOL(__netlink_ns_capable);
@@ -1402,6 +1404,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
struct sk_buff *skb;
int err;
struct scm_cookie scm;
+ u32 netlink_skb_flags = 0;
if (msg->msg_flags&MSG_OOB)
return -EOPNOTSUPP;
@@ -1423,6 +1426,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
if ((dst_group || dst_pid) &&
!netlink_allowed(sock, NL_NONROOT_SEND))
goto out;
+ netlink_skb_flags |= NETLINK_SKB_DST;
} else {
dst_pid = nlk->dst_pid;
dst_group = nlk->dst_group;
@@ -1444,6 +1448,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
NETLINK_CB(skb).pid = nlk->pid;
NETLINK_CB(skb).dst_group = dst_group;
+ NETLINK_CB(skb).flags = netlink_skb_flags;
memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred));
err = -EFAULT;