The parser currently treats any keyword it does not recognise inside a label body as the end of that label, pushing the token back so the caller can dispatch it as menu-level input. That is correct for extlinux/pxelinux, where the only thing legitimately following a label body is another 'label' (or a top-level 'menu ...') line.
Other formats that share enough syntax to reuse this parser have different rules. The Boot Loader Specification, in particular, lists a number of entry-level keys (title, version, sort-key, machine-id, architecture, ...) that this parser knows nothing about, and the spec explicitly requires implementations to silently ignore unrecognised keys rather than treat them as a structural boundary. Add an ignore_unknown flag to parse_label_keys(): when set, the default switch case consumes the rest of the offending line via eol_or_eof() and continues parsing instead of returning. The existing extlinux caller passes false and so is unaffected. Signed-off-by: Alexey Charkov <[email protected]> --- boot/pxe_utils.c | 29 +++++++++++++++++++++++++++-- include/pxe_utils.h | 8 +++++++- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/boot/pxe_utils.c b/boot/pxe_utils.c index 6dad3045f9d4..7ecee86a9ada 100644 --- a/boot/pxe_utils.c +++ b/boot/pxe_utils.c @@ -1266,7 +1266,8 @@ static int parse_label_kernel(char **c, struct pxe_label *label) return 1; } -int parse_label_keys(char **c, struct pxe_menu *cfg, struct pxe_label *label) +int parse_label_keys(char **c, struct pxe_menu *cfg, struct pxe_label *label, + bool ignore_unknown) { struct token t; char *s; @@ -1339,7 +1340,31 @@ int parse_label_keys(char **c, struct pxe_menu *cfg, struct pxe_label *label) case T_EOL: break; + case T_EOF: + if (ignore_unknown) { + /* + * BLS-style callers parse a standalone label + * body, so there is no outer context to push + * T_EOF back into — stop cleanly here. + */ + return 1; + } + /* + * For pxelinux/extlinux, fall through so the default + * case pushes T_EOF back for the top-level parser. + */ + fallthrough; default: + if (ignore_unknown) { + /* + * Skip the rest of the line and keep going. + * Used for formats like the Boot Loader + * Specification, where the spec mandates that + * unknown keys must be silently ignored. + */ + eol_or_eof(c); + break; + } /* * put the token back! we don't want it - it's the end * of a label and whatever token this is, it's @@ -1381,7 +1406,7 @@ static int parse_label(char **c, struct pxe_menu *cfg) list_add_tail(&label->list, &cfg->labels); - return parse_label_keys(c, cfg, label); + return parse_label_keys(c, cfg, label, false); } /* diff --git a/include/pxe_utils.h b/include/pxe_utils.h index e639e59e5dc8..653e1a7d866e 100644 --- a/include/pxe_utils.h +++ b/include/pxe_utils.h @@ -237,9 +237,15 @@ void label_destroy(struct pxe_label *label); * @cfg: Menu the label belongs to (used for 'menu default' bookkeeping) * @label: Label to populate; must already be allocated and (when called for * a file that has a 'label' header) attached to @cfg->labels + * @ignore_unknown: If true, silently skip unknown keys (and consume the + * rest of their lines) instead of stopping. This matches the Boot + * Loader Specification's requirement that unknown keys be ignored. + * If false (extlinux/pxelinux behaviour), an unknown token is pushed + * back so the caller can treat it as the start of the next label. * Return: 1 on success, < 0 on error */ -int parse_label_keys(char **c, struct pxe_menu *cfg, struct pxe_label *label); +int parse_label_keys(char **c, struct pxe_menu *cfg, struct pxe_label *label, + bool ignore_unknown); /** * label_boot() - Boot according to the contents of a single pxe_label -- 2.53.0

