Messages in this thread Patch in this message | | | Subject | [PATCH net] KEYS: DNS: fix parsing multiple options | From | David Howells <> | Date | Tue, 26 Jun 2018 17:20:36 +0100 |
| |
From: Eric Biggers <ebiggers@google.com>
My recent fix for dns_resolver_preparse() printing very long strings was incomplete, as shown by syzbot which still managed to hit the WARN_ONCE() in set_precision() by adding a crafted "dns_resolver" key:
precision 50001 too large WARNING: CPU: 7 PID: 864 at lib/vsprintf.c:2164 vsnprintf+0x48a/0x5a0
The bug this time isn't just a printing bug, but also a logical error when multiple options ("#"-separated strings) are given in the key payload. Specifically, when separating an option string into name and value, if there is no value then the name is incorrectly considered to end at the end of the key payload, rather than the end of the current option. This bypasses validation of the option length, and also means that specifying multiple options is broken -- which presumably has gone unnoticed as there is currently only one valid option anyway.
Fix it by correctly calculating the length of the option name.
Reproducer:
perl -e 'print "#A#", "\x00" x 50000' | keyctl padd dns_resolver desc @s
Fixes: 4a2d789267e0 ("DNS: If the DNS server returns an error, allow that to be cached [ver #2]") Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: David Howells <dhowells@redhat.com> ---
net/dns_resolver/dns_key.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index 40c851693f77..d448823d4d2e 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c @@ -97,7 +97,7 @@ dns_resolver_preparse(struct key_preparsed_payload *prep) return -EINVAL; } - eq = memchr(opt, '=', opt_len) ?: end; + eq = memchr(opt, '=', opt_len) ?: next_opt; opt_nlen = eq - opt; eq++; opt_vlen = next_opt - eq; /* will be -1 if no value */
| |