[Devel] [PATCH rh7] tun: Silence allocation failer if user asked for too big header

Andrey Ryabinin aryabinin at virtuozzo.com
Tue Oct 6 13:38:13 MSK 2020



On 10/6/20 11:17 AM, Konstantin Khorenko wrote:
> On 10/05/2020 04:42 PM, Andrey Ryabinin wrote:
>> Userspace may ask tun device to send packet with ridiculously
>> big header and trigger this:
>>
>>  ------------[ cut here ]------------
>>  WARNING: CPU: 1 PID: 15366 at mm/page_alloc.c:3548 __alloc_pages_nodemask+0x537/0x1200
>>  order 19 >= 11, gfp 0x2044d0
>>  Call Trace:
>>    dump_stack+0x19/0x1b
>>    __warn+0x17f/0x1c0
>>    warn_slowpath_fmt+0xad/0xe0
>>    __alloc_pages_nodemask+0x537/0x1200
>>    kmalloc_large_node+0x5f/0xd0
>>    __kmalloc_node_track_caller+0x425/0x630
>>    __kmalloc_reserve.isra.33+0x47/0xd0
>>    __alloc_skb+0xdd/0x5f0
>>    alloc_skb_with_frags+0x8f/0x540
>>    sock_alloc_send_pskb+0x5e5/0x940
>>    tun_get_user+0x38b/0x24a0 [tun]
>>    tun_chr_aio_write+0x13a/0x250 [tun]
>>    do_sync_readv_writev+0xdf/0x1c0
>>    do_readv_writev+0x1a5/0x850
>>    vfs_writev+0xba/0x190
>>    SyS_writev+0x17c/0x340
>>    system_call_fastpath+0x25/0x2a
>>
>> Just add __GFP_NOWARN and silently return -ENOMEM to fix this.
>>
>> https://jira.sw.ru/browse/PSBM-103639
>> Signed-off-by: Andrey Ryabinin <aryabinin at virtuozzo.com>
>> ---
>>  drivers/net/tun.c  | 4 ++--
>>  include/net/sock.h | 7 +++++++
>>  net/core/sock.c    | 9 +++++++++
>>  3 files changed, 18 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/net/tun.c b/drivers/net/tun.c
>> index e95a89ba48b7..c0879c6a9703 100644
>> --- a/drivers/net/tun.c
>> +++ b/drivers/net/tun.c
>> @@ -1142,8 +1142,8 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
>>      if (prepad + len < PAGE_SIZE || !linear)
>>          linear = len;
>>
>> -    skb = sock_alloc_send_pskb(sk, prepad + linear, len - linear, noblock,
>> -                   &err, 0);
>> +    skb = sock_alloc_send_pskb_flags(sk, prepad + linear, len - linear, noblock,
>> +                &err, 0, __GFP_NOWARN);
> 
> May be __GFP_ORDER_NOWARN ?
> 

__GFP_ORDER_NOWARN doesn't silence the WARN triggered here:
	if (order >= MAX_ORDER) {
		WARN_ON_ONCE(!(gfp_mask & __GFP_NOWARN));
		return NULL;
	}






More information about the Devel mailing list