blob: 81a7027f6402e7c3b523fa5d482769f48694b1a9 [file] [log] [blame]
When we have a zero length for an embedded option, warn if any
more data or not the last option and return the number of
currently processed options. This fixes a potential buffer
overrun for options where the last embedded optional is an
optional string. Thanks to Paul Stewart @ Chromium for the fix.
http://roy.marples.name/projects/dhcpcd/ci/732e88eaa0?sbs=0
--- dhcp-common.c
+++ dhcp-common.c
@@ -873,13 +873,24 @@
/* Embedded options are always processed first as that
* is a fixed layout */
n = 0;
for (i = 0, eopt = opt->embopts; i < opt->embopts_len; i++, eopt++) {
e = dhcp_optlen(eopt, ol);
- if (e == 0)
- /* Report error? */
- return 0;
+ if (e == 0) {
+ /* An option was expected, but there is not enough
+ * data for it.
+ * This may not be an error as some options like
+ * DHCP FQDN in RFC4702 have a string as the last
+ * option which is optional.
+ * FIXME: Add an flag to the options to indicate
+ * wether this is allowable or not. */
+ if (ol != 0 || i + 1 < opt->embopts_len)
+ logger(ctx, LOG_WARNING,
+ "%s: %s: malformed option %d",
+ ifname, __func__, opt->option);
+ goto out;
+ }
/* Use the option prefix if the embedded option
* name is different.
* This avoids new_fqdn_fqdn which would be silly. */
if (!(eopt->type & RESERVED)) {
ov = strcmp(opt->var, eopt->var);
@@ -930,10 +941,11 @@
od += eos + eol;
ol -= eos + eol;
}
}
+out:
if (env)
free(pfx);
/* Return number of options found */
return n;