linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* dns_resolver_preparse tries to print arbitrarily-large user-provided strings
@ 2018-02-27 16:43 Mark Rutland
  2018-02-28  1:31 ` Eric Biggers
  0 siblings, 1 reply; 2+ messages in thread
From: Mark Rutland @ 2018-02-27 16:43 UTC (permalink / raw)
  To: netdev, linux-kernel; +Cc: David S. Miller, David Howells, Eric Biggers

Hi,

As a heads-up, while fuzzing v4.16-rc3 on arm64 with Syzkaller, I hit a
system hang which I was able to minize to the reproducer below. It looks
like the system hang is an artifact of Syzkaller using panic_on_warn, as
dns_resolver_preparse can trigger a WARN_ONCE() in the bowels of
printk(), and we recurse on a lock that's already held.

The underlying issue is that dns_resolver_preparse() may try to dump an
arbitrarily large chunk of user-provided data, even from an unprivileged
user, while printk() has some internal limit on string precision.

On bare metal (without panic_on_warn), this means I get the following in
my dmesg:

$ ./repro
[   56.870339] Option '                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
[   56.870350] ------------[ cut here ]------------
[   56.870355] precision 1044478 too large
[   56.870362] WARNING: CPU: 2 PID: 2450 at lib/vsprintf.c:2179 vsnprintf+0xdf0/0x1268
[   56.870366] Modules linked in:
[   56.870376] CPU: 2 PID: 2450 Comm: repro Not tainted 4.16.0-rc3-00002-g544c20187688-dirty #4
[   56.870382] Hardware name: ARM Juno development board (r1) (DT)
[   56.870386] pstate: 80000085 (Nzcv daIf -PAN -UAO)
[   56.870390] pc : vsnprintf+0xdf0/0x1268
[   56.870394] lr : vsnprintf+0xdf0/0x1268
[   56.870398] sp : ffff80092b41f6f0
[   56.870401] x29: ffff80092b41f6f0 x28: ffff20000b093f36
[   56.870411] x27: 00000000000003e0 x26: 0000000000000002
[   56.870421] x25: 00000000000feffe x24: 1ffff00125683eee
[   56.870431] x23: ffff20000a433200 x22: ffff20000bc5f3c0
[   56.870440] x21: dfff200000000000 x20: ffff20000bc5efea
[   56.870450] x19: ffff20000a4329ce x18: 0000ffffc51e5860
[   56.870459] x17: 0000000000411018 x16: ffff200008957d28
[   56.870469] x15: 00000000f2000000 x14: ffff20000aa0a6c0
[   56.870479] x13: 0000000000000000 x12: ffff20000aa0a000
[   56.870488] x11: 1ffff00126eda462 x10: ffff100126eda462
[   56.870498] x9 : dfff200000000000 x8 : 0000000000000000
[   56.870507] x7 : ffff8009376d2311 x6 : ffff8009376d2312
[   56.870517] x5 : ffff100126eda463 x4 : ffff100126eda463
[   56.870526] x3 : 0000000000000000 x2 : 0000000000000001
[   56.870536] x1 : fdb9418241605c00 x0 : 0000000000000000
[   56.870545] Call trace:
[   56.870549]  vsnprintf+0xdf0/0x1268
[   56.870553]  vscnprintf+0x48/0x88
[   56.870556]  vprintk_emit+0xac/0x5f0
[   56.870560]  vprintk_default+0x44/0x50
[   56.870564]  vprintk_func+0x3dc/0x630
[   56.870568]  printk+0xbc/0xec
[   56.870572]  dns_resolver_preparse+0x5bc/0x6e8
[   56.870576]  key_create_or_update+0x298/0x828
[   56.870580]  SyS_add_key+0x110/0x3c8
[   56.870584]  el0_svc_naked+0x30/0x34
[   56.870589] ---[ end trace 2b46801cfa43d927 ]---

Any ideas on how to avoid this?

Thanks,
Mark.

---->8----
#include <sys/syscall.h>
#include <unistd.h>

#define BUF_SIZE 0xff000

static char buf[BUF_SIZE] = {
	[0] = '#',
	[1 ... BUF_SIZE - 2] = 'a'
};

int main()
{
	syscall(__NR_add_key, "dns_resolver", "a", buf, BUF_SIZE, -1);
	return 0;
}

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: dns_resolver_preparse tries to print arbitrarily-large user-provided strings
  2018-02-27 16:43 dns_resolver_preparse tries to print arbitrarily-large user-provided strings Mark Rutland
@ 2018-02-28  1:31 ` Eric Biggers
  0 siblings, 0 replies; 2+ messages in thread
From: Eric Biggers @ 2018-02-28  1:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: netdev, linux-kernel, David S. Miller, David Howells, Eric Biggers

Hi Mark,

On Tue, Feb 27, 2018 at 04:43:13PM +0000, Mark Rutland wrote:
> Hi,
> 
> As a heads-up, while fuzzing v4.16-rc3 on arm64 with Syzkaller, I hit a
> system hang which I was able to minize to the reproducer below. It looks
> like the system hang is an artifact of Syzkaller using panic_on_warn, as
> dns_resolver_preparse can trigger a WARN_ONCE() in the bowels of
> printk(), and we recurse on a lock that's already held.
> 
> The underlying issue is that dns_resolver_preparse() may try to dump an
> arbitrarily large chunk of user-provided data, even from an unprivileged
> user, while printk() has some internal limit on string precision.
> 
> On bare metal (without panic_on_warn), this means I get the following in
> my dmesg:
> 
> $ ./repro
> [   56.870339] Option '                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            
> [   56.870350] ------------[ cut here ]------------
> [   56.870355] precision 1044478 too large
> [   56.870362] WARNING: CPU: 2 PID: 2450 at lib/vsprintf.c:2179 vsnprintf+0xdf0/0x1268
> [   56.870366] Modules linked in:
> [   56.870376] CPU: 2 PID: 2450 Comm: repro Not tainted 4.16.0-rc3-00002-g544c20187688-dirty #4
> [   56.870382] Hardware name: ARM Juno development board (r1) (DT)
> [   56.870386] pstate: 80000085 (Nzcv daIf -PAN -UAO)
> [   56.870390] pc : vsnprintf+0xdf0/0x1268
> [   56.870394] lr : vsnprintf+0xdf0/0x1268
> [   56.870398] sp : ffff80092b41f6f0
> [   56.870401] x29: ffff80092b41f6f0 x28: ffff20000b093f36
> [   56.870411] x27: 00000000000003e0 x26: 0000000000000002
> [   56.870421] x25: 00000000000feffe x24: 1ffff00125683eee
> [   56.870431] x23: ffff20000a433200 x22: ffff20000bc5f3c0
> [   56.870440] x21: dfff200000000000 x20: ffff20000bc5efea
> [   56.870450] x19: ffff20000a4329ce x18: 0000ffffc51e5860
> [   56.870459] x17: 0000000000411018 x16: ffff200008957d28
> [   56.870469] x15: 00000000f2000000 x14: ffff20000aa0a6c0
> [   56.870479] x13: 0000000000000000 x12: ffff20000aa0a000
> [   56.870488] x11: 1ffff00126eda462 x10: ffff100126eda462
> [   56.870498] x9 : dfff200000000000 x8 : 0000000000000000
> [   56.870507] x7 : ffff8009376d2311 x6 : ffff8009376d2312
> [   56.870517] x5 : ffff100126eda463 x4 : ffff100126eda463
> [   56.870526] x3 : 0000000000000000 x2 : 0000000000000001
> [   56.870536] x1 : fdb9418241605c00 x0 : 0000000000000000
> [   56.870545] Call trace:
> [   56.870549]  vsnprintf+0xdf0/0x1268
> [   56.870553]  vscnprintf+0x48/0x88
> [   56.870556]  vprintk_emit+0xac/0x5f0
> [   56.870560]  vprintk_default+0x44/0x50
> [   56.870564]  vprintk_func+0x3dc/0x630
> [   56.870568]  printk+0xbc/0xec
> [   56.870572]  dns_resolver_preparse+0x5bc/0x6e8
> [   56.870576]  key_create_or_update+0x298/0x828
> [   56.870580]  SyS_add_key+0x110/0x3c8
> [   56.870584]  el0_svc_naked+0x30/0x34
> [   56.870589] ---[ end trace 2b46801cfa43d927 ]---
> 
> Any ideas on how to avoid this?
> 
> Thanks,
> Mark.
> 
> ---->8----
> #include <sys/syscall.h>
> #include <unistd.h>
> 
> #define BUF_SIZE 0xff000
> 
> static char buf[BUF_SIZE] = {
> 	[0] = '#',
> 	[1 ... BUF_SIZE - 2] = 'a'
> };
> 
> int main()
> {
> 	syscall(__NR_add_key, "dns_resolver", "a", buf, BUF_SIZE, -1);
> 	return 0;
> }
> 

Thanks for the bug report.  At the very least I think dns_resolver_preparse()
should limit the option string lengths.  After all, the only accepted option
currently is "dnserror".  I'll send a patch.

Eric

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2018-02-28  1:31 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-27 16:43 dns_resolver_preparse tries to print arbitrarily-large user-provided strings Mark Rutland
2018-02-28  1:31 ` Eric Biggers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).