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.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d46da6cb92e4..da3163d15ef0 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1361,7 +1361,7 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1361 struct netlink_sock *nlk = nlk_sk(sk); 1361 struct netlink_sock *nlk = nlk_sk(sk);
1362 int noblock = flags&MSG_DONTWAIT; 1362 int noblock = flags&MSG_DONTWAIT;
1363 size_t copied; 1363 size_t copied;
1364 struct sk_buff *skb; 1364 struct sk_buff *skb, *frag __maybe_unused = NULL;
1365 int err; 1365 int err;
1366 1366
1367 if (flags&MSG_OOB) 1367 if (flags&MSG_OOB)
@@ -1373,6 +1373,35 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1373 if (skb == NULL) 1373 if (skb == NULL)
1374 goto out; 1374 goto out;
1375 1375
1376#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
1377 if (unlikely(skb_shinfo(skb)->frag_list)) {
1378 bool need_compat = !!(flags & MSG_CMSG_COMPAT);
1379
1380 /*
1381 * If this skb has a frag_list, then here that means that
1382 * we will have to use the frag_list skb for compat tasks
1383 * and the regular skb for non-compat tasks.
1384 *
1385 * The skb might (and likely will) be cloned, so we can't
1386 * just reset frag_list and go on with things -- we need to
1387 * keep that. For the compat case that's easy -- simply get
1388 * a reference to the compat skb and free the regular one
1389 * including the frag. For the non-compat case, we need to
1390 * avoid sending the frag to the user -- so assign NULL but
1391 * restore it below before freeing the skb.
1392 */
1393 if (need_compat) {
1394 struct sk_buff *compskb = skb_shinfo(skb)->frag_list;
1395 skb_get(compskb);
1396 kfree_skb(skb);
1397 skb = compskb;
1398 } else {
1399 frag = skb_shinfo(skb)->frag_list;
1400 skb_shinfo(skb)->frag_list = NULL;
1401 }
1402 }
1403#endif
1404
1376 msg->msg_namelen = 0; 1405 msg->msg_namelen = 0;
1377 1406
1378 copied = skb->len; 1407 copied = skb->len;
@@ -1403,6 +1432,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock,
1403 siocb->scm->creds = *NETLINK_CREDS(skb); 1432 siocb->scm->creds = *NETLINK_CREDS(skb);
1404 if (flags & MSG_TRUNC) 1433 if (flags & MSG_TRUNC)
1405 copied = skb->len; 1434 copied = skb->len;
1435
1436#ifdef CONFIG_COMPAT_NETLINK_MESSAGES
1437 skb_shinfo(skb)->frag_list = frag;
1438#endif
1439
1406 skb_free_datagram(sk, skb); 1440 skb_free_datagram(sk, skb);
1407 1441
1408 if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) 1442 if (nlk->cb && atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2)