mirror of https://lore.kernel.org/linux-amlogic/
 help / color / mirror / Atom feed
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>,
	"Brian Norris" <computersforpeace@gmail.com>,
	"Boris Brezillon" <bbrezillon@kernel.org>,
	"Arseniy Krasnov" <AVKrasnov@sberdevices.ru>,
	"Chen-Yu Tsai" <wens@kernel.org>,
	"Jernej Skrabec" <jernej.skrabec@gmail.com>,
	"Samuel Holland" <samuel@sholland.org>,
	"Thomas Gleixner" <tglx@kernel.org>,
	"Vitaly Wool" <vitalywool@gmail.com>,
	"David Woodhouse" <dwmw2@infradead.org>,
	"Russell King" <rmk+kernel@arm.linux.org.uk>,
	"David Woodhouse" <David.Woodhouse@intel.com>,
	"Mike Rapoport" <rppt@kernel.org>,
	"Maxime Coquelin" <mcoquelin.stm32@gmail.com>,
	"Alexandre Torgue" <alexandre.torgue@foss.st.com>,
	"Christophe Kerello" <christophe.kerello@st.com>,
	"Jason Roberts" <jason.e.roberts@intel.com>,
	"Michal Simek" <michal.simek@amd.com>,
	"Boris Brezillon" <boris.brezillon@collabora.com>,
	"Mason Yang" <masonccyang@mxic.com.tw>,
	"Ramuthevar Vadivel Murugan"
	<vadivel.muruganx.ramuthevar@linux.intel.com>,
	"Stefan Agner" <stefan@agner.ch>, "Lucas Stach" <dev@lynxeye.de>,
	"Thierry Reding" <thierry.reding@kernel.org>,
	"Jonathan Hunter" <jonathanh@nvidia.com>,
	"Dmitry Osipenko" <digetx@gmail.com>,
	"Matthias Brugger" <matthias.bgg@gmail.com>,
	"AngeloGioacchino Del Regno"
	<angelogioacchino.delregno@collabora.com>,
	"Jorge Ramirez-Ortiz" <jorge.ramirez@oss.qualcomm.com>,
	"Heiko Stuebner" <heiko@sntech.de>,
	"Yifeng Zhao" <yifeng.zhao@rock-chips.com>,
	"Nicolas Ferre" <nicolas.ferre@microchip.com>,
	"Alexandre Belloni" <alexandre.belloni@bootlin.com>,
	"Claudiu Beznea" <claudiu.beznea@tuxon.dev>,
	"Keguang Zhang" <keguang.zhang@gmail.com>,
	"Jacky Huang" <ychuang3@nuvoton.com>,
	"Shan-Chun Hung" <schung@nuvoton.com>,
	"Frank Li" <Frank.Li@nxp.com>,
	"Sascha Hauer" <s.hauer@pengutronix.de>,
	"Pengutronix Kernel Team" <kernel@pengutronix.de>,
	"Fabio Estevam" <festevam@gmail.com>, "Han Xu" <han.xu@nxp.com>,
	"Liang Yang" <liang.yang@amlogic.com>,
	"Neil Armstrong" <neil.armstrong@linaro.org>,
	"Kevin Hilman" <khilman@baylibre.com>,
	"Jerome Brunet" <jbrunet@baylibre.com>,
	"Martin Blumenstingl" <martin.blumenstingl@googlemail.com>,
	"Manivannan Sadhasivam" <mani@kernel.org>,
	"Kamal Dasu" <kamal.dasu@broadcom.com>,
	"Broadcom internal kernel review list"
	<bcm-kernel-feedback-list@broadcom.com>,
	"Vladimir Zapolskiy" <vz@mleia.com>,
	"Piotr Wojtaszczyk" <piotr.wojtaszczyk@timesys.com>,
	"Paul Cercueil" <paul@crapouillou.net>,
	"Harvey Hunt" <harveyhuntnexus@gmail.com>,
	"Maxim Levitsky" <maximlevitsky@gmail.com>,
	"Michael Walle" <michael@walle.cc>,
	"Srinivas Kandagatla" <srini@kernel.org>
Cc: "Tze Yee Ng" <tze.yee.ng@altera.com>,
	linux-mtd@lists.infradead.org, linux-sunxi@lists.linux.dev,
	imx@lists.linux.dev, linux-amlogic@lists.infradead.org,
	Frank.Li@kernel.org, wsa+renesas@sang-engineering.com
Subject: Re: [PATCH 03/58] mtd: add opt-in lifetime ownership for backing objects
Date: Sat, 07 Nov 2026 20:50:21 +0000	[thread overview]
Message-ID: <sashiko-outbox-203330@kernel.org> (raw)
In-Reply-To: <20261107-submit-rawnand-retained-handle-lifetime-v1-v1-3-0181ef0cc4c8@gmail.com>

Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [Medium] mtd: refcount imbalance in __put_mtd_device() when
  master->dev.type changes
- [Medium] mtd: mtd_add_partition() allows adding partitions to an
  unregistered master
- [Medium] mtd: add_mtd_device() leaves mtd->dev.type set when
  dev_set_name() fails
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [Critical] mtd: core: use-after-free in add_mtd_device() [1]
--

commit da12394511d438335fb25ce60156c3307163ed8f
Author: James Hilliard <james.hilliard1@gmail.com>

mtd: add opt-in lifetime ownership for backing objects

This commit introduces opt-in reference-counted lifetime management for
master MTD backing objects via mtd_set_release() and mtd_put_master(),
retaining the master and partition hierarchy while MTD handles, device
nodes, or OTP NVMEM providers remain active.

> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 558a605ba7495..42c06a02cd99d 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
[ ... ]
> @@ -748,16 +840,28 @@ int add_mtd_device(struct mtd_info *mtd)
[ ... ]
>  	mtd->index = i;
>  	kref_init(&mtd->refcnt);
> +	if (master->master.release) {
> +		mtd_get_lifetime(master);
> +		mtd->ref_master = master;
> +		if (mtd->parent && mtd->parent != master)
> +			get_device(&mtd->parent->dev);
> +	}

[Severity: Medium]
Can a partition still be added through mtd_add_partition() after the
parent or master has been unregistered?

If a process keeps an open file descriptor to /dev/mtd0 across driver
unbind (mtd_device_unregister() and mtd_put_master()) and issues
BLKPG_ADD_PARTITION, mtdchar_blkpg_ioctl() -> mtd_add_partition() calls
add_mtd_device(child) without checking whether parent->registered is still
true.  Because del_mtd_partitions() has already run, the new partition is
never cleaned up, leaking the partition, its MTD ID, THIS_MODULE, and
master.life_refcnt.  Furthermore, once the open handle on the managed
master is closed, mtd_device_release() leaves master->dev.type set, so
opening and closing the leaked child partition will do kref_get() on a
zero master->refcnt and call mtd_device_release() a second time.

> @@ -839,29 +946,38 @@ int add_mtd_device(struct mtd_info *mtd)
>  		}
>  	}
>  
> -	/* We _know_ we aren't being removed, because
> -	   our caller is still holding us here. So none
> -	   of this try_ nonsense, and no bitching about it
> -	   either. :) */
> -	__module_get(THIS_MODULE);
>  	return 0;
>  
>  fail_nvmem_add:
>  	device_del(&mtd->dev);
>  fail_added:
>  	/*
> -	 * Clear type and set nop release to prevent mtd_release() ->
> +	 * Clear type and override release to prevent mtd_release() ->
>  	 * release_mtd_partition() -> free_partition() from freeing mtd.
>  	 * The caller handles cleanup on failure.
>  	 */
>  	mtd->dev.type = NULL;
> -	mtd->dev.release = mtd_dev_release_nop;
> +	mtd->dev.release = mtd_dev_release_done;
> +	dev_set_drvdata(&mtd->dev, &released);
> +	wait_for_release = true;
>  	put_device(&mtd->dev);
>  	of_node_put(mtd_get_of_node(mtd));
>  fail_devname:
>  	idr_remove(&mtd_idr, i);
> +	ida_free(&mtd_ids, i);
> +	if (mtd->ref_master) {
> +		mtd->ref_master = NULL;
> +		if (mtd->parent && mtd->parent != master)
> +			put_device(&mtd->parent->dev);
> +		mtd_put_lifetime(master);
> +	}

[Severity: Critical]
This problem wasn't introduced by this patch, but can add_mtd_device()
trigger a use-after-free on the device_node [1] when
mtd_check_of_node() matches a partition node?

drivers/mtd/mtdcore.c:mtd_check_of_node() {
    ...
		if (plen == mtd_name_len &&
		    !strncmp(mtd->name, pname + offset, plen)) {
			mtd_set_of_node(mtd, mtd_dn);
			of_node_put(mtd_dn);
			break;
		}
    ...
}

mtd_check_of_node() stores mtd_dn in mtd and immediately drops its
reference via of_node_put(mtd_dn) before add_mtd_device() calls
of_node_get(mtd_get_of_node(mtd)).  In a dynamic DT environment, if the
node is removed in that window, of_node_put() frees mtd_dn and
of_node_get() dereferences freed memory.

[Severity: Medium]
Does jumping to fail_devname when dev_set_name() fails leave mtd->dev.type
set to &mtd_devtype?

mtd->dev.type is assigned right before dev_set_name(), and clearing it only
happens under fail_added.  Leaving mtd->dev.type non-NULL causes any retry
of add_mtd_device() to fail at WARN_ONCE(mtd->dev.type, ...), and causes
__put_mtd_device() on an open partition to call kref_put(&master->refcnt,
mtd_device_release) on a master whose struct device was never registered.

[ ... ]

> @@ -1348,13 +1484,14 @@ int __get_mtd_device(struct mtd_info *mtd)
>  		return -ENODEV;
>  	}
>  
> +	mtd_get_lifetime(master);
>  	while (mtd) {
>  		if (mtd != master)
>  			kref_get(&mtd->refcnt);
>  		mtd = mtd->parent;
>  	}
>  
> -	if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
> +	if (master->dev.type)
>  		kref_get(&master->refcnt);
>  
>  	return 0;
> @@ -1441,6 +1578,7 @@ void __put_mtd_device(struct mtd_info *mtd)
>  	struct mtd_info *master = mtd_get_master(mtd);
>  	/* master can be freed in _put_device */
>  	struct module *owner = master->owner;
> +	bool managed = master->master.release;
>  
>  	while (mtd) {
>  		/* kref_put() can relese mtd, so keep a reference mtd->parent */
> @@ -1451,12 +1589,14 @@ void __put_mtd_device(struct mtd_info *mtd)
>  		mtd = parent;
>  	}
>  
> -	if (IS_ENABLED(CONFIG_MTD_PARTITIONED_MASTER))
> +	if (master->dev.type)
>  		kref_put(&master->refcnt, mtd_device_release);

[Severity: Medium]
Can master->dev.type change from NULL to non-NULL between
__get_mtd_device() and __put_mtd_device(), causing an unmatched
kref_put(&master->refcnt, mtd_device_release)?

When CONFIG_MTD_PARTITIONED_MASTER=n, master->dev.type is NULL while
mtd_device_parse_register() runs parse_mtd_partitions().  If a first
partition is registered and opened by a notifier or userspace (seeing
master->dev.type == NULL in __get_mtd_device()), and a later partition
fails to register in add_mtd_partitions(), del_mtd_partitions() unregisters
the first partition while it remains open:

drivers/mtd/mtdcore.c:mtd_device_parse_register() {
    ...
	ret = parse_mtd_partitions(mtd, types, parser_data);
	if (ret == -EPROBE_DEFER)
		goto out;

	if (ret > 0)
		ret = 0;
	else if (nr_parts)
		ret = add_mtd_partitions(mtd, parts, nr_parts);
	else if (!device_is_registered(&mtd->dev))
		ret = add_mtd_device(mtd);
    ...
}

When nr_parts == 0 and parse_mtd_partitions() returns a non-defer error,
mtd_device_parse_register() falls back to add_mtd_device(mtd), which sets
master->dev.type = &mtd_devtype and initializes master->refcnt to 1.
Closing the open partition handle then sees master->dev.type != NULL in
__put_mtd_device() and drops master->refcnt to 0 while the master is still
registered.

[1] https://sashiko.dev/#/bug/linux-11fdb383-132f-473b-9284-101b4753fcd6

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261107-submit-rawnand-retained-handle-lifetime-v1-v1-0-0181ef0cc4c8@gmail.com?part=3

_______________________________________________
linux-amlogic mailing list
linux-amlogic@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-amlogic

  reply	other threads:[~2026-11-07 20:50 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07 10:15 [PATCH 00/58] mtd: rawnand: retain chip and controller state across removal James Hilliard
2026-11-07 10:15 ` [PATCH 01/58] mtd: clear OTP provider pointers after unregistering them James Hilliard
2026-11-07 20:21   ` sashiko-bot
2026-11-07 10:15 ` [PATCH 02/58] nvmem: retain provider context through final device release James Hilliard
2026-11-07 20:26   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 03/58] mtd: add opt-in lifetime ownership for backing objects James Hilliard
2026-11-07 20:50   ` sashiko-bot [this message]
2026-11-07 10:16 ` [PATCH 04/58] mtd: rawnand: separate hardware disconnection from cleanup James Hilliard
2026-11-07 20:42   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 05/58] mtd: rawnand: share retained chip and controller ownership James Hilliard
2026-11-07 10:16 ` [PATCH 06/58] mtd: rawnand: macronix: serialize OTP access with NAND operations James Hilliard
2026-11-07 10:16 ` [PATCH 07/58] mtd: rawnand: sunxi: retain chip state until the final MTD put James Hilliard
2026-11-07 10:16 ` [PATCH 08/58] mtd: rawnand: plat_nand: retain open-handle state on removal James Hilliard
2026-11-07 10:16 ` [PATCH 09/58] mtd: rawnand: gpio: " James Hilliard
2026-11-07 10:16 ` [PATCH 10/58] mtd: rawnand: stm32_fmc2: " James Hilliard
2026-11-07 10:16 ` [PATCH 11/58] mtd: rawnand: denali: retain chips across controller removal James Hilliard
2026-11-07 20:25   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 12/58] mtd: rawnand: arasan: " James Hilliard
2026-11-07 10:16 ` [PATCH 13/58] mtd: rawnand: mxic: retain open-handle state on removal James Hilliard
2026-11-07 10:16 ` [PATCH 14/58] mtd: rawnand: intel: " James Hilliard
2026-11-07 20:31   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 15/58] mtd: rawnand: tegra: " James Hilliard
2026-11-07 20:32   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 16/58] mtd: rawnand: mtk: retain chips across controller removal James Hilliard
2026-11-07 10:16 ` [PATCH 17/58] mtd: rawnand: rockchip: " James Hilliard
2026-11-07 10:16 ` [PATCH 18/58] mtd: rawnand: atmel: " James Hilliard
2026-11-07 20:31   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 19/58] mtd: rawnand: orion: retain open-handle state on removal James Hilliard
2026-11-07 20:29   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 20/58] mtd: rawnand: socrates: " James Hilliard
2026-11-07 10:16 ` [PATCH 21/58] mtd: rawnand: fsl_upm: " James Hilliard
2026-11-07 10:16 ` [PATCH 22/58] mtd: rawnand: pasemi: " James Hilliard
2026-11-07 10:16 ` [PATCH 23/58] mtd: rawnand: ams-delta: " James Hilliard
2026-11-07 10:16 ` [PATCH 24/58] mtd: rawnand: xway: " James Hilliard
2026-11-07 10:16 ` [PATCH 27/58] mtd: rawnand: technologic: " James Hilliard
2026-11-07 10:16 ` [PATCH 28/58] mtd: rawnand: loongson: " James Hilliard
2026-11-07 10:16 ` [PATCH 29/58] mtd: rawnand: ma35d1: " James Hilliard
2026-11-07 10:16 ` [PATCH 30/58] mtd: rawnand: pl35x: " James Hilliard
2026-11-07 10:16 ` [PATCH 31/58] mtd: rawnand: mxc: " James Hilliard
2026-11-07 10:16 ` [PATCH 32/58] mtd: rawnand: fsmc: " James Hilliard
2026-11-07 10:16 ` [PATCH 33/58] mtd: rawnand: gpmi: " James Hilliard
2026-11-07 10:16 ` [PATCH 34/58] mtd: rawnand: omap2: " James Hilliard
2026-11-07 10:16 ` [PATCH 35/58] mtd: rawnand: marvell: " James Hilliard
2026-11-07 10:16 ` [PATCH 36/58] mtd: rawnand: renesas: " James Hilliard
2026-11-07 10:16 ` [PATCH 37/58] mtd: rawnand: meson: " James Hilliard
2026-11-07 10:16 ` [PATCH 38/58] mtd: rawnand: cadence: " James Hilliard
2026-11-07 10:16 ` [PATCH 39/58] mtd: rawnand: qcom: " James Hilliard
2026-11-07 20:47   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 40/58] mtd: rawnand: cafe: " James Hilliard
2026-11-07 10:16 ` [PATCH 41/58] mtd: rawnand: brcmnand: " James Hilliard
2026-11-07 10:16 ` [PATCH 42/58] mtd: rawnand: au1550nd: retain chip state across removal James Hilliard
2026-11-07 20:44   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 43/58] mtd: rawnand: sharpsl: " James Hilliard
2026-11-07 10:16 ` [PATCH 44/58] mtd: rawnand: davinci: " James Hilliard
2026-11-07 10:16 ` [PATCH 45/58] mtd: rawnand: sh_flctl: " James Hilliard
2026-11-07 10:16 ` [PATCH 46/58] mtd: rawnand: lpc32xx_slc: " James Hilliard
2026-11-07 10:16 ` [PATCH 47/58] mtd: rawnand: lpc32xx_mlc: " James Hilliard
2026-11-07 10:16 ` [PATCH 48/58] mtd: rawnand: ndfc: " James Hilliard
2026-11-07 10:16 ` [PATCH 49/58] mtd: rawnand: txx9ndfmc: " James Hilliard
2026-11-07 10:16 ` [PATCH 50/58] mtd: rawnand: ingenic: " James Hilliard
2026-11-07 10:16 ` [PATCH 51/58] mtd: rawnand: mpc5121: " James Hilliard
2026-11-07 20:48   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 52/58] mtd: rawnand: bcm47xxnflash: " James Hilliard
2026-11-07 10:16 ` [PATCH 53/58] mtd: rawnand: fsl_elbc: " James Hilliard
2026-11-07 10:16 ` [PATCH 54/58] mtd: rawnand: fsl_ifc: " James Hilliard
2026-11-07 10:16 ` [PATCH 55/58] mtd: rawnand: r852: " James Hilliard
2026-11-07 20:59   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 56/58] mtd: rawnand: nandsim: " James Hilliard
2026-11-07 20:52   ` sashiko-bot
2026-11-07 10:16 ` [PATCH 57/58] mtd: rawnand: cs553x: " James Hilliard
2026-11-07 10:16 ` [PATCH 58/58] mtd: rawnand: diskonchip: " James Hilliard
2026-11-07 19:33 ` [PATCH 25/58] mtd: rawnand: hisi504: retain open-handle state on removal James Hilliard
2026-11-07 19:33 ` [PATCH 26/58] mtd: rawnand: vf610: " 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-203330@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=AVKrasnov@sberdevices.ru \
    --cc=David.Woodhouse@intel.com \
    --cc=Frank.Li@kernel.org \
    --cc=Frank.Li@nxp.com \
    --cc=alexandre.belloni@bootlin.com \
    --cc=alexandre.torgue@foss.st.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=bbrezillon@kernel.org \
    --cc=bcm-kernel-feedback-list@broadcom.com \
    --cc=boris.brezillon@collabora.com \
    --cc=christophe.kerello@st.com \
    --cc=claudiu.beznea@tuxon.dev \
    --cc=computersforpeace@gmail.com \
    --cc=dev@lynxeye.de \
    --cc=digetx@gmail.com \
    --cc=dwmw2@infradead.org \
    --cc=festevam@gmail.com \
    --cc=han.xu@nxp.com \
    --cc=harveyhuntnexus@gmail.com \
    --cc=heiko@sntech.de \
    --cc=imx@lists.linux.dev \
    --cc=james.hilliard1@gmail.com \
    --cc=jason.e.roberts@intel.com \
    --cc=jbrunet@baylibre.com \
    --cc=jernej.skrabec@gmail.com \
    --cc=jonathanh@nvidia.com \
    --cc=jorge.ramirez@oss.qualcomm.com \
    --cc=kamal.dasu@broadcom.com \
    --cc=keguang.zhang@gmail.com \
    --cc=kernel@pengutronix.de \
    --cc=khilman@baylibre.com \
    --cc=liang.yang@amlogic.com \
    --cc=linux-amlogic@lists.infradead.org \
    --cc=linux-mtd@lists.infradead.org \
    --cc=linux-sunxi@lists.linux.dev \
    --cc=mani@kernel.org \
    --cc=martin.blumenstingl@googlemail.com \
    --cc=masonccyang@mxic.com.tw \
    --cc=matthias.bgg@gmail.com \
    --cc=maximlevitsky@gmail.com \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=michael@walle.cc \
    --cc=michal.simek@amd.com \
    --cc=miquel.raynal@bootlin.com \
    --cc=neil.armstrong@linaro.org \
    --cc=nicolas.ferre@microchip.com \
    --cc=paul@crapouillou.net \
    --cc=piotr.wojtaszczyk@timesys.com \
    --cc=richard@nod.at \
    --cc=rmk+kernel@arm.linux.org.uk \
    --cc=rppt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=samuel@sholland.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=schung@nuvoton.com \
    --cc=srini@kernel.org \
    --cc=stefan@agner.ch \
    --cc=tglx@kernel.org \
    --cc=thierry.reding@kernel.org \
    --cc=tze.yee.ng@altera.com \
    --cc=vadivel.muruganx.ramuthevar@linux.intel.com \
    --cc=vigneshr@ti.com \
    --cc=vitalywool@gmail.com \
    --cc=vz@mleia.com \
    --cc=wens@kernel.org \
    --cc=wsa+renesas@sang-engineering.com \
    --cc=ychuang3@nuvoton.com \
    --cc=yifeng.zhao@rock-chips.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 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®