aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c42
1 files changed, 29 insertions, 13 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a2eb965207d3..2cbf380377d5 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1076,14 +1076,15 @@ int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 pid,
1076 sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list) 1076 sk_for_each_bound(sk, node, &nl_table[ssk->sk_protocol].mc_list)
1077 do_one_broadcast(sk, &info); 1077 do_one_broadcast(sk, &info);
1078 1078
1079 kfree_skb(skb); 1079 consume_skb(skb);
1080 1080
1081 netlink_unlock_table(); 1081 netlink_unlock_table();
1082 1082
1083 kfree_skb(info.skb2); 1083 if (info.delivery_failure) {
1084 1084 kfree_skb(info.skb2);
1085 if (info.delivery_failure)
1086 return -ENOBUFS; 1085 return -ENOBUFS;
1086 } else
1087 consume_skb(info.skb2);
1087 1088
1088 if (info.delivered) { 1089 if (info.delivered) {
1089 if (info.congested && (allocation & __GFP_WAIT)) 1090 if (info.congested && (allocation & __GFP_WAIT))
@@ -1323,19 +1324,23 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
1323 if (msg->msg_flags&MSG_OOB) 1324 if (msg->msg_flags&MSG_OOB)
1324 return -EOPNOTSUPP; 1325 return -EOPNOTSUPP;
1325 1326
1326 if (NULL == siocb->scm) 1327 if (NULL == siocb->scm) {
1327 siocb->scm = &scm; 1328 siocb->scm = &scm;
1329 memset(&scm, 0, sizeof(scm));
1330 }
1328 err = scm_send(sock, msg, siocb->scm); 1331 err = scm_send(sock, msg, siocb->scm);
1329 if (err < 0) 1332 if (err < 0)
1330 return err; 1333 return err;
1331 1334
1332 if (msg->msg_namelen) { 1335 if (msg->msg_namelen) {
1336 err = -EINVAL;
1333 if (addr->nl_family != AF_NETLINK) 1337 if (addr->nl_family != AF_NETLINK)
1334 return -EINVAL; 1338 goto out;
1335 dst_pid = addr->nl_pid; 1339 dst_pid = addr->nl_pid;
1336 dst_group = ffs(addr->nl_groups); 1340 dst_group = ffs(addr->nl_groups);
1341 err = -EPERM;
1337 if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) 1342 if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
1338 return -EPERM; 1343 goto out;
1339 } else { 1344 } else {
1340 dst_pid = nlk->dst_pid; 1345 dst_pid = nlk->dst_pid;
1341 dst_group = nlk->dst_group; 1346 dst_group = nlk->dst_group;
@@ -1387,6 +1392,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
1387 err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT); 1392 err = netlink_unicast(sk, skb, dst_pid, msg->msg_flags&MSG_DONTWAIT);
1388 1393
1389out: 1394out:
1395 scm_destroy(siocb->scm);
1390 return err; 1396 return err;
1391} 1397}
1392 1398
@@ -1400,7 +1406,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1400 struct netlink_sock *nlk = nlk_sk(sk); 1406 struct netlink_sock *nlk = nlk_sk(sk);
1401 int noblock = flags&MSG_DONTWAIT; 1407 int noblock = flags&MSG_DONTWAIT;
1402 size_t copied; 1408 size_t copied;
1403 struct sk_buff *skb, *frag __maybe_unused = NULL; 1409 struct sk_buff *skb;
1404 int err; 1410 int err;
1405 1411
1406 if (flags&MSG_OOB) 1412 if (flags&MSG_OOB)
@@ -1435,7 +1441,21 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1435 kfree_skb(skb); 1441 kfree_skb(skb);
1436 skb = compskb; 1442 skb = compskb;
1437 } else { 1443 } else {
1438 frag = skb_shinfo(skb)->frag_list; 1444 /*
1445 * Before setting frag_list to NULL, we must get a
1446 * private copy of skb if shared (because of MSG_PEEK)
1447 */
1448 if (skb_shared(skb)) {
1449 struct sk_buff *nskb;
1450
1451 nskb = pskb_copy(skb, GFP_KERNEL);
1452 kfree_skb(skb);
1453 skb = nskb;
1454 err = -ENOMEM;
1455 if (!skb)
1456 goto out;
1457 }
1458 kfree_skb(skb_shinfo(skb)->frag_list);
1439 skb_shinfo(skb)->frag_list = NULL; 1459 skb_shinfo(skb)->frag_list = NULL;
1440 } 1460 }
1441 } 1461 }
@@ -1472,10 +1492,6 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1472 if (flags & MSG_TRUNC) 1492 if (flags & MSG_TRUNC)
1473 copied = skb->len; 1493 copied = skb->len;
1474 1494
1475#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
1476 skb_shinfo(skb)->frag_list = frag;
1477#endif
1478
1479 skb_free_datagram(sk, skb); 1495 skb_free_datagram(sk, skb);
1480 1496
1481 if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) 1497 if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)