Skip to content

Commit 9c438d7

Browse files
ebiggersdavem330
authored andcommitted
KEYS: DNS: limit the length of option strings
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]>
1 parent 89bda97 commit 9c438d7

File tree

1 file changed

+5
-7
lines changed

1 file changed

+5
-7
lines changed

net/dns_resolver/dns_key.c

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,9 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
9191

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

@@ -127,10 +127,8 @@ dns_resolver_preparse(struct key_preparsed_payload *prep)
127127
}
128128

129129
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);
130+
pr_warn_ratelimited("Option '%*.*s' to dns_resolver key: bad/missing value\n",
131+
opt_nlen, opt_nlen, opt);
134132
return -EINVAL;
135133
} while (opt = next_opt + 1, opt < end);
136134
}

0 commit comments

Comments
 (0)