From: sashiko-bot@kernel.org
To: "James Hilliard" <james.hilliard1@gmail.com>,
"Miquel Raynal" <miquel.raynal@bootlin.com>,
"Richard Weinberger" <richard@nod.at>,
"Vignesh Raghavendra" <vigneshr@ti.com>
Cc: linux-mtd@lists.infradead.org,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Srinivas Kandagatla" <srini@kernel.org>,
"Tze Yee Ng" <tze.yee.ng@altera.com>
Subject: Re: [PATCH v3 01/58] nvmem: disconnect provider callbacks before unregister returns
Date: Thu, 12 Nov 2026 02:00:58 +0000 [thread overview]
Message-ID: <sashiko-outbox-210134@kernel.org> (raw)
In-Reply-To: <20261111-submit-rawnand-retained-handle-lifetime-v1-v3-1-ce537999741d@gmail.com>
Thank you for your contribution! Sashiko AI review found 5 potential
issues to consider:
- [Medium] nvmem: nvmem_populate_sysfs_cells() skips layout cells and
tags provider cells
- [Medium] nvmem: leaked devres and stale cells_group in
nvmem_populate_sysfs_cells()
- [Medium] nvmem: unpaired NVMEM_REMOVE notifier event on
nvmem_register() failure
- [Medium] nvmem: sysfs bin_attribute UAF during device_del() in
nvmem_unregister()
- [Low] nvmem: unreachable disconnected check in nvmem_device_match()
--
commit 7e668831f84b8e65137e3150ab3a241d5d20c765
Author: James Hilliard <james.hilliard1@gmail.com>
nvmem: disconnect provider callbacks before unregister returns
This commit disconnects NVMEM provider and layout callbacks using SRCU
when unregistering a provider or layout, and adds reference counting to
struct nvmem_cell_entry so consumers can safely outlive provider unbind.
> diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
> index 0556d140170a4..8571d821591c9 100644
> --- a/drivers/nvmem/core.c
> +++ b/drivers/nvmem/core.c
[ ... ]
> @@ -511,9 +516,10 @@ static int nvmem_populate_sysfs_cells(struct nvmem_device *nvmem)
> i++;
> }
>
> - group.bin_attrs = pattrs;
> + nvmem->cells_group.name = "cells";
> + nvmem->cells_group.bin_attrs = pattrs;
>
> - ret = device_add_group(&nvmem->dev, &group);
> + ret = device_add_group(&nvmem->dev, &nvmem->cells_group);
> if (ret)
> return ret;
[Severity: Medium]
Does an error in nvmem_populate_sysfs_cells() during layout registration
leak the devres allocations on nvmem->dev and leave a stale
nvmem->cells_group.bin_attrs pointer?
pattrs, attrs, and attrs[i].attr.name are allocated with devm_kcalloc()
and devm_kasprintf() on the parent &nvmem->dev, not &layout->dev. If one
of those allocations or device_add_group() fails (for example, with
-EEXIST on a duplicate cell attribute name), nvmem->sysfs_cells_populated
remains false. When nvmem_layout_register() then unwinds through
nvmem_layout_unregister(), the devm_kfree() cleanup is skipped because
nvmem->sysfs_cells_populated is false, leaking those allocations across
layout probe retries and leaving nvmem->cells_group.bin_attrs pointing to
attributes whose private pointers reference freed nvmem_cell_entry
objects.
[ ... ]
> @@ -663,6 +682,8 @@ int nvmem_add_one_cell(struct nvmem_device *nvmem,
> return rval;
> }
>
> + kref_init(&cell->refcnt);
> + cell->layout = nvmem->layout;
> nvmem_cell_entry_add(cell);
>
> return 0;
[ ... ]
> @@ -851,29 +877,81 @@ int nvmem_layout_register(struct nvmem_layout *layout)
> if (!layout->add_cells)
> return -EINVAL;
>
> - /* Populate the cells */
> - ret = layout->add_cells(layout);
> + scoped_guard(srcu, &layout->nvmem->srcu) {
> + if (READ_ONCE(layout->nvmem->disconnected))
> + return -ENODEV;
> + ret = layout->add_cells(layout);
> + }
> if (ret)
> - return ret;
> + goto err_unregister;
>
> #ifdef CONFIG_NVMEM_SYSFS
> ret = nvmem_populate_sysfs_cells(layout->nvmem);
> - if (ret) {
> - nvmem_device_remove_all_cells(layout->nvmem);
> - return ret;
> - }
> + if (ret)
> + goto err_unregister;
> #endif
>
> return 0;
> +
> +err_unregister:
> + nvmem_layout_unregister(layout);
> + return ret;
> }
> EXPORT_SYMBOL_GPL(nvmem_layout_register);
>
> void nvmem_layout_unregister(struct nvmem_layout *layout)
> {
> - /* Keep the API even with an empty stub in case we need it later */
> + struct nvmem_device *nvmem = layout->nvmem;
> + struct nvmem_cell_entry *cell, *next;
> + struct attribute_group group = {};
> + LIST_HEAD(cells);
> +
> + scoped_guard(mutex, &nvmem_mutex) {
> + if (nvmem->sysfs_cells_populated)
> + group = nvmem->cells_group;
> + list_for_each_entry_safe(cell, next, &nvmem->cells, node) {
> + if (cell->layout != layout)
> + continue;
> + WRITE_ONCE(cell->disconnected, true);
> + list_move_tail(&cell->node, &cells);
> + }
> + }
> +
> + if (group.bin_attrs) {
> + device_remove_group(&nvmem->dev, &group);
> + scoped_guard(mutex, &nvmem_mutex) {
> + nvmem->sysfs_cells_populated = false;
> + memset(&nvmem->cells_group, 0, sizeof(nvmem->cells_group));
> + }
> + for (int i = 0; group.bin_attrs[i]; i++)
> + devm_kfree(&nvmem->dev, (void *)group.bin_attrs[i]->attr.name);
> + devm_kfree(&nvmem->dev, (void *)group.bin_attrs[0]);
> + devm_kfree(&nvmem->dev, group.bin_attrs);
> + }
> +
> + /* Old cell handles retain data, never a departing layout's callbacks. */
> + synchronize_srcu(&nvmem->srcu);
> + list_for_each_entry_safe(cell, next, &cells, node) {
> + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_CELL_REMOVE, cell);
> + list_del(&cell->node);
> + nvmem_cell_entry_put(cell);
> + }
> +#ifdef CONFIG_NVMEM_SYSFS
> + if (!READ_ONCE(nvmem->disconnected) && nvmem_populate_sysfs_cells(nvmem))
> + dev_warn(&nvmem->dev, "Failed to restore provider cell attributes\n");
> +#endif
> }
> EXPORT_SYMBOL_GPL(nvmem_layout_unregister);
[Severity: Medium]
Can nvmem_populate_sysfs_cells() skip layout cell sysfs attributes when
provider cell attributes are already populated, and can nvmem_add_one_cell()
misattribute provider cells to nvmem->layout?
If an nvmem_device has provider cells (or if nvmem_layout_unregister()
restored provider cell attributes on unbind), nvmem_populate_sysfs_cells()
has already set nvmem->sysfs_cells_populated = true. When a layout driver
later probes (or rebinds) and nvmem_layout_register() calls
nvmem_populate_sysfs_cells(), it sees nvmem->sysfs_cells_populated == true
and returns 0 without rebuilding nvmem->cells_group, omitting the layout
cells from sysfs. A similar race exists during nvmem_register() because
nvmem_populate_layout() publishes layout->dev on nvmem_layout_bus_type
before nvmem_register() calls nvmem_populate_sysfs_cells().
In addition, nvmem->layout is set in nvmem_layout_create_device() for the
lifetime of the layout device, so setting cell->layout = nvmem->layout in
nvmem_add_one_cell() tags any cells added by a provider after
nvmem_register() (such as in mtk_mfg_init_nvmem_provider() or
u_boot_env_probe()) as layout cells and removes them on layout unbind.
[ ... ]
> @@ -1010,7 +1086,7 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
>
> rval = nvmem_populate_layout(nvmem);
> if (rval)
> - goto err_remove_dev;
> + goto err_unregister;
>
> /* If the device has WP GPIO, default to read-only */
> if (nvmem->wp_gpio)
> @@ -1019,23 +1095,24 @@ struct nvmem_device *nvmem_register(const struct nvmem_config *config)
> #ifdef CONFIG_NVMEM_SYSFS
> rval = nvmem_populate_sysfs_cells(nvmem);
> if (rval)
> - goto err_destroy_layout;
> + goto err_unregister;
> #endif
>
> blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem);
>
> return nvmem;
>
> -#ifdef CONFIG_NVMEM_SYSFS
> -err_destroy_layout:
> - nvmem_destroy_layout(nvmem);
> -#endif
> -err_remove_dev:
> - device_del(&nvmem->dev);
> +err_unregister:
> + nvmem_unregister(nvmem);
> + return ERR_PTR(rval);
[Severity: Medium]
Does jumping to err_unregister on failure in nvmem_populate_layout() or
nvmem_populate_sysfs_cells() emit an unpaired NVMEM_REMOVE notification?
blocking_notifier_call_chain(&nvmem_notifier, NVMEM_ADD, nvmem) is only
called after both functions succeed, but nvmem_unregister()
unconditionally sends NVMEM_REMOVE.
[ ... ]
> @@ -1048,24 +1125,29 @@ static void nvmem_device_release(struct kref *kref)
>
> nvmem = container_of(kref, struct nvmem_device, refcnt);
>
> - blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
> -
> - nvmem_sysfs_remove_compat(nvmem);
> -
> - nvmem_device_remove_all_cells(nvmem);
> - nvmem_destroy_layout(nvmem);
> - device_unregister(&nvmem->dev);
> + put_device(&nvmem->dev);
> }
>
> /**
> * nvmem_unregister() - Unregister previously registered nvmem device
> *
> * @nvmem: Pointer to previously registered nvmem device.
> + *
> + * Stop and drain provider callbacks before returning. Existing consumers keep
> + * their core-owned metadata, but further access returns -ENODEV.
> */
> void nvmem_unregister(struct nvmem_device *nvmem)
> {
> - if (nvmem)
> - kref_put(&nvmem->refcnt, nvmem_device_release);
> + if (!nvmem)
> + return;
> +
> + nvmem_disconnect(nvmem);
> + nvmem_destroy_layout(nvmem);
> + blocking_notifier_call_chain(&nvmem_notifier, NVMEM_REMOVE, nvmem);
> + nvmem_sysfs_remove_compat(nvmem);
> + device_del(&nvmem->dev);
> + nvmem_device_remove_all_cells(nvmem);
> + kref_put(&nvmem->refcnt, nvmem_device_release);
> }
[Severity: Medium]
Can device_del(&nvmem->dev) in nvmem_unregister() cause a use-after-free
on the devres-allocated bin_attribute array if a sysfs read races with
unregistration?
nvmem_populate_sysfs_cells() allocates pattrs, attrs, and
attrs[i].attr.name with devm_kcalloc() and devm_kasprintf() on &nvmem->dev,
and registers them via non-devres device_add_group(&nvmem->dev,
&nvmem->cells_group). When nvmem_unregister() runs with provider cell
attributes populated, it calls device_del(&nvmem->dev) without first
calling device_remove_group(&nvmem->dev, &nvmem->cells_group):
CPU0 CPU1
nvmem_unregister()
device_del(&nvmem->dev)
devres_release_all(&nvmem->dev)
/* frees attrs */
sysfs_kf_bin_read()
battr = of->kn->priv;
battr->read(...) <-- use-after-free
kobject_del(&nvmem->dev.kobj)
In device_del(), device_remove_attrs() only removes dev->groups, so
nvmem->cells_group remains active in sysfs until kobject_del() runs after
devres_release_all().
[ ... ]
> @@ -1103,26 +1185,46 @@ struct nvmem_device *devm_nvmem_register(struct device *dev,
> }
> EXPORT_SYMBOL_GPL(devm_nvmem_register);
>
> +struct nvmem_match_data {
> + void *data;
> + int (*match)(struct device *dev, const void *data);
> +};
> +
> +static int nvmem_match_device(struct device *dev, const void *data)
> +{
> + const struct nvmem_match_data *match = data;
> + struct nvmem_device *nvmem = to_nvmem_device(dev);
> +
> + guard(srcu)(&nvmem->srcu);
> + if (READ_ONCE(nvmem->disconnected))
> + return 0;
> + return match->match(dev, match->data);
> +}
> +
> static struct nvmem_device *nvmem_device_match(void *data,
> int (*match)(struct device *dev, const void *data))
> {
> + struct nvmem_match_data match_data = { .data = data, .match = match };
> struct nvmem_device *nvmem = NULL;
> struct device *dev;
>
> - scoped_guard(mutex, &nvmem_mutex) {
> - dev = bus_find_device(&nvmem_bus_type, NULL, data, match);
> - if (dev)
> - nvmem = to_nvmem_device(dev);
> - }
> + guard(mutex)(&nvmem_mutex);
> + dev = bus_find_device(&nvmem_bus_type, NULL, &match_data, nvmem_match_device);
> + if (dev)
> + nvmem = to_nvmem_device(dev);
> if (!nvmem)
> return ERR_PTR(-EPROBE_DEFER);
>
> + if (READ_ONCE(nvmem->disconnected)) {
> + put_device(dev);
> + return ERR_PTR(-ENODEV);
> + }
[Severity: Low]
Is the second READ_ONCE(nvmem->disconnected) check in nvmem_device_match()
reachable?
nvmem_disconnect() sets nvmem->disconnected under nvmem_mutex, and
nvmem_device_match() holds nvmem_mutex across bus_find_device(), where
nvmem_match_device() already rejects disconnected devices.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261111-submit-rawnand-retained-handle-lifetime-v1-v3-0-ce537999741d@gmail.com?part=1
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2026-11-12 2:01 UTC|newest]
Thread overview: 124+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-12 1:27 [PATCH v3 00/58] mtd: rawnand: retain chip and controller state across removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 01/58] nvmem: disconnect provider callbacks before unregister returns James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 2:00 ` sashiko-bot [this message]
2026-11-12 1:27 ` [PATCH v3 02/58] mtd: acquire an MTD handle from a referenced class device James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 03/58] mtd: separate class devices from retained backing objects James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 2:48 ` sashiko-bot
2026-11-12 1:27 ` [PATCH v3 04/58] mtd: retain virtual concatenations across component removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 3:09 ` sashiko-bot
2026-11-12 1:27 ` [PATCH v3 05/58] mtd: rawnand: separate hardware disconnection from cleanup James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 06/58] mtd: rawnand: share retained chip and controller ownership James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 07/58] mtd: rawnand: sunxi: retain chip state until the final MTD put James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 08/58] mtd: rawnand: plat_nand: retain open-handle state on removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 09/58] mtd: rawnand: gpio: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 10/58] mtd: rawnand: stm32_fmc2: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 11/58] mtd: rawnand: denali: retain chips across controller removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 12/58] mtd: rawnand: arasan: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 13/58] mtd: rawnand: mxic: retain open-handle state on removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 14/58] mtd: rawnand: intel: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 15/58] mtd: rawnand: tegra: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 16/58] mtd: rawnand: mtk: retain chips across controller removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 17/58] mtd: rawnand: rockchip: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 18/58] mtd: rawnand: atmel: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 19/58] mtd: rawnand: orion: retain open-handle state on removal James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:27 ` [PATCH v3 20/58] mtd: rawnand: socrates: " James Hilliard
2026-11-12 1:27 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 21/58] mtd: rawnand: fsl_upm: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 22/58] mtd: rawnand: pasemi: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 23/58] mtd: rawnand: ams-delta: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 24/58] mtd: rawnand: xway: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 25/58] mtd: rawnand: hisi504: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 26/58] mtd: rawnand: vf610: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 27/58] mtd: rawnand: technologic: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 28/58] mtd: rawnand: loongson: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 29/58] mtd: rawnand: ma35d1: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 30/58] mtd: rawnand: pl35x: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 31/58] mtd: rawnand: mxc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 32/58] mtd: rawnand: fsmc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 33/58] mtd: rawnand: gpmi: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 34/58] mtd: rawnand: omap2: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 35/58] mtd: rawnand: marvell: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 36/58] mtd: rawnand: renesas: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 37/58] mtd: rawnand: meson: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 38/58] mtd: rawnand: cadence: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 39/58] mtd: rawnand: qcom: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 40/58] mtd: rawnand: cafe: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 41/58] mtd: rawnand: brcmnand: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 42/58] mtd: rawnand: au1550nd: retain chip state across removal James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 43/58] mtd: rawnand: sharpsl: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 44/58] mtd: rawnand: davinci: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 45/58] mtd: rawnand: sh_flctl: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 46/58] mtd: rawnand: lpc32xx_slc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 47/58] mtd: rawnand: lpc32xx_mlc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 48/58] mtd: rawnand: ndfc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 49/58] mtd: rawnand: txx9ndfmc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 50/58] mtd: rawnand: ingenic: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 51/58] mtd: rawnand: mpc5121: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 52/58] mtd: rawnand: bcm47xxnflash: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 53/58] mtd: rawnand: fsl_elbc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 54/58] mtd: rawnand: fsl_ifc: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 55/58] mtd: rawnand: r852: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 56/58] mtd: rawnand: nandsim: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 57/58] mtd: rawnand: cs553x: " James Hilliard
2026-11-12 1:28 ` James Hilliard
2026-11-12 1:28 ` [PATCH v3 58/58] mtd: rawnand: diskonchip: " James Hilliard
2026-11-12 1:28 ` James Hilliard
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=sashiko-outbox-210134@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=james.hilliard1@gmail.com \
--cc=linux-mtd@lists.infradead.org \
--cc=miquel.raynal@bootlin.com \
--cc=richard@nod.at \
--cc=sashiko-reviews@lists.linux.dev \
--cc=srini@kernel.org \
--cc=tze.yee.ng@altera.com \
--cc=vigneshr@ti.com \
/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.