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 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®