diff options
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r-- | net/netlink/af_netlink.c | 42 |
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 | ||
1389 | out: | 1394 | out: |
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) |