Linux Documentation
 help / color / mirror / Atom feed
* Re: [PATCH 4/4] block: add configurable error injection
From: Damien Le Moal @ 2026-06-06  7:33 UTC (permalink / raw)
  To: Christoph Hellwig, Jens Axboe; +Cc: Jonathan Corbet, linux-block, linux-doc
In-Reply-To: <20260605184441.590927-5-hch@lst.de>

On 2026/06/06 2:44, Christoph Hellwig wrote:
> Add a new block error injection interface that allows to inject specific
> status code for specific ranges.
> 
> Signed-off-by: Christoph Hellwig <hch@lst.de>

[...]

> +===================	=======================================================
> +op=%s			block layer operation this rule applies to, e.g. READ
> +			or WRITE.

Like you did in the commit message of patch 3, maybe mention that this should
match "XYZ" of one of the defined REQ_OP_XYZ operation ?

> +			Mandatory.
> +start=%u		First block layer sector the rule applies to.
> +			Optional, defaults to 0.
> +nr_sectors=%u		Number of sectors this rule applies.
> +			Optional, defaults to the remainder of the device.
> +status=%s		Status to return.

Maybe mention that this should match XYZ for one one of the defined BLK_STS_XYZ ?

> +			Mandatory.
> +chance=%u		Only return a failure with a likelihood of 1/chance.
> +			Optional, defaults to 1 (always).
> +===================	=======================================================

[...]

> +	/*
> +	 * Add to the front of the list so that newer entries can partially
> +	 * override other entries.  This also intentional allows duplicate

s/intentional/intentionally

> +	 * entries as there is no real reason to reject them.
> +	 */

Beside these nits, looks good to me.

Reviewed-by: Damien Le Moal <dlemoal@kernel.org>

-- 
Damien Le Moal
Western Digital Research

^ permalink raw reply

* Re: [PATCH v1] docs/ja_JP: translate submitting-patches.rst (interleaved-replies)
From: Akira Yokosawa @ 2026-06-06  9:11 UTC (permalink / raw)
  To: Akiyoshi Kurita, linux-doc; +Cc: linux-kernel, corbet
In-Reply-To: <20260606035954.27605-1-weibu@redadmin.org>

Hi,

On Sat,  6 Jun 2026 12:59:54 +0900, Akiyoshi Kurita wrote:
> Translate the "Use trimmed interleaved replies in email discussions"
> and "Don't get discouraged - or impatient" sections in
> Documentation/translations/ja_JP/process/submitting-patches.rst.
> 
> Keep the wording close to the English text and wrap lines to match
> the style used in the surrounding Japanese translation.
> 
> Signed-off-by: Akiyoshi Kurita <weibu@redadmin.org>

I see a couple of English terms left untranslated, but they can be
taken care of later.  So,

Acked-by: Akira Yokosawa <akiyks@gmail.com>

Thanks, Akira

> ---
>  .../ja_JP/process/submitting-patches.rst      | 47 +++++++++++++++++++
>  1 file changed, 47 insertions(+)
[...]


^ permalink raw reply

* Re: [PATCH v6 03/12] PCI: liveupdate: Track incoming preserved PCI devices
From: Pranjal Shrivastava @ 2026-06-06 10:08 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-4-dmatlack@google.com>

On Fri, May 22, 2026 at 08:24:01PM +0000, David Matlack wrote:
> During PCI enumeration, the previous kernel might have passed state about
> devices that were preserved across kexec. The PCI core needs to fetch
> this state to identify which devices are "incoming" and require special
> handling.
> 
> Add pci_liveupdate_setup_device() which is called during device setup
> to fetch the serialized state (struct pci_ser) from the Live Update
> Orchestrator. The first time this happens, pci_flb_retrieve() will run
> and convert the array of pci_dev_ser structs into an xarray so that it
> can be looked up efficiently.
> 
> If a device is found in the xarray, the PCI core stores a pointer to its
> state in dev->liveupdate_incoming and holds a reference to the incoming
> FLB until pci_liveupdate_finish() is called by the driver.
> 
> This ensures proper lifecycle management for incoming preserved devices
> and allows the PCI core and drivers to apply specific Live Update
> logic to them in subsequent commits.
> 
> Drivers can check if a device is an incoming preserved device (e.g.
> during probe) by calling pci_liveupdate_is_incoming().
> 
> CONFIG_64BIT is now required to enable CONFIG_PCI_LIVEUPDATE so that the
> domain and bdf can be guaranteed to fit in an unsigned long and be used
> as the xarray key.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
>  MAINTAINERS                    |   1 +
>  drivers/pci/Kconfig            |   2 +-
>  drivers/pci/liveupdate.c       | 230 ++++++++++++++++++++++++++++++++-
>  drivers/pci/liveupdate.h       |   5 +
>  drivers/pci/probe.c            |   3 +
>  include/linux/pci_liveupdate.h |  13 ++
>  6 files changed, 251 insertions(+), 3 deletions(-)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6c618830cf61..0e262c0ceb43 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -20537,6 +20537,7 @@ L:	linux-pci@vger.kernel.org
>  S:	Maintained
>  T:	git git://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux.git
>  F:	drivers/pci/liveupdate.c
> +F:	drivers/pci/liveupdate.h
>  F:	include/linux/kho/abi/pci.h
>  F:	include/linux/pci_liveupdate.h
>  
> diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
> index 10c9b65aa242..e68ae5c172d4 100644
> --- a/drivers/pci/Kconfig
> +++ b/drivers/pci/Kconfig
> @@ -330,7 +330,7 @@ config VGA_ARB_MAX_GPUS
>  
>  config PCI_LIVEUPDATE
>  	bool "PCI Live Update Support"
> -	depends on PCI && LIVEUPDATE
> +	depends on PCI && LIVEUPDATE && 64BIT

I see that the static assertions in Patch 1 work because of the 64BIT
enforcement here. In that case, should we have the assertions check u64?

>  	help
>  	  Enable PCI core support for preserving PCI devices across Live
>  	  Update. This, in combination with support in a device's driver,
>

[...]

>  static int pci_flb_retrieve(struct liveupdate_flb_op_args *args)
>  {
> -	args->obj = phys_to_virt(args->data);
> +	struct pci_ser *ser = phys_to_virt(args->data);
> +	struct pci_flb_incoming *incoming;
> +	int ret = -ENOMEM;
> +	u32 i;
> +
> +	incoming = kmalloc_obj(*incoming);
> +	if (!incoming)
> +		goto err_restore_free;
> +
> +	incoming->ser = ser;
> +	xa_init(&incoming->xa);
> +
> +	for (i = 0; i < incoming->ser->max_nr_devices; i++) {
> +		struct pci_dev_ser *dev_ser = &incoming->ser->devices[i];
> +		unsigned long key;
> +
> +		if (!dev_ser->refcount)
> +			continue;
> +
> +		key = pci_ser_xa_key(dev_ser->domain, dev_ser->bdf);
> +		ret = xa_insert(&incoming->xa, key, dev_ser, GFP_KERNEL);
> +		if (ret)
> +			goto err_xa_destroy;
> +	}
> +
> +	args->obj = incoming;
>  	return 0;
> +
> +err_xa_destroy:
> +	xa_destroy(&incoming->xa);
> +	kfree(incoming);
> +err_restore_free:
> +	kho_restore_free(ser);

I tend to partly agree with Sashiko[1] here.. it raises a policy-hole.
We may need a policy here, the options I have in mind are:

1. Retrieve shall ONLY be tried once, if it fails (like -ENOMEM in the
   xArray alloc), it's a liveupdate failure. We can't retry liveupdate.

2. Retrying retrieve is allowed.

The only downside with option 1 is, the user may want flexibility due to
certain subsystems OR may choose NOT to use the proposed LUOd and instead
have its own user-space component which might try funny things or have a
different use-case.

In such a situation, the system may have transiently run out of memory
during the kexec transition (for e.g. a subsystem uses GFP_ATOMIC to
allocate memory and temporarily runs out of the atomic pool). [Note we
removed it in IOMMU v1 [2] but subsystems may have a use-case for it]

If the kernel frees the KHO page on the first failure, it removes any
chance of recovery. :/

Thus, it might make sense to let the user decide if it wants to fail the
liveupdate or retry again based on the failure type / source?

[...]

The changes LGTM, except for policy-based, kho_restore_free discussion.

Reviewed-by: Pranjal Shrivastava <praan@google.com>

Thanks,
Praan

[1] https://lore.kernel.org/all/20260522211333.D56A21F000E9@smtp.kernel.org/
[2] https://lore.kernel.org/all/20260203220948.2176157-2-skhawaja@google.com/

^ permalink raw reply

* Re: [PATCH v6 04/12] PCI: liveupdate: Document driver binding responsibilities
From: Pranjal Shrivastava @ 2026-06-06 10:20 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-5-dmatlack@google.com>

On Fri, May 22, 2026 at 08:24:02PM +0000, David Matlack wrote:
> Document how driver binding works during a Live Update and what the PCI
> core expects of drivers and users. Note that this is only a description
> of the current division of responsibilities. These can change in the
> future if we decide.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>

Reviewed-by: Pranjal Shrivastava praan@google.com

Thanks,
Praan

^ permalink raw reply

* Re: [PATCH mm-unstable v19 11/14] mm/khugepaged: Introduce mTHP collapse support
From: Lance Yang @ 2026-06-06 10:28 UTC (permalink / raw)
  To: npache
  Cc: linux-doc, linux-kernel, linux-mm, linux-trace-kernel, aarcange,
	akpm, anshuman.khandual, apopple, baohua, baolin.wang, byungchul,
	catalin.marinas, cl, corbet, dave.hansen, david, dev.jain, gourry,
	hannes, hughd, jack, jackmanb, jannh, jglisse, joshua.hahnjy, kas,
	lance.yang, liam, ljs, mathieu.desnoyers, matthew.brost, mhiramat,
	mhocko, peterx, pfalcato, rakie.kim, raquini, rdunlap,
	richard.weiyang, rientjes, rostedt, rppt, ryan.roberts, shivankg,
	sunnanyong, surenb, thomas.hellstrom, tiwai, usamaarif642, vbabka,
	vishal.moola, wangkefeng.wang, will, willy, yang, ying.huang, ziy,
	zokeefe
In-Reply-To: <20260605161422.213817-12-npache@redhat.com>


On Fri, Jun 05, 2026 at 10:14:18AM -0600, Nico Pache wrote:
>Enable khugepaged to collapse to mTHP orders. This patch implements the
>main scanning logic using a bitmap to track occupied pages and the
>algorithm to find optimal collapse sizes.
>
>Previous to this patch, PMD collapse had 3 main phases, a light weight
>scanning phase (mmap_read_lock) that determines a potential PMD
>collapse, an alloc phase (mmap unlocked), then finally heavier collapse
>phase (mmap_write_lock).
>
>To enabled mTHP collapse we make the following changes:
>
>During PMD scan phase, track occupied pages in a bitmap. When mTHP
>orders are enabled, we remove the restriction of max_ptes_none during the
>scan phase to avoid missing potential mTHP collapse candidates. Once we
>have scanned the full PMD range and updated the bitmap to track occupied
>pages, we use the bitmap to find the optimal mTHP size.
>
>Implement mthp_collapse() to walk forward through the bitmap and
>determine the best eligible order for each naturally-aligned region. The
>algorithm starts at the beginning of the PMD range and, for each offset,
>tries the highest order that fits the alignment. If the number of
>occupied PTEs in that region satisfies the max_ptes_none threshold for
>that order, a collapse is attempted. On failure, the order is
>decremented and the same offset is retried at the next smaller size. Once
>the smallest enabled order is exhausted (or a collapse succeeds), the
>offset advances past the region just processed, and the next attempt
>starts at the highest order permitted by the new offset's natural
>alignment.
>
>The algorithm works as follows:
>    1) set offset=0 and order=HPAGE_PMD_ORDER
>    2) if the order is not enabled, go to step (5)
>    3) count occupied PTEs in the (offset, order) range using
>       bitmap_weight_from()
>    4) if the count satisfies the max_ptes_none threshold, attempt
>       collapse; on success, advance to step (6)
>    5) if a smaller enabled order exists, decrement order and retry
>       from step (2) at the same offset
>    6) advance offset past the current region and compute the next
>       order from the new offset's natural alignment via __ffs(offset),
>       capped at HPAGE_PMD_ORDER
>    7) repeat from step (2) until the full PMD range is covered
>
>mTHP collapses reject regions containing swapped out or shared pages.
>This is because adding new entries can lead to new none pages, and these
>may lead to constant promotion into a higher order mTHP. A similar
>issue can occur with "max_ptes_none > HPAGE_PMD_NR/2" due to a collapse
>introducing at least 2x the number of pages, and on a future scan will
>satisfy the promotion condition once again. This issue is prevented via
>the collapse_max_ptes_none() function which imposes the max_ptes_none
>restrictions above.
>
>We currently only support mTHP collapse for max_ptes_none values of 0
>and HPAGE_PMD_NR - 1. resulting in the following behavior:
>
>    - max_ptes_none=0: Never introduce new empty pages during collapse
>    - max_ptes_none=HPAGE_PMD_NR-1: Always try collapse to the highest
>      available mTHP order
>
>Any other max_ptes_none value will emit a warning and default mTHP
>collapse to max_ptes_none=0. There should be no behavior change for PMD
>collapse.
>
>Once we determine what mTHP sizes fits best in that PMD range a collapse
>is attempted. A minimum collapse order of 2 is used as this is the lowest
>order supported by anon memory as defined by THP_ORDERS_ALL_ANON.
>
>Currently madv_collapse is not supported and will only attempt PMD
>collapse.
>
>We can also remove the check for is_khugepaged inside the PMD scan as
>the collapse_max_ptes_none() function handles this logic now.
>
>Signed-off-by: Nico Pache <npache@redhat.com>
>---
> mm/khugepaged.c | 146 +++++++++++++++++++++++++++++++++++++++++++++---
> 1 file changed, 138 insertions(+), 8 deletions(-)
>
>diff --git a/mm/khugepaged.c b/mm/khugepaged.c
>index ec886a031952..430047316f43 100644
>--- a/mm/khugepaged.c
>+++ b/mm/khugepaged.c
>@@ -99,6 +99,8 @@ static DEFINE_READ_MOSTLY_HASHTABLE(mm_slots_hash, MM_SLOTS_HASH_BITS);
> 
> static struct kmem_cache *mm_slot_cache __ro_after_init;
> 
>+#define KHUGEPAGED_MIN_MTHP_ORDER	2
>+
> struct collapse_control {
> 	bool is_khugepaged;
> 
>@@ -110,6 +112,9 @@ struct collapse_control {
> 
> 	/* nodemask for allocation fallback */
> 	nodemask_t alloc_nmask;
>+
>+	/* Each bit represents a single occupied (!none/zero) page. */
>+	DECLARE_BITMAP(mthp_present_ptes, MAX_PTRS_PER_PTE);
> };
> 
> /**
>@@ -1440,20 +1445,130 @@ static enum scan_result collapse_huge_page(struct mm_struct *mm, unsigned long s
> 	return result;
> }
> 
>+/* Return the highest naturally aligned order that fits at @offset within a PMD. */
>+static unsigned int max_order_from_offset(unsigned int offset)
>+{
>+	if (offset == 0)
>+		return HPAGE_PMD_ORDER;
>+
>+	return min_t(unsigned int, __ffs(offset), HPAGE_PMD_ORDER);
>+}
>+
>+/*
>+ * mthp_collapse() consumes the bitmap that is generated during
>+ * collapse_scan_pmd() to determine what regions and mTHP orders fit best.
>+ *
>+ * Each bit in cc->mthp_present_ptes represents a single occupied (!none/zero)
>+ * page. We start at the PMD order and check if it is eligible for collapse;
>+ * if not, we check the left and right halves of the PTE page table we are
>+ * examining at a lower order.
>+ *
>+ * For each of these, we determine how many PTE entries are occupied in the
>+ * range of PTE entries we propose to collapse, then we compare this to a
>+ * threshold number of PTE entries which would need to be occupied for a
>+ * collapse to be permitted at that order (accounting for max_ptes_none).
>+ *
>+ * If a collapse is permitted, we attempt to collapse the PTE range into a
>+ * mTHP.
>+ */
>+static enum scan_result mthp_collapse(struct mm_struct *mm,
>+		unsigned long address, int referenced, int unmapped,
>+		struct collapse_control *cc, unsigned long enabled_orders)
>+{
>+	unsigned int nr_occupied_ptes, nr_ptes, max_ptes_none;
>+	enum scan_result last_result = SCAN_FAIL;
>+	int collapsed = 0;
>+	bool alloc_failed = false;
>+	unsigned long collapse_address;
>+	unsigned int offset = 0;
>+	unsigned int order = HPAGE_PMD_ORDER;
>+
>+	while (offset < HPAGE_PMD_NR) {
>+		nr_ptes = 1UL << order;
>+
>+		if (!test_bit(order, &enabled_orders))
>+			goto next_order;
>+
>+		max_ptes_none = collapse_max_ptes_none(cc, NULL, order);
>+		nr_occupied_ptes = bitmap_weight_from(cc->mthp_present_ptes, offset,
>+						      offset + nr_ptes);
>+
>+		if (nr_occupied_ptes >= nr_ptes - max_ptes_none) {

Looks broken for swap PTEs in PMD collapse ...

collapse_scan_pmd() allows them up to max_ptes_swap and record them in
unmapped, but they don't get a bit in mthp_present_ptes. And then
mthp_collapse() does the check above:

nr_occupied_ptes >= nr_ptes - max_ptes_none

So max_ptes_none=0 + 511 present PTEs + one allowed swap PTE won't even
call collapse_huge_page() for PMD order.

Shouldn't we account for them in the PMD-order check? Something like:

if (is_pmd_order(order))
	nr_occupied_ptes += unmapped;

Cheers, Lance
 
>+			enum scan_result ret;
>+
>+			collapse_address = address + offset * PAGE_SIZE;
>+			ret = collapse_huge_page(mm, collapse_address, referenced,
>+						 unmapped, cc, order);
>+			switch (ret) {
>+			/* Cases where we continue to next collapse candidate */
>+			case SCAN_SUCCEED:
>+				collapsed += nr_ptes;
>+				fallthrough;
>+			case SCAN_PTE_MAPPED_HUGEPAGE:
>+				goto next_offset;
>+			/* Cases where lower orders might still succeed */
>+			case SCAN_ALLOC_HUGE_PAGE_FAIL:
>+				alloc_failed = true;
>+				last_result = ret;
>+				goto next_order;
>+			/* Cases where no further collapse is possible */
>+			case SCAN_PMD_MAPPED:
>+				fallthrough;
>+			default:
>+				last_result = ret;
>+				goto done;
>+			}
>+		}
>+
>+next_order:
>+		/*
>+		 * Continue with the next smaller order if there is still
>+		 * any smaller order enabled. When at the smallest order
>+		 * we must always move to the next offset.
>+		 */
>+		if (order > KHUGEPAGED_MIN_MTHP_ORDER &&
>+			(enabled_orders & GENMASK(order - 1, 0))) {
>+			order--;
>+			continue;
>+		}
>+next_offset:
>+		/*
>+		 * Advance past the region we just processed and determine the
>+		 * highest order we can attempt next. Since huge pages must be
>+		 * naturally aligned, the max order we can attempt next is
>+		 * limited by the alignment of the new offset.
>+		 * E.g. if we collapsed a order-2 mTHP at offset 0, offset
>+		 * becomes 4 and __ffs(4) == 2, so the next attempt starts at
>+		 * order 2.
>+		 */
>+		offset += nr_ptes;
>+		order = max_order_from_offset(offset);
>+	}
>+done:
>+	if (collapsed)
>+		return SCAN_SUCCEED;
>+	if (alloc_failed)
>+		return SCAN_ALLOC_HUGE_PAGE_FAIL;
>+	return last_result;
>+}
>+
> static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> 		struct vm_area_struct *vma, unsigned long start_addr,
> 		bool *lock_dropped, struct collapse_control *cc)
> {
>-	const unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma, HPAGE_PMD_ORDER);
> 	const unsigned int max_ptes_shared = collapse_max_ptes_shared(cc, HPAGE_PMD_ORDER);
> 	const unsigned int max_ptes_swap = collapse_max_ptes_swap(cc, HPAGE_PMD_ORDER);
>+	unsigned int max_ptes_none = collapse_max_ptes_none(cc, vma, HPAGE_PMD_ORDER);
>+	enum tva_type tva_flags = cc->is_khugepaged ? TVA_KHUGEPAGED : TVA_FORCED_COLLAPSE;
> 	pmd_t *pmd;
>-	pte_t *pte, *_pte;
>+	pte_t *pte, *_pte, pteval;
>+	int i;
> 	int none_or_zero = 0, shared = 0, referenced = 0;
> 	enum scan_result result = SCAN_FAIL;
> 	struct page *page = NULL;
> 	struct folio *folio = NULL;
> 	unsigned long addr;
>+	unsigned long enabled_orders;
> 	spinlock_t *ptl;
> 	int node = NUMA_NO_NODE, unmapped = 0;
> 
>@@ -1465,8 +1580,19 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> 		goto out;
> 	}
> 
>+	bitmap_zero(cc->mthp_present_ptes, MAX_PTRS_PER_PTE);
> 	memset(cc->node_load, 0, sizeof(cc->node_load));
> 	nodes_clear(cc->alloc_nmask);
>+
>+	enabled_orders = collapse_possible_orders(vma, vma->vm_flags, tva_flags);
>+
>+	/*
>+	 * If PMD is the only enabled order, enforce max_ptes_none, otherwise
>+	 * scan all pages to populate the bitmap for mTHP collapse.
>+	 */
>+	if (enabled_orders != BIT(HPAGE_PMD_ORDER))
>+		max_ptes_none = KHUGEPAGED_MAX_PTES_LIMIT;
>+
> 	pte = pte_offset_map_lock(mm, pmd, start_addr, &ptl);
> 	if (!pte) {
> 		cc->progress++;
>@@ -1474,11 +1600,13 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> 		goto out;
> 	}
> 
>-	for (addr = start_addr, _pte = pte; _pte < pte + HPAGE_PMD_NR;
>-	     _pte++, addr += PAGE_SIZE) {
>+	for (i = 0; i < HPAGE_PMD_NR; i++) {
>+		_pte = pte + i;
>+		addr = start_addr + i * PAGE_SIZE;
>+		pteval = ptep_get(_pte);
>+
> 		cc->progress++;
> 
>-		pte_t pteval = ptep_get(_pte);
> 		if (pte_none_or_zero(pteval)) {
> 			if (++none_or_zero > max_ptes_none) {
> 				result = SCAN_EXCEED_NONE_PTE;
>@@ -1558,6 +1686,8 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> 			}
> 		}
> 
>+		/* Set bit for occupied pages */
>+		__set_bit(i, cc->mthp_present_ptes);
> 		/*
> 		 * Record which node the original page is from and save this
> 		 * information to cc->node_load[].
>@@ -1616,9 +1746,9 @@ static enum scan_result collapse_scan_pmd(struct mm_struct *mm,
> 	if (result == SCAN_SUCCEED) {
> 		/* collapse_huge_page expects the lock to be dropped before calling */
> 		mmap_read_unlock(mm);
>-		result = collapse_huge_page(mm, start_addr, referenced,
>-					    unmapped, cc, HPAGE_PMD_ORDER);
>-		/* collapse_huge_page will return with the mmap_lock released */
>+		result = mthp_collapse(mm, start_addr, referenced,
>+				       unmapped, cc, enabled_orders);
>+		/* mmap_lock was released above, set lock_dropped */
> 		*lock_dropped = true;
> 	}
> out:
>-- 
>2.54.0
>
>

^ permalink raw reply

* Re: [PATCH v6 05/12] PCI: liveupdate: Keep bus numbers constant during Live Update
From: Pranjal Shrivastava @ 2026-06-06 11:10 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-6-dmatlack@google.com>

On Fri, May 22, 2026 at 08:24:03PM +0000, David Matlack wrote:
> During a Live Update, preserved devices must be allowed to continue
> performing memory transactions so the kernel cannot change the fabric
> topology, including bus numbers, since that would require disabling
> and flushing any memory transactions first.
> 
> To keep bus numbers constant, always inherit the secondary and
> subordinate bus numbers assigned to bridges during scanning, instead of
> assigning new ones, if any PCI devices are being preserved. Note that
> the kernel inherits bus numbers even on bridges without any downstream
> endpoints that were preserved. This avoids accidentally assigning a
> bridge a new window that overlaps with a preserved device that is
> downstream of a different bridge.
> 
> If a bridge is scanned with a broken topology or has no bus numbers
> set during a Live Update, refuse to assign it new bus numbers and refuse
> to enumerate devices below it until the Live Update is finished. This is
> a safety measure to prevent topology conflicts.
> 
> Require that CONFIG_CARDBUS is not enabled to enable
> CONFIG_PCI_LIVEUPDATE since inheriting bus numbers on PCI-to-CardBus
> bridges requires additional work but is not a priority at the moment.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
>  .../admin-guide/kernel-parameters.txt         |  6 +-
>  drivers/pci/Kconfig                           |  2 +-
>  drivers/pci/liveupdate.c                      | 83 ++++++++++++++++++-
>  drivers/pci/liveupdate.h                      | 14 ++++
>  drivers/pci/probe.c                           | 17 +++-
>  include/linux/pci_liveupdate.h                |  4 +
>  6 files changed, 119 insertions(+), 7 deletions(-)
> 

[...]

> +		incoming = pci_liveupdate_flb_get_incoming();
> +		if (!incoming) {
> +			dev->liveupdate.inherit_buses = false;
> +			goto out;
> +		}
> +
> +		/*
> +		 * It is safe to sample incoming->ser->nr_devices and then
> +		 * drop the rwsem since nr_devices will only decrease. Thus the
> +		 * only "race" is that the current scan will be overly
> +		 * conservative and force bus inheritance.
> +		 */
> +		dev->liveupdate.inherit_buses = incoming->ser->nr_devices;

Nit: inherit_buses is a bool, while compiler will handle it correctly,
maybe we could:

dev->liveupdate.inherit_buses = !!incoming->ser->nr_devices 

OR

dev->liveupdate.inherit_buses = (incoming->ser->nr_devices > 0)

for readability?

> +		pci_liveupdate_flb_put_incoming();
> +	}
> +
> +out:
> +	return dev->liveupdate.inherit_buses;
> +}
> +
 
[...]

>  		/*
> @@ -1497,8 +1501,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
>  		 * do in the second pass.
>  		 */
>  		if (!pass) {
> -			if (pcibios_assign_all_busses() || broken)
> -
> +			if (assign_new_buses || broken)
>  				/*
>  				 * Temporarily disable forwarding of the
>  				 * configuration cycles on all bridges in
> @@ -1512,6 +1515,11 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
>  			goto out;
>  		}
>  
> +		if (liveupdate) {
> +			pci_err(dev, "Cannot reconfigure bridge during Live Update, skipping\n");
> +			goto out;
> +		}

Quite helpful! Thanks :)

> +
>  		/* Clear errors */
>  		pci_write_config_word(dev, PCI_STATUS, 0xffff);
>  
> @@ -1572,6 +1580,7 @@ static int pci_scan_bridge_extend(struct pci_bus *bus, struct pci_dev *dev,
>  	pci_write_config_word(dev, PCI_BRIDGE_CONTROL, bctl);
>  
>  	pm_runtime_put(&dev->dev);
> +	pci_liveupdate_scan_bridge_end(dev, pass);
>  
>  	return max;
>  }

With the minor nit above,
Reviewed-by: Pranjal Shrivastava <praan@google.com>

Thanks,
Praan

^ permalink raw reply

* [PATCH] docs/mm: document slab cache isolation with SLAB_NO_MERGE
From: Mohammed EL Kadiri @ 2026-06-06 15:58 UTC (permalink / raw)
  To: Andrew Morton, Vlastimil Babka
  Cc: David Hildenbrand, Lorenzo Stoakes, Jonathan Corbet, Kees Cook,
	linux-mm, linux-doc, linux-hardening, linux-kernel,
	Mohammed EL Kadiri

Add documentation explaining when and how to use SLAB_NO_MERGE to
protect security-critical slab caches from cross-cache heap
exploitation.

The document covers:
- Criteria for identifying caches that need isolation
- How the SLUB merge mechanism works and what prevents merging
- How to verify merge status on a running system
- The cross-cache attack class with CVE reference
- Tradeoffs (memory cost vs security benefit)
- Relationship to CONFIG_RANDOM_KMALLOC_CACHES, SLAB_TYPESAFE_BY_RCU,
  and the slab_nomerge boot parameter

This information was previously undocumented, requiring developers to
read mm/slab_common.c to understand when SLAB_NO_MERGE is appropriate.

Signed-off-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
---
 Documentation/mm/index.rst          |   1 +
 Documentation/mm/slab-isolation.rst | 113 ++++++++++++++++++++++++++++
 2 files changed, 114 insertions(+)
 create mode 100644 Documentation/mm/slab-isolation.rst

diff --git a/Documentation/mm/index.rst b/Documentation/mm/index.rst
index fb45acba16ac..c2d5349dfc34 100644
--- a/Documentation/mm/index.rst
+++ b/Documentation/mm/index.rst
@@ -17,6 +17,7 @@ see the :doc:`admin guide <../admin-guide/mm/index>`.
    page_allocation
    vmalloc
    slab
+   slab-isolation
    highmem
    page_reclaim
    swap
diff --git a/Documentation/mm/slab-isolation.rst b/Documentation/mm/slab-isolation.rst
new file mode 100644
index 000000000000..d51472eb0c95
--- /dev/null
+++ b/Documentation/mm/slab-isolation.rst
@@ -0,0 +1,113 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================================
+Slab Cache Isolation for Security
+==================================
+
+Overview
+========
+
+The SLUB allocator merges slab caches with compatible size, alignment, and
+flags to reduce memory fragmentation. While this improves memory efficiency,
+it allows objects of different types to share the same slab pages. This
+enables cross-cache heap exploitation, where a use-after-free in one object
+type can be leveraged to corrupt an unrelated type.
+
+The `SLAB_NO_MERGE` flag prevents a cache from being merged, ensuring it
+receives dedicated slab pages.
+
+When to use SLAB_NO_MERGE
+==========================
+
+`SLAB_NO_MERGE` should be considered for slab caches that meet the
+following criteria:
+
+1. *Security-critical contents*: The object holds data whose corruption
+   leads directly to privilege escalation or security bypass, such as
+   credentials, cryptographic keys, or capability sets.
+
+2. *Actually mergeable*: The cache must not already be unmergeable.
+   A cache is already unmergeable if any of the following is true:
+
+   - It has a constructor (`ctor` argument is non-NULL).
+   - It has a non-zero `usersize` (with `CONFIG_HARDENED_USERCOPY`).
+   - It already has `SLAB_NO_MERGE` or another `SLAB_NEVER_MERGE` flag.
+
+3. *Bounded allocation volume*: The cache has a predictable number of
+   active objects, so the memory cost of dedicated slab pages is
+   acceptable.
+
+How merging works
+=================
+
+When `kmem_cache_create()` is called:
+
+1. If `usersize` is non-zero, the merge path is skipped entirely.
+
+2. Otherwise, `find_mergeable()` in `mm/slab_common.c` searches for a
+   compatible existing cache. A merge is prevented if:
+
+   - The `slab_nomerge` boot parameter is set
+   - The new cache has a constructor
+   - The new cache's flags include `SLAB_NO_MERGE`
+   - No existing cache has compatible size and flags
+
+3. If a compatible cache is found, the new cache becomes an alias. Both
+   share the same slab pages.
+
+Verifying merge status
+======================
+
+To check whether a cache is merged on a running system::
+
+    # Check how many other caches share its pages
+    cat /sys/kernel/slab/<cache_name>/aliases
+
+    # aliases > 0 means other types share this cache's pages
+
+The cross-cache attack class
+=============================
+
+Cross-cache attacks exploit slab merging to achieve type confusion:
+
+1. Attacker triggers a use-after-free in object type A.
+2. Type A's cache is merged with type B (they share slab pages).
+3. The freed type A slot is reallocated as type B.
+4. Attacker uses the dangling pointer to corrupt type B.
+5. Privilege escalation.
+
+CVE-2022-29582 demonstrates this technique: an io_uring use-after-free is
+exploited via cross-cache page-level reallocation to achieve root.
+
+`SLAB_NO_MERGE` prevents step 2: dedicated pages mean a freed slot of
+one type cannot be reallocated as a different type.
+
+Tradeoffs
+=========
+
+*Memory*: Isolated caches may have partially-filled slab pages that
+cannot be used by other types. For caches with bounded allocation counts,
+this is typically a few extra pages.
+
+*Performance*: Zero impact on `kmem_cache_alloc()` and
+`kmem_cache_free()`. The only effect is at boot when the cache is
+created.
+
+Relationship to other mitigations
+==================================
+
+`CONFIG_RANDOM_KMALLOC_CACHES`
+    Creates 16 copies of each `kmalloc` size class and randomly assigns
+    allocations among them. Only affects `kmalloc()` users. Does not
+    affect named caches created with `kmem_cache_create()`.
+
+`SLAB_TYPESAFE_BY_RCU`
+    Delays freeing the slab page by an RCU grace period. Does not delay
+    object slot reuse. Does not prevent cross-cache merging. Solves a
+    different problem: safe lockless access to freed-and-reallocated
+    objects of the same type.
+
+`slab_nomerge` boot parameter
+    Disables merging for all caches globally. `SLAB_NO_MERGE` provides
+    the same protection selectively for individual caches without the
+    global memory cost.
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH] docs/mm: document slab cache isolation with SLAB_NO_MERGE
From: Jonathan Corbet @ 2026-06-06 16:11 UTC (permalink / raw)
  To: Mohammed EL Kadiri, Andrew Morton, Vlastimil Babka
  Cc: David Hildenbrand, Lorenzo Stoakes, Kees Cook, linux-mm,
	linux-doc, linux-hardening, linux-kernel, Mohammed EL Kadiri
In-Reply-To: <20260606155856.15548-1-med08elkadiri@gmail.com>

Mohammed EL Kadiri <med08elkadiri@gmail.com> writes:

> Add documentation explaining when and how to use SLAB_NO_MERGE to
> protect security-critical slab caches from cross-cache heap
> exploitation.
>
> The document covers:
> - Criteria for identifying caches that need isolation
> - How the SLUB merge mechanism works and what prevents merging
> - How to verify merge status on a running system
> - The cross-cache attack class with CVE reference
> - Tradeoffs (memory cost vs security benefit)
> - Relationship to CONFIG_RANDOM_KMALLOC_CACHES, SLAB_TYPESAFE_BY_RCU,
>   and the slab_nomerge boot parameter
>
> This information was previously undocumented, requiring developers to
> read mm/slab_common.c to understand when SLAB_NO_MERGE is appropriate.
>
> Signed-off-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
> ---
>  Documentation/mm/index.rst          |   1 +
>  Documentation/mm/slab-isolation.rst | 113 ++++++++++++++++++++++++++++
>  2 files changed, 114 insertions(+)
>  create mode 100644 Documentation/mm/slab-isolation.rst

Thank you for working to improve our documentation.

Did you write this with machine assistance?

Please review our documentation and adhere to our markup conventions.
For example, function names should just be function(), with no
additional markup.

Thanks,

jon

^ permalink raw reply

* Re: [PATCH] docs/mm: document slab cache isolation with SLAB_NO_MERGE
From: Mohammed EL Kadiri @ 2026-06-06 17:44 UTC (permalink / raw)
  To: Jonathan Corbet
  Cc: Andrew Morton, Vlastimil Babka, David Hildenbrand,
	Lorenzo Stoakes, Kees Cook, linux-mm, linux-doc, linux-hardening,
	linux-kernel
In-Reply-To: <874ijfvec2.fsf@trenco.lwn.net>

Hi Jonathan,

Thank you for the review.

Yes, I used AI assistance in writing this document. The technical
content reflects my understanding from working on the SLAB_NO_MERGE
patches (one of which was Acked by Vlastimil Babka), but I failed to
follow the documentation markup conventions.

I will fix the markup and resubmit as v2.

Mohammed

^ permalink raw reply

* Re: [PATCH] Document: Fix missing reference pages
From: Ko Han Chen @ 2026-06-06 17:45 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: David S . Miller, Eric Dumazet, Paolo Abeni, Jonathan Corbet,
	Simon Horman, Shuah Khan, netdev, linux-doc, linux-kernel
In-Reply-To: <20260605171401.0586831d@kernel.org>

[-- Attachment #1: Type: text/plain, Size: 1142 bytes --]

On Fri, Jun 05, 2026 at 05:14:01PM -0700, Jakub Kicinski wrote:
> On Fri,  5 Jun 2026 16:41:30 +0800 [Ko Han Chen] wrote:
> > Subject: [PATCH] Document: Fix missing reference pages
> > Date: Fri,  5 Jun 2026 16:41:30 +0800
> > X-Mailer: git-send-email 2.48.1
> > 
> > Today, my friend and I are discussing a wwan driver produced by
> > Mediatek. I am reading the related document and reference link,
> > then I found the page is missing. So after a short search I am
> > giving the better link and test the two pages with my bash
> > program for more dead links. It turns out only this one. I check
> > the page and the following documents. Details are covered in
> > this markdown [page](https://hackmd.io/@Urbaner/lk_patch_doc).
> 
> Nothing really wrong with your commit message, but the narrative
> format is quite unusual. Please rewrite it as if you were telling
> the code base what to do.
> 
> 	Correct the links to ... in ...
> 
> > Signed-off-by: [Ko Han Chen] <urbaner3@gmail.com>
> 
> And please remove the brackets around your name in the Author line and
> the Signed line.
Hi Jakub:

  Thanks for the advice. Updated the patch.

[-- Attachment #2: 0001-Document-Fix-missing-reference-pages.patch --]
[-- Type: text/x-diff, Size: 2057 bytes --]

From 1c11e2d24116cb86ebba6ac1c8463d6efc59c70b Mon Sep 17 00:00:00 2001
From: Ko Han Chen <urbaner3@gmail.com>
Date: Sun, 7 Jun 2026 01:37:42 +0800
Subject: [PATCH] Document: Fix missing reference pages

Fix the first reference link in t7xx and iost pages because the site
reports the content is missing. Replaced it with a page offering the
right content. Tested and confirmed it was the only broken link.

Link: https://hackmd.io/@Urbaner/lk_patch_doc

Signed-off-by: Ko Han Chen <urbaner3@gmail.com>
---
 Documentation/networking/device_drivers/wwan/iosm.rst | 2 +-
 Documentation/networking/device_drivers/wwan/t7xx.rst | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/networking/device_drivers/wwan/iosm.rst b/Documentation/networking/device_drivers/wwan/iosm.rst
index 6f9e955af984..d28a922391ce 100644
--- a/Documentation/networking/device_drivers/wwan/iosm.rst
+++ b/Documentation/networking/device_drivers/wwan/iosm.rst
@@ -84,7 +84,7 @@ session 1.
 References
 ==========
 [1] "MBIM (Mobile Broadband Interface Model) Errata-1"
-      - https://www.usb.org/document-library/
+      - http://usb.org/document-library/mobile-broadband-interface-model-v10-errata-1-and-adopters-agreement
 
 [2] libmbim - "a glib-based library for talking to WWAN modems and
       devices which speak the Mobile Interface Broadband Model (MBIM)
diff --git a/Documentation/networking/device_drivers/wwan/t7xx.rst b/Documentation/networking/device_drivers/wwan/t7xx.rst
index e07de7700dfc..fd532a7e225a 100644
--- a/Documentation/networking/device_drivers/wwan/t7xx.rst
+++ b/Documentation/networking/device_drivers/wwan/t7xx.rst
@@ -187,7 +187,7 @@ References
 ==========
 [1] *MBIM (Mobile Broadband Interface Model) Errata-1*
 
-- https://www.usb.org/document-library/
+- http://usb.org/document-library/mobile-broadband-interface-model-v10-errata-1-and-adopters-agreement
 
 [2] *libmbim "a glib-based library for talking to WWAN modems and devices which
 speak the Mobile Interface Broadband Model (MBIM) protocol"*
-- 
2.48.1


^ permalink raw reply related

* Re: [PATCH v2] Documentation: bug-hunting.rst: fix grammar
From: Randy Dunlap @ 2026-06-06 18:59 UTC (permalink / raw)
  To: Manuel Ebner, Jonathan Corbet, Shuah Khan,
	open list:DOCUMENTATION, open list
In-Reply-To: <20260605190055.15921-2-manuelebner@mailbox.org>



On 6/5/26 12:00 PM, Manuel Ebner wrote:
> Fix a grammar issue to improve readability
> 
> Signed-off-by: Manuel Ebner <manuelebner@mailbox.org>

Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.

> ---
>  Documentation/admin-guide/bug-hunting.rst | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/Documentation/admin-guide/bug-hunting.rst b/Documentation/admin-guide/bug-hunting.rst
> index 3901b43c96df..642bf8474726 100644
> --- a/Documentation/admin-guide/bug-hunting.rst
> +++ b/Documentation/admin-guide/bug-hunting.rst
> @@ -63,8 +63,8 @@ Documentation/admin-guide/tainted-kernels.rst, "being loaded" is
>  annotated with "+", and "being unloaded" is annotated with "-".
>  
>  
> -Where is the Oops message is located?
> --------------------------------------
> +Where is the Oops message located?
> +----------------------------------
>  
>  Normally the Oops text is read from the kernel buffers by klogd and
>  handed to ``syslogd`` which writes it to a syslog file, typically

-- 
~Randy

^ permalink raw reply

* Re: [PATCH 1/1] docs: Fix minor grammatical error
From: Randy Dunlap @ 2026-06-06 19:10 UTC (permalink / raw)
  To: Brigham Campbell, Thorsten Leemhuis, Jonathan Corbet, Shuah Khan,
	open list:DOCUMENTATION REPORTING ISSUES, open list
In-Reply-To: <20260605053826.7836-1-me@brighamcampbell.com>



On 6/4/26 10:38 PM, Brigham Campbell wrote:
> Fix minor grammatical error in the admin guide docs.
> 
> Signed-off-by: Brigham Campbell <me@brighamcampbell.com>
> ---
> 
> I happened across this minor mistake while investigating techniques to
> use a partial kernel config to generate a complete config. If
> maintainers that I don't send out minor fixes like this, please let me
> know and I'll remember that for the future.
> 
>  Documentation/admin-guide/quickly-build-trimmed-linux.rst | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/Documentation/admin-guide/quickly-build-trimmed-linux.rst b/Documentation/admin-guide/quickly-build-trimmed-linux.rst
> index cb178e0a6208..194d22f56449 100644
> --- a/Documentation/admin-guide/quickly-build-trimmed-linux.rst
> +++ b/Documentation/admin-guide/quickly-build-trimmed-linux.rst
> @@ -217,10 +217,10 @@ again.
>  
>     There is a catch: 'localmodconfig' is likely to disable kernel features you
>     did not use since you booted your Linux -- like drivers for currently
> -   disconnected peripherals or a virtualization software not haven't used yet.
> -   You can reduce or nearly eliminate that risk with tricks the reference
> -   section outlines; but when building a kernel just for quick testing purposes
> -   it is often negligible if such features are missing. But you should keep that
> +   disconnected peripherals or virtualization software not currently in use. You
> +   can reduce or nearly eliminate that risk with tricks the reference section
> +   outlines; but when building a kernel just for quick testing purposes it is
> +   often negligible if such features are missing. But you should keep that
>     aspect in mind when using a kernel built with this make target, as it might
>     be the reason why something you only use occasionally stopped working.
>  

Can't you just modify the first line only and leave the other 3 changed lines
intact?

-- 
~Randy


^ permalink raw reply

* Re: [PATCH] docs/mm: document slab cache isolation with SLAB_NO_MERGE
From: Jonathan Corbet @ 2026-06-06 19:36 UTC (permalink / raw)
  To: Mohammed EL Kadiri
  Cc: Andrew Morton, Vlastimil Babka, David Hildenbrand,
	Lorenzo Stoakes, Kees Cook, linux-mm, linux-doc, linux-hardening,
	linux-kernel
In-Reply-To: <20260606174412.4843-1-med08elkadiri@gmail.com>

Mohammed EL Kadiri <med08elkadiri@gmail.com> writes:

> Hi Jonathan,
>
> Thank you for the review.
>
> Yes, I used AI assistance in writing this document.

Please see Documentation/process/coding-assistants.rst for information
on how to document that use.

I would also consider starting to fill out Documentation/mm/slab.rst
rather than creating a new standalone file.

Thanks,

jon

^ permalink raw reply

* Re: [PATCH] docs: memfd_preservation: fix rendering of ABI documentation
From: Randy Dunlap @ 2026-06-06 19:36 UTC (permalink / raw)
  To: Pratyush Yadav, Pasha Tatashin, Mike Rapoport, Andrew Morton,
	David Hildenbrand, Jonathan Corbet, Shuah Khan
  Cc: kexec, linux-kernel, linux-mm, linux-doc
In-Reply-To: <20260605160645.3650271-1-pratyush@kernel.org>



On 6/5/26 9:06 AM, Pratyush Yadav wrote:
> From: "Pratyush Yadav (Google)" <pratyush@kernel.org>
> 
> The "memfd Live Update ABI" section in include/linux/kho/abi/memfd.h
> currently does not render in the exported documentation. This is because
> it should not include the "DOC:" in its reference. Drop it to ensure
> correct rendering. Tested by running make htmldocs.
> 
> Fixes: 15fc11bb2cb6 ("docs: add documentation for memfd preservation via LUO")
> Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org>

Tested-by: Randy Dunlap <rdunlap@infradead.org>
Acked-by: Randy Dunlap <rdunlap@infradead.org>
Thanks.

> ---
> 
> Notes:
>     Mike/Pasha, I reckon this can still go in liveupdate/next. But if you
>     think it is too late, we can probably take it via -rc1 fixes as well.
> 
>  Documentation/mm/memfd_preservation.rst | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/Documentation/mm/memfd_preservation.rst b/Documentation/mm/memfd_preservation.rst
> index a8a5b476afd3..c908a12dffa7 100644
> --- a/Documentation/mm/memfd_preservation.rst
> +++ b/Documentation/mm/memfd_preservation.rst
> @@ -11,7 +11,7 @@ Memfd Preservation ABI
>  ======================
>  
>  .. kernel-doc:: include/linux/kho/abi/memfd.h
> -   :doc: DOC: memfd Live Update ABI
> +   :doc: memfd Live Update ABI
>  
>  .. kernel-doc:: include/linux/kho/abi/memfd.h
>     :internal:
> 
> base-commit: 2935777b418d2bfcbfe96705bb2c0fa6c0d94e18

-- 
~Randy

^ permalink raw reply

* Re: [PATCH] docs/mm: document slab cache isolation with SLAB_NO_MERGE
From: Matthew Wilcox @ 2026-06-06 20:19 UTC (permalink / raw)
  To: Mohammed EL Kadiri
  Cc: Andrew Morton, Vlastimil Babka, David Hildenbrand,
	Lorenzo Stoakes, Jonathan Corbet, Kees Cook, linux-mm, linux-doc,
	linux-hardening, linux-kernel
In-Reply-To: <20260606155856.15548-1-med08elkadiri@gmail.com>

On Sat, Jun 06, 2026 at 04:58:55PM +0100, Mohammed EL Kadiri wrote:
> +The SLUB allocator merges slab caches with compatible size, alignment, and

More of a question for Vlastimil ... do we want to continue to
distinguish between slab (the API) and SLUB (the implementation)?
I don't think we ever want to go back to a situation where we have
multiple competing implementations of the slab API in the kernel.
So shouldn't we deprecate uses of SLUB, particularly in the
documentation?

> +flags to reduce memory fragmentation. While this improves memory efficiency,
> +it allows objects of different types to share the same slab pages. This

s/ pages//

> +enables cross-cache heap exploitation, where a use-after-free in one object
> +type can be leveraged to corrupt an unrelated type.
> +
> +The `SLAB_NO_MERGE` flag prevents a cache from being merged, ensuring it
> +receives dedicated slab pages.

s/slab pages/a dedicated slab/

> +2. *Actually mergeable*: The cache must not already be unmergeable.
> +   A cache is already unmergeable if any of the following is true:
> +
> +   - It has a constructor (`ctor` argument is non-NULL).
> +   - It has a non-zero `usersize` (with `CONFIG_HARDENED_USERCOPY`).
> +   - It already has `SLAB_NO_MERGE` or another `SLAB_NEVER_MERGE` flag.

I don't know if this is good advice for users of the API.  It's true
that the slab will already be unmergable for these other reasons, but
it's harmless to specify SLAB_NO_MERGE in that case.  And it
communicates intent.  And in case somebody removes the ctor in the
future, or we decide to change which flags are in SLAB_NEVER_MERGE,
the slab will still be unmergable.

> +3. *Bounded allocation volume*: The cache has a predictable number of
> +   active objects, so the memory cost of dedicated slab pages is
> +   acceptable.

I don't understand why this is a criteria.

> +How merging works
> +=================
> +
> +When `kmem_cache_create()` is called:
> +
> +1. If `usersize` is non-zero, the merge path is skipped entirely.
> +
> +2. Otherwise, `find_mergeable()` in `mm/slab_common.c` searches for a
> +   compatible existing cache. A merge is prevented if:
> +
> +   - The `slab_nomerge` boot parameter is set
> +   - The new cache has a constructor
> +   - The new cache's flags include `SLAB_NO_MERGE`
> +   - No existing cache has compatible size and flags
> +
> +3. If a compatible cache is found, the new cache becomes an alias. Both
> +   share the same slab pages.

This feels like documenting internals rather than documenting how to use
the flag.  I'd drop it entirely.

> +The cross-cache attack class
> +=============================
> +
> +Cross-cache attacks exploit slab merging to achieve type confusion:
> +
> +1. Attacker triggers a use-after-free in object type A.
> +2. Type A's cache is merged with type B (they share slab pages).
> +3. The freed type A slot is reallocated as type B.
> +4. Attacker uses the dangling pointer to corrupt type B.
> +5. Privilege escalation.
> +
> +CVE-2022-29582 demonstrates this technique: an io_uring use-after-free is
> +exploited via cross-cache page-level reallocation to achieve root.
> +
> +`SLAB_NO_MERGE` prevents step 2: dedicated pages mean a freed slot of
> +one type cannot be reallocated as a different type.

Not sure this section adds anything to what was already described.

> +Tradeoffs
> +=========
> +
> +*Memory*: Isolated caches may have partially-filled slab pages that
> +cannot be used by other types. For caches with bounded allocation counts,
> +this is typically a few extra pages.
> +
> +*Performance*: Zero impact on `kmem_cache_alloc()` and
> +`kmem_cache_free()`. The only effect is at boot when the cache is
> +created.
> +
> +Relationship to other mitigations
> +==================================
> +
> +`CONFIG_RANDOM_KMALLOC_CACHES`
> +    Creates 16 copies of each `kmalloc` size class and randomly assigns
> +    allocations among them. Only affects `kmalloc()` users. Does not
> +    affect named caches created with `kmem_cache_create()`.
> +
> +`SLAB_TYPESAFE_BY_RCU`
> +    Delays freeing the slab page by an RCU grace period. Does not delay
> +    object slot reuse. Does not prevent cross-cache merging. Solves a
> +    different problem: safe lockless access to freed-and-reallocated
> +    objects of the same type.
> +
> +`slab_nomerge` boot parameter
> +    Disables merging for all caches globally. `SLAB_NO_MERGE` provides
> +    the same protection selectively for individual caches without the
> +    global memory cost.

These two sections also feel unnecessary.

^ permalink raw reply

* Re: [PATCH v2 4/4] dt-bindings: input: remove obsolete matrix-keymap.txt
From: Dmitry Torokhov @ 2026-06-06 21:03 UTC (permalink / raw)
  To: Rob Herring (Arm), Lee Jones
  Cc: Akash Sukhavasi, Conor Dooley, David S. Miller, Andrew Lunn,
	linux-tegra, linux-input, Mauro Carvalho Chehab, Heiner Kallweit,
	Thierry Reding, linux-media, Krzysztof Kozlowski, Jakub Kicinski,
	Vladimir Oltean, linux-doc, linux-kernel, Eric Dumazet,
	Jonathan Hunter, Simon Horman, devicetree, Paolo Abeni, netdev,
	Shuah Khan, Russell King, Jonathan Corbet
In-Reply-To: <178052559618.2296868.8781332297681333925.robh@kernel.org>

On Wed, Jun 03, 2026 at 05:26:38PM -0500, Rob Herring (Arm) wrote:
> 
> On Wed, 03 Jun 2026 15:42:21 -0500, Akash Sukhavasi wrote:
> > matrix-keymap.txt has been a single-line redirect to
> > matrix-keymap.yaml since commit 639d6eda3b80 ("dt-bindings: input:
> > Convert matrix-keymap to json-schema"), which introduced the .yaml
> > schema and reduced the .txt to a stub in the same change. The .yaml
> > has the same filename in the same directory, making this redirect
> > unnecessary for discoverability.
> > 
> > Eight instances across six files still reference matrix-keymap.txt,
> > forcing readers through an extra hop to reach the .yaml. The stub has
> > not been touched since June 2020. Update all references across input
> > and mfd binding documentation to point directly to matrix-keymap.yaml
> > and remove the stub.
> > 
> > Signed-off-by: Akash Sukhavasi <akash.sukhavasi@gmail.com>
> > ---
> > v2:
> > - Patch 4/4: corrected commit message (eight references in six files,
> >   not eight files), Sashiko review.
> >   https://sashiko.dev/#/patchset/20260529052246.4934-1-akash.sukhavasi@gmail.com?part=4
> > 
> > v1: https://lore.kernel.org/all/20260529052246.4934-5-akash.sukhavasi@gmail.com/
> > ---
> >  Documentation/devicetree/bindings/input/brcm,bcm-keypad.txt    | 2 +-
> >  Documentation/devicetree/bindings/input/clps711x-keypad.txt    | 2 +-
> >  Documentation/devicetree/bindings/input/matrix-keymap.txt      | 1 -
> >  Documentation/devicetree/bindings/input/nvidia,tegra20-kbc.txt | 2 +-
> >  Documentation/devicetree/bindings/input/pxa27x-keypad.txt      | 2 +-
> >  Documentation/devicetree/bindings/input/st-keyscan.txt         | 2 +-
> >  Documentation/devicetree/bindings/mfd/tc3589x.txt              | 6 +++---
> >  7 files changed, 8 insertions(+), 9 deletions(-)
> > 
> 
> Acked-by: Rob Herring (Arm) <robh@kernel.org>
> 

Lee, could you please ack for MFD piece and I can take it through input?

Thanks.

-- 
Dmitry

^ permalink raw reply

* Re: [PATCH v6 06/12] PCI: liveupdate: Auto-preserve upstream bridges across Live Update
From: Pranjal Shrivastava @ 2026-06-06 22:15 UTC (permalink / raw)
  To: David Matlack
  Cc: kexec, linux-doc, linux-kernel, linux-mm, linux-pci,
	Adithya Jayachandran, Alexander Graf, Alex Williamson,
	Bjorn Helgaas, Chris Li, David Rientjes, Jacob Pan,
	Jason Gunthorpe, Jonathan Corbet, Josh Hilke, Leon Romanovsky,
	Lukas Wunner, Mike Rapoport, Parav Pandit, Pasha Tatashin,
	Pratyush Yadav, Saeed Mahameed, Samiullah Khawaja, Shuah Khan,
	Vipin Sharma, William Tu, Yi Liu
In-Reply-To: <20260522202410.3104264-7-dmatlack@google.com>

On Fri, May 22, 2026 at 08:24:04PM +0000, David Matlack wrote:
> When a PCI device is preserved across a Live Update, all of its upstream
> bridges up to the root port must also be preserved. This enables the PCI
> core and any drivers bound to the bridges to manage bridges correctly
> across a Live Update.
> 
> Notably, this will be used in subsequent commits to ensure that
> preserved devices can continue performing memory transactions without a
> disruption or change in routing.
> 
> To preserve bridges, the PCI core tracks the number of downstream
> devices preserved under each bridge using a reference count in struct
> pci_dev_ser. This allows a bridge to remain preserved until all its
> downstream preserved devices are unpreserved or finish their
> participation in the Live Update.
> 
> Signed-off-by: David Matlack <dmatlack@google.com>
> ---
>  drivers/pci/liveupdate.c    | 136 +++++++++++++++++++++++++++++++-----
>  include/linux/kho/abi/pci.h |   5 +-
>  2 files changed, 122 insertions(+), 19 deletions(-)
> 

[...]

> +
> +#define for_each_pci_dev_in_path(_d, _start, _end) \
> +	for ((_d) = (_start); (_d) != (_end); (_d) = (_d)->bus->self)
> +
> +static void __pci_liveupdate_unpreserve_path(struct pci_ser *ser,
> +					     struct pci_dev *start,
> +					     struct pci_dev *end)
> +{
> +	struct pci_dev *dev;
> +
> +	for_each_pci_dev_in_path(dev, start, end) {
> +		if (pci_liveupdate_unpreserve_device(ser, dev))

I might be reading this wrong but are we leaking some upstream devs if 
an intermediate node fails?

			  EP0
			/
Assume we have: RC -> B1 -> B2 
				\
				 EP1

and EP0 & EP1 were preserved successfully.

And then we try unpreserving EP1, we follow:

unpreserve EP1 -> unpreserve B2 failed due to a corruption.

This aborts the loop, skipping B1 and RC completely?
Their refcounts remain elevated, effectively leaking them as preserved 
state permanently? (i.e. if we unpreserve EP0 after this, B1 & RC will
still get preserved).

> +			return;
> +	}
> +}
> +
> +static void pci_liveupdate_unpreserve_path(struct pci_ser *ser,
> +					   struct pci_dev *start)
> +{
> +	__pci_liveupdate_unpreserve_path(ser, start, /*end=*/NULL);
> +}
> +
> +static int pci_liveupdate_preserve_path(struct pci_ser *ser,
> +					struct pci_dev *start)
> +{
> +	struct pci_dev *dev;
> +	int ret;
> +
> +	for_each_pci_dev_in_path(dev, start, NULL) {
> +		ret = pci_liveupdate_preserve_device(ser, dev);
> +		if (ret) {
> +			__pci_liveupdate_unpreserve_path(ser, start, dev);
> +			return ret;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
>  /**
>   * pci_liveupdate_preserve() - Preserve a PCI device across Live Update
>   * @dev: The PCI device to preserve.
> @@ -321,6 +403,9 @@ static int pci_liveupdate_preserve_device(struct pci_ser *ser, struct pci_dev *d
>   * pci_liveupdate_preserve() from their struct liveupdate_file_handler
>   * preserve() callback to ensure the outgoing struct pci_ser is already set up.
>   *
> + * pci_liveupdate_preserve() automatically preserves all bridges upstream of
> + * @dev.
> + *
>   * Returns: 0 on success, <0 on failure.
>   */
>  int pci_liveupdate_preserve(struct pci_dev *dev)
> @@ -336,7 +421,7 @@ int pci_liveupdate_preserve(struct pci_dev *dev)
>  	if (IS_ERR(ser))
>  		return PTR_ERR(ser);
>  
> -	return pci_liveupdate_preserve_device(ser, dev);
> +	return pci_liveupdate_preserve_path(ser, dev);

Minor nit: I might be too nitpicky here (and it's NOT a strong opinion)
but naming it pci_liveupdate_preserve_path_for_dev() reads better to me.

>  }
>  EXPORT_SYMBOL_GPL(pci_liveupdate_preserve);
>  

[...]

Thanks,
Praan

^ permalink raw reply

* Re: [PATCH v2 4/7] seg6: add End.M.GTP6.D behavior
From: Andrea Mayer @ 2026-06-07  0:05 UTC (permalink / raw)
  To: Yuya Kusakabe
  Cc: David S. Miller, Eric Dumazet, David Ahern, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Justin Iurman, Shuah Khan,
	Jonathan Corbet, Shuah Khan, linux-kernel, netdev,
	linux-kselftest, linux-doc, stefano.salsano, ahabdels,
	Andrea Mayer, andrea
In-Reply-To: <20260505-seg6-mobile-v2-4-9e8022bdfdb6@gmail.com>

On Tue, 05 May 2026 01:30:14 +0900
Yuya Kusakabe <yuya.kusakabe@gmail.com> wrote:

Hi Yuya,

I do not repeat below the points from my cover letter and patch 1-3 replies
(drop reasons, OIF/VRF removal, C helper, coding style, etc.).

> Add the End.M.GTP6.D headend behavior (RFC 9433 Section 6.3), which
> receives an IPv6/UDP/GTP-U packet matching a locally instantiated
> End.M.GTP6.D SID and re-encapsulates the inner T-PDU in SRv6 using
> the configured SR Policy.  TEID and QFI are folded into the 40-bit
> Args.Mob.Session field defined by RFC 9433 Section 6.1.
>
> RFC 9433 Section 6.3 Step S08 specifies "Write in the SRH[0] the
> Args.Mob.Session" for a single-SID SR Policy.  When the SR Policy
> contains more segments, the augmented SRH must reserve a leading
> slot for the original outer destination D so that the downstream
> End.M.GTP6.E (which Section 6.5 requires to sit at the penultimate
> SID and Step S01 instructs to "Copy SRH[0] and D to buffer memory")
> can rebuild the GTP-U tunnel.  Args.Mob.Session is therefore stamped
> into segments[1] (the End.M.GTP6.E SID's locator-relative tail).
>
> The augmented SRH (slwt->srh + one extra leading slot) is built
> once at build_state time and reused on every packet.
>
> The new SEG6_LOCAL_MOBILE_SR_PREFIX_LEN attribute carries the
> locator length used by the remote End.M.GTP6.E SID; it is required
> because the SR Gateway has no way to discover the remote SID's
> prefix length from the FIB on its own.
>
> When net.netfilter.nf_hooks_lwtunnel=1, the inner T-PDU traverses
> NF_INET_PRE_ROUTING between the GTP-U strip and the SRv6 push,
> mirroring End.DX4 / End.DX6.
>
> Inbound GTP-U packets are classified by message type (3GPP TS
> 29.281 Section 5.1).  Only T-PDU (type 255) is encapsulated into
> SRv6.  Any other GTP-U message (Echo Request/Response, Error
> Indication, ...) is forwarded unchanged via the lwtunnel's saved
> orig_input so that a downstream peer that owns the GTP-U control
> plane can process it.
>
> Configuration:
>
>   ip -6 route add 2001:db8:f::/64 \
>       encap seg6local action End.M.GTP6.D \
>           srh segs 2001:db8:2::e \
>           src 2001:db8:2::1 \

The "src" attribute is used verbatim here as the outer IPv6 source address,
same as patch 3. The src dual-semantics overload flagged in the patch 3
reply applies here too.

>           sr_prefix_len 64 \
>       dev <dev>
>

Thank you for the follow-up in the cover letter thread. The finish callback
writes orig_dst into SRH[0] and Args.Mob.Session into SRH[1]. As far as I
can see, this matches neither Section 6.3 (Args.Mob.Session in SRH[0], no
D) nor Section 6.4 (D in SRH[0], no Args.Mob).

The comments below apply regardless of which section the behavior
ends up implementing.

> Link: https://www.rfc-editor.org/rfc/rfc9433.html#section-6.3
> Signed-off-by: Yuya Kusakabe <yuya.kusakabe@gmail.com>
> ---
>  include/uapi/linux/seg6_local.h                    |   3 +
>  net/ipv6/seg6_local.c                              | 512 +++++++++++++++++++++
>  tools/testing/selftests/net/Makefile               |   1 +
>  .../selftests/net/srv6_end_m_gtp6_d_test.sh        | 497 ++++++++++++++++++++
>  4 files changed, 1013 insertions(+)
>
> diff --git a/include/uapi/linux/seg6_local.h b/include/uapi/linux/seg6_local.h
> index 8e46ede2980d..7d3d3d245b47 100644
> --- a/include/uapi/linux/seg6_local.h
> +++ b/include/uapi/linux/seg6_local.h
> @@ -33,6 +33,7 @@ enum {
>  	SEG6_LOCAL_MOBILE_V4_MASK_LEN,
>  	SEG6_LOCAL_MOBILE_PDU_TYPE,
>  	SEG6_LOCAL_MOBILE_V6_SRC_PREFIX_LEN,
> +	SEG6_LOCAL_MOBILE_SR_PREFIX_LEN,
>  	__SEG6_LOCAL_MAX,
>  };
>  #define SEG6_LOCAL_MAX (__SEG6_LOCAL_MAX - 1)
> @@ -77,6 +78,8 @@ enum {
>  	SEG6_LOCAL_ACTION_END_M_GTP4_E	= 18,
>  	/* SRv6 to IPv6/GTP-U encap (RFC 9433 Section 6.5) */
>  	SEG6_LOCAL_ACTION_END_M_GTP6_E	= 19,
> +	/* IPv6/GTP-U decap into SRv6 (RFC 9433 Section 6.3) */
> +	SEG6_LOCAL_ACTION_END_M_GTP6_D	= 20,
>
>  	__SEG6_LOCAL_ACTION_MAX,
>  };
> diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
> index 4e5d138c3657..09e912e17df8 100644
> --- a/net/ipv6/seg6_local.c
> +++ b/net/ipv6/seg6_local.c

> + [snip]
>
> +/* Parse the GTP-U header at @skb offset @gtp_off.  Pulls each
> + * additional region (long header, extension chain) into the linear
> + * area as it walks; on success returns the total header length to
> + * consume (mandatory + optional + extension headers), or a negative
> + * errno on failure.
> + *
> + * Returns -EOPNOTSUPP if the packet is a well-formed GTPv1-U header
> + * that this code path does not consume itself (any non-T-PDU message
> + * such as Echo Request / Error Indication).  Callers pass such packets
> + * through to the configured forwarding path via
> + * seg6_mobile_passthrough_non_tpdu().
> + *
> + * Returns -EINVAL when the GTP-U header is structurally malformed
> + * (truncated extension chain, ext_units == 0, etc.).  Callers should
> + * drop those.
> + *
> + * On success, *@teid is set to the GTP-U TEID and *@qfi is set to the
> + * QFI found in a PDU Session extension header, or 0 if none is present.
> + *
> + * Callers must re-derive any pointers into @skb->data after this
> + * function returns: pskb_may_pull() may have reallocated skb->head.
> + */
> +static int seg6_mobile_parse_gtpu(struct sk_buff *skb, unsigned int gtp_off,
> +				  u32 *teid, u8 *qfi)
> +{
> +	const struct gtp1_header *gtph;
> +	const struct gtp1_header_long *gtphl;
> +	const u8 *gtp;
> +	unsigned int hdrlen;
> +	u8 flags, next;

Same reverse Christmas tree as patch 2; same issue in the other functions
introduced by this patch.

gtp is only used as a cast intermediary. Could it be inlined?

> +
> +	if (!pskb_may_pull(skb, gtp_off + sizeof(*gtph)))
> +		return -EINVAL;
> +	gtp = skb->data + gtp_off;
> +	gtph = (const struct gtp1_header *)gtp;
> +	flags = gtph->flags;
> +
> +	/* Accept only GTPv1-U T-PDU (3GPP TS 29.281 Section 5.1).  Other
> +	 * GTPv1-U message types (Echo Request/Response, Error Indication,
> +	 * ...) are dispatched separately by the caller.
> +	 */
> +	if ((flags & ~GTP1_F_MASK) != SEG6_MOBILE_GTP1U_FLAGS_BASE)
> +		return -EOPNOTSUPP;
> +	if (gtph->type != GTP_TPDU)
> +		return -EOPNOTSUPP;
> +
> +	*teid = ntohl(gtph->tid);
> +	*qfi = 0;
> +
> +	if (!(flags & (GTP1_F_EXTHDR | GTP1_F_SEQ | GTP1_F_NPDU)))
> +		return sizeof(*gtph);
> +
> +	if (!pskb_may_pull(skb, gtp_off + sizeof(*gtphl)))
> +		return -EINVAL;
> +	gtp = skb->data + gtp_off;
> +	gtphl = (const struct gtp1_header_long *)gtp;
> +	hdrlen = sizeof(*gtphl);
> +
> +	if (!(flags & GTP1_F_EXTHDR))
> +		return hdrlen;

Nit: gtphl and hdrlen are assigned before the GTP1_F_EXTHDR check. On the
path where the E flag is not set, gtphl is unused. Moving the gtphl
assignment after the check would make the flow clearer.

> +
> +	next = gtphl->next;
> +	while (next != 0) {
> +		unsigned int ext_units, ext_bytes;
> +		const u8 *ext;

Maybe ext could be renamed to ext_hdr? It would be easier to distinguish
from ext_units and ext_bytes.

> +
> +		if (!pskb_may_pull(skb, gtp_off + hdrlen + 1))
> +			return -EINVAL;
> +		ext = skb->data + gtp_off + hdrlen;
> +		ext_units = ext[0];
> +		if (ext_units == 0)
> +			return -EINVAL;
> +
> +		ext_bytes = ext_units * 4;
> +		if (!pskb_may_pull(skb, gtp_off + hdrlen + ext_bytes))
> +			return -EINVAL;
> +		ext = skb->data + gtp_off + hdrlen;

ext_units is only used to derive ext_bytes. A single ext_len would
remove the intermediate variable.

> +
> +		if (next == SEG6_MOBILE_PDU_SESSION_NH) {
> +			/* 3GPP TS 38.415: the PDU Session extension header
> +			 * is exactly 4 bytes long.
> +			 */
> +			if (ext_bytes != 4)
> +				return -EINVAL;
> +			*qfi = ext[2] & SEG6_MOBILE_PDU_SESSION_QFI_MASK;
> +		}

If the extension chain contains more than one PDU Session Container, *qfi
is silently overwritten. Is that intentional, or should the function reject
a duplicate?

> +
> +		next = ext[ext_bytes - 1];

ext[ext_bytes - 1] reads the Next Extension Header Type field from the last
byte of the current extension. Would a short comment help the reader?

> +		hdrlen += ext_bytes;
> +	}
> +
> +	return hdrlen;
> +}

> + [snip]

> +static int seg6_mobile_passthrough_non_tpdu(struct sk_buff *skb)
> +{
> +	struct dst_entry *dst = skb_dst(skb);
> +
> +	if (dst && dst->lwtstate && dst->lwtstate->orig_input)
> +		return dst->lwtstate->orig_input(skb);
> +
> +	kfree_skb_reason(skb, SKB_DROP_REASON_SEG6_MOBILE_BAD_GTPU);

input_action_end_m_gtp6_d() does not change skb_dst(skb) before this call,
so dst and lwtstate are the same ones the caller already dereferenced. When
can this NULL check trigger?

> +	return -EINVAL;
> +}

> + [snip]

> +static int input_action_end_m_gtp6_d_finish(struct net *net,
> +					    struct sock *sk,
> +					    struct sk_buff *skb)
> +{
> +	struct seg6_mobile_gtp6_d_cb cb = *SEG6_MOBILE_GTP6_D_CB(skb);
> +	struct dst_entry *orig_dst = skb_dst(skb);
> +	enum skb_drop_reason reason;
> +	const struct seg6_mobile_info *minfo;
> +	struct seg6_local_lwt *slwt;
> +	struct ipv6_sr_hdr *new_srh;
> +	int inner_proto;
> +	int err;
> +
> +	slwt = seg6_local_lwtunnel(orig_dst->lwtstate);
> +	minfo = &slwt->mobile_info;

Same dst/lwtstate issue as patch 2. Not introduced by this patch.

> +
> +	inner_proto = (skb->protocol == htons(ETH_P_IP)) ? IPPROTO_IPIP
> +							 : IPPROTO_IPV6;
> +
> +	err = seg6_do_srh_encap(skb, minfo->aug_srh, inner_proto);

Same missing iptunnel_handle_offloads() as patch 2.

> +	if (err) {
> +		reason = (err == -ENOMEM) ? SKB_DROP_REASON_SEG6_MOBILE_NOMEM
> +					  : SKB_DROP_REASON_SEG6_MOBILE_BAD_INNER;

Same BAD_INNER misuse as patch 2. seg6_do_srh_encap() can also fail from
seg6_push_hmac(), which is an HMAC error on the new SRH, not an inner-T-PDU
problem.

> +		goto drop;
> +	}
> +
> +	skb->protocol = htons(ETH_P_IPV6);
> +
> +	new_srh = (struct ipv6_sr_hdr *)(skb_network_header(skb) +
> +					 sizeof(struct ipv6hdr));
> +	new_srh->segments[0] = cb.orig_dst;
> +	if (seg6_mobile_write_args_mob(&new_srh->segments[1],
> +				       minfo->sr_prefix_len, cb.args_mob)) {
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_SID;
> +		goto drop;
> +	}
> +
> +	ipv6_hdr(skb)->saddr = minfo->src_addr;
> +
> +	/* seg6_do_srh_encap() copied segments[first_segment] to the outer
> +	 * DA before Args.Mob.Session was stamped; refresh it.
> +	 */
> +	ipv6_hdr(skb)->daddr = new_srh->segments[new_srh->first_segment];

As noted at the top of this reply, segments[0] = orig_dst and
segments[1] = Args.Mob.Session matches neither Section 6.3 nor Section 6.4.

segments[0], segments[1], saddr, and daddr are written after
seg6_do_srh_encap() already called skb_postpush_rcsum(). skb->csum can
be stale. Same for any later change to the outer header or SRH.

HMAC, if configured, is computed on non-final SRH and saddr, hence invalid.

> +
> +	skb_set_transport_header(skb, sizeof(struct ipv6hdr));
> +	nf_reset_ct(skb);
> +	skb_dst_drop(skb);
> +
> +	seg6_lookup_any_nexthop(skb, NULL, 0, false, slwt->oif);
> +	return dst_input(skb);
> +
> +drop:
> +	kfree_skb_reason(skb, reason);
> +	return -EINVAL;
> +}

Same redundant skb_dst_drop() as patch 3.

> +
> +/* RFC 9433 Section 6.3 -- End.M.GTP6.D
> + * Receives an IPv6/UDP/GTP-U packet matching a locally instantiated
> + * End.M.GTP6.D SID and re-encapsulates the inner T-PDU in SRv6 using
> + * the configured SR Policy.  TEID and QFI are folded into
> + * Args.Mob.Session.  Per RFC 9433 Section 6.5 ("End.M.GTP6.E SID MUST
> + * always be the penultimate SID"), Args.Mob.Session is encoded into
> + * segments[1] of the new SRH (the penultimate SID at the egress UPF)
> + * while segments[0] holds the original outer DA so that the egress
> + * has a real GTP-U destination after End.M.GTP6.E decap.
> + *
> + * When net.netfilter.nf_hooks_lwtunnel=1 the inner T-PDU is exposed
> + * to NF_INET_PRE_ROUTING after the GTP-U strip and before the SRv6
> + * push, mirroring End.DX4 / End.DX6.  This lets nftables / conntrack
> + * apply policy on the inner 5-tuple at the SR Gateway.
> + */
> +static int input_action_end_m_gtp6_d(struct sk_buff *skb,
> +				     struct seg6_local_lwt *slwt)
> +{
> +	unsigned int outer_len, inner_off;
> +	int gtp_hdrlen, inner_proto, inner_nfproto;
> +	struct in6_addr orig_dst;
> +	u8 inner_first, qfi;
> +	struct ipv6_sr_hdr *srh;
> +	struct ipv6hdr *ip6h;
> +	struct udphdr *uh;
> +	u64 args_mob;
> +	u32 teid;
> +	enum skb_drop_reason reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_GTPU;

The initializer on reason is dead. Every goto drop path sets reason
explicitly before the jump. The variable can be left uninitialized here.

> +
> +	BUILD_BUG_ON(sizeof(struct seg6_mobile_gtp6_d_cb) >
> +		     sizeof_field(struct sk_buff, cb));
> +
> +	/* RFC 9433 Section 6.3 SRH-S01: drop if outer SRH carries
> +	 * SegmentsLeft != 0
> +	 */
> +	srh = seg6_get_srh(skb, 0);
> +	if (srh && srh->segments_left != 0) {
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_INVALID_SRH_SL;
> +		goto drop;
> +	}

Same SRH validation concerns as patch 1. HMAC is not validated here.

> +
> +	if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) {
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_INNER;
> +		goto drop;
> +	}

Same BAD_INNER misuse as patch 2: this is pulling the outer IPv6 header,
not the inner T-PDU.

> +
> +	ip6h = ipv6_hdr(skb);
> +	orig_dst = ip6h->daddr;
> +
> +	/* RFC 9433 Section 6.3 upper-layer S01-S11: dispatch on
> +	 * (NH == UDP && UDP dport == GTP-U); otherwise delegate to the
> +	 * regular End behaviour (S10-S11).
> +	 */
> +	{

The anonymous { } block scopes three variables that should be declared at
function top. Splitting into smaller helpers would make this easier to
follow.

> +		__be16 frag_off;
> +		u8 nh = ip6h->nexthdr;
> +		int upper_off;
> +
> +		upper_off = ipv6_skip_exthdr(skb, sizeof(*ip6h), &nh,
> +					     &frag_off);
> +		if (upper_off < 0) {
> +			/* Outer IPv6 ext-header walk failed; the GTP-U
> +			 * envelope below it is unreachable.
> +			 */
> +			reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_GTPU;
> +			goto drop;
> +		}

Same missing frag_off check as patch 2.

> +
> +		if (nh != IPPROTO_UDP)
> +			return input_action_end(skb, slwt);
> +
> +		if (!pskb_may_pull(skb, upper_off + sizeof(*uh))) {
> +			reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_GTPU;
> +			goto drop;
> +		}
> +
> +		ip6h = ipv6_hdr(skb);
> +		uh = (struct udphdr *)((u8 *)ip6h + upper_off);
> +		if (uh->dest != htons(GTP1U_PORT))
> +			return input_action_end(skb, slwt);

Limitation note for both input_action_end() calls above: correct per RFC
9433 Section 6.3 S10-S11, but the SRH is absent or SL == 0 here, so
input_action_end() will always drop without signaling non-GTP-U traffic.
Perhaps you meant to drop directly with BAD_GTPU?

> +
> +		gtp_hdrlen = seg6_mobile_parse_gtpu(skb,
> +						    upper_off + sizeof(*uh),
> +						    &teid, &qfi);
> +		if (gtp_hdrlen == -EOPNOTSUPP)
> +			return seg6_mobile_passthrough_non_tpdu(skb);
> +		if (gtp_hdrlen < 0) {
> +			reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_GTPU;
> +			goto drop;
> +		}
> +
> +		outer_len = upper_off + sizeof(*uh) + gtp_hdrlen;
> +	}
> +
> +	args_mob = seg6_mobile_args_from_teid_qfi(teid, qfi);
> +
> +	if (!pskb_may_pull(skb, outer_len + 1)) {
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_INNER;
> +		goto drop;
> +	}
> +
> +	inner_off = outer_len;
> +	inner_first = *((u8 *)skb->data + inner_off);
> +	switch (inner_first >> 4) {

Nit: inner_first could be an inner_ver with the shift done at assignment.
The name would say what the variable holds.

> +	case 4:
> +		inner_proto = IPPROTO_IPIP;
> +		inner_nfproto = NFPROTO_IPV4;
> +		break;
> +	case 6:
> +		inner_proto = IPPROTO_IPV6;
> +		inner_nfproto = NFPROTO_IPV6;
> +		break;
> +	default:
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_INNER;
> +		goto drop;
> +	}
> +
> +	if (!pskb_may_pull(skb, outer_len +
> +			   ((inner_proto == IPPROTO_IPIP) ?
> +			    sizeof(struct iphdr) : sizeof(struct ipv6hdr)))) {
> +		reason = SKB_DROP_REASON_SEG6_MOBILE_BAD_INNER;
> +		goto drop;
> +	}
> +
> +	skb_pull_rcsum(skb, outer_len);
> +	skb_reset_network_header(skb);
> +
> +	/* Set skb->protocol to match the inner header so that the
> +	 * NF_INET_PRE_ROUTING hook (and seg6_do_srh_encap() inside
> +	 * the finish half) see a coherent IPv4/IPv6 packet.
> +	 */
> +	skb->protocol = (inner_proto == IPPROTO_IPIP) ? htons(ETH_P_IP)
> +						      : htons(ETH_P_IPV6);
> +
> +	skb_set_transport_header(skb,
> +				 (inner_proto == IPPROTO_IPIP) ?
> +				 sizeof(struct iphdr) :
> +				 sizeof(struct ipv6hdr));

Same repeated size-selection ternary as patch 2.

> +	nf_reset_ct(skb);
> +
> +	SEG6_MOBILE_GTP6_D_CB(skb)->args_mob = args_mob;
> +	SEG6_MOBILE_GTP6_D_CB(skb)->orig_dst = orig_dst;
> +
> +	if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
> +		return NF_HOOK(inner_nfproto, NF_INET_PRE_ROUTING,
> +			       dev_net(skb->dev), NULL, skb, skb->dev,
> +			       NULL, input_action_end_m_gtp6_d_finish);
> +
> +	return input_action_end_m_gtp6_d_finish(dev_net(skb->dev), NULL, skb);
> +
> +drop:
> +	kfree_skb_reason(skb, reason);
> +	return -EINVAL;
> +}

> +
> +/* Shared between End.M.GTP6.D and End.M.GTP6.D.Di -- both
> + * prepend a single leading slot to the user-configured SRH to leave
> + * room for the original outer DA at SRH[0].  End.M.GTP6.D writes
> + * Args.Mob.Session into segments[1] at runtime; End.M.GTP6.D.Di
> + * leaves segments[1+] as the user provided them.
> + */
> +static int seg6_end_m_gtp6_d_aug_build(struct seg6_local_lwt *slwt,
> +				       const void *cfg,
> +				       struct netlink_ext_ack *extack)
> +{
> +	struct ipv6_sr_hdr *aug;
> +	int orig_len, aug_len;
> +
> +	if (!slwt->srh) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "End.M.GTP6.D{,.Di} requires srh segs");
> +		return -EINVAL;
> +	}

The "{,.Di}" shell brace notation is unusual. Emitting the actual
behavior name (End.M.GTP6.D or End.M.GTP6.D.Di) would be clearer.
Same applies wherever this notation appears in the patchset.

> +
> +	/* The augmented SRH adds one extra leading slot, so its hdrlen
> +	 * field (u8) must still fit the +2-segment-equivalent encoding.
> +	 * Reject pathological srh inputs at setup time so that no
> +	 * silent overflow can produce an undersized aug->hdrlen and a
> +	 * subsequent OOB read in seg6_do_srh_encap().
> +	 */
> +	if (slwt->srh->hdrlen > 253) {
> +		NL_SET_ERR_MSG_MOD(extack,
> +				   "End.M.GTP6.D{,.Di} srh too large to augment (max 126 segments)");
> +		return -EINVAL;
> +	}
> +
> +	orig_len = (slwt->srh->hdrlen + 1) << 3;
> +	aug_len = orig_len + sizeof(struct in6_addr);
> +
> +	aug = kzalloc(aug_len, GFP_KERNEL);
> +	if (!aug)
> +		return -ENOMEM;
> +
> +	memcpy(aug, slwt->srh, sizeof(*aug));
> +	aug->hdrlen = (aug_len >> 3) - 1;
> +	aug->segments_left = slwt->srh->segments_left + 1;
> +	aug->first_segment = slwt->srh->first_segment + 1;
> +	/* segments[0] left zero; data path stamps the original outer
> +	 * DA into the in-skb copy after seg6_do_srh_encap().
> +	 */
> +	memcpy(&aug->segments[1], &slwt->srh->segments[0],
> +	       orig_len - sizeof(*aug));
> +
> +	slwt->mobile_info.aug_srh = aug;
> +	return 0;
> +}

> + [snip]

Thanks,

Ciao,
Andrea

P.S. I am temporarily writing from another address due to a mail
delivery issue at my @uniroma2.it address. Please always Cc my default
andrea.mayer@uniroma2.it address on replies.

^ permalink raw reply

* Re: [RFC PATCH v2 01/10] liveupdate: luo_file: Add internal APIs for file preservation
From: tarunsahu @ 2026-06-07  0:35 UTC (permalink / raw)
  To: Jonathan Corbet, vannapurve, fvdl, Pasha Tatashin, Shuah Khan,
	sagis, aneesh.kumar, skhawaja, vipinsh, ackerleytng,
	Pratyush Yadav, david, dmatlack, mark.rutland, Paolo Bonzini,
	Mike Rapoport, Alexander Graf, seanjc, axelrasmussen
  Cc: linux-kselftest, kexec, linux-kernel, linux-doc, kvm, linux-mm
In-Reply-To: <c054ba0fb2639932bbe354420d3f4f84cce84905.1780676742.git.tarunsahu@google.com>


Hi,

I am sorry for incorrect layout of this series. After copy-pasting
I forgot to change the message id in header and the cover letter is not
attached to the same thread.

Please find the V2 cover letter here:
https://lore.kernel.org/all/cover.1780667929.git.tarunsahu@google.com/

Also for latest discussion related to scope:
https://lore.kernel.org/all/9huzldcrxkch.fsf@tarunix.c.googlers.com/

Thankyou

Tarun Sahu <tarunsahu@google.com> writes:

> From: Pasha Tatashin <pasha.tatashin@soleen.com>
>
> The core liveupdate mechanism allows userspace to preserve file
> descriptors. However, kernel subsystems often manage struct file
> objects directly and need to participate in the preservation process
> programmatically without relying solely on userspace interaction.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> Signed-off-by: Samiullah Khawaja <skhawaja@google.com>
> Signed-off-by: Tarun Sahu <tarunsahu@google.com>
> ---
>  include/linux/liveupdate.h       | 21 ++++++++++
>  kernel/liveupdate/luo_file.c     | 69 ++++++++++++++++++++++++++++++++
>  kernel/liveupdate/luo_internal.h | 17 ++++++++
>  3 files changed, 107 insertions(+)
>
> diff --git a/include/linux/liveupdate.h b/include/linux/liveupdate.h
> index 30c5a39ff9e9..de052438eaac 100644
> --- a/include/linux/liveupdate.h
> +++ b/include/linux/liveupdate.h
> @@ -24,6 +24,7 @@ struct file;
>  /**
>   * struct liveupdate_file_op_args - Arguments for file operation callbacks.
>   * @handler:          The file handler being called.
> + * @session:          The session this file belongs to.
>   * @retrieve_status:  The retrieve status for the 'can_finish / finish'
>   *                    operation. A value of 0 means the retrieve has not been
>   *                    attempted, a positive value means the retrieve was
> @@ -44,6 +45,7 @@ struct file;
>   */
>  struct liveupdate_file_op_args {
>  	struct liveupdate_file_handler *handler;
> +	struct liveupdate_session *session;
>  	int retrieve_status;
>  	struct file *file;
>  	u64 serialized_data;
> @@ -240,6 +242,13 @@ void liveupdate_unregister_flb(struct liveupdate_file_handler *fh,
>  
>  int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp);
>  int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp);
> +/* kernel can internally retrieve files */
> +int liveupdate_get_file_incoming(struct liveupdate_session *s, u64 token,
> +				 struct file **filep);
> +
> +/* Get a token for an outgoing file, or -ENOENT if file is not preserved */
> +int liveupdate_get_token_outgoing(struct liveupdate_session *s,
> +				  struct file *file, u64 *tokenp);
>  
>  #else /* CONFIG_LIVEUPDATE */
>  
> @@ -285,5 +294,17 @@ static inline int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb,
>  	return -EOPNOTSUPP;
>  }
>  
> +static inline int liveupdate_get_file_incoming(struct liveupdate_session *s,
> +					       u64 token, struct file **filep)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
> +static inline int liveupdate_get_token_outgoing(struct liveupdate_session *s,
> +						struct file *file, u64 *tokenp)
> +{
> +	return -EOPNOTSUPP;
> +}
> +
>  #endif /* CONFIG_LIVEUPDATE */
>  #endif /* _LINUX_LIVEUPDATE_H */
> diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
> index a0a419085e28..0aa0b4e5339f 100644
> --- a/kernel/liveupdate/luo_file.c
> +++ b/kernel/liveupdate/luo_file.c
> @@ -323,6 +323,7 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
>  	mutex_init(&luo_file->mutex);
>  
>  	args.handler = fh;
> +	args.session = luo_session_from_file_set(file_set);
>  	args.file = file;
>  	err = fh->ops->preserve(&args);
>  	if (err)
> @@ -380,6 +381,7 @@ void luo_file_unpreserve_files(struct luo_file_set *file_set)
>  					   struct luo_file, list);
>  
>  		args.handler = luo_file->fh;
> +		args.session = luo_session_from_file_set(file_set);
>  		args.file = luo_file->file;
>  		args.serialized_data = luo_file->serialized_data;
>  		args.private_data = luo_file->private_data;
> @@ -411,6 +413,7 @@ static int luo_file_freeze_one(struct luo_file_set *file_set,
>  		struct liveupdate_file_op_args args = {0};
>  
>  		args.handler = luo_file->fh;
> +		args.session = luo_session_from_file_set(file_set);
>  		args.file = luo_file->file;
>  		args.serialized_data = luo_file->serialized_data;
>  		args.private_data = luo_file->private_data;
> @@ -432,6 +435,7 @@ static void luo_file_unfreeze_one(struct luo_file_set *file_set,
>  		struct liveupdate_file_op_args args = {0};
>  
>  		args.handler = luo_file->fh;
> +		args.session = luo_session_from_file_set(file_set);
>  		args.file = luo_file->file;
>  		args.serialized_data = luo_file->serialized_data;
>  		args.private_data = luo_file->private_data;
> @@ -621,6 +625,7 @@ int luo_retrieve_file(struct luo_file_set *file_set, u64 token,
>  	}
>  
>  	args.handler = luo_file->fh;
> +	args.session = luo_session_from_file_set(file_set);
>  	args.serialized_data = luo_file->serialized_data;
>  	err = luo_file->fh->ops->retrieve(&args);
>  	if (err) {
> @@ -654,6 +659,7 @@ static int luo_file_can_finish_one(struct luo_file_set *file_set,
>  		struct liveupdate_file_op_args args = {0};
>  
>  		args.handler = luo_file->fh;
> +		args.session = luo_session_from_file_set(file_set);
>  		args.file = luo_file->file;
>  		args.serialized_data = luo_file->serialized_data;
>  		args.retrieve_status = luo_file->retrieve_status;
> @@ -671,6 +677,7 @@ static void luo_file_finish_one(struct luo_file_set *file_set,
>  	guard(mutex)(&luo_file->mutex);
>  
>  	args.handler = luo_file->fh;
> +	args.session = luo_session_from_file_set(file_set);
>  	args.file = luo_file->file;
>  	args.serialized_data = luo_file->serialized_data;
>  	args.retrieve_status = luo_file->retrieve_status;
> @@ -924,3 +931,65 @@ void liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
>  	luo_flb_unregister_all(fh);
>  	list_del(&ACCESS_PRIVATE(fh, list));
>  }
> +EXPORT_SYMBOL_GPL(liveupdate_unregister_file_handler);
> +
> +/**
> + * liveupdate_get_token_outgoing - Get the token for a preserved file.
> + * @s:      The outgoing liveupdate session.
> + * @file:   The file object to search for.
> + * @tokenp: Output parameter for the found token.
> + *
> + * Searches the list of preserved files in an outgoing session for a matching
> + * file object. If found, the corresponding user-provided token is returned.
> + *
> + * This function is intended for in-kernel callers that need to correlate a
> + * file with its liveupdate token.
> + *
> + * Context: It must be called with session mutex acquired.
> + * Return: 0 on success, -ENOENT if the file is not preserved in this session.
> + */
> +int liveupdate_get_token_outgoing(struct liveupdate_session *s,
> +				  struct file *file, u64 *tokenp)
> +{
> +	struct luo_file_set *file_set = luo_file_set_from_session_locked(s);
> +	struct luo_file *luo_file;
> +	int err = -ENOENT;
> +
> +	list_for_each_entry(luo_file, &file_set->files_list, list) {
> +		if (luo_file->file == file) {
> +			if (tokenp)
> +				*tokenp = luo_file->token;
> +			err = 0;
> +			break;
> +		}
> +	}
> +
> +	return err;
> +}
> +
> +/**
> + * liveupdate_get_file_incoming - Retrieves a preserved file for in-kernel use.
> + * @s:      The incoming liveupdate session (restored from the previous kernel).
> + * @token:  The unique token identifying the file to retrieve.
> + * @filep:  On success, this will be populated with a pointer to the retrieved
> + *          'struct file'.
> + *
> + * Provides a kernel-internal API for other subsystems to retrieve their
> + * preserved files after a live update. This function is a simple wrapper
> + * around luo_retrieve_file(), allowing callers to find a file by its token.
> + *
> + * The caller receives a new reference to the file and must call fput() when it
> + * is no longer needed. The file's lifetime is managed by LUO and any userspace
> + * file descriptors. If the caller needs to hold a reference to the file beyond
> + * the immediate scope, it must call get_file() itself.
> + *
> + * Context: It must be called with session mutex acquired of a restored session.
> + * Return: 0 on success. Returns -ENOENT if no file with the matching token is
> + *         found, or any other negative errno on failure.
> + */
> +int liveupdate_get_file_incoming(struct liveupdate_session *s, u64 token,
> +				 struct file **filep)
> +{
> +	return luo_retrieve_file(luo_file_set_from_session_locked(s),
> +				 token, filep);
> +}
> diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
> index 875844d7a41d..08b198802e7f 100644
> --- a/kernel/liveupdate/luo_internal.h
> +++ b/kernel/liveupdate/luo_internal.h
> @@ -79,6 +79,23 @@ struct luo_session {
>  
>  extern struct rw_semaphore luo_register_rwlock;
>  
> +static inline struct liveupdate_session *luo_session_from_file_set(struct luo_file_set *file_set)
> +{
> +	struct luo_session *session;
> +
> +	session = container_of(file_set, struct luo_session, file_set);
> +
> +	return (struct liveupdate_session *)session;
> +}
> +
> +static inline struct luo_file_set *luo_file_set_from_session_locked(struct liveupdate_session *s)
> +{
> +	struct luo_session *session = (struct luo_session *)s;
> +
> +	lockdep_assert_held(&session->mutex);
> +	return &session->file_set;
> +}
> +
>  int luo_session_create(const char *name, struct file **filep);
>  int luo_session_retrieve(const char *name, struct file **filep);
>  int __init luo_session_setup_outgoing(void *fdt);
> -- 
> 2.54.0.1032.g2f8565e1d1-goog

^ permalink raw reply

* Re: [PATCH RESEND] riscv: enable HAVE_CMPXCHG_{DOUBLE,LOCAL}
From: Paul Walmsley @ 2026-06-07  0:50 UTC (permalink / raw)
  To: Miquel Sabaté Solà
  Cc: linux-riscv, corbet, skhan, pjw, palmer, alex, linux-doc,
	linux-kernel
In-Reply-To: <20260605141247.253315-1-mssola@mssola.com>

[-- Attachment #1: Type: text/plain, Size: 2180 bytes --]

Hi,

On Fri, 5 Jun 2026, Miquel Sabaté Solà wrote:

> Support for atomic Compare-And-Swap instructions has been in the RISC-V
> port of the Linux kernel for a long time. That being said, we apparently
> never bothered to set HAVE_CMPXCHG_DOUBLE and HAVE_CMPXCHG_LOCAL in the
> Kconfig, despite having all the framework to support them.
> 
> Signed-off-by: Miquel Sabaté Solà <mssola@mssola.com>
> ---
> This is a resend of [1], rebased on top of the latest commit from the
> for-next branch.
> 
> I have built this patch with multiple configurations and ran it with KVM
> (the VisionFive2 board that I have lacks the needed extensions). All seems
> to work, but I do wonder if we did not enable these for a reason or this
> just slipped through. So far in the code I believe everything is in place,
> and I haven't seen any commit in the git log stating otherwise.
> 
> [1] https://lore.kernel.org/all/20260220074449.8526-1-mssola@mssola.com/

Thanks for the patch.  Your comments above are why I've been hesitant to 
merge it.  I'm not aware of any publicly available hardware that supports 
Zacas/Zabha.  No one has stepped forward to provide any Tested-by:s on 
hardware that hasn't been released yet.  You mention that you tested on 
your VisionFive2 board, but it would not have exercised those code paths.

Of course, we already have Zacas/Zabha support, merged back in 2024, in 
cmpxchg.h.  I assume (?) that it was tested in QEMU, but I don't see any 
comments about that in the patch series.  No one sent any Tested-by:s 
then, either.

It would be good if you (and ideally others) could put this patch through 
some testing on QEMU with Zacas and Zabha enabled, before we merge it.  
The affected code paths for HAVE_CMPXCHG_LOCAL seem to primarily involve 
per-CPU counters and MM zone counters, so those would be the areas to 
focus.  HAVE_CMPXCHG_DOUBLE seems to do nothing useful other than 
preventing the AMD IOMMU driver from being selected if it's not present, 
so that part of the patch seems fairly useless.  In fact I'd suggest 
dropping that from the patch and just sending a separate patch to remove 
HAVE_CMPXCHG_DOUBLE from the kernel completely.


- Paul

^ permalink raw reply

* Re: [PATCH] docs: memfd_preservation: fix rendering of ABI documentation
From: Mike Rapoport @ 2026-06-07  5:40 UTC (permalink / raw)
  To: Pasha Tatashin, Andrew Morton, David Hildenbrand, Jonathan Corbet,
	Shuah Khan, Pratyush Yadav
  Cc: kexec, linux-kernel, linux-mm, linux-doc
In-Reply-To: <20260605160645.3650271-1-pratyush@kernel.org>

On Fri, 05 Jun 2026 18:06:44 +0200, Pratyush Yadav wrote:
> docs: memfd_preservation: fix rendering of ABI documentation

Applied to next branch of liveupdate/linux.git tree, thanks!

[1/1] docs: memfd_preservation: fix rendering of ABI documentation
      commit: 3a358c78093f98a70d84c934b7054f636bc846f2

tree: https://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux
branch: next

--
Sincerely yours,
Mike.



^ permalink raw reply

* Re: [PATCH net-next v4 16/16] Documentation: networking: Add timestamp related APIs to OA TC6 framework
From: Randy Dunlap @ 2026-06-07  5:49 UTC (permalink / raw)
  To: Selvamani.Rajagopal, Andrew Lunn, Piergiorgio Beruto,
	Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Andrew Lunn, Parthiban Veerasooran,
	Richard Cochran, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan
  Cc: netdev, linux-kernel, devicetree, linux-doc, Jerry Ray
In-Reply-To: <20260605-s2500-mac-phy-support-v4-16-de0fbc13c6d8@onsemi.com>

Hi,
These needs a few additional blank lines to avoid docs build warnings:

Documentation/networking/oa-tc6-framework.rst:554: WARNING: Explicit markup ends without a blank line; unexpected unindent. [docutils]
Documentation/networking/oa-tc6-framework.rst:561: WARNING: Explicit markup ends without a blank line; unexpected unindent. [docutils]
Documentation/networking/oa-tc6-framework.rst:566: WARNING: Explicit markup ends without a blank line; unexpected unindent. [docutils]
Documentation/networking/oa-tc6-framework.rst:573: WARNING: Explicit markup ends without a blank line; unexpected unindent. [docutils]

See below.


On 6/5/26 10:42 PM, Selvamani Rajagopal via B4 Relay wrote:
> From: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> 
> Added new APIs to support hardware timestamp feature as defined in
> OPEN Alliance 10BASE-T1x MAC-PHY serial interface specification.
> 
> Signed-off-by: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> ---
>  Documentation/networking/oa-tc6-framework.rst | 76 +++++++++++++++++++++++++++
>  1 file changed, 76 insertions(+)
> 
> diff --git a/Documentation/networking/oa-tc6-framework.rst b/Documentation/networking/oa-tc6-framework.rst
> index fe2aabde923a..694d9485b1c5 100644
> --- a/Documentation/networking/oa-tc6-framework.rst
> +++ b/Documentation/networking/oa-tc6-framework.rst
> @@ -153,6 +153,10 @@ OPEN Alliance TC6 Framework
>  - Forwards the received Ethernet frame from 10Base-T1x MAC-PHY to n/w
>    subsystem.
>  
> +- If supported by the hardware and enabled, updates hardware timestamp
> +  in skb, when indicated by one of the three timestamp capture registers
> +  through TSC fields of the header.
> +
>  Data Transaction
>  ~~~~~~~~~~~~~~~~
>  
> @@ -495,3 +499,75 @@ the MAC-PHY.
>  Zero align receive frame feature can be enabled to align all receive ethernet
>  frames data to start at the beginning of any receive data chunk payload with a
>  start word offset (SWO) of zero.
> +
> +.. c:function:: int oa_tc6_ptp_register(struct oa_tc6 *tc6, \
> +                                        struct ptp_clock_info *info);
> +
> +Registers the PTP hardware clock related functions with the kernel.
> +This API simply registers. Initialization of the fields in the
> +ptp_clock_info structure are left to the vendor as programming hardware
> +timer is expected to be vendor dependent. The fields max_adj, owner,
> +and all the functions for the clock operations, like adjfine, gettimex64,
> +settime64, adjtime are expected to be initialized in the structure before
> +calling the registering the hardware clock.
> +
> +.. c:function:: void oa_tc6_ptp_unregister(struct oa_tc6 *tc6);
> +
> +Unregisters the PTP hardware clock related callbacks.
> +
> +.. c:function:: int oa_tc6_ioctl(struct oa_tc6 *tc6, struct ifreq *rq, \
> +                                 int cmd);
> +
> +ioctl interface to handle hardware timestamp and PHY related commands.
> +
> +.. c:function:: int oa_tc6_get_ts_info(struct oa_tc6 *tc6, \
> +                                       struct kernel_ethtool_ts_info *info);
> +
> +Provides timestamp related settings that are supported to ethtool.
> +
> +.. c:function:: void oa_tc6_hwtstamp_get(struct oa_tc6 *tc6, \
> +                                         struct kernel_hwtstamp_config *cfg);
> +
> +Returns hardware timestamp configuration. Part of net_device_ops callbacks.
> +
> +.. c:function:: void oa_tc6_get_ts_stats(struct oa_tc6 *tc6, \
> +                                         struct ethtool_ts_stats *ts_stats);
> +
> +Provides hardware timestamp related traffic statistics for ethtool.
> +
> +.. c:function:: int oa_tc6_hwtstamp_set(struct oa_tc6 *tc6, \
> +                                         struct kernel_hwtstamp_config *cfg);
> +
> +Helper to set hardware timestamp configuration. Part of net_device_ops
> +callbacks.
> +
> +.. c:function:: void oa_tc6_set_vend1_mms(struct oa_tc6 *tc6, int mms);
> +
> +Helper to map MDIO_MMD_VEND1 command to vendor specific Memory Map Select
> +(MMS) value. This function offers flexibility for vendors that may have
> +used any MMS value between 10 and 15 as allowed by the specification.
> +MDIO_MMD_VEND2 is already mapped to MMS4 in the OA TC6 frame work code.
> +
> +.. c:function:: int oa_tc6_write_registers_mms(struct oa_tc6 *tc6, \
> +                                               u16 address, u16 mms, \
> +                                               u32 value[], u8 length);

Insert blank line here.

> +Writing multiple consecutive registers starting from @address for the
> +given @mms memory map selector in the MAC-PHY. Maximum of 128 consecutive
> +registers can be written starting at @address.
> +
> +.. c:function:: int oa_tc6_write_register_mms(struct oa_tc6 *tc6, \
> +                                              u16 address, u16 mms, \
> +                                              u32 value);

and here.

> +Write a single register addressed by @address and @mms in the MAC-PHY.
> +
> +.. c:function:: int oa_tc6_read_registers_mms(struct oa_tc6 *tc6, \
> +                                              u16 address, u16 mms, \
> +                                              u32 value[], u8 length);
and here.

> +Reading multiple consecutive registers starting from @address for the
> +given @mms memory map selector value, in the MAC-PHY. Maximum of 128
> +consecutive registers can be read starting at @address.
> +
> +.. c:function:: int oa_tc6_read_register_mms(struct oa_tc6 *tc6, \
> +                                             u16 address, u16 mms, \
> +                                             u32 *value);

and here.

> +Read a single register addressed by @address and @mms in the MAC-PHY.
> 

-- 
~Randy


^ permalink raw reply

* Re: [PATCH net-next v4 13/16] onsemi: s2500: Add driver support for TS2500 MAC-PHY
From: Randy Dunlap @ 2026-06-07  5:56 UTC (permalink / raw)
  To: Selvamani.Rajagopal, Andrew Lunn, Piergiorgio Beruto,
	Heiner Kallweit, Russell King, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Andrew Lunn, Parthiban Veerasooran,
	Richard Cochran, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
	Simon Horman, Jonathan Corbet, Shuah Khan
  Cc: netdev, linux-kernel, devicetree, linux-doc, Jerry Ray
In-Reply-To: <20260605-s2500-mac-phy-support-v4-13-de0fbc13c6d8@onsemi.com>



On 6/5/26 10:42 PM, Selvamani Rajagopal via B4 Relay wrote:
> From: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> 
> Support for onsemi's S2500, 802.3 cg compliant Ethernet
> transceiver with integrated MAC-PHY. Works with
> Open Alliance TC6 framework.
> 
> adjtime callback is implemented using adjfine. If time
> delta is too big, bigger than 1 second, using adjtime
> would take long to reduce the delta. In those cases,
> settime callback is used to reduce the delta. Once delta
> becomes less than a second, it uses adjfine to reduce
> the drift further.
> 
> Signed-off-by: Selvamani Rajagopal <Selvamani.Rajagopal@onsemi.com>
> ---
>  MAINTAINERS                                       |   7 +
>  drivers/net/ethernet/oa_tc6/oa_tc6_std_def.h      |   2 +-
>  drivers/net/ethernet/onsemi/Kconfig               |  21 +
>  drivers/net/ethernet/onsemi/Makefile              |   7 +
>  drivers/net/ethernet/onsemi/s2500/Kconfig         |  21 +
>  drivers/net/ethernet/onsemi/s2500/Makefile        |   7 +
>  drivers/net/ethernet/onsemi/s2500/s2500_ethtool.c | 347 ++++++++++++
>  drivers/net/ethernet/onsemi/s2500/s2500_hw_def.h  | 225 ++++++++
>  drivers/net/ethernet/onsemi/s2500/s2500_main.c    | 632 ++++++++++++++++++++++
>  drivers/net/ethernet/onsemi/s2500/s2500_ptp.c     | 233 ++++++++
>  10 files changed, 1501 insertions(+), 1 deletion(-)
> 

> diff --git a/drivers/net/ethernet/onsemi/Kconfig b/drivers/net/ethernet/onsemi/Kconfig
> new file mode 100644
> index 000000000000..8dd3a3f074a2
> --- /dev/null
> +++ b/drivers/net/ethernet/onsemi/Kconfig
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# onsemi network device configuration
> +#
> +
> +config NET_VENDOR_ONSEMI
> +	bool "onsemi network devices"
> +	help
> +	  If you have a network card belonging to this class, say Y.
> +
> +	  Note that the answer to this question doesn't directly affect the
> +	  kernel: saying N will just cause the configurator to skip all
> +	  the questions about onsemi ethernet devices. If you say Y, you
> +          will be asked for your specific card in the following questions.

Above line should be indented with one tab + spaces.

> +
> +if NET_VENDOR_ONSEMI
> +
> +source "drivers/net/ethernet/onsemi/s2500/Kconfig"
> +
> +endif # NET_VENDOR_ONSEMI
> +


> diff --git a/drivers/net/ethernet/onsemi/s2500/Kconfig b/drivers/net/ethernet/onsemi/s2500/Kconfig
> new file mode 100644
> index 000000000000..22b0afad7a21
> --- /dev/null
> +++ b/drivers/net/ethernet/onsemi/s2500/Kconfig
> @@ -0,0 +1,21 @@
> +# SPDX-License-Identifier: GPL-2.0-only
> +#
> +# onsemi S2500 Driver Support
> +#
> +
> +if NET_VENDOR_ONSEMI
> +
> +config S2500_MACPHY
> +	help
> +	tristate "S2500 support"
> +	depends on SPI
> +	select NCN26000_PHY
> +	select OA_TC6
> +	  Support for the onsemi TS2500 MACPHY Ethernet chip.
> +          It works under the framework that conform to OPEN Alliance
> +          10BASE-T1x Serial Interface specification.
> +
> +          To compile this driver as a module, choose M here. The module will be
> +          called s2500.

Kconfig help text should be indented with one tab + 2 spaces (applies to
all lines following the "Support for the ..." line).

> +
> +endif # NET_VENDOR_ONSEMI
> diff --git a/drivers/net/ethernet/onsemi/s2500/s2500_ptp.c b/drivers/net/ethernet/onsemi/s2500/s2500_ptp.c
> new file mode 100644
> index 000000000000..fd6617c7ac79
> --- /dev/null
> +++ b/drivers/net/ethernet/onsemi/s2500/s2500_ptp.c


> +static int s2500_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
> +{
> +	struct s2500_info *priv = container_of(ptp, struct s2500_info,
> +					       ptp_clock_info);
> +	u32 sign_bit = 0;
> +	long adj;
> +	u32 val;
> +	u64 ppm;
> +
> +	if (scaled_ppm < 0) {
> +		/* split sign / mod */
> +		sign_bit = 1U << 31;
> +		scaled_ppm = ~scaled_ppm + 1;
> +	}
> +
> +	/**

Use	/*
since this is not a kernel-doc comment.

> +	 * Convert unsigned scaled_ppm to atto-seconds per clock cycles.
> +	 * The scaled_ppm format is Qx.16 --> 1 lsb = 1/65536 ppm.
> +	 * The clock period of the S2500 is 8ns (125 MHz), so 1 lsb of
> +	 * adj register LSB is 1 atto-sec / 8ns = 0.000125 ppm.
> +	 * Represented in Qx.16 format, this is 0.000125 * 2^16 = 8(.192)
> +	 * To convert scaled_ppm into a register value we need to divide
> +	 * it by the LSB value, hence adj = (scaled_ppm * 1000) / 8192 to
> +	 * minimize the precision loss due to the integer arithmetic.
> +	 * That further reduces to (scaled_ppm * 125) / 1024.
> +	 */
> +	ppm = (u64)scaled_ppm * 125;
> +	do_div(ppm, 1024);
> +	adj = (long)ppm;
> +
> +	/* check overflow */
> +	if (adj >= (1L << 28))
> +		return -ERANGE;
> +
> +	val = (u32)adj | sign_bit;
> +	return oa_tc6_write_register_mms(priv->tc6, S2500_REG_VS_PTP_ADJ,
> +					 OA_TC6_PHY_C45_VS_MMS12, val);
> +}


-- 
~Randy


^ permalink raw reply

* [PATCH] ata: pata_legacy: remove documentation for removed module parameters
From: Ethan Nelson-Moore @ 2026-06-07  6:40 UTC (permalink / raw)
  To: linux-doc
  Cc: Ethan Nelson-Moore, stable, Jonathan Corbet, Shuah Khan,
	Damien Le Moal

Commit 3c4d783f6922 ("ata: pata_legacy: remove VLB support") removed
several module parameters from the pata_legacy driver, but neglected to
remove their documentation. Remove it.

Fixes: 3c4d783f6922 ("ata: pata_legacy: remove VLB support")
Cc: stable@vger.kernel.org # 7.0+
Signed-off-by: Ethan Nelson-Moore <enelsonmoore@gmail.com>
---
 .../admin-guide/kernel-parameters.txt         | 37 -------------------
 1 file changed, 37 deletions(-)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 97007f4f69d4..47bccc148a54 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4935,18 +4935,6 @@ Kernel parameters
 			Set to non-zero if a chip is present that snoops speed
 			changes.  Disabled by default.
 
-	pata_legacy.ht6560a=	[HW,LIBATA]
-			Format: <int>
-			Set to 1, 2, or 3 for HT 6560A on the primary channel,
-			the secondary channel, or both channels respectively.
-			Disabled by default.
-
-	pata_legacy.ht6560b=	[HW,LIBATA]
-			Format: <int>
-			Set to 1, 2, or 3 for HT 6560B on the primary channel,
-			the secondary channel, or both channels respectively.
-			Disabled by default.
-
 	pata_legacy.iordy_mask=	[HW,LIBATA]
 			Format: <int>
 			IORDY enable mask.  Set individual bits to allow IORDY
@@ -4959,18 +4947,6 @@ Kernel parameters
 			with the sequence.  By default IORDY is allowed across
 			all channels.
 
-	pata_legacy.opti82c46x=	[HW,LIBATA]
-			Format: <int>
-			Set to 1, 2, or 3 for Opti 82c611A on the primary
-			channel, the secondary channel, or both channels
-			respectively.  Disabled by default.
-
-	pata_legacy.opti82c611a=	[HW,LIBATA]
-			Format: <int>
-			Set to 1, 2, or 3 for Opti 82c465MV on the primary
-			channel, the secondary channel, or both channels
-			respectively.  Disabled by default.
-
 	pata_legacy.pio_mask=	[HW,LIBATA]
 			Format: <int>
 			PIO mode mask for autospeed devices.  Set individual
@@ -4994,19 +4970,6 @@ Kernel parameters
 			the first port in the list above (0x1f0), and so on.
 			By default all supported ports are probed.
 
-	pata_legacy.qdi=	[HW,LIBATA]
-			Format: <int>
-			Set to non-zero to probe QDI controllers.  By default
-			set to 1 if CONFIG_PATA_QDI_MODULE, 0 otherwise.
-
-	pata_legacy.winbond=	[HW,LIBATA]
-			Format: <int>
-			Set to non-zero to probe Winbond controllers.  Use
-			the standard I/O port (0x130) if 1, otherwise the
-			value given is the I/O port to use (typically 0x1b0).
-			By default set to 1 if CONFIG_PATA_WINBOND_VLB_MODULE,
-			0 otherwise.
-
 	pata_platform.pio_mask=	[HW,LIBATA]
 			Format: <int>
 			Supported PIO mode mask.  Set individual bits to allow
-- 
2.43.0


^ permalink raw reply related

* [PATCH v2] docs/mm/slab: document cache isolation with SLAB_NO_MERGE
From: Mohammed EL Kadiri @ 2026-06-07  7:06 UTC (permalink / raw)
  To: Jonathan Corbet, Andrew Morton
  Cc: Vlastimil Babka, Matthew Wilcox, David Hildenbrand,
	Lorenzo Stoakes, Kees Cook, linux-mm, linux-doc, linux-hardening,
	linux-kernel, Mohammed EL Kadiri
In-Reply-To: <20260606155856.15548-1-med08elkadiri@gmail.com>

Add documentation to slab.rst explaining when and how to use
SLAB_NO_MERGE to protect security-critical slab caches from
cross-cache heap exploitation.

The document covers:
- When to use SLAB_NO_MERGE and what it communicates
- How to verify merge status on a running system
- Tradeoffs (memory cost vs performance)
- Relationship to CONFIG_RANDOM_KMALLOC_CACHES, SLAB_TYPESAFE_BY_RCU,
  and the slab_nomerge boot parameter

Assisted-by: Claude:claude-opus-4.6
Signed-off-by: Mohammed EL Kadiri <med08elkadiri@gmail.com>
---
Changes in v2 (per Jonathan Corbet and Matthew Wilcox feedback):
- Add content to existing slab.rst instead of creating new file
- Fix markup: use plain function() without additional formatting
- Use slab terminology consistently, not SLUB
- Remove How merging works section (implementation internals)
- Remove cross-cache attack class section (redundant)
- Remove Bounded allocation volume criteria
- Rephrase unmergeability guidance per Matthew Wilcox suggestion
- Add Assisted-by tag per coding-assistants.rst
 Documentation/mm/slab.rst | 60 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+)

diff --git a/Documentation/mm/slab.rst b/Documentation/mm/slab.rst
index 2bcc58ada302..c485bd257c44 100644
--- a/Documentation/mm/slab.rst
+++ b/Documentation/mm/slab.rst
@@ -4,6 +4,66 @@
 Slab Allocation
 ===============
 
+Cache isolation with SLAB_NO_MERGE
+===================================
+
+The slab allocator merges caches with compatible size, alignment, and flags
+to reduce memory fragmentation. While this improves memory efficiency, it
+allows objects of different types to share the same slab. This enables
+cross-cache heap exploitation, where a use-after-free in one object type can
+be leveraged to corrupt an unrelated type.
+
+SLAB_NO_MERGE prevents a cache from being merged, ensuring it receives a
+dedicated slab. A freed slot in an isolated cache can only be reallocated as
+the same object type.
+
+When to use SLAB_NO_MERGE
+--------------------------
+
+SLAB_NO_MERGE should be considered for caches holding security-critical
+objects whose corruption leads directly to privilege escalation, such as
+credentials, cryptographic keys, or capability sets.
+
+It is harmless to specify SLAB_NO_MERGE even if the cache is already
+unmergeable for other reasons (e.g., it has a constructor or a non-zero
+usersize). The flag communicates intent and ensures the cache remains
+isolated if those other properties change in the future.
+
+Verifying merge status
+-----------------------
+
+To check whether a cache is merged on a running system::
+
+    # Check how many other caches share its slab
+    cat /sys/kernel/slab/<cache_name>/aliases
+
+    # aliases > 0 means other types share this cache's slab
+
+Tradeoffs
+----------
+
+**Memory**: Isolated caches may have partially-filled slabs that cannot be
+used by other types. The overhead is typically a few extra pages.
+
+**Performance**: Zero impact on kmem_cache_alloc() and kmem_cache_free().
+The only effect is at boot when the cache is created.
+
+Relationship to other mitigations
+----------------------------------
+
+CONFIG_RANDOM_KMALLOC_CACHES creates multiple copies of each kmalloc size
+class and randomly assigns allocations among them. It only affects kmalloc()
+users and does not affect named caches created with kmem_cache_create().
+
+SLAB_TYPESAFE_BY_RCU delays freeing the slab by an RCU grace period. It
+does not delay object slot reuse and does not prevent cross-cache merging.
+It solves a different problem: safe lockless access to freed-and-reallocated
+objects of the same type.
+
+The slab_nomerge boot parameter disables merging for all caches globally.
+SLAB_NO_MERGE provides the same protection selectively for individual caches
+without the global memory cost.
+
 Functions and structures
 ========================
 
-- 
2.43.0


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox