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

Reply via email to