Skip to content

Commit c05cdb1

Browse files
ummakynesdavem330
authored andcommitted
netlink: allow large data transfers from user-space
I can hit ENOBUFS in the sendmsg() path with a large batch that is composed of many netlink messages. Here that limit is 8 MBytes of skbuff data area as kmalloc does not manage to get more than that. While discussing atomic rule-set for nftables with Patrick McHardy, we decided to put all rule-set updates that need to be applied atomically in one single batch to simplify the existing approach. However, as explained above, the existing netlink code limits us to a maximum of ~20000 rules that fit in one single batch without hitting ENOBUFS. iptables does not have such limitation as it is using vmalloc. This patch adds netlink_alloc_large_skb() which is only used in the netlink_sendmsg() path. It uses alloc_skb if the memory requested is <= one memory page, that should be the common case for most subsystems, else vmalloc for higher memory allocations. Signed-off-by: Pablo Neira Ayuso <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 1b5acd2 commit c05cdb1

File tree

1 file changed

+35
-2
lines changed

1 file changed

+35
-2
lines changed

net/netlink/af_netlink.c

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,10 @@ static void netlink_skb_destructor(struct sk_buff *skb)
750750
skb->head = NULL;
751751
}
752752
#endif
753+
if (is_vmalloc_addr(skb->head)) {
754+
vfree(skb->head);
755+
skb->head = NULL;
756+
}
753757
if (skb->sk != NULL)
754758
sock_rfree(skb);
755759
}
@@ -1420,6 +1424,35 @@ struct sock *netlink_getsockbyfilp(struct file *filp)
14201424
return sock;
14211425
}
14221426

1427+
static struct sk_buff *netlink_alloc_large_skb(unsigned int size)
1428+
{
1429+
struct sk_buff *skb;
1430+
void *data;
1431+
1432+
if (size <= NLMSG_GOODSIZE)
1433+
return alloc_skb(size, GFP_KERNEL);
1434+
1435+
skb = alloc_skb_head(GFP_KERNEL);
1436+
if (skb == NULL)
1437+
return NULL;
1438+
1439+
data = vmalloc(size);
1440+
if (data == NULL)
1441+
goto err;
1442+
1443+
skb->head = data;
1444+
skb->data = data;
1445+
skb_reset_tail_pointer(skb);
1446+
skb->end = skb->tail + size;
1447+
skb->len = 0;
1448+
skb->destructor = netlink_skb_destructor;
1449+
1450+
return skb;
1451+
err:
1452+
kfree_skb(skb);
1453+
return NULL;
1454+
}
1455+
14231456
/*
14241457
* Attach a skb to a netlink socket.
14251458
* The caller must hold a reference to the destination socket. On error, the
@@ -1510,7 +1543,7 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
15101543
return skb;
15111544

15121545
delta = skb->end - skb->tail;
1513-
if (delta * 2 < skb->truesize)
1546+
if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize)
15141547
return skb;
15151548

15161549
if (skb_shared(skb)) {
@@ -2096,7 +2129,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
20962129
if (len > sk->sk_sndbuf - 32)
20972130
goto out;
20982131
err = -ENOBUFS;
2099-
skb = alloc_skb(len, GFP_KERNEL);
2132+
skb = netlink_alloc_large_skb(len);
21002133
if (skb == NULL)
21012134
goto out;
21022135

0 commit comments

Comments
 (0)