diff options
-rw-r--r-- | include/linux/netlink.h | 7 | ||||
-rw-r--r-- | net/netlink/af_netlink.c | 7 |
2 files changed, 10 insertions, 4 deletions
diff --git a/include/linux/netlink.h b/include/linux/netlink.h index f64b01787ddc..034cda789a15 100644 --- a/include/linux/netlink.h +++ b/include/linux/netlink.h | |||
@@ -16,9 +16,10 @@ static inline struct nlmsghdr *nlmsg_hdr(const struct sk_buff *skb) | |||
16 | } | 16 | } |
17 | 17 | ||
18 | enum netlink_skb_flags { | 18 | enum netlink_skb_flags { |
19 | NETLINK_SKB_MMAPED = 0x1, /* Packet data is mmaped */ | 19 | NETLINK_SKB_MMAPED = 0x1, /* Packet data is mmaped */ |
20 | NETLINK_SKB_TX = 0x2, /* Packet was sent by userspace */ | 20 | NETLINK_SKB_TX = 0x2, /* Packet was sent by userspace */ |
21 | NETLINK_SKB_DELIVERED = 0x4, /* Packet was delivered */ | 21 | NETLINK_SKB_DELIVERED = 0x4, /* Packet was delivered */ |
22 | NETLINK_SKB_DST = 0x8, /* Dst set in sendto or sendmsg */ | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | struct netlink_skb_parms { | 25 | struct netlink_skb_parms { |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 81dca96d2be6..f22757a29cd0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -1373,7 +1373,9 @@ retry: | |||
1373 | bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, | 1373 | bool __netlink_ns_capable(const struct netlink_skb_parms *nsp, |
1374 | struct user_namespace *user_ns, int cap) | 1374 | struct user_namespace *user_ns, int cap) |
1375 | { | 1375 | { |
1376 | return sk_ns_capable(nsp->sk, user_ns, cap); | 1376 | return ((nsp->flags & NETLINK_SKB_DST) || |
1377 | file_ns_capable(nsp->sk->sk_socket->file, user_ns, cap)) && | ||
1378 | ns_capable(user_ns, cap); | ||
1377 | } | 1379 | } |
1378 | EXPORT_SYMBOL(__netlink_ns_capable); | 1380 | EXPORT_SYMBOL(__netlink_ns_capable); |
1379 | 1381 | ||
@@ -2293,6 +2295,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
2293 | struct sk_buff *skb; | 2295 | struct sk_buff *skb; |
2294 | int err; | 2296 | int err; |
2295 | struct scm_cookie scm; | 2297 | struct scm_cookie scm; |
2298 | u32 netlink_skb_flags = 0; | ||
2296 | 2299 | ||
2297 | if (msg->msg_flags&MSG_OOB) | 2300 | if (msg->msg_flags&MSG_OOB) |
2298 | return -EOPNOTSUPP; | 2301 | return -EOPNOTSUPP; |
@@ -2314,6 +2317,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
2314 | if ((dst_group || dst_portid) && | 2317 | if ((dst_group || dst_portid) && |
2315 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) | 2318 | !netlink_allowed(sock, NL_CFG_F_NONROOT_SEND)) |
2316 | goto out; | 2319 | goto out; |
2320 | netlink_skb_flags |= NETLINK_SKB_DST; | ||
2317 | } else { | 2321 | } else { |
2318 | dst_portid = nlk->dst_portid; | 2322 | dst_portid = nlk->dst_portid; |
2319 | dst_group = nlk->dst_group; | 2323 | dst_group = nlk->dst_group; |
@@ -2343,6 +2347,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
2343 | NETLINK_CB(skb).portid = nlk->portid; | 2347 | NETLINK_CB(skb).portid = nlk->portid; |
2344 | NETLINK_CB(skb).dst_group = dst_group; | 2348 | NETLINK_CB(skb).dst_group = dst_group; |
2345 | NETLINK_CB(skb).creds = siocb->scm->creds; | 2349 | NETLINK_CB(skb).creds = siocb->scm->creds; |
2350 | NETLINK_CB(skb).flags = netlink_skb_flags; | ||
2346 | 2351 | ||
2347 | err = -EFAULT; | 2352 | err = -EFAULT; |
2348 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 2353 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |