From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
To: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Cc: "Linus Torvalds" <torvalds@linux-foundation.org>,
Sang-Heon Jeon <ekffu200098@gmail.com>,
Steven Rostedt <rostedt@goodmis.org>,
linux-kernel@vger.kernel.org
Subject: Re: Bootconfig updates for v7.4
Date: Thu, 22 Oct 2026 09:43:29 +0900 [thread overview]
Message-ID: <20261022094329.3f945e236aa91ff0f5e71e2e@kernel.org> (raw)
In-Reply-To: <undine-1792628050192621158-acf139ac8ccbe10b@undined.local>
Sorry, please ignore this. I missed [GIT PULL] tag. So I resent with it.
On Thu, 22 Oct 2026 09:14:10 +0900
Masami Hiramatsu (Google) <mhiramat@kernel.org> wrote:
> Hi Linus,
>
> Bootconfig updates for v7.4:
>
> - bootconfig: Parser robustness and validation improvements
> . Skip printing early params to cmdline from bootconfig: Suppress
> early_param keys from /proc/cmdline and warn the user, since bootconfig
> does not invoke early_param handlers and silently ignoring them is
> misleading.
> . Reject unexpected data after null character: Detect and reject non-null
> data following an intermediate null character in the bootconfig buffer,
> preventing silently ignored configuration after an early termination.
>
> - bootconfig: Code cleanups
> . Merge _xbc_exit() into xbc_exit(): Since memblock_free() now handles
> late freeing and NULL addresses, the separate _xbc_exit() helper and
> its early argument are unnecessary. Inline it into xbc_exit().
> . Remove redundant assignment in xbc_parse_array(): The node->child = 0
> assignment after the loop duplicates what xbc_init_node() already did.
> . Skip internal tree sanity checks in kernel: Move the node index bounds
> loop from xbc_verify_tree() into a userspace-only xbc_sanity_check_tree()
> to reduce boot-time overhead, since out-of-bounds indices cannot be
> produced by malformed input.
> . Move BOOTCONFIG_FOOTER_SIZE to include/linux/bootconfig.h: Share the
> footer size constant between kernel and user-space tools, replacing the
> hardcoded (BOOTCONFIG_MAGIC_LEN + 8) expression in init/main.c.
>
> - tools/bootconfig: Tooling improvements
> . Remove unused PAGE_SIZE macro from the bootconfig tool.
> . Consolidate xbc_init() to error message wrapper: Use
> init_xbc_with_error() for all bootconfig initialization paths in the
> tool for simpler and more consistent error handling.
>
>
> Please pull the latest bootconfig-v7.4 tree, which can be found at:
>
>
> git://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace.git
> bootconfig-v7.4
>
> Tag SHA1: 8c84ad1d280719b36079cdd280da8214c3a8013d
> Head SHA1: 677f83795fdfc25ddc51b665a9111f5ff199f7ca
>
>
> Masami Hiramatsu (Google) (5):
> bootconfig: Skip printing early params to cmdline from bootconfig
> bootconfig: Reject unexpected data after null character
> tools/bootconfig: Consolidate xbc_init() to error message wrapper
> bootconfig: Skip internal tree sanity checks in kernel
> bootconfig: Move BOOTCONFIG_FOOTER_SIZE to include/linux/bootconfig.h
>
> Sang-Heon Jeon (3):
> bootconfig: merge _xbc_exit() into xbc_exit()
> bootconfig: remove redundant assignment in xbc_parse_array()
> tools/bootconfig: remove unused PAGE_SIZE macro
>
> ----
> include/linux/bootconfig.h | 21 ++++---
> init/main.c | 75 ++++++++++++++++++++++---
> lib/bootconfig.c | 84 +++++++++++++++++-----------
> tools/bootconfig/main.c | 108 +++++++++++++++---------------------
> tools/bootconfig/test-bootconfig.sh | 12 ++++
> 5 files changed, 192 insertions(+), 108 deletions(-)
> ---------------------------
> diff --git a/include/linux/bootconfig.h b/include/linux/bootconfig.h
> index deda507500da..260a6f46042e 100644
> --- a/include/linux/bootconfig.h
> +++ b/include/linux/bootconfig.h
> @@ -27,6 +27,10 @@ bool __init cmdline_has_extra_options(void);
> #define BOOTCONFIG_ALIGN (1 << BOOTCONFIG_ALIGN_SHIFT)
> #define BOOTCONFIG_ALIGN_MASK (BOOTCONFIG_ALIGN - 1)
>
> +/* Bootconfig footer is [size][csum][BOOTCONFIG_MAGIC]. */
> +#define BOOTCONFIG_FOOTER_SIZE \
> + (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN)
> +
> /**
> * xbc_calc_checksum() - Calculate checksum of bootconfig
> * @data: Bootconfig data.
> @@ -266,7 +270,15 @@ int __init xbc_node_compose_key_after(struct xbc_node *root,
> struct xbc_node *node, char *buf, size_t size);
>
> /* Render key/value pairs under @root as a flat cmdline string */
> -int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root);
> +typedef bool (*xbc_cmdline_filter_fn)(struct xbc_node *node, const char *key, void *data);
> +
> +int __init xbc_snprint_cmdline_filter(char *buf, size_t size, struct xbc_node *root,
> + xbc_cmdline_filter_fn filter, void *data);
> +
> +static inline int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
> +{
> + return xbc_snprint_cmdline_filter(buf, size, root, NULL, NULL);
> +}
>
> /**
> * xbc_node_compose_key() - Compose full key string of the XBC node
> @@ -291,12 +303,7 @@ int __init xbc_init(const char *buf, size_t size, const char **emsg, int *epos);
> int __init xbc_get_info(int *node_size, size_t *data_size);
>
> /* XBC cleanup data structures */
> -void __init _xbc_exit(bool early);
> -
> -static __always_inline void xbc_exit(void)
> -{
> - _xbc_exit(false);
> -}
> +void __init xbc_exit(void);
>
> /* XBC embedded bootconfig data in kernel */
> #ifdef CONFIG_BOOT_CONFIG_EMBED
> diff --git a/init/main.c b/init/main.c
> index 16749bb7a219..861e07f6c05c 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -278,7 +278,7 @@ static void * __init get_boot_config_from_initrd(size_t *_size)
> int i;
>
> if (!initrd_end || initrd_end < initrd_start ||
> - initrd_end - initrd_start < BOOTCONFIG_MAGIC_LEN + 8)
> + initrd_end - initrd_start < BOOTCONFIG_FOOTER_SIZE)
> return NULL;
>
> data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN;
> @@ -336,9 +336,64 @@ static void * __init get_boot_config_from_initrd(size_t *_size)
>
> #ifdef CONFIG_BOOT_CONFIG
>
> +/* Check if a parameter name matches an obs_kernel_param entry */
> +static bool __init match_obs_param(const char *param, const char *pattern)
> +{
> + size_t n = strlen(pattern);
> +
> + if (n > 0 && pattern[n - 1] == '=')
> + return parameqn(param, pattern, n - 1) && param[n - 1] == '\0';
> +
> + return parameq(param, pattern);
> +}
> +
> +/* Return true if the given param is only defined by early_param(). */
> +static bool __init is_early_only_param(const char *param)
> +{
> + const struct obs_kernel_param *p;
> + const struct kernel_param *kp;
> + bool has_early = false;
> +
> + /* If handled by a regular module_param, it is not early-only */
> + for (kp = __start___param; kp < __stop___param; kp++) {
> + if (parameq(param, kp->name))
> + return false;
> + }
> +
> + /* Check __setup / early_param table */
> + for (p = __setup_start; p < __setup_end; p++) {
> + if (match_obs_param(param, p->str)) {
> + if (!p->early)
> + return false;
> + has_early = true;
> + }
> + }
> + return has_early;
> +}
> +
> +struct xbc_filter_data {
> + bool warn;
> +};
> +
> +static bool __init xbc_kernel_param_filter(struct xbc_node *node,
> + const char *key, void *data)
> +{
> + struct xbc_filter_data *fdata = data;
> +
> + if (is_early_only_param(key)) {
> + if (fdata && fdata->warn)
> + pr_warn("bootconfig: early_param 'kernel.%s' cannot be applied from bootconfig, skipping\n",
> + key);
> + return false;
> + }
> + return true;
> +}
> +
> /* Make an extra command line under given key word */
> -static char * __init xbc_make_cmdline(const char *key)
> +static char * __init xbc_make_cmdline(const char *key, bool is_kernel)
> {
> + struct xbc_filter_data fdata = { .warn = true };
> + xbc_cmdline_filter_fn filter = is_kernel ? xbc_kernel_param_filter : NULL;
> struct xbc_node *root;
> char *new_cmdline;
> int ret, len = 0;
> @@ -347,8 +402,12 @@ static char * __init xbc_make_cmdline(const char *key)
> if (!root)
> return NULL;
>
> - /* Count required buffer size */
> - len = xbc_snprint_cmdline(NULL, 0, root);
> + /*
> + * Pass 1: Count required buffer size. Emit warnings for skipped early
> + * params in this pass so they are logged even if all parameters under
> + * @key are skipped and len becomes 0.
> + */
> + len = xbc_snprint_cmdline_filter(NULL, 0, root, filter, &fdata);
> if (len <= 0)
> return NULL;
>
> @@ -358,7 +417,9 @@ static char * __init xbc_make_cmdline(const char *key)
> return NULL;
> }
>
> - ret = xbc_snprint_cmdline(new_cmdline, len + 1, root);
> + /* Pass 2: Render into buffer with warnings suppressed */
> + fdata.warn = false;
> + ret = xbc_snprint_cmdline_filter(new_cmdline, len + 1, root, filter, &fdata);
> if (ret < 0 || ret > len) {
> pr_err("Failed to print extra kernel cmdline.\n");
> memblock_free(new_cmdline, len + 1);
> @@ -432,9 +493,9 @@ static void __init setup_boot_config(void)
> * before this series.
> */
> if (!from_embedded || !xbc_embedded_cmdline_applied())
> - extra_command_line = xbc_make_cmdline("kernel");
> + extra_command_line = xbc_make_cmdline("kernel", true);
> /* Also, "init." keys are init arguments */
> - extra_init_args = xbc_make_cmdline("init");
> + extra_init_args = xbc_make_cmdline("init", false);
> }
> return;
> }
> diff --git a/lib/bootconfig.c b/lib/bootconfig.c
> index 89c88e359179..819685d6c68d 100644
> --- a/lib/bootconfig.c
> +++ b/lib/bootconfig.c
> @@ -187,12 +187,9 @@ static inline void * __init xbc_alloc_mem(size_t size)
> return memblock_alloc(size, SMP_CACHE_BYTES);
> }
>
> -static inline void __init xbc_free_mem(void *addr, size_t size, bool early)
> +static inline void __init xbc_free_mem(void *addr, size_t size)
> {
> - if (early)
> - memblock_free(addr, size);
> - else if (addr)
> - memblock_free(addr, size);
> + memblock_free(addr, size);
> }
>
> #else /* !__KERNEL__ */
> @@ -202,7 +199,7 @@ static inline void *xbc_alloc_mem(size_t size)
> return calloc(1, size);
> }
>
> -static inline void xbc_free_mem(void *addr, size_t size, bool early)
> +static inline void xbc_free_mem(void *addr, size_t size)
> {
> free(addr);
> }
> @@ -539,18 +536,21 @@ static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata;
> #define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0)
>
> /**
> - * xbc_snprint_cmdline() - Render bootconfig keys under @root as a cmdline string
> + * xbc_snprint_cmdline_filter() - Render bootconfig keys as cmdline string
> * @buf: Destination buffer (may be NULL when @size is 0 to query the length)
> * @size: Size of @buf in bytes
> * @root: Subtree root whose key=value pairs should be rendered
> + * @filter: Filter callback (returns true to include, false to skip; may be NULL)
> + * @data: Private context passed to @filter
> *
> * Walk all key/value pairs under @root and emit them as a space-separated
> * cmdline string into @buf. Values containing whitespace are quoted with
> - * double quotes. Returns the number of bytes that would be written if @buf
> - * were large enough (matching snprintf semantics), or a negative errno on
> - * failure.
> + * double quotes. Keys for which @filter returns false are omitted.
> + * Returns the number of bytes that would be written if @buf were large enough
> + * (matching snprintf semantics), or a negative errno on failure.
> */
> -int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
> +int __init xbc_snprint_cmdline_filter(char *buf, size_t size, struct xbc_node *root,
> + xbc_cmdline_filter_fn filter, void *data)
> {
> struct xbc_node *knode, *vnode;
> const char *val, *q;
> @@ -582,6 +582,9 @@ int __init xbc_snprint_cmdline(char *buf, size_t size, struct xbc_node *root)
> if (ret < 0)
> return ret;
>
> + if (filter && !filter(knode, xbc_namebuf, data))
> + continue;
> +
> vnode = xbc_node_get_child(knode);
> if (!vnode) {
> ret = snprintf(buf ? buf + len : NULL, rest(len, size),
> @@ -836,7 +839,6 @@ static int __init xbc_parse_array(char **__v)
> return -ENOMEM;
> *__v = next;
> } while (c == ',');
> - node->child = 0;
>
> return c;
> }
> @@ -1003,9 +1005,30 @@ static int __init xbc_close_brace(char **k, char *n)
> return __xbc_close_brace(n - 1);
> }
>
> +#ifndef __KERNEL__
> +/* Sanity check for regression: node indices must be within bounds */
> +static int __init xbc_sanity_check_tree(void)
> +{
> + int i;
> +
> + for (i = 0; i < xbc_node_num; i++) {
> + if (xbc_nodes[i].next >= xbc_node_num) {
> + return xbc_parse_error("No closing brace",
> + xbc_node_get_data(xbc_nodes + i));
> + }
> + if (xbc_nodes[i].child >= xbc_node_num) {
> + return xbc_parse_error("Broken child node",
> + xbc_node_get_data(xbc_nodes + i));
> + }
> + }
> +
> + return 0;
> +}
> +#endif
> +
> static int __init xbc_verify_tree(void)
> {
> - int i, depth;
> + int depth;
> size_t len, wlen;
> struct xbc_node *n, *m;
>
> @@ -1022,17 +1045,6 @@ static int __init xbc_verify_tree(void)
> return -ENOENT;
> }
>
> - for (i = 0; i < xbc_node_num; i++) {
> - if (xbc_nodes[i].next >= xbc_node_num) {
> - return xbc_parse_error("No closing brace",
> - xbc_node_get_data(xbc_nodes + i));
> - }
> - if (xbc_nodes[i].child >= xbc_node_num) {
> - return xbc_parse_error("Broken child node",
> - xbc_node_get_data(xbc_nodes + i));
> - }
> - }
> -
> /* Key tree limitation check */
> n = &xbc_nodes[0];
> depth = 1;
> @@ -1119,24 +1131,30 @@ static int __init xbc_parse_tree(void)
> }
> } while (!ret);
>
> + if (!ret) {
> + while (p < xbc_data + xbc_data_size - 1 && *p == '\0')
> + p++;
> + if (p < xbc_data + xbc_data_size - 1)
> + ret = xbc_parse_error("Unexpected data after null character", p);
> + }
> +
> return ret;
> }
>
> /**
> - * _xbc_exit() - Clean up all parsed bootconfig
> - * @early: Set true if this is called before budy system is initialized.
> + * xbc_exit() - Clean up all parsed bootconfig
> *
> * This clears all data structures of parsed bootconfig on memory.
> * If you need to reuse xbc_init() with new boot config, you can
> * use this.
> */
> -void __init _xbc_exit(bool early)
> +void __init xbc_exit(void)
> {
> - xbc_free_mem(xbc_data, xbc_data_size, early);
> + xbc_free_mem(xbc_data, xbc_data_size);
> xbc_data = NULL;
> xbc_data_size = 0;
> xbc_node_num = 0;
> - xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX, early);
> + xbc_free_mem(xbc_nodes, sizeof(struct xbc_node) * XBC_NODE_MAX);
> xbc_nodes = NULL;
> brace_index = 0;
> }
> @@ -1189,20 +1207,24 @@ int __init xbc_init(const char *data, size_t size, const char **emsg, int *epos)
> if (!xbc_nodes) {
> if (emsg)
> *emsg = "Failed to allocate bootconfig nodes";
> - _xbc_exit(true);
> + xbc_exit();
> return -ENOMEM;
> }
>
> ret = xbc_parse_tree();
> if (!ret)
> ret = xbc_verify_tree();
> +#ifndef __KERNEL__
> + if (!ret)
> + ret = xbc_sanity_check_tree();
> +#endif
>
> if (ret < 0) {
> if (epos)
> *epos = xbc_err_pos;
> if (emsg)
> *emsg = xbc_err_msg;
> - _xbc_exit(true);
> + xbc_exit();
> } else {
> ret = xbc_node_num;
> }
> diff --git a/tools/bootconfig/main.c b/tools/bootconfig/main.c
> index 17d971d47f87..56d76bdeaa09 100644
> --- a/tools/bootconfig/main.c
> +++ b/tools/bootconfig/main.c
> @@ -17,9 +17,38 @@
>
> #define pr_err(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
>
> -/* Bootconfig footer is [size][csum][BOOTCONFIG_MAGIC]. */
> -#define BOOTCONFIG_FOOTER_SIZE \
> - (sizeof(uint32_t) * 2 + BOOTCONFIG_MAGIC_LEN)
> +static void show_xbc_error(const char *data, const char *msg, int pos)
> +{
> + int lin = 1, col, i;
> +
> + if (pos < 0) {
> + pr_err("Error: %s.\n", msg);
> + return;
> + }
> +
> + /* Note that pos starts from 0 but lin and col should start from 1. */
> + col = pos + 1;
> + for (i = 0; i < pos; i++) {
> + if (data[i] == '\n') {
> + lin++;
> + col = pos - i;
> + }
> + }
> + pr_err("Parse Error: %s at %d:%d\n", msg, lin, col);
> +
> +}
> +
> +static int init_xbc_with_error(char *buf, int len)
> +{
> + const char *msg;
> + int ret, pos;
> +
> + ret = xbc_init(buf, len, &msg, &pos);
> + if (ret < 0)
> + show_xbc_error(buf, msg, pos);
> +
> + return ret;
> +}
>
> static int xbc_show_value(struct xbc_node *node, bool semicolon)
> {
> @@ -134,8 +163,6 @@ static void xbc_show_list(void)
> }
> }
>
> -#define PAGE_SIZE 4096
> -
> static int load_xbc_fd(int fd, char **buf, int size)
> {
> int ret;
> @@ -197,7 +224,6 @@ static int load_xbc_from_initrd(int fd, char **buf)
> int ret;
> uint32_t size = 0, csum = 0, rcsum;
> char magic[BOOTCONFIG_MAGIC_LEN];
> - const char *msg;
>
> ret = fstat(fd, &stat);
> if (ret < 0)
> @@ -249,52 +275,9 @@ static int load_xbc_from_initrd(int fd, char **buf)
> return -EINVAL;
> }
>
> - ret = xbc_init(*buf, size, &msg, NULL);
> - /* Wrong data */
> - if (ret < 0) {
> - pr_err("parse error: %s.\n", msg);
> - return ret;
> - }
> -
> - return size;
> -}
> -
> -static void show_xbc_error(const char *data, const char *msg, int pos)
> -{
> - int lin = 1, col, i;
> -
> - if (pos < 0) {
> - pr_err("Error: %s.\n", msg);
> - return;
> - }
> -
> - /* Note that pos starts from 0 but lin and col should start from 1. */
> - col = pos + 1;
> - for (i = 0; i < pos; i++) {
> - if (data[i] == '\n') {
> - lin++;
> - col = pos - i;
> - }
> - }
> - pr_err("Parse Error: %s at %d:%d\n", msg, lin, col);
> + ret = init_xbc_with_error(*buf, size);
>
> -}
> -
> -static int init_xbc_with_error(char *buf, int len)
> -{
> - char *copy = strdup(buf);
> - const char *msg;
> - int ret, pos;
> -
> - if (!copy)
> - return -ENOMEM;
> -
> - ret = xbc_init(buf, len, &msg, &pos);
> - if (ret < 0)
> - show_xbc_error(copy, msg, pos);
> - free(copy);
> -
> - return ret;
> + return ret < 0 ? ret : size;
> }
>
> static int show_xbc_kernel_cmdline(void)
> @@ -423,9 +406,8 @@ static int apply_xbc(const char *path, const char *xbc_path)
> char *buf, *data;
> size_t total_size;
> struct stat stat;
> - const char *msg;
> uint32_t size, csum;
> - int pos, pad;
> + int pad;
> int ret, fd;
>
> ret = load_xbc_file(xbc_path, &buf);
> @@ -433,9 +415,18 @@ static int apply_xbc(const char *path, const char *xbc_path)
> pr_err("Failed to load %s : %d\n", xbc_path, ret);
> return ret;
> }
> - size = strlen(buf) + 1;
> + size = ret;
> + if (size == 0 || buf[size - 1] != '\0')
> + size++;
> csum = xbc_calc_checksum(buf, size);
>
> + /* Verify the data format */
> + ret = init_xbc_with_error(buf, size);
> + if (ret < 0) {
> + free(buf);
> + return ret;
> + }
> +
> /* Backup the bootconfig data */
> data = calloc(size + BOOTCONFIG_ALIGN + BOOTCONFIG_FOOTER_SIZE, 1);
> if (!data) {
> @@ -444,15 +435,6 @@ static int apply_xbc(const char *path, const char *xbc_path)
> }
> memcpy(data, buf, size);
>
> - /* Check the data format */
> - ret = xbc_init(buf, size, &msg, &pos);
> - if (ret < 0) {
> - show_xbc_error(data, msg, pos);
> - free(data);
> - free(buf);
> -
> - return ret;
> - }
> printf("Apply %s to %s\n", xbc_path, path);
> xbc_get_info(&ret, NULL);
> printf("\tNumber of nodes: %d\n", ret);
> diff --git a/tools/bootconfig/test-bootconfig.sh b/tools/bootconfig/test-bootconfig.sh
> index fc69f815ce4a..530ce7e28d63 100755
> --- a/tools/bootconfig/test-bootconfig.sh
> +++ b/tools/bootconfig/test-bootconfig.sh
> @@ -180,6 +180,18 @@ EOF
> $BOOTCONF -a $TEMPCONF $INITRD 2> $OUTFILE
> xpass grep -q "1:1" $OUTFILE
>
> +echo "Intermediate null character test"
> +printf "key = value\n\0extra = data\n" > $TEMPCONF
> +xfail $BOOTCONF -a $TEMPCONF $INITRD
> +$BOOTCONF -a $TEMPCONF $INITRD 2> $OUTFILE
> +xpass grep -q "Unexpected" $OUTFILE
> +
> +echo "Trailing null character test"
> +printf "key = value\n\0" > $TEMPCONF
> +xpass $BOOTCONF -a $TEMPCONF $INITRD
> +$BOOTCONF $INITRD > $OUTFILE
> +xpass grep -q "value" $OUTFILE
> +
> echo "=== expected failure cases ==="
> for i in samples/bad-* ; do
> xfail $BOOTCONF -a $i $INITRD
> --
> Masami Hiramatsu (Google) <mhiramat@kernel.org>
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
prev parent reply other threads:[~2026-10-22 0:43 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 0:14 Bootconfig updates for v7.4 Masami Hiramatsu
2026-10-22 0:43 ` Masami Hiramatsu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261022094329.3f945e236aa91ff0f5e71e2e@kernel.org \
--to=mhiramat@kernel.org \
--cc=ekffu200098@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.