Skip to content

Commit c7a936b

Browse files
ebiggersgregkh
authored andcommitted
KEYS: DNS: limit the length of option strings
[ Upstream commit 9c438d7 ] Adding a dns_resolver key whose payload contains a very long option name resulted in that string being printed in full. This hit the WARN_ONCE() in set_precision() during the printk(), because printk() only supports a precision of up to 32767 bytes: precision 1000000 too large WARNING: CPU: 0 PID: 752 at lib/vsprintf.c:2189 vsnprintf+0x4bc/0x5b0 Fix it by limiting option strings (combined name + value) to a much more reasonable 128 bytes. The exact limit is arbitrary, but currently the only recognized option is formatted as "dnserror=%lu" which fits well within this limit. Also ratelimit the printks. Reproducer: perl -e 'print "#", "A" x 1000000, "\x00"' | keyctl padd dns_resolver desc @s This bug was found using syzkaller. Reported-by: Mark Rutland <[email protected]> Fixes: 4a2d789 ("DNS: If the DNS server returns an error, allow that to be cached [ver #2]") Signed-off-by: Eric Biggers <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent a370d8a commit c7a936b

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

net/dns_resolver/dns_key.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <linux/moduleparam.h>
2626
#include <linux/slab.h>
2727
#include <linux/string.h>
28+
#include <linux/ratelimit.h>
2829
#include <linux/kernel.h>
2930
#include <linux/keyctl.h>
3031
#include <linux/err.h>
@@ -91,9 +92,9 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
9192

9293
next_opt = memchr(opt, '#', end - opt) ?: end;
9394
opt_len = next_opt - opt;
94-
if (!opt_len) {
95-
printk(KERN_WARNING
96-
"Empty option to dns_resolver key\n");
95+
if (opt_len <= 0 || opt_len > 128) {
96+
pr_warn_ratelimited("Invalid option length (%d) for dns_resolver key\n",
97+
opt_len);
9798
return -EINVAL;
9899
}
99100

@@ -127,10 +128,8 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
127128
}
128129

129130
bad_option_value:
130-
printk(KERN_WARNING
131-
"Option '%*.*s' to dns_resolver key:"
132-
" bad/missing value\n",
133-
opt_nlen, opt_nlen, opt);
131+
pr_warn_ratelimited("Option '%*.*s' to dns_resolver key: bad/missing value\n",
132+
opt_nlen, opt_nlen, opt);
134133
return -EINVAL;
135134
} while (opt = next_opt + 1, opt < end);
136135
}

0 commit comments

Comments
 (0)