* [PATCH 06/12] mm: update secretmem to use VMA flags on mmap_prepare
From: Lorenzo Stoakes @ 2026-01-19 14:48 UTC (permalink / raw)
To: Andrew Morton
Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
Reinette Chatre, Dave Martin, James Morse, Babu Moger,
Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
ntfs3, devel, linux-xfs, keyrings, linux-security-module,
Jason Gunthorpe
In-Reply-To: <cover.1768834061.git.lorenzo.stoakes@oracle.com>
This patch updates secretmem to use the new vma_flags_t type which will
soon supersede vm_flags_t altogether.
In order to make this change we also have to update mlock_future_ok(), we
replace the vm_flags_t parameter with a simple boolean is_vma_locked one,
which also simplifies the invocation here.
This is laying the groundwork for eliminating the vm_flags_t in
vm_area_desc and more broadly throughout the kernel.
No functional changes intended.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
mm/internal.h | 2 +-
mm/mmap.c | 8 ++++----
mm/mremap.c | 2 +-
mm/secretmem.c | 7 +++----
mm/vma.c | 2 +-
5 files changed, 10 insertions(+), 11 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index 27509a909915..da78f187412c 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -1044,7 +1044,7 @@ extern long populate_vma_page_range(struct vm_area_struct *vma,
unsigned long start, unsigned long end, int *locked);
extern long faultin_page_range(struct mm_struct *mm, unsigned long start,
unsigned long end, bool write, int *locked);
-bool mlock_future_ok(const struct mm_struct *mm, vm_flags_t vm_flags,
+bool mlock_future_ok(const struct mm_struct *mm, bool is_vma_locked,
unsigned long bytes);
/*
diff --git a/mm/mmap.c b/mm/mmap.c
index 35d11f08005d..d7a5b44fd6e0 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -225,12 +225,12 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
return hint;
}
-bool mlock_future_ok(const struct mm_struct *mm, vm_flags_t vm_flags,
- unsigned long bytes)
+bool mlock_future_ok(const struct mm_struct *mm, bool is_vma_locked,
+ unsigned long bytes)
{
unsigned long locked_pages, limit_pages;
- if (!(vm_flags & VM_LOCKED) || capable(CAP_IPC_LOCK))
+ if (!is_vma_locked || capable(CAP_IPC_LOCK))
return true;
locked_pages = bytes >> PAGE_SHIFT;
@@ -416,7 +416,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
if (!can_do_mlock())
return -EPERM;
- if (!mlock_future_ok(mm, vm_flags, len))
+ if (!mlock_future_ok(mm, vm_flags & VM_LOCKED, len))
return -EAGAIN;
if (file) {
diff --git a/mm/mremap.c b/mm/mremap.c
index 8391ae17de64..2be876a70cc0 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1740,7 +1740,7 @@ static int check_prep_vma(struct vma_remap_struct *vrm)
if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP))
return -EFAULT;
- if (!mlock_future_ok(mm, vma->vm_flags, vrm->delta))
+ if (!mlock_future_ok(mm, vma->vm_flags & VM_LOCKED, vrm->delta))
return -EAGAIN;
if (!may_expand_vm(mm, vma->vm_flags, vrm->delta >> PAGE_SHIFT))
diff --git a/mm/secretmem.c b/mm/secretmem.c
index edf111e0a1bb..11a779c812a7 100644
--- a/mm/secretmem.c
+++ b/mm/secretmem.c
@@ -122,13 +122,12 @@ static int secretmem_mmap_prepare(struct vm_area_desc *desc)
{
const unsigned long len = vma_desc_size(desc);
- if ((desc->vm_flags & (VM_SHARED | VM_MAYSHARE)) == 0)
+ if (!vma_desc_test_flags(desc, VMA_SHARED_BIT, VMA_MAYSHARE_BIT))
return -EINVAL;
- if (!mlock_future_ok(desc->mm, desc->vm_flags | VM_LOCKED, len))
+ vma_desc_set_flags(desc, VMA_LOCKED_BIT, VMA_DONTDUMP_BIT);
+ if (!mlock_future_ok(desc->mm, /*is_vma_locked=*/ true, len))
return -EAGAIN;
-
- desc->vm_flags |= VM_LOCKED | VM_DONTDUMP;
desc->vm_ops = &secretmem_vm_ops;
return 0;
diff --git a/mm/vma.c b/mm/vma.c
index 3dbe414eff89..8f1ea5c66cb9 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -3049,7 +3049,7 @@ static int acct_stack_growth(struct vm_area_struct *vma,
return -ENOMEM;
/* mlock limit tests */
- if (!mlock_future_ok(mm, vma->vm_flags, grow << PAGE_SHIFT))
+ if (!mlock_future_ok(mm, vma->vm_flags & VM_LOCKED, grow << PAGE_SHIFT))
return -ENOMEM;
/* Check to ensure the stack will not grow into a hugetlb-only region */
--
2.52.0
^ permalink raw reply related
* [PATCH 02/12] mm: add mk_vma_flags() bitmap flag macro helper
From: Lorenzo Stoakes @ 2026-01-19 14:48 UTC (permalink / raw)
To: Andrew Morton
Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
Reinette Chatre, Dave Martin, James Morse, Babu Moger,
Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
ntfs3, devel, linux-xfs, keyrings, linux-security-module,
Jason Gunthorpe
In-Reply-To: <cover.1768834061.git.lorenzo.stoakes@oracle.com>
This patch introduces the mk_vma_flags() macro helper to allow easy
manipulation of VMA flags utilising the new bitmap representation
implemented of VMA flags defined by the vma_flags_t type.
It is a variadic macro which provides a bitwise-or'd representation of all
of each individual VMA flag specified.
Note that, while we maintain VM_xxx flags for backwards compatibility until
the conversion is complete, we define VMA flags of type vma_flag_t using
VMA_xxx_BIT to avoid confusing the two.
This helper macro therefore can be used thusly:
vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT);
We allow for up to 5 flags to specified at a time which should accommodate
all current kernel uses of combined VMA flags.
Testing has demonstrated that the compiler optimises this code such that it
generates the same assembly utilising this macro as it does if the flags
were specified manually, for instance:
vma_flags_t get_flags(void)
{
return mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
}
Generates the same code as:
vma_flags_t get_flags(void)
{
vma_flags_t flags;
vma_flags_clear_all(&flags);
vma_flag_set(&flags, VMA_READ_BIT);
vma_flag_set(&flags, VMA_WRITE_BIT);
vma_flag_set(&flags, VMA_EXEC_BIT);
return flags;
}
And:
vma_flags_t get_flags(void)
{
vma_flags_t flags;
unsigned long *bitmap = ACCESS_PRIVATE(&flags, __vma_flags);
*bitmap = 1UL << (__force int)VMA_READ_BIT;
*bitmap |= 1UL << (__force int)VMA_WRITE_BIT;
*bitmap |= 1UL << (__force int)VMA_EXEC_BIT;
return flags;
}
That is:
get_flags:
movl $7, %eax
ret
Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
include/linux/mm.h | 33 +++++++++++++++++++++++++++++++++
1 file changed, 33 insertions(+)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 25f7679df55c..36c3a31a4e0e 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2,6 +2,7 @@
#ifndef _LINUX_MM_H
#define _LINUX_MM_H
+#include <linux/args.h>
#include <linux/errno.h>
#include <linux/mmdebug.h>
#include <linux/gfp.h>
@@ -1029,6 +1030,38 @@ static inline bool vma_test_atomic_flag(struct vm_area_struct *vma, vma_flag_t b
return false;
}
+/* Set an individual VMA flag in flags, non-atomically. */
+static inline void vma_flag_set(vma_flags_t *flags, vma_flag_t bit)
+{
+ unsigned long *bitmap = ACCESS_PRIVATE(flags, __vma_flags);
+
+ __set_bit((__force int)bit, bitmap);
+}
+
+static inline vma_flags_t __mk_vma_flags(size_t count, const vma_flag_t *bits)
+{
+ vma_flags_t flags;
+ int i;
+
+ vma_flags_clear_all(&flags);
+ for (i = 0; i < count; i++)
+ vma_flag_set(&flags, bits[i]);
+ return flags;
+}
+
+/*
+ * Helper macro which bitwise-or combines the specified input flags into a
+ * vma_flags_t bitmap value. E.g.:
+ *
+ * vma_flags_t flags = mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT,
+ * VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT);
+ *
+ * The compiler cleverly optimises away all of the work and this ends up being
+ * equivalent to aggregating the values manually.
+ */
+#define mk_vma_flags(...) __mk_vma_flags(COUNT_ARGS(__VA_ARGS__), \
+ (const vma_flag_t []){__VA_ARGS__})
+
static inline void vma_set_anonymous(struct vm_area_struct *vma)
{
vma->vm_ops = NULL;
--
2.52.0
^ permalink raw reply related
* [PATCH 03/12] tools: bitmap: add missing bitmap_[subset(), andnot()]
From: Lorenzo Stoakes @ 2026-01-19 14:48 UTC (permalink / raw)
To: Andrew Morton
Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
Reinette Chatre, Dave Martin, James Morse, Babu Moger,
Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
ntfs3, devel, linux-xfs, keyrings, linux-security-module,
Jason Gunthorpe
In-Reply-To: <cover.1768834061.git.lorenzo.stoakes@oracle.com>
The bitmap_subset() and bitmap_andnot() functions are not present in the
tools version of include/linux/bitmap.h, so add them as subsequent patches
implement test code that requires them.
We also add the missing __bitmap_subset() to tools/lib/bitmap.c.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
tools/include/linux/bitmap.h | 22 ++++++++++++++++++++++
tools/lib/bitmap.c | 29 +++++++++++++++++++++++++++++
2 files changed, 51 insertions(+)
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 0d992245c600..250883090a5d 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -24,6 +24,10 @@ void __bitmap_set(unsigned long *map, unsigned int start, int len);
void __bitmap_clear(unsigned long *map, unsigned int start, int len);
bool __bitmap_intersects(const unsigned long *bitmap1,
const unsigned long *bitmap2, unsigned int bits);
+bool __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int nbits);
+bool __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int nbits);
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
#define BITMAP_LAST_WORD_MASK(nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1)))
@@ -81,6 +85,15 @@ static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
__bitmap_or(dst, src1, src2, nbits);
}
+static __always_inline
+bool bitmap_andnot(unsigned long *dst, const unsigned long *src1,
+ const unsigned long *src2, unsigned int nbits)
+{
+ if (small_const_nbits(nbits))
+ return (*dst = *src1 & ~(*src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
+ return __bitmap_andnot(dst, src1, src2, nbits);
+}
+
static inline unsigned long *bitmap_alloc(unsigned int nbits, gfp_t flags __maybe_unused)
{
return malloc(bitmap_size(nbits));
@@ -157,6 +170,15 @@ static inline bool bitmap_intersects(const unsigned long *src1,
return __bitmap_intersects(src1, src2, nbits);
}
+static __always_inline
+bool bitmap_subset(const unsigned long *src1, const unsigned long *src2, unsigned int nbits)
+{
+ if (small_const_nbits(nbits))
+ return ! ((*src1 & ~(*src2)) & BITMAP_LAST_WORD_MASK(nbits));
+ else
+ return __bitmap_subset(src1, src2, nbits);
+}
+
static inline void bitmap_set(unsigned long *map, unsigned int start, unsigned int nbits)
{
if (__builtin_constant_p(nbits) && nbits == 1)
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 51255c69754d..aa83d22c45e3 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -140,3 +140,32 @@ void __bitmap_clear(unsigned long *map, unsigned int start, int len)
*p &= ~mask_to_clear;
}
}
+
+bool __bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int bits)
+{
+ unsigned int k;
+ unsigned int lim = bits/BITS_PER_LONG;
+ unsigned long result = 0;
+
+ for (k = 0; k < lim; k++)
+ result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
+ if (bits % BITS_PER_LONG)
+ result |= (dst[k] = bitmap1[k] & ~bitmap2[k] &
+ BITMAP_LAST_WORD_MASK(bits));
+ return result != 0;
+}
+
+bool __bitmap_subset(const unsigned long *bitmap1,
+ const unsigned long *bitmap2, unsigned int bits)
+{
+ unsigned int k, lim = bits/BITS_PER_LONG;
+ for (k = 0; k < lim; ++k)
+ if (bitmap1[k] & ~bitmap2[k])
+ return false;
+
+ if (bits % BITS_PER_LONG)
+ if ((bitmap1[k] & ~bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits))
+ return false;
+ return true;
+}
--
2.52.0
^ permalink raw reply related
* [PATCH 00/12] mm: add bitmap VMA flag helpers and convert all mmap_prepare to use them
From: Lorenzo Stoakes @ 2026-01-19 14:48 UTC (permalink / raw)
To: Andrew Morton
Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
Reinette Chatre, Dave Martin, James Morse, Babu Moger,
Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
ntfs3, devel, linux-xfs, keyrings, linux-security-module,
Jason Gunthorpe
We introduced the bitmap VMA type vma_flags_t in the aptly named commit
9ea35a25d51b ("mm: introduce VMA flags bitmap type") in order to permit
future growth in VMA flags and to prevent the asinine requirement that VMA
flags be available to 64-bit kernels only if they happened to use a bit
number about 32-bits.
This is a long-term project as there are very many users of VMA flags
within the kernel that need to be updated in order to utilise this new
type.
In order to further this aim, this series adds a number of helper functions
to enable ordinary interactions with VMA flags - that is testing, setting
and clearing them.
In order to make working with VMA bit numbers less cumbersome this series
introduces the mk_vma_flags() helper macro which generates a vma_flags_t
from a variadic parameter list, e.g.:
vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT,
VMA_EXEC_BIT);
It turns out that the compiler optimises this very well to the point that
this is just as efficient as using VM_xxx pre-computed bitmap values.
This series then introduces the following functions:
bool vma_flags_test_mask(vma_flags_t flags, vma_flags_t to_test);
bool vma_flags_test_all_mask(vma_flags_t flags, vma_flags_t to_test);
void vma_flags_set_mask(vma_flags_t *flags, vma_flags_t to_set);
void vma_flags_clear_mask(vma_flags_t *flags, vma_flags_t to_clear);
Providing means of testing, setting, and clearing a specific vma_flags_t
mask.
For convenience, helper macros are provided - vma_flags_test(),
vma_flags_set() and vma_flags_clear(), each of which utilise mk_vma_flags()
to make these operations easier, as well as an EMPTY_VMA_FLAGS macro to
make initialisation of an empty vma_flags_t value easier, e.g.:
vma_flags_t flags = EMPTY_VMA_FLAGS;
vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
...
if (vma_flags_test(flags, VMA_READ_BIT)) {
...
}
...
if (vma_flags_test_all_mask(flags, VMA_REMAP_FLAGS)) {
...
}
...
vma_flags_clear(&flags, VMA_READ_BIT);
Since callers are often dealing with a vm_area_struct (VMA) or vm_area_desc
(VMA descriptor as used in .mmap_prepare) object, this series further
provides helpers for these - firstly vma_set_flags_mask() and vma_set_flags() for a
VMA:
vma_flags_t flags = EMPTY_VMA_FLAGS:
vma_flags_set(&flags, VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
...
vma_set_flags_mask(&vma, flags);
...
vma_set_flags(&vma, VMA_DONTDUMP_BIT);
Note that these do NOT ensure appropriate locks are taken and assume the
callers takes care of this.
For VMA descriptors this series adds vma_desc_[test, set,
clear]_flags_mask() and vma_desc_[test, set, clear]_flags() for a VMA
descriptor, e.g.:
static int foo_mmap_prepare(struct vm_area_desc *desc)
{
...
vma_desc_set_flags(desc, VMA_SEQ_READ_BIT);
vma_desc_clear_flags(desc, VMA_RAND_READ_BIT);
...
if (vma_desc_test_flags(desc, VMA_SHARED_BIT) {
...
}
...
}
With these helpers introduced, this series then updates all mmap_prepare
users to make use of the vma_flags_t vm_area_desc->vma_flags field rather
than the legacy vm_flags_t vm_area_desc->vm_flags field.
In order to do so, several other related functions need to be updated, with
separate patches for larger changes in hugetlbfs, secretmem and shmem
before finally removing vm_area_desc->vm_flags altogether.
This lays the foundations for future elimination of vm_flags_t and
associated defines and functionality altogether in the long run, and
elimination of the use of vm_flags_t in f_op->mmap() hooks in the near term
as mmap_prepare replaces these.
There is a useful synergy between the VMA flags and mmap_prepare work here
as with this change in place, converting f_op->mmap() to f_op->mmap_prepare
naturally also converts use of vm_flags_t to vma_flags_t in all drivers
which declare mmap handlers.
This accounts for the majority of the users of the legacy vm_flags_*()
helpers and thus a large number of drivers which need to interact with VMA
flags in general.
This series also updates the userland VMA tests to account for the change,
and adds unit tests for these helper functions to assert that they behave
as expected.
In order to faciliate this change in a sensible way, the series also
separates out the VMA unit tests into - code that is duplicated from the
kernel that should be kept in sync, code that is customised for test
purposes and code that is stubbed out.
We also separate out the VMA userland tests into separate files to make it
easier to manage and to provide a sensible baseline for adding the userland
tests for these helpers.
Lorenzo Stoakes (12):
mm: rename vma_flag_test/set_atomic() to vma_test/set_atomic_flag()
mm: add mk_vma_flags() bitmap flag macro helper
tools: bitmap: add missing bitmap_[subset(), andnot()]
mm: add basic VMA flag operation helper functions
mm: update hugetlbfs to use VMA flags on mmap_prepare
mm: update secretmem to use VMA flags on mmap_prepare
mm: update shmem_[kernel]_file_*() functions to use vma_flags_t
mm: update all remaining mmap_prepare users to use vma_flags_t
mm: make vm_area_desc utilise vma_flags_t only
tools/testing/vma: separate VMA userland tests into separate files
tools/testing/vma: separate out vma_internal.h into logical headers
tools/testing/vma: add VMA userland tests for VMA flag functions
arch/x86/kernel/cpu/sgx/ioctl.c | 2 +-
drivers/char/mem.c | 6 +-
drivers/dax/device.c | 10 +-
drivers/gpu/drm/drm_gem.c | 5 +-
drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 2 +-
drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 3 +-
drivers/gpu/drm/i915/gt/shmem_utils.c | 3 +-
drivers/gpu/drm/ttm/tests/ttm_tt_test.c | 2 +-
drivers/gpu/drm/ttm/ttm_backup.c | 3 +-
drivers/gpu/drm/ttm/ttm_tt.c | 2 +-
fs/aio.c | 2 +-
fs/erofs/data.c | 5 +-
fs/ext4/file.c | 4 +-
fs/hugetlbfs/inode.c | 14 +-
fs/ntfs3/file.c | 2 +-
fs/orangefs/file.c | 4 +-
fs/ramfs/file-nommu.c | 2 +-
fs/resctrl/pseudo_lock.c | 2 +-
fs/romfs/mmap-nommu.c | 2 +-
fs/xfs/scrub/xfile.c | 3 +-
fs/xfs/xfs_buf_mem.c | 2 +-
fs/xfs/xfs_file.c | 4 +-
fs/zonefs/file.c | 3 +-
include/linux/dax.h | 4 +-
include/linux/hugetlb.h | 6 +-
include/linux/hugetlb_inline.h | 10 +
include/linux/mm.h | 244 ++-
include/linux/mm_types.h | 9 +-
include/linux/shmem_fs.h | 8 +-
ipc/shm.c | 12 +-
kernel/relay.c | 2 +-
mm/filemap.c | 2 +-
mm/hugetlb.c | 22 +-
mm/internal.h | 2 +-
mm/khugepaged.c | 2 +-
mm/madvise.c | 2 +-
mm/memfd.c | 6 +-
mm/memory.c | 17 +-
mm/mmap.c | 10 +-
mm/mremap.c | 2 +-
mm/secretmem.c | 7 +-
mm/shmem.c | 59 +-
mm/util.c | 2 +-
mm/vma.c | 13 +-
mm/vma.h | 3 +-
security/keys/big_key.c | 2 +-
tools/include/linux/bitmap.h | 22 +
tools/lib/bitmap.c | 29 +
tools/testing/vma/Makefile | 7 +-
tools/testing/vma/include/custom.h | 119 ++
tools/testing/vma/include/dup.h | 1320 ++++++++++++++
tools/testing/vma/include/stubs.h | 431 +++++
tools/testing/vma/main.c | 55 +
tools/testing/vma/shared.c | 131 ++
tools/testing/vma/shared.h | 114 ++
tools/testing/vma/{vma.c => tests/merge.c} | 332 +---
tools/testing/vma/tests/mmap.c | 57 +
tools/testing/vma/tests/vma.c | 339 ++++
tools/testing/vma/vma_internal.h | 1847 +-------------------
59 files changed, 3033 insertions(+), 2303 deletions(-)
create mode 100644 tools/testing/vma/include/custom.h
create mode 100644 tools/testing/vma/include/dup.h
create mode 100644 tools/testing/vma/include/stubs.h
create mode 100644 tools/testing/vma/main.c
create mode 100644 tools/testing/vma/shared.c
create mode 100644 tools/testing/vma/shared.h
rename tools/testing/vma/{vma.c => tests/merge.c} (82%)
create mode 100644 tools/testing/vma/tests/mmap.c
create mode 100644 tools/testing/vma/tests/vma.c
--
2.52.0
^ permalink raw reply
* [PATCH 01/12] mm: rename vma_flag_test/set_atomic() to vma_test/set_atomic_flag()
From: Lorenzo Stoakes @ 2026-01-19 14:48 UTC (permalink / raw)
To: Andrew Morton
Cc: Jarkko Sakkinen, Dave Hansen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, x86, H . Peter Anvin, Arnd Bergmann,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, David Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian Koenig, Huang Rui, Matthew Auld,
Matthew Brost, Alexander Viro, Christian Brauner, Jan Kara,
Benjamin LaHaise, Gao Xiang, Chao Yu, Yue Hu, Jeffle Xu,
Sandeep Dhavale, Hongbo Li, Chunhai Guo, Theodore Ts'o,
Andreas Dilger, Muchun Song, Oscar Salvador, David Hildenbrand,
Konstantin Komarov, Mike Marshall, Martin Brandenburg, Tony Luck,
Reinette Chatre, Dave Martin, James Morse, Babu Moger,
Carlos Maiolino, Damien Le Moal, Naohiro Aota, Johannes Thumshirn,
Matthew Wilcox, Liam R . Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Hugh Dickins, Baolin Wang,
Zi Yan, Nico Pache, Ryan Roberts, Dev Jain, Barry Song,
Lance Yang, Jann Horn, Pedro Falcato, David Howells, Paul Moore,
James Morris, Serge E . Hallyn, Yury Norov, Rasmus Villemoes,
linux-sgx, linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
ntfs3, devel, linux-xfs, keyrings, linux-security-module,
Jason Gunthorpe
In-Reply-To: <cover.1768834061.git.lorenzo.stoakes@oracle.com>
In order to stay consistent between functions which manipulate a vm_flags_t
argument of the form of vma_flags_...() and those which manipulate a
VMA (in this case the flags field of a VMA), rename
vma_flag_[test/set]_atomic() to vma_[test/set]_atomic_flag().
This lays the groundwork for adding VMA flag manipulation functions in a
subsequent commit.
Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
---
include/linux/mm.h | 13 +++++--------
mm/khugepaged.c | 2 +-
mm/madvise.c | 2 +-
3 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a18ade628c8e..25f7679df55c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -987,8 +987,7 @@ static inline void vm_flags_mod(struct vm_area_struct *vma,
__vm_flags_mod(vma, set, clear);
}
-static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,
- vma_flag_t bit)
+static inline bool __vma_atomic_valid_flag(struct vm_area_struct *vma, vma_flag_t bit)
{
const vm_flags_t mask = BIT((__force int)bit);
@@ -1003,8 +1002,7 @@ static inline bool __vma_flag_atomic_valid(struct vm_area_struct *vma,
* Set VMA flag atomically. Requires only VMA/mmap read lock. Only specific
* valid flags are allowed to do this.
*/
-static inline void vma_flag_set_atomic(struct vm_area_struct *vma,
- vma_flag_t bit)
+static inline void vma_set_atomic_flag(struct vm_area_struct *vma, vma_flag_t bit)
{
unsigned long *bitmap = ACCESS_PRIVATE(&vma->flags, __vma_flags);
@@ -1012,7 +1010,7 @@ static inline void vma_flag_set_atomic(struct vm_area_struct *vma,
if (!rwsem_is_locked(&vma->vm_mm->mmap_lock))
vma_assert_locked(vma);
- if (__vma_flag_atomic_valid(vma, bit))
+ if (__vma_atomic_valid_flag(vma, bit))
set_bit((__force int)bit, bitmap);
}
@@ -1023,10 +1021,9 @@ static inline void vma_flag_set_atomic(struct vm_area_struct *vma,
* This is necessarily racey, so callers must ensure that serialisation is
* achieved through some other means, or that races are permissible.
*/
-static inline bool vma_flag_test_atomic(struct vm_area_struct *vma,
- vma_flag_t bit)
+static inline bool vma_test_atomic_flag(struct vm_area_struct *vma, vma_flag_t bit)
{
- if (__vma_flag_atomic_valid(vma, bit))
+ if (__vma_atomic_valid_flag(vma, bit))
return test_bit((__force int)bit, &vma->vm_flags);
return false;
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 9f790ec34400..e4fe9144667a 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -1749,7 +1749,7 @@ static bool file_backed_vma_is_retractable(struct vm_area_struct *vma)
* obtained on guard region installation after the flag is set, so this
* check being performed under this lock excludes races.
*/
- if (vma_flag_test_atomic(vma, VMA_MAYBE_GUARD_BIT))
+ if (vma_test_atomic_flag(vma, VMA_MAYBE_GUARD_BIT))
return false;
return true;
diff --git a/mm/madvise.c b/mm/madvise.c
index 4bf4c8c38fd3..98d0fddcc165 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1142,7 +1142,7 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
* acquire an mmap/VMA write lock to read it. All remaining readers may
* or may not see the flag set, but we don't care.
*/
- vma_flag_set_atomic(vma, VMA_MAYBE_GUARD_BIT);
+ vma_set_atomic_flag(vma, VMA_MAYBE_GUARD_BIT);
/*
* If anonymous and we are establishing page tables the VMA ought to
--
2.52.0
^ permalink raw reply related
* Re: [PATCH v7 0/9] Implement LANDLOCK_ADD_RULE_QUIET
From: Justin Suess @ 2026-01-19 14:26 UTC (permalink / raw)
To: Tingmao Wang, Mickaël Salaün
Cc: Günther Noack, Jan Kara, Abhinav Saxena,
linux-security-module
In-Reply-To: <cover.1766330134.git.m@maowtm.org>
On 12/21/25 10:20, Tingmao Wang wrote:
> Hi,
>
> This is the v7 of the "quiet flag" series, implementing the feature as
> proposed in [1].
>
> v6: https://lore.kernel.org/all/cover.1765040503.git.m@maowtm.org/
> v5: https://lore.kernel.org/all/cover.1763931318.git.m@maowtm.org/
> v4: https://lore.kernel.org/all/cover.1763330228.git.m@maowtm.org/
> v3: https://lore.kernel.org/all/cover.1761511023.git.m@maowtm.org/
> v2: https://lore.kernel.org/all/cover.1759686613.git.m@maowtm.org/
> v1: https://lore.kernel.org/all/cover.1757376311.git.m@maowtm.org/
>
> v6..v7:
>
> - Remove "landlock: Fix wrong type usage" (merged)
> - Revert back to taking rule_flags separately from landlock_request until
> we call landlock_log_denial (https://lore.kernel.org/all/20251219.ahn3aiJuKahb@digikod.net/)
> - Rebase to mic/next
>
> v5..v6 rebases on top of the new simpler disconnected directory handling,
> change some bools into u32, and fix some typo and style.
>
> v4..v5 addresses review feedbacks, most significantly:
> - reduces code changes by pushing rule_flags into landlock_request.
> - adding test cases for two layers handling different access bits.
>
> v3..v4 is a one-character formatting change, plus more tests.
>
> We now have 5 patches for the selftest - I'm happy to squash it into one
> depending on preference (and happy for Mickaël to do the squash if no
> other feedback):
> - selftests/landlock: Replace hard-coded 16 with a constant
> - selftests/landlock: add tests for quiet flag with fs rules
> - selftests/landlock: add tests for quiet flag with net rules
> - selftests/landlock: Add tests for quiet flag with scope
> - selftests/landlock: Add tests for invalid use of quiet flag
>
> v2..v3:
> Not much has changed in the actual functionality except various comment,
> typing, asserts and general style fixes based on feedback. The major new
> thing here is tests (a bit of KUnit squashed into the optional access
> commit, a lot of selftests especially in fs_tests.c).
>
> The added fs_tests should exercise code path for optional and non-optional
> access, renames, and mountpoint and disconnected directory handling. I
> will add the above missing bits to v4.
>
> Removed:
> - "Implement quiet for optional accesses"
> (squashed into "landlock: Suppress logging when quiet flag is present")
>
>
> Old feature summary below:
>
> The quiet flag allows a sandboxer to suppress audit logs for uninteresting
> denials. The flag can be set on objects and inherits downward in the
> filesystem hierarchy. On a denial, the youngest denying layer's quiet
> flag setting decides whether to audit. The motivation for this feature is
> to reduce audit noise, and also prepare for a future supervisor feature
> which will use this bit to suppress supervisor notifications.
>
> This patch introduces a new quiet access mask in the ruleset_attr, which
> gets eventually stored in the hierarchy. This allows the user to specify
> which access should be affected by quiet bits. One can then, for example,
> make it such that read accesses to certain files are not audited (but
> still denied), but all writes are still audited, regardless of location.
>
> The sandboxer is extended to show example usage of this feature,
> supporting quieting filesystem, network and scope accesses.
>
> Demo:
>
> /# LL_FS_RO=/usr LL_FS_RW= LL_FORCE_LOG=1 LL_FS_QUIET=/dev:/tmp:/etc LL_FS_QUIET_ACCESS=r ./sandboxer bash
> ...
> audit: type=1423 audit(1759680175.562:195): domain=15bb25f6b blockers=fs.write_file,fs.read_file path="/dev/tty" dev="devtmpfs" ino=11
> ^^^^^^^^
> # note: because write is not quieted, we see the above line. blockers
> # contains read as well since that's the originally requested access.
> audit: type=1424 audit(1759680175.562:195): domain=15bb25f6b status=allocated mode=enforcing pid=616 uid=0 exe="/sandboxer" comm="sandboxer"
> audit: type=1300 audit(1759680175.562:195): arch=c000003e syscall=257 success=no exit=-13 a0=ffffffffffffff9c a1=5565c86113d1 a2=802 a3=0 items=0 ppid=605 pid=616 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null)
> audit: type=1327 audit(1759680175.562:195): proctitle="bash"
> bash: cannot set terminal process group (605): Inappropriate ioctl for device
> bash: no job control in this shell
> bash: /etc/bash.bashrc: Permission denied
> audit: type=1423 audit(1759680175.570:196): domain=15bb25f6b blockers=fs.read_file path="/.bash_history" dev="virtiofs" ino=36963
> ^^^^^^^^
> # read outside /dev:/tmp:/etc - not quieted
> audit: type=1300 audit(1759680175.570:196): arch=c000003e syscall=257 success=no exit=-13 a0=ffffffffffffff9c a1=5565c868e400 a2=0 a3=0 items=0 ppid=605 pid=616 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null)
> audit: type=1327 audit(1759680175.570:196): proctitle="bash"
> audit: type=1423 audit(1759680175.570:197): domain=15bb25f6b blockers=fs.read_file path="/.bash_history" dev="virtiofs" ino=36963
> audit: type=1300 audit(1759680175.570:197): arch=c000003e syscall=257 success=no exit=-13 a0=ffffffffffffff9c a1=5565c868e400 a2=0 a3=0 items=0 ppid=605 pid=616 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null)
> audit: type=1327 audit(1759680175.570:197): proctitle="bash"
>
> bash-5.2# head /etc/passwd
> head: cannot open '/etc/passwd' for reading: Permission denied
> ^^^^^^^^
> # reads to /etc are quieted
>
> bash-5.2# echo evil >> /etc/passwd
> bash: /etc/passwd: Permission denied
> audit: type=1423 audit(1759680227.030:198): domain=15bb25f6b blockers=fs.write_file path="/etc/passwd" dev="virtiofs" ino=790
> ^^^^^^^^
> # writes are not quieted
> audit: type=1300 audit(1759680227.030:198): arch=c000003e syscall=257 success=no exit=-13 a0=ffffffffffffff9c a1=5565c86ab030 a2=441 a3=1b6 items=0 ppid=605 pid=616 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) ses=4294967295 comm="bash" exe="/usr/bin/bash" key=(null)
> audit: type=1327 audit(1759680227.030:198): proctitle="bash"
>
> Design:
>
> - The user can set the quiet flag for a layer on any part of the fs
> hierarchy (whether it allows any access on it or not), and the flag
> inherits down (no support for "cancelling" the inheritance of the flag
> in specific subdirectories).
>
> - The youngest layer that denies a request gets to decide whether the
> denial is audited or not. This means that a compromised binary, for
> example, cannot "turn off" Landlock auditing when it tries to access
> files, unless it denies access to the files itself. There is some
> debate to be had on whether, if a parent layer sets the quiet flag, but
> the request is denied by a deeper layer, whether Landlock should still
> audit anyway (since the rule author of the child layer likely did not
> expect the denial, so it would be good diagnostic). The current
> approach is to ignore the quiet on the parent layer and audit anyway.
>
> [1]: https://github.com/landlock-lsm/linux/issues/44#issuecomment-2876500918
>
> Kind regards,
> Tingmao
>
> Tingmao Wang (9):
> landlock: Add a place for flags to layer rules
> landlock: Add API support and docs for the quiet flags
> landlock: Suppress logging when quiet flag is present
> samples/landlock: Add quiet flag support to sandboxer
> selftests/landlock: Replace hard-coded 16 with a constant
> selftests/landlock: add tests for quiet flag with fs rules
> selftests/landlock: add tests for quiet flag with net rules
> selftests/landlock: Add tests for quiet flag with scope
> selftests/landlock: Add tests for invalid use of quiet flag
>
> include/uapi/linux/landlock.h | 64 +
> samples/landlock/sandboxer.c | 129 +-
> security/landlock/access.h | 5 +
> security/landlock/audit.c | 255 +-
> security/landlock/audit.h | 3 +
> security/landlock/domain.c | 33 +
> security/landlock/domain.h | 10 +
> security/landlock/fs.c | 120 +-
> security/landlock/fs.h | 19 +-
> security/landlock/net.c | 10 +-
> security/landlock/net.h | 5 +-
> security/landlock/ruleset.c | 19 +-
> security/landlock/ruleset.h | 38 +-
> security/landlock/syscalls.c | 72 +-
> tools/testing/selftests/landlock/audit_test.c | 27 +-
> tools/testing/selftests/landlock/base_test.c | 61 +-
> tools/testing/selftests/landlock/common.h | 2 +
> tools/testing/selftests/landlock/fs_test.c | 2456 ++++++++++++++++-
> tools/testing/selftests/landlock/net_test.c | 121 +-
> .../landlock/scoped_abstract_unix_test.c | 77 +-
> 20 files changed, 3394 insertions(+), 132 deletions(-)
>
>
> base-commit: 161db1810f3625e97ab414908dbcf4b2ab73c309
Hey Tingmao,
Thank you for your work on this patch-- I don’t have any further nits,
this looks very clean.
Do you plan to rebase/resend this series on the current mic-next branch
at some point? It would be helpful to be able to test it alongside some
of the other Landlock series that are in flight.
Feedback on the latest version of the series has been fairly quiet so far,
and having it rebased would make cross-testing easier. I’d also rebase the
LANDLOCK_ADD_RULE_NO_INHERIT series on top for further consideration.
Kind Regards,
Justin
^ permalink raw reply
* Re: [GIT PULL] Landlock fix for v6.19-rc6
From: pr-tracker-bot @ 2026-01-19 13:54 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Linus Torvalds, Mickaël Salaün, Günther Noack,
Matthieu Buffet, Tingmao Wang, linux-kernel,
linux-security-module
In-Reply-To: <20260115214740.803611-1-mic@digikod.net>
The pull request you sent on Thu, 15 Jan 2026 22:47:40 +0100:
> https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git tags/landlock-6.19-rc6
has been merged into torvalds/linux.git:
https://git.kernel.org/torvalds/c/90a855e75a99f2932b19f4d04bac1edef158d95e
Thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/prtracker.html
^ permalink raw reply
* [PATCH 1/1] apparmor: avoid per-cpu hold underflow in aa_get_buffer
From: Zhengmian Hu @ 2026-01-19 12:21 UTC (permalink / raw)
To: john.johansen, john, apparmor
Cc: linux-security-module, linux-kernel, Zhengmian Hu
In-Reply-To: <20260119122119.3648154-1-huzhengmian@gmail.com>
Signed-off-by: Zhengmian Hu <huzhengmian@gmail.com>
---
security/apparmor/lsm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 9b6c2f157..a6c884ba6 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1868,7 +1868,8 @@ char *aa_get_buffer(bool in_atomic)
if (!list_empty(&cache->head)) {
aa_buf = list_first_entry(&cache->head, union aa_buffer, list);
list_del(&aa_buf->list);
- cache->hold--;
+ if (cache->hold)
+ cache->hold--;
cache->count--;
put_cpu_ptr(&aa_local_buffers);
return &aa_buf->buffer[0];
--
2.52.0
^ permalink raw reply related
* [PATCH 0/1] apparmor: avoid per-cpu hold underflow in aa_get_buffer
From: Zhengmian Hu @ 2026-01-19 12:21 UTC (permalink / raw)
To: john.johansen, john, apparmor
Cc: linux-security-module, linux-kernel, Zhengmian Hu
Hi all,
This series fixes a per-cpu hold counter underflow in the AppArmor buffer
cache. Under high-frequency execve workloads with AppArmor enabled, cache->hold
can wrap to UINT_MAX, preventing buffers from returning to the global list and
forcing repeated kmalloc(aa_g_path_max) allocations.
Summary:
On high-frequency execve workloads with AppArmor enabled, the per-CPU buffer
cache can enter a pathological state: aa_get_buffer() decrements hold even
when it is already zero, causing an unsigned underflow. The resulting huge
hold value prevents aa_put_buffer() from refilling the global list, which
starves other CPUs and forces repeated kmalloc(aa_g_path_max) allocations.
Because the AppArmor pool does not shrink, this accumulates into large
kmalloc-8k slab growth over time.
Repro (QEMU TCG, 4 vCPU, 1 GiB RAM, v6.16):
- Unpatched: kmalloc-8k objects grow 12->16 in 120s (run1), 16->20 in 120s (run2)
- Patched: kmalloc-8k stays at 12 for 120s
Notes:
This fix targets the observed underflow mechanism without changing the overall
AppArmor buffer pool design. Happy to provide the reproduction script and logs
on request.
Thanks,
Zhengmian Hu
Zhengmian Hu (1):
apparmor: avoid per-cpu hold underflow in aa_get_buffer
security/apparmor/lsm.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
--
2.52.0
^ permalink raw reply
* Re: [PATCH v2 2/5] landlock: Control pathname UNIX domain socket resolution by path
From: Mickaël Salaün @ 2026-01-19 11:43 UTC (permalink / raw)
To: Justin Suess
Cc: Günther Noack, Jann Horn, linux-security-module,
Tingmao Wang, Samasth Norway Ananda, Matthieu Buffet,
Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
Alyssa Ross, Tahera Fahimi
In-Reply-To: <735dd623-f8ff-43ff-8d06-fc0443e0f892@gmail.com>
On Mon, Jan 12, 2026 at 10:38:44AM -0500, Justin Suess wrote:
> On 1/10/26 09:32, Günther Noack wrote:
> > * Add new access rights which control the look up operations for named
> > UNIX domain sockets. The resolution happens during connect() and
> > sendmsg() (depending on socket type).
> > * LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM
> > * LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM
> > * LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET
> Might be a crazy thought but would it be better to implement the
> STREAM/DGRAM/SEQPACKET as an add_rule flag rather than as a separate
> access right? There are other types of address families like AF_CAN,
> AF_BLUETOOTH, AF_VSOCK that support multiple socket types.
There should only be one LANDLOCK_ACCESS_FS_RESOLVE_UNIX, not one per
stream/dgram/seqpacket.
I guess there is no other type of address families that can be tied to
the filesystem, so there is no need for a more generic approach.
Moreover, each new access right should come with a good test coverage,
so adding a generic access right would be too much work.
The add_rule flags should make sense for any kind of rule type e.g.,
related to how the rule is applied. We also have a lot of flexibility
with the landlock_*_attr structs where we can add new fields.
FYI, this patch series will make it possible to restrict socket creation
according to their properties:
https://lore.kernel.org/all/20251118134639.3314803-1-ivanov.mikhail1@huawei-partners.com/
>
> This saves us on access right numbers if they get added in the future to
> landlock.
Even if we reach 64 access rights per type, we can still add new types.
Anyway, I guess this would not happen because more specific
landlock_*_attr would probably fit best.
>
> So we could have:
>
> LANDLOCK_ADD_RULE_SOCK_STREAM
> LANDLOCK_ADD_RULE_SOCK_DGRAM
> LANDLOCK_ADD_RULE_SOCK_SEQPACKET
This would be the wrong semantic because users don't really care about
the stream/dgram/seqpacket type but about the path name and the peer.
If we want to restrict other socket types, we would probably use
landlock_net_port_attr or create a new struct if necessary.
>
> and use it as such:
>
> landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
> &path_beneath_for_unix_socket,
> LANDLOCK_ADD_RULE_SOCK_STREAM |
> LANDLOCK_ADD_RULE_SOCK_DGRAM);
>
> For address families with only one socket type (ie tcp and udp), the
> socket family be implied, which keeps backward compatibility w/ the
> existing tcp access right.
>
> This way, we don't have to make completely separate access rights for
> future socket families. So we could add a single access right for bluetooth,
> for instance, and distinguish which socket families we give it with the
> LANDLOCK_ADD_RULE_SOCK_* flags.
>
> We'd have to track the SOCK_(socket_type) for unix sockets as we gather
> access rights. But afaik unix sockets should be the only socket type that
> has to deal with tree traversal.
> > * Hook into the path lookup in unix_find_bsd() in af_unix.c, using a
> > LSM hook. Make policy decisions based on the new access rights
> > * Increment the Landlock ABI version.
> > * Minor test adaptions to keep the tests working.
> >
> > Cc: Justin Suess <utilityemal77@gmail.com>
> > Cc: Mickaël Salaün <mic@digikod.net>
> > Suggested-by: Jann Horn <jannh@google.com>
> > Link: https://github.com/landlock-lsm/linux/issues/36
> > Signed-off-by: Günther Noack <gnoack3000@gmail.com>
> > ---
> > include/uapi/linux/landlock.h | 10 ++++++
> > security/landlock/access.h | 2 +-
> > security/landlock/audit.c | 6 ++++
> > security/landlock/fs.c | 34 +++++++++++++++++++-
> > security/landlock/limits.h | 2 +-
> > security/landlock/syscalls.c | 2 +-
> > tools/testing/selftests/landlock/base_test.c | 2 +-
> > tools/testing/selftests/landlock/fs_test.c | 7 ++--
> > 8 files changed, 58 insertions(+), 7 deletions(-)
> >
> > diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> > index f030adc462ee..455edc241c12 100644
> > --- a/include/uapi/linux/landlock.h
> > +++ b/include/uapi/linux/landlock.h
> > @@ -216,6 +216,13 @@ struct landlock_net_port_attr {
> > * :manpage:`ftruncate(2)`, :manpage:`creat(2)`, or :manpage:`open(2)` with
> > * ``O_TRUNC``. This access right is available since the third version of the
> > * Landlock ABI.
> > + * - %LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM: Connect to named
> > + * :manpage:`unix(7)` ``SOCK_STREAM`` sockets.
> > + * - %LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM: Send messages to named
> > + * :manpage:`unix(7)` ``SOCK_DGRAM`` sockets or connect to them using
> > + * :manpage:`connect(2)`.
> > + * - %LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET: Connect to named
> > + * :manpage:`unix(7)` ``SOCK_SEQPACKET`` sockets.
> > *
> > * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
> > * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
> > @@ -321,6 +328,9 @@ struct landlock_net_port_attr {
> > #define LANDLOCK_ACCESS_FS_REFER (1ULL << 13)
> > #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14)
> > #define LANDLOCK_ACCESS_FS_IOCTL_DEV (1ULL << 15)
> > +#define LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM (1ULL << 16)
> > +#define LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM (1ULL << 17)
> > +#define LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET (1ULL << 18)
> > /* clang-format on */
> >
> > /**
> > diff --git a/security/landlock/access.h b/security/landlock/access.h
> > index 7961c6630a2d..c7784922be3c 100644
> > --- a/security/landlock/access.h
> > +++ b/security/landlock/access.h
> > @@ -34,7 +34,7 @@
> > LANDLOCK_ACCESS_FS_IOCTL_DEV)
> > /* clang-format on */
> >
> > -typedef u16 access_mask_t;
> > +typedef u32 access_mask_t;
> >
> > /* Makes sure all filesystem access rights can be stored. */
> > static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
> > diff --git a/security/landlock/audit.c b/security/landlock/audit.c
> > index e899995f1fd5..0645304e0375 100644
> > --- a/security/landlock/audit.c
> > +++ b/security/landlock/audit.c
> > @@ -37,6 +37,12 @@ static const char *const fs_access_strings[] = {
> > [BIT_INDEX(LANDLOCK_ACCESS_FS_REFER)] = "fs.refer",
> > [BIT_INDEX(LANDLOCK_ACCESS_FS_TRUNCATE)] = "fs.truncate",
> > [BIT_INDEX(LANDLOCK_ACCESS_FS_IOCTL_DEV)] = "fs.ioctl_dev",
> > + [BIT_INDEX(LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM)] =
> > + "fs.resolve_unix_stream",
> > + [BIT_INDEX(LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM)] =
> > + "fs.resolve_unix_dgram",
> > + [BIT_INDEX(LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET)] =
> > + "fs.resolve_unix_seqpacket",
> > };
> >
> > static_assert(ARRAY_SIZE(fs_access_strings) == LANDLOCK_NUM_ACCESS_FS);
> > diff --git a/security/landlock/fs.c b/security/landlock/fs.c
> > index 8205673c8b1c..94f5fc7ee9fd 100644
> > --- a/security/landlock/fs.c
> > +++ b/security/landlock/fs.c
> > @@ -9,6 +9,7 @@
> > * Copyright © 2023-2024 Google LLC
> > */
> >
> > +#include "linux/net.h"
> > #include <asm/ioctls.h>
> > #include <kunit/test.h>
> > #include <linux/atomic.h>
> > @@ -314,7 +315,10 @@ static struct landlock_object *get_inode_object(struct inode *const inode)
> > LANDLOCK_ACCESS_FS_WRITE_FILE | \
> > LANDLOCK_ACCESS_FS_READ_FILE | \
> > LANDLOCK_ACCESS_FS_TRUNCATE | \
> > - LANDLOCK_ACCESS_FS_IOCTL_DEV)
> > + LANDLOCK_ACCESS_FS_IOCTL_DEV | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET)
> > /* clang-format on */
> >
> > /*
> > @@ -1588,6 +1592,33 @@ static int hook_path_truncate(const struct path *const path)
> > return current_check_access_path(path, LANDLOCK_ACCESS_FS_TRUNCATE);
> > }
> >
> > +static int hook_unix_path_connect(const struct path *const path, int type,
> > + int flags)
> > +{
> > + access_mask_t access_request = 0;
> > +
> > + /* Lookup for the purpose of saving coredumps is OK. */
> > + if (flags & SOCK_COREDUMP)
> > + return 0;
> > +
> > + switch (type) {
> > + case SOCK_STREAM:
> > + access_request = LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM;
> > + break;
> > + case SOCK_DGRAM:
> > + access_request = LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM;
> > + break;
> > + case SOCK_SEQPACKET:
> > + access_request = LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET;
> > + break;
> > + }
> > +
> > + if (!access_request)
> > + return 0;
> > +
> > + return current_check_access_path(path, access_request);
> > +}
> > +
> > /* File hooks */
> >
> > /**
> > @@ -1872,6 +1903,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
> > LSM_HOOK_INIT(path_unlink, hook_path_unlink),
> > LSM_HOOK_INIT(path_rmdir, hook_path_rmdir),
> > LSM_HOOK_INIT(path_truncate, hook_path_truncate),
> > + LSM_HOOK_INIT(unix_path_connect, hook_unix_path_connect),
> >
> > LSM_HOOK_INIT(file_alloc_security, hook_file_alloc_security),
> > LSM_HOOK_INIT(file_open, hook_file_open),
> > diff --git a/security/landlock/limits.h b/security/landlock/limits.h
> > index 65b5ff051674..1f6f864afec2 100644
> > --- a/security/landlock/limits.h
> > +++ b/security/landlock/limits.h
> > @@ -19,7 +19,7 @@
> > #define LANDLOCK_MAX_NUM_LAYERS 16
> > #define LANDLOCK_MAX_NUM_RULES U32_MAX
> >
> > -#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_IOCTL_DEV
> > +#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET
> > #define LANDLOCK_MASK_ACCESS_FS ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
> > #define LANDLOCK_NUM_ACCESS_FS __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
> >
> > diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
> > index 0116e9f93ffe..66fd196be85a 100644
> > --- a/security/landlock/syscalls.c
> > +++ b/security/landlock/syscalls.c
> > @@ -161,7 +161,7 @@ static const struct file_operations ruleset_fops = {
> > * Documentation/userspace-api/landlock.rst should be updated to reflect the
> > * UAPI change.
> > */
> > -const int landlock_abi_version = 7;
> > +const int landlock_abi_version = 8;
> >
> > /**
> > * sys_landlock_create_ruleset - Create a new ruleset
> > diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c
> > index 7b69002239d7..f4b1a275d8d9 100644
> > --- a/tools/testing/selftests/landlock/base_test.c
> > +++ b/tools/testing/selftests/landlock/base_test.c
> > @@ -76,7 +76,7 @@ TEST(abi_version)
> > const struct landlock_ruleset_attr ruleset_attr = {
> > .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
> > };
> > - ASSERT_EQ(7, landlock_create_ruleset(NULL, 0,
> > + ASSERT_EQ(8, landlock_create_ruleset(NULL, 0,
> > LANDLOCK_CREATE_RULESET_VERSION));
> >
> > ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
> > diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
> > index 968a91c927a4..0cbde65e032a 100644
> > --- a/tools/testing/selftests/landlock/fs_test.c
> > +++ b/tools/testing/selftests/landlock/fs_test.c
> > @@ -575,9 +575,12 @@ TEST_F_FORK(layout1, inval)
> > LANDLOCK_ACCESS_FS_WRITE_FILE | \
> > LANDLOCK_ACCESS_FS_READ_FILE | \
> > LANDLOCK_ACCESS_FS_TRUNCATE | \
> > - LANDLOCK_ACCESS_FS_IOCTL_DEV)
> > + LANDLOCK_ACCESS_FS_IOCTL_DEV | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_STREAM | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_DGRAM | \
> > + LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET)
> >
> > -#define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL_DEV
> > +#define ACCESS_LAST LANDLOCK_ACCESS_FS_RESOLVE_UNIX_SEQPACKET
> >
> > #define ACCESS_ALL ( \
> > ACCESS_FILE | \
>
^ permalink raw reply
* [PATCH tip/locking/core 6/6] compiler-context-analysis: Remove __assume_ctx_lock from initializers
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Remove __assume_ctx_lock() from lock initializers.
Implicitly asserting an active context during initialization caused
false-positive double-lock errors when acquiring a lock immediately after its
initialization. Moving forward, guarded member initialization must either:
1. Use guard(type_init)(&lock) or scoped_guard(type_init, ...).
2. Use context_unsafe() for simple initialization.
Link: https://lore.kernel.org/all/57062131-e79e-42c2-aa0b-8f931cb8cac2@acm.org/
Reported-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Marco Elver <elver@google.com>
---
include/linux/local_lock_internal.h | 3 ---
include/linux/mutex.h | 1 -
include/linux/rwlock.h | 3 +--
include/linux/rwlock_rt.h | 1 -
include/linux/rwsem.h | 2 --
include/linux/seqlock.h | 1 -
include/linux/spinlock.h | 5 +----
include/linux/spinlock_rt.h | 1 -
include/linux/ww_mutex.h | 1 -
lib/test_context-analysis.c | 6 ------
10 files changed, 2 insertions(+), 22 deletions(-)
diff --git a/include/linux/local_lock_internal.h b/include/linux/local_lock_internal.h
index 4521c40895f8..ebfcdf517224 100644
--- a/include/linux/local_lock_internal.h
+++ b/include/linux/local_lock_internal.h
@@ -87,13 +87,11 @@ do { \
0, LD_WAIT_CONFIG, LD_WAIT_INV, \
LD_LOCK_PERCPU); \
local_lock_debug_init(lock); \
- __assume_ctx_lock(lock); \
} while (0)
#define __local_trylock_init(lock) \
do { \
__local_lock_init((local_lock_t *)lock); \
- __assume_ctx_lock(lock); \
} while (0)
#define __spinlock_nested_bh_init(lock) \
@@ -105,7 +103,6 @@ do { \
0, LD_WAIT_CONFIG, LD_WAIT_INV, \
LD_LOCK_NORMAL); \
local_lock_debug_init(lock); \
- __assume_ctx_lock(lock); \
} while (0)
#define __local_lock_acquire(lock) \
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 6b12009351d2..ecaa0440f6ec 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -62,7 +62,6 @@ do { \
static struct lock_class_key __key; \
\
__mutex_init((mutex), #mutex, &__key); \
- __assume_ctx_lock(mutex); \
} while (0)
/**
diff --git a/include/linux/rwlock.h b/include/linux/rwlock.h
index 65a5b55e1bcd..3390d21c95dd 100644
--- a/include/linux/rwlock.h
+++ b/include/linux/rwlock.h
@@ -22,11 +22,10 @@ do { \
static struct lock_class_key __key; \
\
__rwlock_init((lock), #lock, &__key); \
- __assume_ctx_lock(lock); \
} while (0)
#else
# define rwlock_init(lock) \
- do { *(lock) = __RW_LOCK_UNLOCKED(lock); __assume_ctx_lock(lock); } while (0)
+ do { *(lock) = __RW_LOCK_UNLOCKED(lock); } while (0)
#endif
#ifdef CONFIG_DEBUG_SPINLOCK
diff --git a/include/linux/rwlock_rt.h b/include/linux/rwlock_rt.h
index 37b387dcab21..5353abbfdc0b 100644
--- a/include/linux/rwlock_rt.h
+++ b/include/linux/rwlock_rt.h
@@ -22,7 +22,6 @@ do { \
\
init_rwbase_rt(&(rwl)->rwbase); \
__rt_rwlock_init(rwl, #rwl, &__key); \
- __assume_ctx_lock(rwl); \
} while (0)
extern void rt_read_lock(rwlock_t *rwlock) __acquires_shared(rwlock);
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index ea1bbdb57a47..9bf1d93d3d7b 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -121,7 +121,6 @@ do { \
static struct lock_class_key __key; \
\
__init_rwsem((sem), #sem, &__key); \
- __assume_ctx_lock(sem); \
} while (0)
/*
@@ -175,7 +174,6 @@ do { \
static struct lock_class_key __key; \
\
__init_rwsem((sem), #sem, &__key); \
- __assume_ctx_lock(sem); \
} while (0)
static __always_inline int rwsem_is_locked(const struct rw_semaphore *sem)
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 22216df47b0f..c0c6235dff59 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -817,7 +817,6 @@ static __always_inline void write_seqcount_latch_end(seqcount_latch_t *s)
do { \
spin_lock_init(&(sl)->lock); \
seqcount_spinlock_init(&(sl)->seqcount, &(sl)->lock); \
- __assume_ctx_lock(sl); \
} while (0)
/**
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 7b11991c742a..e1e2f144af9b 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -106,12 +106,11 @@ do { \
static struct lock_class_key __key; \
\
__raw_spin_lock_init((lock), #lock, &__key, LD_WAIT_SPIN); \
- __assume_ctx_lock(lock); \
} while (0)
#else
# define raw_spin_lock_init(lock) \
- do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); __assume_ctx_lock(lock); } while (0)
+ do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
#endif
#define raw_spin_is_locked(lock) arch_spin_is_locked(&(lock)->raw_lock)
@@ -324,7 +323,6 @@ do { \
\
__raw_spin_lock_init(spinlock_check(lock), \
#lock, &__key, LD_WAIT_CONFIG); \
- __assume_ctx_lock(lock); \
} while (0)
#else
@@ -333,7 +331,6 @@ do { \
do { \
spinlock_check(_lock); \
*(_lock) = __SPIN_LOCK_UNLOCKED(_lock); \
- __assume_ctx_lock(_lock); \
} while (0)
#endif
diff --git a/include/linux/spinlock_rt.h b/include/linux/spinlock_rt.h
index 0a585768358f..373618a4243c 100644
--- a/include/linux/spinlock_rt.h
+++ b/include/linux/spinlock_rt.h
@@ -20,7 +20,6 @@ static inline void __rt_spin_lock_init(spinlock_t *lock, const char *name,
do { \
rt_mutex_base_init(&(slock)->lock); \
__rt_spin_lock_init(slock, name, key, percpu); \
- __assume_ctx_lock(slock); \
} while (0)
#define _spin_lock_init(slock, percpu) \
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index 58e959ee10e9..c47d4b9b88b3 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -107,7 +107,6 @@ context_lock_struct(ww_acquire_ctx) {
*/
static inline void ww_mutex_init(struct ww_mutex *lock,
struct ww_class *ww_class)
- __assumes_ctx_lock(lock)
{
ww_mutex_base_init(&lock->base, ww_class->mutex_name, &ww_class->mutex_key);
lock->ctx = NULL;
diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c
index 0f05943d957f..140efa8a9763 100644
--- a/lib/test_context-analysis.c
+++ b/lib/test_context-analysis.c
@@ -542,12 +542,6 @@ struct test_ww_mutex_data {
int counter __guarded_by(&mtx);
};
-static void __used test_ww_mutex_init(struct test_ww_mutex_data *d)
-{
- ww_mutex_init(&d->mtx, &ww_class);
- d->counter = 0;
-}
-
static void __used test_ww_mutex_lock_noctx(struct test_ww_mutex_data *d)
{
if (!ww_mutex_lock(&d->mtx, NULL)) {
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 5/6] tomoyo: Use scoped init guard
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Convert lock initialization to scoped guarded initialization where
lock-guarded members are initialized in the same scope.
This ensures the context analysis treats the context as active during member
initialization. This is required to avoid errors once implicit context
assertion is removed.
Signed-off-by: Marco Elver <elver@google.com>
---
security/tomoyo/common.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c
index 86ce56c32d37..7e1f825d903b 100644
--- a/security/tomoyo/common.c
+++ b/security/tomoyo/common.c
@@ -2557,7 +2557,7 @@ int tomoyo_open_control(const u8 type, struct file *file)
if (!head)
return -ENOMEM;
- mutex_init(&head->io_sem);
+ guard(mutex_init)(&head->io_sem);
head->type = type;
switch (type) {
case TOMOYO_DOMAINPOLICY:
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 4/6] crypto: Use scoped init guard
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Convert lock initialization to scoped guarded initialization where
lock-guarded members are initialized in the same scope.
This ensures the context analysis treats the context as active during member
initialization. This is required to avoid errors once implicit context
assertion is removed.
Signed-off-by: Marco Elver <elver@google.com>
---
crypto/crypto_engine.c | 2 +-
crypto/drbg.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/crypto/crypto_engine.c b/crypto/crypto_engine.c
index 1653a4bf5b31..afb6848f7df4 100644
--- a/crypto/crypto_engine.c
+++ b/crypto/crypto_engine.c
@@ -453,7 +453,7 @@ struct crypto_engine *crypto_engine_alloc_init_and_set(struct device *dev,
snprintf(engine->name, sizeof(engine->name),
"%s-engine", dev_name(dev));
- spin_lock_init(&engine->queue_lock);
+ guard(spinlock_init)(&engine->queue_lock);
crypto_init_queue(&engine->queue, qlen);
engine->kworker = kthread_run_worker(0, "%s", engine->name);
diff --git a/crypto/drbg.c b/crypto/drbg.c
index 0a6f6c05a78f..21b339c76cca 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -1780,7 +1780,7 @@ static inline int __init drbg_healthcheck_sanity(void)
if (!drbg)
return -ENOMEM;
- mutex_init(&drbg->drbg_mutex);
+ guard(mutex_init)(&drbg->drbg_mutex);
drbg->core = &drbg_cores[coreref];
drbg->reseed_threshold = drbg_max_requests(drbg);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 3/6] kcov: Use scoped init guard
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Convert lock initialization to scoped guarded initialization where
lock-guarded members are initialized in the same scope.
This ensures the context analysis treats the context as active during
member initialization. This is required to avoid errors once implicit
context assertion is removed.
Signed-off-by: Marco Elver <elver@google.com>
---
kernel/kcov.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 6cbc6e2d8aee..5397d0c14127 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -530,7 +530,7 @@ static int kcov_open(struct inode *inode, struct file *filep)
kcov = kzalloc(sizeof(*kcov), GFP_KERNEL);
if (!kcov)
return -ENOMEM;
- spin_lock_init(&kcov->lock);
+ guard(spinlock_init)(&kcov->lock);
kcov->mode = KCOV_MODE_DISABLED;
kcov->sequence = 1;
refcount_set(&kcov->refcount, 1);
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 2/6] compiler-context-analysis: Introduce scoped init guards
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Add scoped init guard definitions for common synchronization primitives
supported by context analysis.
The scoped init guards treat the context as active within initialization
scope of the underlying context lock, given initialization implies
exclusive access to the underlying object. This allows initialization of
guarded members without disabling context analysis, while documenting
initialization from subsequent usage.
The documentation is updated with the new recommendation. Where scoped
init guards are not provided or cannot be implemented (ww_mutex omitted
for lack of multi-arg guard initializers), the alternative is to just
disable context analysis where guarded members are initialized.
Link: https://lore.kernel.org/all/20251212095943.GM3911114@noisy.programming.kicks-ass.net/
Suggested-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Marco Elver <elver@google.com>
---
Documentation/dev-tools/context-analysis.rst | 30 ++++++++++++++++++--
include/linux/compiler-context-analysis.h | 9 ++----
include/linux/local_lock.h | 8 ++++++
include/linux/local_lock_internal.h | 1 +
include/linux/mutex.h | 3 ++
include/linux/rwsem.h | 4 +++
include/linux/seqlock.h | 5 ++++
include/linux/spinlock.h | 12 ++++++++
lib/test_context-analysis.c | 16 +++++------
9 files changed, 70 insertions(+), 18 deletions(-)
diff --git a/Documentation/dev-tools/context-analysis.rst b/Documentation/dev-tools/context-analysis.rst
index e69896e597b6..54d9ee28de98 100644
--- a/Documentation/dev-tools/context-analysis.rst
+++ b/Documentation/dev-tools/context-analysis.rst
@@ -83,9 +83,33 @@ Currently the following synchronization primitives are supported:
`bit_spinlock`, RCU, SRCU (`srcu_struct`), `rw_semaphore`, `local_lock_t`,
`ww_mutex`.
-For context locks with an initialization function (e.g., `spin_lock_init()`),
-calling this function before initializing any guarded members or globals
-prevents the compiler from issuing warnings about unguarded initialization.
+To initialize variables guarded by a context lock with an initialization
+function (``type_init(&lock)``), prefer using ``guard(type_init)(&lock)`` or
+``scoped_guard(type_init, &lock) { ... }`` to initialize such guarded members
+or globals in the enclosing scope. This initializes the context lock and treats
+the context as active within the initialization scope (initialization implies
+exclusive access to the underlying object).
+
+For example::
+
+ struct my_data {
+ spinlock_t lock;
+ int counter __guarded_by(&lock);
+ };
+
+ void init_my_data(struct my_data *d)
+ {
+ ...
+ guard(spinlock_init)(&d->lock);
+ d->counter = 0;
+ ...
+ }
+
+Alternatively, initializing guarded variables can be done with context analysis
+disabled, preferably in the smallest possible scope (due to lack of any other
+checking): either with a ``context_unsafe(var = init)`` expression, or by
+marking small initialization functions with the ``__context_unsafe(init)``
+attribute.
Lockdep assertions, such as `lockdep_assert_held()`, inform the compiler's
context analysis that the associated synchronization primitive is held after
diff --git a/include/linux/compiler-context-analysis.h b/include/linux/compiler-context-analysis.h
index db7e0d48d8f2..27ea01adeb2c 100644
--- a/include/linux/compiler-context-analysis.h
+++ b/include/linux/compiler-context-analysis.h
@@ -32,13 +32,8 @@
/*
* The "assert_capability" attribute is a bit confusingly named. It does not
* generate a check. Instead, it tells the analysis to *assume* the capability
- * is held. This is used for:
- *
- * 1. Augmenting runtime assertions, that can then help with patterns beyond the
- * compiler's static reasoning abilities.
- *
- * 2. Initialization of context locks, so we can access guarded variables right
- * after initialization (nothing else should access the same object yet).
+ * is held. This is used for augmenting runtime assertions, that can then help
+ * with patterns beyond the compiler's static reasoning abilities.
*/
# define __assumes_ctx_lock(...) __attribute__((assert_capability(__VA_ARGS__)))
# define __assumes_shared_ctx_lock(...) __attribute__((assert_shared_capability(__VA_ARGS__)))
diff --git a/include/linux/local_lock.h b/include/linux/local_lock.h
index 99c06e499375..b8830148a859 100644
--- a/include/linux/local_lock.h
+++ b/include/linux/local_lock.h
@@ -104,6 +104,8 @@ DEFINE_LOCK_GUARD_1(local_lock_nested_bh, local_lock_t __percpu,
local_lock_nested_bh(_T->lock),
local_unlock_nested_bh(_T->lock))
+DEFINE_LOCK_GUARD_1(local_lock_init, local_lock_t, local_lock_init(_T->lock), /* */)
+
DECLARE_LOCK_GUARD_1_ATTRS(local_lock, __acquires(_T), __releases(*(local_lock_t __percpu **)_T))
#define class_local_lock_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(local_lock, _T)
DECLARE_LOCK_GUARD_1_ATTRS(local_lock_irq, __acquires(_T), __releases(*(local_lock_t __percpu **)_T))
@@ -112,5 +114,11 @@ DECLARE_LOCK_GUARD_1_ATTRS(local_lock_irqsave, __acquires(_T), __releases(*(loca
#define class_local_lock_irqsave_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(local_lock_irqsave, _T)
DECLARE_LOCK_GUARD_1_ATTRS(local_lock_nested_bh, __acquires(_T), __releases(*(local_lock_t __percpu **)_T))
#define class_local_lock_nested_bh_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(local_lock_nested_bh, _T)
+DECLARE_LOCK_GUARD_1_ATTRS(local_lock_init, __acquires(_T), __releases(*(local_lock_t **)_T))
+#define class_local_lock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(local_lock_init, _T)
+
+DEFINE_LOCK_GUARD_1(local_trylock_init, local_trylock_t, local_trylock_init(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(local_trylock_init, __acquires(_T), __releases(*(local_trylock_t **)_T))
+#define class_local_trylock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(local_trylock_init, _T)
#endif
diff --git a/include/linux/local_lock_internal.h b/include/linux/local_lock_internal.h
index e8c4803d8db4..4521c40895f8 100644
--- a/include/linux/local_lock_internal.h
+++ b/include/linux/local_lock_internal.h
@@ -6,6 +6,7 @@
#include <linux/percpu-defs.h>
#include <linux/irqflags.h>
#include <linux/lockdep.h>
+#include <linux/debug_locks.h>
#include <asm/current.h>
#ifndef CONFIG_PREEMPT_RT
diff --git a/include/linux/mutex.h b/include/linux/mutex.h
index 89977c215cbd..6b12009351d2 100644
--- a/include/linux/mutex.h
+++ b/include/linux/mutex.h
@@ -254,6 +254,7 @@ extern int atomic_dec_and_mutex_lock(atomic_t *cnt, struct mutex *lock) __cond_a
DEFINE_LOCK_GUARD_1(mutex, struct mutex, mutex_lock(_T->lock), mutex_unlock(_T->lock))
DEFINE_LOCK_GUARD_1_COND(mutex, _try, mutex_trylock(_T->lock))
DEFINE_LOCK_GUARD_1_COND(mutex, _intr, mutex_lock_interruptible(_T->lock), _RET == 0)
+DEFINE_LOCK_GUARD_1(mutex_init, struct mutex, mutex_init(_T->lock), /* */)
DECLARE_LOCK_GUARD_1_ATTRS(mutex, __acquires(_T), __releases(*(struct mutex **)_T))
#define class_mutex_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(mutex, _T)
@@ -261,6 +262,8 @@ DECLARE_LOCK_GUARD_1_ATTRS(mutex_try, __acquires(_T), __releases(*(struct mutex
#define class_mutex_try_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(mutex_try, _T)
DECLARE_LOCK_GUARD_1_ATTRS(mutex_intr, __acquires(_T), __releases(*(struct mutex **)_T))
#define class_mutex_intr_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(mutex_intr, _T)
+DECLARE_LOCK_GUARD_1_ATTRS(mutex_init, __acquires(_T), __releases(*(struct mutex **)_T))
+#define class_mutex_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(mutex_init, _T)
extern unsigned long mutex_get_owner(struct mutex *lock);
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 8da14a08a4e1..ea1bbdb57a47 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -280,6 +280,10 @@ DECLARE_LOCK_GUARD_1_ATTRS(rwsem_write_try, __acquires(_T), __releases(*(struct
DECLARE_LOCK_GUARD_1_ATTRS(rwsem_write_kill, __acquires(_T), __releases(*(struct rw_semaphore **)_T))
#define class_rwsem_write_kill_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(rwsem_write_kill, _T)
+DEFINE_LOCK_GUARD_1(rwsem_init, struct rw_semaphore, init_rwsem(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(rwsem_init, __acquires(_T), __releases(*(struct rw_semaphore **)_T))
+#define class_rwsem_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(rwsem_init, _T)
+
/*
* downgrade write lock to read lock
*/
diff --git a/include/linux/seqlock.h b/include/linux/seqlock.h
index 113320911a09..22216df47b0f 100644
--- a/include/linux/seqlock.h
+++ b/include/linux/seqlock.h
@@ -14,6 +14,7 @@
*/
#include <linux/compiler.h>
+#include <linux/cleanup.h>
#include <linux/kcsan-checks.h>
#include <linux/lockdep.h>
#include <linux/mutex.h>
@@ -1359,4 +1360,8 @@ static __always_inline void __scoped_seqlock_cleanup_ctx(struct ss_tmp **s)
#define scoped_seqlock_read(_seqlock, _target) \
__scoped_seqlock_read(_seqlock, _target, __UNIQUE_ID(seqlock))
+DEFINE_LOCK_GUARD_1(seqlock_init, seqlock_t, seqlock_init(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(seqlock_init, __acquires(_T), __releases(*(seqlock_t **)_T))
+#define class_seqlock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(seqlock_init, _T)
+
#endif /* __LINUX_SEQLOCK_H */
diff --git a/include/linux/spinlock.h b/include/linux/spinlock.h
index 396b8c5d6c1b..7b11991c742a 100644
--- a/include/linux/spinlock.h
+++ b/include/linux/spinlock.h
@@ -582,6 +582,10 @@ DEFINE_LOCK_GUARD_1_COND(raw_spinlock_irqsave, _try,
DECLARE_LOCK_GUARD_1_ATTRS(raw_spinlock_irqsave_try, __acquires(_T), __releases(*(raw_spinlock_t **)_T))
#define class_raw_spinlock_irqsave_try_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(raw_spinlock_irqsave_try, _T)
+DEFINE_LOCK_GUARD_1(raw_spinlock_init, raw_spinlock_t, raw_spin_lock_init(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(raw_spinlock_init, __acquires(_T), __releases(*(raw_spinlock_t **)_T))
+#define class_raw_spinlock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(raw_spinlock_init, _T)
+
DEFINE_LOCK_GUARD_1(spinlock, spinlock_t,
spin_lock(_T->lock),
spin_unlock(_T->lock))
@@ -626,6 +630,10 @@ DEFINE_LOCK_GUARD_1_COND(spinlock_irqsave, _try,
DECLARE_LOCK_GUARD_1_ATTRS(spinlock_irqsave_try, __acquires(_T), __releases(*(spinlock_t **)_T))
#define class_spinlock_irqsave_try_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(spinlock_irqsave_try, _T)
+DEFINE_LOCK_GUARD_1(spinlock_init, spinlock_t, spin_lock_init(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(spinlock_init, __acquires(_T), __releases(*(spinlock_t **)_T))
+#define class_spinlock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(spinlock_init, _T)
+
DEFINE_LOCK_GUARD_1(read_lock, rwlock_t,
read_lock(_T->lock),
read_unlock(_T->lock))
@@ -664,5 +672,9 @@ DEFINE_LOCK_GUARD_1(write_lock_irqsave, rwlock_t,
DECLARE_LOCK_GUARD_1_ATTRS(write_lock_irqsave, __acquires(_T), __releases(*(rwlock_t **)_T))
#define class_write_lock_irqsave_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(write_lock_irqsave, _T)
+DEFINE_LOCK_GUARD_1(rwlock_init, rwlock_t, rwlock_init(_T->lock), /* */)
+DECLARE_LOCK_GUARD_1_ATTRS(rwlock_init, __acquires(_T), __releases(*(rwlock_t **)_T))
+#define class_rwlock_init_constructor(_T) WITH_LOCK_GUARD_1_ATTRS(rwlock_init, _T)
+
#undef __LINUX_INSIDE_SPINLOCK_H
#endif /* __LINUX_SPINLOCK_H */
diff --git a/lib/test_context-analysis.c b/lib/test_context-analysis.c
index 1c5a381461fc..0f05943d957f 100644
--- a/lib/test_context-analysis.c
+++ b/lib/test_context-analysis.c
@@ -35,7 +35,7 @@ static void __used test_common_helpers(void)
}; \
static void __used test_##class##_init(struct test_##class##_data *d) \
{ \
- type_init(&d->lock); \
+ guard(type_init)(&d->lock); \
d->counter = 0; \
} \
static void __used test_##class(struct test_##class##_data *d) \
@@ -83,7 +83,7 @@ static void __used test_common_helpers(void)
TEST_SPINLOCK_COMMON(raw_spinlock,
raw_spinlock_t,
- raw_spin_lock_init,
+ raw_spinlock_init,
raw_spin_lock,
raw_spin_unlock,
raw_spin_trylock,
@@ -109,7 +109,7 @@ static void __used test_raw_spinlock_trylock_extra(struct test_raw_spinlock_data
TEST_SPINLOCK_COMMON(spinlock,
spinlock_t,
- spin_lock_init,
+ spinlock_init,
spin_lock,
spin_unlock,
spin_trylock,
@@ -163,7 +163,7 @@ struct test_mutex_data {
static void __used test_mutex_init(struct test_mutex_data *d)
{
- mutex_init(&d->mtx);
+ guard(mutex_init)(&d->mtx);
d->counter = 0;
}
@@ -226,7 +226,7 @@ struct test_seqlock_data {
static void __used test_seqlock_init(struct test_seqlock_data *d)
{
- seqlock_init(&d->sl);
+ guard(seqlock_init)(&d->sl);
d->counter = 0;
}
@@ -275,7 +275,7 @@ struct test_rwsem_data {
static void __used test_rwsem_init(struct test_rwsem_data *d)
{
- init_rwsem(&d->sem);
+ guard(rwsem_init)(&d->sem);
d->counter = 0;
}
@@ -475,7 +475,7 @@ static DEFINE_PER_CPU(struct test_local_lock_data, test_local_lock_data) = {
static void __used test_local_lock_init(struct test_local_lock_data *d)
{
- local_lock_init(&d->lock);
+ guard(local_lock_init)(&d->lock);
d->counter = 0;
}
@@ -519,7 +519,7 @@ static DEFINE_PER_CPU(struct test_local_trylock_data, test_local_trylock_data) =
static void __used test_local_trylock_init(struct test_local_trylock_data *d)
{
- local_trylock_init(&d->lock);
+ guard(local_trylock_init)(&d->lock);
d->counter = 0;
}
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 1/6] cleanup: Make __DEFINE_LOCK_GUARD handle commas in initializers
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel, kernel test robot
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
Initialization macros can expand to structure initializers containing
commas, which when used as a "lock" function resulted in errors such as:
>> include/linux/spinlock.h:582:56: error: too many arguments provided to function-like macro invocation
582 | DEFINE_LOCK_GUARD_1(raw_spinlock_init, raw_spinlock_t, raw_spin_lock_init(_T->lock), /* */)
| ^
include/linux/spinlock.h:113:17: note: expanded from macro 'raw_spin_lock_init'
113 | do { *(lock) = __RAW_SPIN_LOCK_UNLOCKED(lock); } while (0)
| ^
include/linux/spinlock_types_raw.h:70:19: note: expanded from macro '__RAW_SPIN_LOCK_UNLOCKED'
70 | (raw_spinlock_t) __RAW_SPIN_LOCK_INITIALIZER(lockname)
| ^
include/linux/spinlock_types_raw.h:67:34: note: expanded from macro '__RAW_SPIN_LOCK_INITIALIZER'
67 | RAW_SPIN_DEP_MAP_INIT(lockname) }
| ^
include/linux/cleanup.h:496:9: note: macro '__DEFINE_LOCK_GUARD_1' defined here
496 | #define __DEFINE_LOCK_GUARD_1(_name, _type, _lock) \
| ^
include/linux/spinlock.h:582:1: note: parentheses are required around macro argument containing braced initializer list
582 | DEFINE_LOCK_GUARD_1(raw_spinlock_init, raw_spinlock_t, raw_spin_lock_init(_T->lock), /* */)
| ^
| (
include/linux/cleanup.h:558:60: note: expanded from macro 'DEFINE_LOCK_GUARD_1'
558 | __DEFINE_UNLOCK_GUARD(_name, _type, _unlock, __VA_ARGS__) \
| ^
Make __DEFINE_LOCK_GUARD_0 and __DEFINE_LOCK_GUARD_1 variadic so that
__VA_ARGS__ captures everything.
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Marco Elver <elver@google.com>
---
include/linux/cleanup.h | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
index ee6df68c2177..dbc4162921e9 100644
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -493,22 +493,22 @@ static __always_inline void class_##_name##_destructor(class_##_name##_t *_T) \
\
__DEFINE_GUARD_LOCK_PTR(_name, &_T->lock)
-#define __DEFINE_LOCK_GUARD_1(_name, _type, _lock) \
+#define __DEFINE_LOCK_GUARD_1(_name, _type, ...) \
static __always_inline class_##_name##_t class_##_name##_constructor(_type *l) \
__no_context_analysis \
{ \
class_##_name##_t _t = { .lock = l }, *_T = &_t; \
- _lock; \
+ __VA_ARGS__; \
return _t; \
}
-#define __DEFINE_LOCK_GUARD_0(_name, _lock) \
+#define __DEFINE_LOCK_GUARD_0(_name, ...) \
static __always_inline class_##_name##_t class_##_name##_constructor(void) \
__no_context_analysis \
{ \
class_##_name##_t _t = { .lock = (void*)1 }, \
*_T __maybe_unused = &_t; \
- _lock; \
+ __VA_ARGS__; \
return _t; \
}
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* [PATCH tip/locking/core 0/6] compiler-context-analysis: Scoped init guards
From: Marco Elver @ 2026-01-19 9:05 UTC (permalink / raw)
To: elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, Bart Van Assche, kasan-dev,
llvm, linux-crypto, linux-doc, linux-security-module,
linux-kernel
Current context analysis treats lock_init() as implicitly "holding" the
lock to allow initializing guarded members. This causes false-positive
"double lock" reports if the lock is acquired immediately after
initialization in the same scope; for example:
mutex_init(&d->mtx);
/* ... counter is guarded by mtx ... */
d->counter = 0; /* ok, but mtx is now "held" */
...
mutex_lock(&d->mtx); /* warning: acquiring mutex already held */
This series proposes a solution to this by introducing scoped init
guards which Peter suggested, using the guard(type_init)(&lock) or
scoped_guard(type_init, ..) interface. This explicitly marks init scope
where we can initialize guarded members. With that we can revert the
"implicitly hold" after init annotations, which allows use after
initialization scope as follows:
scoped_guard(mutex_init, &d->mtx) {
d->counter = 0;
}
...
mutex_lock(&d->mtx); /* ok */
Note: Scoped guarded initialization remains optional, and normal
initialization can still be used if no guarded members are being
initialized. Another alternative is to just disable context analysis to
initialize guarded members with `context_unsafe(var = init)` or adding
the `__context_unsafe(init)` function attribute (the latter not being
recommended for non-trivial functions due to lack of any checking):
mutex_init(&d->mtx);
context_unsafe(d->counter = 0); /* ok */
...
mutex_lock(&d->mtx);
This series is an alternative to the approach in [1]:
* Scoped init guards (this series): Sound interface, requires use of
guard(type_init)(&lock) or scoped_guard(type_init, ..) for guarded
member initialization.
* Reentrant init [1]: Less intrusive, type_init() just works, and
also allows guarded member initialization with later lock use in
the same function. But unsound, and e.g. misses double-lock bugs
immediately after init, trading false positives for false negatives.
[1] https://lore.kernel.org/all/20260115005231.1211866-1-elver@google.com/
Marco Elver (6):
cleanup: Make __DEFINE_LOCK_GUARD handle commas in initializers
compiler-context-analysis: Introduce scoped init guards
kcov: Use scoped init guard
crypto: Use scoped init guard
tomoyo: Use scoped init guard
compiler-context-analysis: Remove __assume_ctx_lock from initializers
Documentation/dev-tools/context-analysis.rst | 30 ++++++++++++++++++--
crypto/crypto_engine.c | 2 +-
crypto/drbg.c | 2 +-
include/linux/cleanup.h | 8 +++---
include/linux/compiler-context-analysis.h | 9 ++----
include/linux/local_lock.h | 8 ++++++
include/linux/local_lock_internal.h | 4 +--
include/linux/mutex.h | 4 ++-
include/linux/rwlock.h | 3 +-
include/linux/rwlock_rt.h | 1 -
include/linux/rwsem.h | 6 ++--
include/linux/seqlock.h | 6 +++-
include/linux/spinlock.h | 17 ++++++++---
include/linux/spinlock_rt.h | 1 -
include/linux/ww_mutex.h | 1 -
kernel/kcov.c | 2 +-
lib/test_context-analysis.c | 22 ++++++--------
security/tomoyo/common.c | 2 +-
18 files changed, 80 insertions(+), 48 deletions(-)
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply
* [PATCH -next] lockdown: Add break in lockdown_write
From: Cai Xinchen @ 2026-01-19 9:12 UTC (permalink / raw)
To: nicolas.bouchinet, xiujianfeng, paul, jmorris, serge
Cc: linux-security-module, linux-kernel, caixinchen1
After the label is matched successful, any other levels judgements
are meaningless. Therefore, add break to return early
Signed-off-by: Cai Xinchen <caixinchen1@huawei.com>
---
security/lockdown/lockdown.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 8d46886d2cca..263dcc80d839 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -139,8 +139,10 @@ static ssize_t lockdown_write(struct file *file, const char __user *buf,
enum lockdown_reason level = lockdown_levels[i];
const char *label = lockdown_reasons[level];
- if (label && !strcmp(state, label))
+ if (label && !strcmp(state, label)) {
err = lock_kernel_down("securityfs", level);
+ break;
+ }
}
kfree(state);
--
2.34.1
^ permalink raw reply related
* Re: [PATCH] security: export binder symbols
From: Greg Kroah-Hartman @ 2026-01-19 9:13 UTC (permalink / raw)
To: Alice Ryhl
Cc: Paul Moore, James Morris, Serge E. Hallyn, Carlos Llamas,
linux-security-module, linux-kernel
In-Reply-To: <20260119085109.2238878-1-aliceryhl@google.com>
On Mon, Jan 19, 2026 at 08:51:07AM +0000, Alice Ryhl wrote:
> To enable building Rust Binder (possibly also C Binder) as a module,
> export these symbols.
>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
> ---
> security/security.c | 4 ++++
> 1 file changed, 4 insertions(+)
We need this as a patch series that actually uses these symbols from a
module please.
thanks,
greg k-h
^ permalink raw reply
* [PATCH] security: export binder symbols
From: Alice Ryhl @ 2026-01-19 8:51 UTC (permalink / raw)
To: Paul Moore, James Morris, Serge E. Hallyn
Cc: Alice Ryhl, Carlos Llamas, Greg Kroah-Hartman,
linux-security-module, linux-kernel
To enable building Rust Binder (possibly also C Binder) as a module,
export these symbols.
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
security/security.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/security/security.c b/security/security.c
index 31a688650601..b4776f0e25b3 100644
--- a/security/security.c
+++ b/security/security.c
@@ -479,61 +479,65 @@ int security_binder_set_context_mgr(const struct cred *mgr)
/**
* security_binder_set_context_mgr() - Check if becoming binder ctx mgr is ok
* @mgr: task credentials of current binder process
*
* Check whether @mgr is allowed to be the binder context manager.
*
* Return: Return 0 if permission is granted.
*/
int security_binder_set_context_mgr(const struct cred *mgr)
{
return call_int_hook(binder_set_context_mgr, mgr);
}
+EXPORT_SYMBOL_GPL(security_binder_set_context_mgr);
/**
* security_binder_transaction() - Check if a binder transaction is allowed
* @from: sending process
* @to: receiving process
*
* Check whether @from is allowed to invoke a binder transaction call to @to.
*
* Return: Returns 0 if permission is granted.
*/
int security_binder_transaction(const struct cred *from,
const struct cred *to)
{
return call_int_hook(binder_transaction, from, to);
}
+EXPORT_SYMBOL_GPL(security_binder_transaction);
/**
* security_binder_transfer_binder() - Check if a binder transfer is allowed
* @from: sending process
* @to: receiving process
*
* Check whether @from is allowed to transfer a binder reference to @to.
*
* Return: Returns 0 if permission is granted.
*/
int security_binder_transfer_binder(const struct cred *from,
const struct cred *to)
{
return call_int_hook(binder_transfer_binder, from, to);
}
+EXPORT_SYMBOL_GPL(security_binder_transfer_binder);
/**
* security_binder_transfer_file() - Check if a binder file xfer is allowed
* @from: sending process
* @to: receiving process
* @file: file being transferred
*
* Check whether @from is allowed to transfer @file to @to.
*
* Return: Returns 0 if permission is granted.
*/
int security_binder_transfer_file(const struct cred *from,
const struct cred *to, const struct file *file)
{
return call_int_hook(binder_transfer_file, from, to, file);
}
+EXPORT_SYMBOL_GPL(security_binder_transfer_file);
/**
* security_ptrace_access_check() - Check if tracing is allowed
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
prerequisite-patch-id: 0000000000000000000000000000000000000000
--
2.52.0.457.g6b5491de43-goog
^ permalink raw reply related
* Re: [PATCH 2/3] evm: Don't enable fix mode when secure boot is enabled
From: Coiby Xu @ 2026-01-19 4:10 UTC (permalink / raw)
To: Roberto Sassu
Cc: Mimi Zohar, linux-integrity, Heiko Carstens, Roberto Sassu,
Dmitry Kasatkin, Eric Snowberg, Paul Moore, James Morris,
Serge E. Hallyn, open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <f38b2512d51351f83c51b6e2b5dec11eb7e6959d.camel@huaweicloud.com>
On Fri, Jan 16, 2026 at 01:06:32PM +0100, Roberto Sassu wrote:
>On Thu, 2026-01-15 at 13:15 -0500, Mimi Zohar wrote:
>> On Thu, 2026-01-15 at 08:43 +0800, Coiby Xu wrote:
>> > Similar to IMA fix mode, forbid EVM fix mode when secure boot is
>> > enabled.
>> >
>> > Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
>> > Suggested-by: Roberto Sassu <roberto.sassu@huaweicloud.com>
>
>Ah, if possible, could you please change the email to
>roberto.sassu@huawei.com?
Thanks for the reminder! I'll use the above email.
--
Best regards,
Coiby
^ permalink raw reply
* Re: [PATCH 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Coiby Xu @ 2026-01-19 4:04 UTC (permalink / raw)
To: Ard Biesheuvel, Mimi Zohar
Cc: linux-integrity, Heiko Carstens, Roberto Sassu, Catalin Marinas,
Will Deacon, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Vasily Gorbik,
Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT), H. Peter Anvin,
Roberto Sassu, Dmitry Kasatkin, Eric Snowberg, Paul Moore,
James Morris, Serge E. Hallyn, Jarkko Sakkinen,
moderated list:ARM64 PORT (AARCH64 ARCHITECTURE), open list,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
open list:S390 ARCHITECTURE,
open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <ac5e5e45c12e9b0bda19807e60b06057d74be0b3.camel@linux.ibm.com>
On Sun, Jan 18, 2026 at 01:25:52PM -0500, Mimi Zohar wrote:
>On Fri, 2026-01-16 at 18:27 +0100, Ard Biesheuvel wrote:
Hi Ard and Mimi,
Thanks for your discussion on improving the patch!
>> On Fri, 16 Jan 2026 at 17:39, Mimi Zohar <zohar@linux.ibm.com> wrote:
>> >
>> > On Fri, 2026-01-16 at 14:18 +0100, Ard Biesheuvel wrote:
>> > > On Fri, 16 Jan 2026 at 14:11, Mimi Zohar <zohar@linux.ibm.com> wrote:
>> > > >
>> > > > On Fri, 2026-01-16 at 10:41 +0100, Ard Biesheuvel wrote:
>> > > > > On Thu, 15 Jan 2026 at 01:43, Coiby Xu <coxu@redhat.com> wrote:
>> > > > > >
>> > > > > > EVM and other LSMs need the ability to query the secure boot status of
>> > > > > > the system, without directly calling the IMA arch_ima_get_secureboot
>> > > > > > function. Refactor the secure boot status check into a general,
>> > > > > > integrity-wide function named arch_integrity_get_secureboot.
>> > > > > >
>> > > > > > Define a new Kconfig option CONFIG_INTEGRITY_SECURE_BOOT, which is
>> > > > > > automatically configured by the supported architectures. The existing
>> > > > > > IMA_SECURE_AND_OR_TRUSTED_BOOT Kconfig loads the architecture specific
>> > > > > > IMA policy based on the refactored secure boot status code.
>> > > > > >
>> > > > > > Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
>> > > > > > Suggested-by: Roberto Sassu <roberto.sassu@huaweicloud.com>
>> > > > > > Signed-off-by: Coiby Xu <coxu@redhat.com>
>> > > > > > ---
>> > > > > > arch/arm64/Kconfig | 1 +
>> > > > > > arch/powerpc/Kconfig | 1 +
>> > > > > > arch/powerpc/kernel/Makefile | 2 +-
>> > > > > > arch/powerpc/kernel/ima_arch.c | 5 --
>> > > > > > arch/powerpc/kernel/integrity_sb_arch.c | 13 +++++
>> > > > > > arch/s390/Kconfig | 1 +
>> > > > > > arch/s390/kernel/Makefile | 1 +
>> > > > > > arch/s390/kernel/ima_arch.c | 6 --
>> > > > > > arch/s390/kernel/integrity_sb_arch.c | 9 +++
>> > > > > > arch/x86/Kconfig | 1 +
>> > > > > > arch/x86/include/asm/efi.h | 4 +-
>> > > > > > arch/x86/platform/efi/efi.c | 2 +-
>> > > > > > include/linux/ima.h | 7 +--
>> > > > > > include/linux/integrity.h | 8 +++
>> > > > > > security/integrity/Kconfig | 6 ++
>> > > > > > security/integrity/Makefile | 3 +
>> > > > > > security/integrity/efi_secureboot.c | 56 +++++++++++++++++++
>> > > > > > security/integrity/ima/ima_appraise.c | 2 +-
>> > > > > > security/integrity/ima/ima_efi.c | 47 +---------------
>> > > > > > security/integrity/ima/ima_main.c | 4 +-
>> > > > > > security/integrity/platform_certs/load_uefi.c | 2 +-
>> > > > > > 21 files changed, 111 insertions(+), 70 deletions(-)
>> > > > > > create mode 100644 arch/powerpc/kernel/integrity_sb_arch.c
>> > > > > > create mode 100644 arch/s390/kernel/integrity_sb_arch.c
>> > > > > > create mode 100644 security/integrity/efi_secureboot.c
>> > > > > >
>> > > > > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
>> > > > > > index 93173f0a09c7..4c265b7386bb 100644
>> > > > > > --- a/arch/arm64/Kconfig
>> > > > > > +++ b/arch/arm64/Kconfig
>> > > > > > @@ -2427,6 +2427,7 @@ config EFI
>> > > > > > select EFI_STUB
>> > > > > > select EFI_GENERIC_STUB
>> > > > > > imply IMA_SECURE_AND_OR_TRUSTED_BOOT
>> > > > > > + imply INTEGRITY_SECURE_BOOT
>> > > > >
>> > > > > This allows both to be en/disabled individually, which I don't think
>> > > > > is what we want. It also results in more churn across the
>> > > > > arch-specific Kconfigs than needed.
>> > > > >
>> > > > > Wouldn't it be better if IMA_SECURE_AND_OR_TRUSTED_BOOT 'select'ed
>> > > > > INTEGRITY_SECURE_BOOT in its Kconfig definition?
>> > > >
>> > > > As much as possible, EVM (and other LSMs) shouldn't be dependent on another LSM,
>> > > > in this case IMA, being configured.
>> > >
>> > > Sure, but that is not my point.
>> > >
>> > > This arrangement allows for IMA_SECURE_AND_OR_TRUSTED_BOOT to be
>> > > enabled without INTEGRITY_SECURE_BOOT, resulting in the stub
>> > > implementation of arch_integrity_get_secureboot() being used, which
>> > > always returns false.
Since both INTEGRITY_SECURE_BOOT and IMA_SECURE_AND_OR_TRUSTED_BOOT
don't define a prompt, they are not user-configurable and will always be
enable/disabled together with arch-specific secure boot feature. So
despite the "imply" key word, the case where
IMA_SECURE_AND_OR_TRUSTED_BOOT is enabled whereas INTEGRITY_SECURE_BOOT
is disabled won't happen.
But I agree an arch may not care much about INTEGRITY_SECURE_BOOT so it
may be a churn. So limiting it to the scope of the integrity subsystem
can be a better idea.
>> >
>> > I understand your concern, but instead of "select"ing INTEGRITY_SECURE_BOOT from
>> > IMA_SECURE_AND_OR_TRUSTED_BOOT, how making IMA_SECURE_AND_OR_TRUSTED_BOOT
>> > dependent on both IMA_ARCH_POLICY and INTEGRITY_SECURE_BOOT.
>> >
>>
>> Given that INTEGRITY_SECURE_BOOT has no dependencies of its own,
>> afaict, selecting it is the least disruptive option, as otherwise,
>> existing configs will disable IMA_SECURE_AND_OR_TRUSTED_BOOT as the
>> kernel is being upgraded. But conceptually, I agree that they are
>> equivalent.
As already pointed out on by Mimi, INTEGRITY_SECURE_BOOT depend on
arch-specific secure boot feature. So we can't say INTEGRITY_SECURE_BOOT
has no dependencies.
>>
>> > Including the "imply INTEGRITY_SECURE_BOOT" here in the arch Kconfig allows EVM
>> > to query the secure boot state without relying on IMA_SECURE_AND_OR_TRUSTED_BOOT
>> > being configured.
>>
>> Yes, I understand that this is the whole point of the exercise. But
>> 'imply' should be used with care, and in this case, implying both from
>> CONFIG_EFI really makes little sense. INTEGRITY_SECURE_BOOT should be
>> selected by options that need the functionality, not 'implied' by
>> options that might provide it.
But again I agree INTEGRITY_SECURE_BOOT should "not 'implied' by options
that might provide it".
>
>As not all arch's implement arch_integrity_get_secureboot, the definition in
>include/linux/integrity.h would need to be updated. Something like:
>
>-#ifdef CONFIG_INTEGRITY_SECURE_BOOT
>+#if (defined(CONFIG_INTEGRITY_SECURE_BOOT) && \
>+ (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
>+ || defined(CONFIG_PPC_SECURE_BOOT))
>
>Then IMA_SECURE_AND_OR_TRUSTED_BOOT and EVM could select INTEGRITY_SECURE_BOOT,
>as suggested.
Since INTEGRITY_SECURE_BOOT has a dependency, select doesn't seem to be
a good choice. If EVM does select INTEGRITY_SECURE_BOOT,
INTEGRITY_SECURE_BOOT will be enabled even if arch-specific secure boot
feature is disabled and this can lead to a building failure. How about
always enabling INTEGRITY_SECURE_BOOT when secure boot feature is
enabled and also making IMA_SECURE_AND_OR_TRUSTED_BOOT depend on
INTEGRITY_SECURE_BOOT?
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 916d4f2bfc44..cd44b46d0325 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -97,6 +97,13 @@ config INTEGRITY_CA_MACHINE_KEYRING_MAX
will not be loaded. The remaining MOK keys are loaded into the
.platform keyring.
+config INTEGRITY_SECURE_BOOT
+ def_bool y
+ depends on EFI || PPC_SECURE_BOOT || S390
+ help
+ Provide secure boot related helper functions like querying the
+ secure boot status.
+
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 976e75f9b9ba..5dce572192d6 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -311,6 +311,7 @@ config IMA_QUEUE_EARLY_BOOT_KEYS
config IMA_SECURE_AND_OR_TRUSTED_BOOT
bool
depends on IMA_ARCH_POLICY
+ depends on INTEGRITY_SECURE_BOOT
Another idea is make a tree-wide arch_get_secureboot i.e. to move
current arch_ima_get_secureboot code to arch-specific secure boot
implementation. By this way, there will no need for a new Kconfig option
INTEGRITY_SECURE_BOOT. But I'm not sure if there is any unforeseen
concern.
--
Best regards,
Coiby
^ permalink raw reply related
* Re: [GIT PULL] Landlock fix for v6.19-rc6
From: Linus Torvalds @ 2026-01-18 23:19 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Günther Noack, Matthieu Buffet, Tingmao Wang, linux-kernel,
linux-security-module
In-Reply-To: <20260116.feegh2ohQuae@digikod.net>
On Fri, 16 Jan 2026 at 06:18, Mickaël Salaün <mic@digikod.net> wrote:
>
> Please let me know what you prefer.
Ok, I took a closer look, and yeah, it's mostly just moved lines that
made it all look rather big for this stage of the release, so I've
pulled it as-is.
I do think some of them could have been delayed, but ..
Linus
^ permalink raw reply
* Re: [PATCH 1/3] integrity: Make arch_ima_get_secureboot integrity-wide
From: Mimi Zohar @ 2026-01-18 18:25 UTC (permalink / raw)
To: Ard Biesheuvel
Cc: Coiby Xu, linux-integrity, Heiko Carstens, Roberto Sassu,
Catalin Marinas, Will Deacon, Madhavan Srinivasan,
Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
Vasily Gorbik, Alexander Gordeev, Christian Borntraeger,
Sven Schnelle, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
Dave Hansen, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
H. Peter Anvin, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Jarkko Sakkinen,
moderated list:ARM64 PORT (AARCH64 ARCHITECTURE), open list,
open list:LINUX FOR POWERPC (32-BIT AND 64-BIT),
open list:S390 ARCHITECTURE,
open list:EXTENSIBLE FIRMWARE INTERFACE (EFI),
open list:SECURITY SUBSYSTEM, open list:KEYS/KEYRINGS_INTEGRITY
In-Reply-To: <CAMj1kXGx4ebaK87W7k0SNUNQnO9+=z1nmYxXC7retmp3OqRRFg@mail.gmail.com>
On Fri, 2026-01-16 at 18:27 +0100, Ard Biesheuvel wrote:
> On Fri, 16 Jan 2026 at 17:39, Mimi Zohar <zohar@linux.ibm.com> wrote:
> >
> > On Fri, 2026-01-16 at 14:18 +0100, Ard Biesheuvel wrote:
> > > On Fri, 16 Jan 2026 at 14:11, Mimi Zohar <zohar@linux.ibm.com> wrote:
> > > >
> > > > On Fri, 2026-01-16 at 10:41 +0100, Ard Biesheuvel wrote:
> > > > > On Thu, 15 Jan 2026 at 01:43, Coiby Xu <coxu@redhat.com> wrote:
> > > > > >
> > > > > > EVM and other LSMs need the ability to query the secure boot status of
> > > > > > the system, without directly calling the IMA arch_ima_get_secureboot
> > > > > > function. Refactor the secure boot status check into a general,
> > > > > > integrity-wide function named arch_integrity_get_secureboot.
> > > > > >
> > > > > > Define a new Kconfig option CONFIG_INTEGRITY_SECURE_BOOT, which is
> > > > > > automatically configured by the supported architectures. The existing
> > > > > > IMA_SECURE_AND_OR_TRUSTED_BOOT Kconfig loads the architecture specific
> > > > > > IMA policy based on the refactored secure boot status code.
> > > > > >
> > > > > > Reported-and-suggested-by: Mimi Zohar <zohar@linux.ibm.com>
> > > > > > Suggested-by: Roberto Sassu <roberto.sassu@huaweicloud.com>
> > > > > > Signed-off-by: Coiby Xu <coxu@redhat.com>
> > > > > > ---
> > > > > > arch/arm64/Kconfig | 1 +
> > > > > > arch/powerpc/Kconfig | 1 +
> > > > > > arch/powerpc/kernel/Makefile | 2 +-
> > > > > > arch/powerpc/kernel/ima_arch.c | 5 --
> > > > > > arch/powerpc/kernel/integrity_sb_arch.c | 13 +++++
> > > > > > arch/s390/Kconfig | 1 +
> > > > > > arch/s390/kernel/Makefile | 1 +
> > > > > > arch/s390/kernel/ima_arch.c | 6 --
> > > > > > arch/s390/kernel/integrity_sb_arch.c | 9 +++
> > > > > > arch/x86/Kconfig | 1 +
> > > > > > arch/x86/include/asm/efi.h | 4 +-
> > > > > > arch/x86/platform/efi/efi.c | 2 +-
> > > > > > include/linux/ima.h | 7 +--
> > > > > > include/linux/integrity.h | 8 +++
> > > > > > security/integrity/Kconfig | 6 ++
> > > > > > security/integrity/Makefile | 3 +
> > > > > > security/integrity/efi_secureboot.c | 56 +++++++++++++++++++
> > > > > > security/integrity/ima/ima_appraise.c | 2 +-
> > > > > > security/integrity/ima/ima_efi.c | 47 +---------------
> > > > > > security/integrity/ima/ima_main.c | 4 +-
> > > > > > security/integrity/platform_certs/load_uefi.c | 2 +-
> > > > > > 21 files changed, 111 insertions(+), 70 deletions(-)
> > > > > > create mode 100644 arch/powerpc/kernel/integrity_sb_arch.c
> > > > > > create mode 100644 arch/s390/kernel/integrity_sb_arch.c
> > > > > > create mode 100644 security/integrity/efi_secureboot.c
> > > > > >
> > > > > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> > > > > > index 93173f0a09c7..4c265b7386bb 100644
> > > > > > --- a/arch/arm64/Kconfig
> > > > > > +++ b/arch/arm64/Kconfig
> > > > > > @@ -2427,6 +2427,7 @@ config EFI
> > > > > > select EFI_STUB
> > > > > > select EFI_GENERIC_STUB
> > > > > > imply IMA_SECURE_AND_OR_TRUSTED_BOOT
> > > > > > + imply INTEGRITY_SECURE_BOOT
> > > > >
> > > > > This allows both to be en/disabled individually, which I don't think
> > > > > is what we want. It also results in more churn across the
> > > > > arch-specific Kconfigs than needed.
> > > > >
> > > > > Wouldn't it be better if IMA_SECURE_AND_OR_TRUSTED_BOOT 'select'ed
> > > > > INTEGRITY_SECURE_BOOT in its Kconfig definition?
> > > >
> > > > As much as possible, EVM (and other LSMs) shouldn't be dependent on another LSM,
> > > > in this case IMA, being configured.
> > >
> > > Sure, but that is not my point.
> > >
> > > This arrangement allows for IMA_SECURE_AND_OR_TRUSTED_BOOT to be
> > > enabled without INTEGRITY_SECURE_BOOT, resulting in the stub
> > > implementation of arch_integrity_get_secureboot() being used, which
> > > always returns false.
> >
> > I understand your concern, but instead of "select"ing INTEGRITY_SECURE_BOOT from
> > IMA_SECURE_AND_OR_TRUSTED_BOOT, how making IMA_SECURE_AND_OR_TRUSTED_BOOT
> > dependent on both IMA_ARCH_POLICY and INTEGRITY_SECURE_BOOT.
> >
>
> Given that INTEGRITY_SECURE_BOOT has no dependencies of its own,
> afaict, selecting it is the least disruptive option, as otherwise,
> existing configs will disable IMA_SECURE_AND_OR_TRUSTED_BOOT as the
> kernel is being upgraded. But conceptually, I agree that they are
> equivalent.
>
> > Including the "imply INTEGRITY_SECURE_BOOT" here in the arch Kconfig allows EVM
> > to query the secure boot state without relying on IMA_SECURE_AND_OR_TRUSTED_BOOT
> > being configured.
>
> Yes, I understand that this is the whole point of the exercise. But
> 'imply' should be used with care, and in this case, implying both from
> CONFIG_EFI really makes little sense. INTEGRITY_SECURE_BOOT should be
> selected by options that need the functionality, not 'implied' by
> options that might provide it.
As not all arch's implement arch_integrity_get_secureboot, the definition in
include/linux/integrity.h would need to be updated. Something like:
-#ifdef CONFIG_INTEGRITY_SECURE_BOOT
+#if (defined(CONFIG_INTEGRITY_SECURE_BOOT) && \
+ (defined(CONFIG_X86) && defined(CONFIG_EFI)) || defined(CONFIG_S390) \
+ || defined(CONFIG_PPC_SECURE_BOOT))
Then IMA_SECURE_AND_OR_TRUSTED_BOOT and EVM could select INTEGRITY_SECURE_BOOT,
as suggested.
Mimi
^ permalink raw reply
* Re: [PATCH v2 0/5] landlock: Pathname-based UNIX connect() control
From: Günther Noack @ 2026-01-18 17:44 UTC (permalink / raw)
To: Justin Suess
Cc: Mickaël Salaün, Paul Moore, James Morris,
Serge E . Hallyn, linux-security-module, Tingmao Wang,
Samasth Norway Ananda, Matthieu Buffet, Mikhail Ivanov,
konstantin.meskhidze, Demi Marie Obenour, Alyssa Ross, Jann Horn,
Tahera Fahimi, Simon Horman, netdev, Alexander Viro,
Christian Brauner
In-Reply-To: <62eda124-de91-4445-b163-9dfb8039d08c@gmail.com>
Hello!
On Sat, Jan 17, 2026 at 01:57:20PM -0500, Justin Suess wrote:
> On 1/12/26 15:53, Günther Noack wrote:
> > On Mon, Jan 12, 2026 at 05:08:02PM +0100, Mickaël Salaün wrote:
> >> On Sat, Jan 10, 2026 at 03:32:55PM +0100, Günther Noack wrote:
> >>> ## Alternatives and Related Work
> >>>
> >>> ### Alternative: Use existing LSM hooks
> >>>
> >>> The existing hooks security_unix_stream_connect(),
> >>> security_unix_may_send() and security_socket_connect() do not give
> >>> access to the resolved file system path.
> >>>
> >>> Resolving the file system path again within Landlock would in my
> >>> understanding produce a TOCTOU race, so making the decision based on
> >>> the struct sockaddr_un contents is not an option.
> >>>
> >>> It is tempting to use the struct path that the listening socket is
> >>> bound to, which can be acquired through the existing hooks.
> >>> Unfortunately, the listening socket may have been bound from within a
> >>> different namespace, and it is therefore a path that can not actually
> >>> be referenced by the sandboxed program at the time of constructing the
> >>> Landlock policy. (More details are on the Github issue at [6] and on
> >>> the LKML at [9]).
> >> Please move (or duplicate) this rationale in the patch dedicated to the
> >> new hook. It helps patch review (and to understand commits when already
> >> merged).
> > Justin, would you like to look into this?
> > Please feel free to copy the wording.
> No problem.
>
> It's quite long, so would it make sense in the notes?
> Instead of directly in the commit message?
I think including it in the commit message is what Mickaël meant here.
The quoted email above is already from the cover letter (which I
assume you meant by "notes"?). IMHO, the considerations that are
specific to the LSM hook are OK to put on the commit that introduces
it, even if they are a bit longer. That way, a summary of the
tradeoffs also makes its way into the overall commit history (unlike
the cover letter).
FWIW, commit messages with long descriptions are not unheard of,
e.g. commit ee6a44da3c87 ("tty: Require CAP_SYS_ADMIN for all usages
of TIOCL_SELMOUSEREPORT"), which I submitted a while back.
For reference, the official guidance on commit messages is
https://www.kernel.org/doc/html/latest/process/submitting-patches.html#describe-your-changes
> >>> Seeking feedback on:
> >>>
> >>> - Feedback on the LSM hook name would be appreciated. We realize that
> >>> not all invocations of the LSM hook are related to connect(2) as the
> >>> name suggests, but some also happen during sendmsg(2).
> >> Renaming security_unix_path_connect() to security_unix_find() would look
> >> appropriate to me wrt the caller.
> > Justin, this is also on your commit. (I find security_unix_find() and
> > security_unix_resolve() equally acceptable options.)
> security_unix_find works for me, and seems to better match the hook
> location. I'll send an updated commit.
Thanks! Please feel free to ping me, I'd be ready to send an updated v3.
–Günther
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox