* Re: [PATCH v2 1/3] landlock: Add missing ABI 7 case in documentation example
From: Günther Noack @ 2026-01-21 9:37 UTC (permalink / raw)
To: Samasth Norway Ananda; +Cc: mic, linux-security-module, linux-kernel
In-Reply-To: <20260103002722.1465371-2-samasth.norway.ananda@oracle.com>
Thanks for the updated documentation!
The comments below are mostly about the structure in the bigger
document context. The wording seems good.
On Fri, Jan 02, 2026 at 04:27:13PM -0800, Samasth Norway Ananda wrote:
> Add the missing case 6 and case 7 handling in the ABI version
> compatibility example to properly handle ABI < 7 kernels.
>
> Add an optional backwards compatibility section for restrict flags
> between the case analysis and landlock_restrict_self() call. The main
> tutorial example remains unchanged with
> landlock_restrict_self(ruleset_fd, 0) to keep it simple for users who
> don't need logging flags.
>
> Also fix misleading description of the /usr rule which incorrectly
> stated it "only allow[s] reading" when the code actually allows both
> reading and executing (LANDLOCK_ACCESS_FS_EXECUTE is included in
> allowed_access).
>
> Signed-off-by: Samasth Norway Ananda <samasth.norway.ananda@oracle.com>
> ---
> Documentation/userspace-api/landlock.rst | 35 +++++++++++++++++++++---
> 1 file changed, 31 insertions(+), 4 deletions(-)
>
> diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
> index 1d0c2c15c22e..650c7b368561 100644
> --- a/Documentation/userspace-api/landlock.rst
> +++ b/Documentation/userspace-api/landlock.rst
> @@ -127,6 +127,12 @@ version, and only use the available subset of access rights:
> /* Removes LANDLOCK_SCOPE_* for ABI < 6 */
> ruleset_attr.scoped &= ~(LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET |
> LANDLOCK_SCOPE_SIGNAL);
> + __attribute__((fallthrough));
> + case 6:
> + /* Removes logging flags for ABI < 7 */
> + __attribute__((fallthrough));
> + case 7:
> + break;
> }
This code does nothing, and the comment about removing logging flags
is unclear in that context without pointing to the later section.
IMHO we can either say that logging flags are removed in the code
further below, or just leave it out.
The "case 7" case is not necessary.
>
> This enables the creation of an inclusive ruleset that will contain our rules.
> @@ -142,8 +148,9 @@ This enables the creation of an inclusive ruleset that will contain our rules.
> }
>
> We can now add a new rule to this ruleset thanks to the returned file
> -descriptor referring to this ruleset. The rule will only allow reading the
> -file hierarchy ``/usr``. Without another rule, write actions would then be
> +descriptor referring to this ruleset. The rule will allow reading and
> +executing files in the ``/usr`` hierarchy. Without another rule, write actions
> +and other operations (make_dir, remove_file, etc.) would then be
> denied by the ruleset. To add ``/usr`` to the ruleset, we open it with the
> ``O_PATH`` flag and fill the &struct landlock_path_beneath_attr with this file
> descriptor.
> @@ -191,10 +198,30 @@ number for a specific action: HTTPS connections.
> err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_NET_PORT,
> &net_port, 0);
>
> +Backwards compatibility for restrict flags
> +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If you were to add this header, then the section about prctl() and
landlock_restrict_self() would also now appear under "Backwards
compatibility for restrict flags", and that would be confusing. I
would recommend to drop the header for now and clarify in the text
what it is about. (IMHO, it is visually reasonably easy to understand
the structure of the different sections, as they always follow the
structure "text + code snippet".)
If we want to introduce a new level of headers below "Defining and
enforcing a security policy", we would have to introduce subsections
for the other steps as well, so that it is more structured. (If we
wanted to do that though, it would probably be better to do it in a
separate commit.)
> +When passing a non-zero ``flags`` argument to ``landlock_restrict_self()``, the
> +following backwards compatibility check needs to be taken into account:
> +
> +.. code-block:: c
> +
> + /*
> + * Desired restriction flags, see ABI version section above.
^^^^^^^^^^^^^^^^^^^^^^^^^
The ABI section does not talk about the restriction flags much;
I would have expected that to link to the place where the restriction
flags are documented, which would be the system call documentation
from the header?
https://docs.kernel.org/userspace-api/landlock.html#enforcing-a-ruleset
> + * This value is only an example and differs by use case.
> + */
> + int restrict_flags = LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON;
> + if (abi < 7) {
> + /* Clear logging flags unsupported in ABI < 7 */
> + restrict_flags &= ~(LANDLOCK_RESTRICT_SELF_LOG_SAME_EXEC_OFF |
> + LANDLOCK_RESTRICT_SELF_LOG_NEW_EXEC_ON |
> + LANDLOCK_RESTRICT_SELF_LOG_SUBDOMAINS_OFF);
> + }
> +
> The next step is to restrict the current thread from gaining more privileges
> (e.g. through a SUID binary). We now have a ruleset with the first rule
> -allowing read access to ``/usr`` while denying all other handled accesses for
> -the filesystem, and a second rule allowing HTTPS connections.
> +allowing read and execute access to ``/usr`` while denying all other handled
> +accesses for the filesystem, and a second rule allowing HTTPS connections.
>
If you are setting a "restrict_flags" variable here, then you would
also need to use that variable in the call to landlock_restrict_self()
in the documentation below, so that the different code sections in the
documentation work together.
—Günther
^ permalink raw reply
* [PATCH] efi: Mark UEFI skip cert quirks list as __initconst
From: Thomas Weißschuh @ 2026-01-21 7:43 UTC (permalink / raw)
To: Jarkko Sakkinen, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn
Cc: linux-integrity, keyrings, linux-security-module, linux-kernel,
Thomas Weißschuh
The only user is marked as __init, so there is no reason to keep this
data around after bootup.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
security/integrity/platform_certs/load_uefi.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/security/integrity/platform_certs/load_uefi.c b/security/integrity/platform_certs/load_uefi.c
index d1fdd113450a..26523a2b29c7 100644
--- a/security/integrity/platform_certs/load_uefi.c
+++ b/security/integrity/platform_certs/load_uefi.c
@@ -19,7 +19,7 @@
* a crash disabling EFI runtime services. The following quirk skips reading
* these variables.
*/
-static const struct dmi_system_id uefi_skip_cert[] = {
+static const struct dmi_system_id uefi_skip_cert[] __initconst = {
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,1") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,2") },
{ UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,3") },
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20260121-uefi-certs-initconst-d5dadc5f01dd
Best regards,
--
Thomas Weißschuh <thomas.weissschuh@linutronix.de>
^ permalink raw reply related
* TVでも話題。地方で儲かる、焼肉ビジネス
From: ときわ亭フランチャイズ事務局 @ 2026-01-21 4:24 UTC (permalink / raw)
To: linux-security-module
新たな事業をお考えの経営者様へ
いつもお世話になります。
TBSテレビ『坂上&指原のつぶれない店』で取り上げられるなど、
今話題の、待ち時間0秒の飲み放題を提供する
焼肉酒場「 ときわ亭 」のフランチャイズシステム説明会をご案内いたします。
わずか2年半で全国80店舗展開した
「0秒レモンサワー ときわ亭」の
ビジネスモデル、収益性や最新の飲食市場実態を
オンラインによる説明会形式で分かりやすく、丁寧にお伝えします。
※本セミナー参加、店舗オープンの場合
研修費用50万円を本部支援!
専門家による、資金調達相談が無料!
このような方におススメ
・銀行融資を受けやすくなるコツをしりたい
・飲食店の経営に興味がある
・焼肉屋の経営実態がしりたい
こういった方は、ぜひお気軽にご視聴くださいませ。
▼ オンライン説明会のご視聴予約はこちら ▼
https://tokiwatei-fc.work/web/
━━━━━━━━━━━━━━━━━━━━━━━━━━━
■ ご説明するフランチャイズシステム
0秒レモンサワー 仙台ホルモン焼肉酒場ときわ亭
■ 開催日程
・ 1月27日(火)15:00〜16:30 @オンライン開催
■ 定員
・10社限定
■ 参加費
・不要
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
本メールが不要の方には大変失礼しました。
今後ご案内が不要な際は、下記URLにて配信解除を承っています。
https://tokiwatei-fc.work/mail/
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
主催:GOSSO株式会社(ときわ亭フランチャイズ本部)
東京都渋谷区宇田川町14-13 宇田川ビルディング6F
03-6316-8191
━━━━━━━━━━━━━━━━━━━━━━━━━━━━
^ permalink raw reply
* [PATCH v2] [Reminder] Landlock documentation improvements
From: Samasth Norway Ananda @ 2026-01-21 2:14 UTC (permalink / raw)
To: samasth.norway.ananda; +Cc: gnoack, linux-kernel, linux-security-module, mic
In-Reply-To: <20260103002722.1465371-1-samasth.norway.ananda@oracle.com>
Hi Mickael/Gunther,
Just a friendly ping on the landlock documentation v2 patchset. I haven't heard back yet, and I wanted to check if you had the chance to review it.
If there are any issues or further changes required, please let me know.
("landlock: Documentation improvements")
https://lore.kernel.org/linux-security-module/20260103002722.1465371-1-samasth.norway.ananda@oracle.com/
Thanks again for your time and feedback!
Best regards,
Samasth.
^ permalink raw reply
* Re: [RFC PATCH 2/2] landlock: transpose the layer masks data structure
From: Tingmao Wang @ 2026-01-21 0:26 UTC (permalink / raw)
To: Günther Noack, Mickaël Salaün
Cc: Justin Suess, linux-security-module, Samasth Norway Ananda,
Matthieu Buffet, Mikhail Ivanov, konstantin.meskhidze
In-Reply-To: <20251230103917.10549-7-gnoack3000@gmail.com>
On 12/30/25 10:39, Günther Noack wrote:
> The layer masks data structure tracks the requested but unfulfilled
> access rights during an operations security check. It stores one bit
> for each combination of access right and layer index. If the bit is
> set, that access right is not granted (yet) in the given layer and we
> have to traverse the path further upwards to grant it.
>
> Previously, the layer masks were stored as arrays mapping from access
> right indices to layer_mask_t. The layer_mask_t value then indicates
> all layers in which the given access right is still (tentatively)
> denied.
>
> This patch introduces struct layer_access_masks instead: This struct
> contains an array with the access_mask_t of each (tentatively) denied
> access right in that layer.
>
> The hypothesis of this patch is that this simplifies the code enough
> so that the resulting code will run faster:
>
> * We can use bitwise operations in multiple places where we previously
> looped over bits individually with macros. (Should require less
> branch speculation)
>
> * Code is ~160 lines smaller.
>
> Other noteworthy changes:
>
> * Clarify deny_mask_t and the code assembling it.
> * Document what that value looks like
> * Make writing and reading functions specific to file system rules.
> (It only worked for FS rules before as well, but going all the way
> simplifies the code logic more.)
In the original commit message that added this type [1] there was this
statement:
> Implementing deny_masks_t with a bitfield instead of a struct enables a
> generic implementation to store and extract layer levels.
At some point when looking at this I was wondering why this wasn't a
struct with 2 u8:4 fields, but rather, a u8 with bit manipulation code.
While it is possible that I might have just misunderstood it, reading the
above statement my take-away was that a struct would have forced us to
address the indices with specific names, e.g. it would need to be defined
like
struct deny_masks_t {
u8 ioctl:4;
u8 truncate:4;
}
And it would thus not be possible to manipulate the indices in a generic
way (e.g. the way it was implemented before, given
all_existing_optional_access and access_bit, read and write the right
bits).
However, since we're now removing that generic-ability, should we consider
turning it into a struct? (If later on we have different access types
that also have optional accesses, we could use a union of structs)
btw, since this causes conflicts with the quiet flag series and Mickaël
has indicated that this should be merged first, I will probably have to
make my series based on top of this. Will watch this series to see if
there are more changes.
Also, this transpose and code simplification should also simplify the
mutable domains work so thanks for the refactor!
A while ago I also made some benchmarking script which I sent a PR to
landlock-test-tools [2], and earlier I tested this patch with it, and saw
some improvement (but it was much less in terms of percentage, which may
be due to the lower directory depth, or may be due to other unknown
reason):
TestDescription(landlock=True, dir_depth=10, nb_extra_rules=10)
base.2:
c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=1718.15, min=1663.00, max=275949.00, median=1696.46, stddev=437.52
95% confidence interval: [1718.03 .. 1718.28]
Estimated landlock overhead (vs no-landlock): 226.5%
48bd90e91fe6.2:
c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=1709.60, min=1633.00, max=280608.00, median=1688.83, stddev=441.83
95% confidence interval: [1709.48 .. 1709.73]
** Improved 0.5% **
...
[1660 .. 1669]: [1660 .. 1669]: ###
[1670 .. 1679]: ## [1670 .. 1679]: ###############
[1680 .. 1689]: ###################### [1680 .. 1689]: #################################
[1690 .. 1699]: ######################################## [1690 .. 1699]: ##################################
[1700 .. 1709]: ############################ [1700 .. 1709]: #############
[1710 .. 1719]: ######### [1710 .. 1719]: ##
[1720 .. 1729]: ## [1720 .. 1729]:
...
Estimated landlock overhead (vs no-landlock): 223.0%
TestDescription(landlock=True, dir_depth=29, nb_extra_rules=10)
base.2:
c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=3869.66, min=3727.00, max=272563.00, median=3813.42, stddev=666.18
95% confidence interval: [3869.47 .. 3869.86]
Estimated landlock overhead (vs no-landlock): 427.3%
48bd90e91fe6.2:
c_measured_syscall_time_ns: 45000000 samples (3 trials), avg=3855.61, min=3697.00, max=271690.00, median=3804.82, stddev=682.74
95% confidence interval: [3855.41 .. 3855.81]
** Improved 0.4% **
...
[3750 .. 3759]: [3750 .. 3759]: #
[3760 .. 3769]: [3760 .. 3769]: #######
[3770 .. 3779]: [3770 .. 3779]: ###############
[3780 .. 3789]: #### [3780 .. 3789]: ###################
[3790 .. 3799]: ################### [3790 .. 3799]: ###################
[3800 .. 3809]: ###################################### [3800 .. 3809]: ########################
[3810 .. 3819]: ######################################## [3810 .. 3819]: ############################
[3820 .. 3829]: ########################## [3820 .. 3829]: #####################
[3830 .. 3839]: ############# [3830 .. 3839]: #########
[3840 .. 3849]: ###### [3840 .. 3849]: ##
[3850 .. 3859]: ## [3850 .. 3859]:
[3860 .. 3869]: [3860 .. 3869]:
[3870 .. 3879]: [3870 .. 3879]:
...
[4980 .. 4989]: [4980 .. 4989]:
[4990 .. 4999]: [4990 .. 4999]:
[5000 .. 272563]: # [5000 .. 271690]: #
Estimated landlock overhead (vs no-landlock): 424.2%
Full data including test with 0 depth, or 1000 rules:
https://fileshare.maowtm.org/landlock-20251230/index.html
[1]: https://lore.kernel.org/all/20250320190717.2287696-15-mic@digikod.net/
[2]: https://github.com/landlock-lsm/landlock-test-tools/pull/17
^ permalink raw reply
* Re: [PATCH v2] ima: Fallback to ctime check for FS without kstat.change_cookie
From: Jeff Layton @ 2026-01-20 22:24 UTC (permalink / raw)
To: Frederick Lawler
Cc: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Darrick J. Wong,
Christian Brauner, Josef Bacik, linux-kernel, linux-integrity,
linux-security-module, kernel-team
In-Reply-To: <aW_4V93kczhzFjQ3@CMGLRV3>
On Tue, 2026-01-20 at 15:49 -0600, Frederick Lawler wrote:
> On Tue, Jan 20, 2026 at 04:22:55PM -0500, Jeff Layton wrote:
> > On Tue, 2026-01-20 at 14:20 -0600, Frederick Lawler wrote:
> > > Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> > > introduced a means to track change detection for an inode
> > > via ctime updates, opposed to setting kstat.change_cookie to
> > > an i_version when calling into xfs_vn_getattr().
> > >
> > > This introduced a regression for IMA such that an action
> > > performed on a LOWER inode on a stacked file systems always
> > > requires a re-evaluation if the LOWER file system does not
> > > leverage kstat.change_cookie to track inode i_version or lacks
> > > i_version support all together.
> > >
> > > In the case of stacking XFS on XFS, an action on either the LOWER or UPPER
> > > will require re-evaluation. Stacking TPMFS on XFS for instance, once the
> > > inode is UPPER is mutated, IMA resumes normal behavior because TMPFS
> > > leverages generic_fillattr() to update the change cookie.
> > >
> > > This is because IMA caches kstat.change_cookie to compare against an
> > > inode's i_version directly in integrity_inode_attrs_changed(), and thus
> > > could be out of date depending on how file systems set
> > > kstat.change_cookie.
> > >
> > > To address this, require integrity_inode_attrs_changed() to query
> > > vfs_getattr_nosec() to compare the cached version against
> > > kstat.change_cookie directly. This ensures that when updates occur,
> > > we're accessing the same changed inode version on changes, and fallback
> > > to compare against kstat.ctime when STATX_CHANGE_COOKIE is missing from
> > > result mask.
> > >
> > > Lastly, because EVM still relies on querying and caching a inode's
> > > i_version directly, the integrity_inode_attrs_changed() falls back to the
> > > original inode.i_version != cached comparison.
> > >
> > > Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> > > Suggested-by: Jeff Layton <jlayton@kernel.org>
> > > Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> > > ---
> > > We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> > > struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> > > using multigrain ctime (as well as other file systems) for
> > > change detection in commit 1cf7e834a6fb ("xfs: switch to
> > > multigrain timestamps").
> > >
> > > Because file systems may implement i_version as they see fit, IMA
> > > caching may be behind as well as file systems that don't support/export
> > > i_version. Thus we're proposing to compare against the kstat.change_cookie
> > > directly to the cached version, and fall back to a ctime guard when
> > > that's not updated.
> > >
> > > EVM is largely left alone since there's no trivial way to query a file
> > > directly in the LSM call paths to obtain kstat.change_cookie &
> > > kstat.ctime to cache. Thus retains accessing i_version directly.
> > >
> > > Regression tests will be added to the Linux Test Project instead of
> > > selftest to help catch future file system changes that may impact
> > > future evaluation of IMA.
> > >
> > > I'd like this to be backported to at least 6.18 if possible.
> > >
> > > Below is a simplified test that demonstrates the issue:
> > >
> > > _fragment.config_
> > > CONFIG_XFS_FS=y
> > > CONFIG_OVERLAY_FS=y
> > > CONFIG_IMA=y
> > > CONFIG_IMA_WRITE_POLICY=y
> > > CONFIG_IMA_READ_POLICY=y
> > >
> > > _./test.sh_
> > >
> > > IMA_POLICY="/sys/kernel/security/ima/policy"
> > > TEST_BIN="/bin/date"
> > > MNT_BASE="/tmp/ima_test_root"
> > >
> > > mkdir -p "$MNT_BASE"
> > > mount -t tmpfs tmpfs "$MNT_BASE"
> > > mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
> > >
> > > dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
> > > mkfs.xfs -q "$MNT_BASE/xfs.img"
> > > mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
> > > cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
> > >
> > > mount -t overlay overlay -o \
> > > "lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
> > > "$MNT_BASE/ovl"
> > >
> > > echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
> > >
> > > target_prog="$MNT_BASE/ovl/test_prog"
> > > setpriv --reuid nobody "$target_prog"
> > > setpriv --reuid nobody "$target_prog"
> > > setpriv --reuid nobody "$target_prog"
> > >
> > > audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
> > >
> > > if [[ "$audit_count" -eq 1 ]]; then
> > > echo "PASS: Found exactly 1 audit event."
> > > else
> > > echo "FAIL: Expected 1 audit event, but found $audit_count."
> > > exit 1
> > > fi
> > > ---
> > > Changes since RFC:
> > > - Remove calls to I_IS_VERSION()
> > > - Function documentation/comments
> > > - Abide IMA/EVM change detection fallback invariants
> > > - Combined ctime guard into version for attributes struct
> > > - Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
> > > ---
> > > Changes in v2:
> > > - Updated commit description + message to clarify the problem.
> > > - compare struct timespec64 to avoid collision possibility [Roberto].
> > > - Don't check inode_attr_changed() in ima_check_last_writer()
> > > - Link to v1: https://lore.kernel.org/r/20260112-xfs-ima-fixup-v1-1-8d13b6001312@cloudflare.com
> > > ---
> > > include/linux/integrity.h | 40 ++++++++++++++++++++++++++++++++-----
> > > security/integrity/evm/evm_crypto.c | 4 +++-
> > > security/integrity/evm/evm_main.c | 5 ++---
> > > security/integrity/ima/ima_api.c | 20 +++++++++++++------
> > > security/integrity/ima/ima_main.c | 18 ++++++++++-------
> > > 5 files changed, 65 insertions(+), 22 deletions(-)
> > >
> > > diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> > > index f5842372359be5341b6870a43b92e695e8fc78af..46f57402b790c9c275b85f0b30819fa196fc20c7 100644
> > > --- a/include/linux/integrity.h
> > > +++ b/include/linux/integrity.h
> > > @@ -9,6 +9,8 @@
> > >
> > > #include <linux/fs.h>
> > > #include <linux/iversion.h>
> > > +#include <linux/kernel.h>
> > > +#include <linux/time64.h>
> > >
> > > enum integrity_status {
> > > INTEGRITY_PASS = 0,
> > > @@ -31,6 +33,7 @@ static inline void integrity_load_keys(void)
> > >
> > > /* An inode's attributes for detection of changes */
> > > struct integrity_inode_attributes {
> > > + struct timespec64 ctime;
> > > u64 version; /* track inode changes */
> > > unsigned long ino;
> > > dev_t dev;
> > > @@ -42,8 +45,10 @@ struct integrity_inode_attributes {
> > > */
> > > static inline void
> > > integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> > > - u64 i_version, const struct inode *inode)
> > > + u64 i_version, struct timespec64 ctime,
> > > + const struct inode *inode)
> > > {
> > > + attrs->ctime = ctime;
> > > attrs->version = i_version;
> > > attrs->dev = inode->i_sb->s_dev;
> > > attrs->ino = inode->i_ino;
> > > @@ -51,14 +56,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> > >
> > > /*
> > > * On stacked filesystems detect whether the inode or its content has changed.
> > > + *
> > > + * Must be called in process context.
> > > */
> > > static inline bool
> > > integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> > > - const struct inode *inode)
> > > + struct file *file, struct inode *inode)
> > > {
> > > - return (inode->i_sb->s_dev != attrs->dev ||
> > > - inode->i_ino != attrs->ino ||
> > > - !inode_eq_iversion(inode, attrs->version));
> > > + struct kstat stat;
> > > +
> > > + might_sleep();
> > > +
> > > + if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> > > + return true;
> > > +
> > > + /*
> > > + * EVM currently relies on backing inode i_version. While IS_I_VERSION
> > > + * is not a good indicator of i_version support, this still retains
> > > + * the logic such that a re-evaluation should still occur for EVM, and
> > > + * only for IMA if vfs_getattr_nosec() fails.
> > > + */
> > > + if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> > > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > > + AT_STATX_SYNC_AS_STAT))
> > > + return !IS_I_VERSION(inode) ||
> > > + !inode_eq_iversion(inode, attrs->version);
> >
> > Seems like a reasonable way to handle getattr failure, given the
> > limitations on EVM.
> >
> > > +
> > > + if (stat.result_mask & STATX_CHANGE_COOKIE)
> > > + return stat.change_cookie != attrs->version;
> > > +
> > > + if (stat.result_mask & STATX_CTIME)
> > > + return !timespec64_equal(&stat.ctime, &attrs->ctime);
> > > +
> > > + return true;
> > > }
> > >
> > >
> > > diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
> > > index a5e730ffda57fbc0a91124adaa77b946a12d08b4..361ee7b216247a0d6d2f518e82fb6e92dc355afe 100644
> > > --- a/security/integrity/evm/evm_crypto.c
> > > +++ b/security/integrity/evm/evm_crypto.c
> > > @@ -297,10 +297,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
> > > hmac_add_misc(desc, inode, type, data->digest);
> > >
> > > if (inode != d_backing_inode(dentry) && iint) {
> > > + struct timespec64 ctime = {0};
> > > +
> > > if (IS_I_VERSION(inode))
> > > i_version = inode_query_iversion(inode);
> >
> > It would be nice if you could change this codepath as well, but that
> > looks like a much bigger project. FWIW, I took a quick look:
> >
> > The problematic codepath is get/setxattr, which can call into this but
> > currently only receives a dentry and not a struct path. That would
> > probably have to be changed. I think it's doable but it's a fair bit of
> > yak shaving.
>
> Agreed. I was looking at that a couple weeks ago to include a patch 2
> for EVM, and came to the same conclusion. I did find struct iattr on the
> setxattr which has struct file *, but that seemed dubious to at best.
>
Yeah, it's not set in all cases. setxattr is a pathname-based
operation, so an open file sometimes just doesn't exist.
> Alternatively, create security_get/setxattr() equivalent hooks, or
> have an internal mapping of sorts.
>
>
Those are possibilities too.
A dentry without a mount is somewhat ambiguous though. IMO, it would be
best to just change all of the xattr_handler functions to take struct
path instead of a dentry.
Maybe a good topic for LSF/MM...
> > > integrity_inode_attrs_store(&iint->metadata_inode, i_version,
> > > - inode);
> > > + ctime, inode);
> > > }
> > >
> > > /* Portable EVM signatures must include an IMA hash */
> > > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> > > index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> > > --- a/security/integrity/evm/evm_main.c
> > > +++ b/security/integrity/evm/evm_main.c
> > > @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
> > > bool ret = false;
> > >
> > > if (iint) {
> > > - ret = (!IS_I_VERSION(metadata_inode) ||
> > > - integrity_inode_attrs_changed(&iint->metadata_inode,
> > > - metadata_inode));
> > > + ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> > > + NULL, metadata_inode);
> > > if (ret)
> > > iint->evm_status = INTEGRITY_UNKNOWN;
> > > }
> > > diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> > > index c35ea613c9f8d404ba4886e3b736c3bab29d1668..0d8e0a3ebd34b70bb1b4cc995aae5d4adc90a585 100644
> > > --- a/security/integrity/ima/ima_api.c
> > > +++ b/security/integrity/ima/ima_api.c
> > > @@ -254,6 +254,7 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> > > int length;
> > > void *tmpbuf;
> > > u64 i_version = 0;
> > > + struct timespec64 ctime = {0};
> > >
> > > /*
> > > * Always collect the modsig, because IMA might have already collected
> > > @@ -272,10 +273,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> > > * to an initial measurement/appraisal/audit, but was modified to
> > > * assume the file changed.
> > > */
> > > - result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> > > + result = vfs_getattr_nosec(&file->f_path, &stat,
> > > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > > AT_STATX_SYNC_AS_STAT);
> > > - if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> > > - i_version = stat.change_cookie;
> > > + if (!result) {
> > > + if (stat.result_mask & STATX_CHANGE_COOKIE)
> > > + i_version = stat.change_cookie;
> > > + if (stat.result_mask & STATX_CTIME)
> > > + ctime = stat.ctime;
> > > + }
> > > hash.hdr.algo = algo;
> > > hash.hdr.length = hash_digest_size[algo];
> > >
> > > @@ -305,11 +311,13 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> > >
> > > iint->ima_hash = tmpbuf;
> > > memcpy(iint->ima_hash, &hash, length);
> > > - if (real_inode == inode)
> > > + if (real_inode == inode) {
> > > iint->real_inode.version = i_version;
> > > - else
> > > + iint->real_inode.ctime = ctime;
> > > + } else {
> > > integrity_inode_attrs_store(&iint->real_inode, i_version,
> > > - real_inode);
> > > + ctime, real_inode);
> > > + }
> > >
> > > /* Possibly temporary failure due to type of read (eg. O_DIRECT) */
> > > if (!result)
> > > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > > index 5770cf691912aa912fc65280c59f5baac35dd725..54b638663c9743d39e5fb65711dbd9698b38e39b 100644
> > > --- a/security/integrity/ima/ima_main.c
> > > +++ b/security/integrity/ima/ima_main.c
> > > @@ -22,12 +22,14 @@
> > > #include <linux/mount.h>
> > > #include <linux/mman.h>
> > > #include <linux/slab.h>
> > > +#include <linux/stat.h>
> > > #include <linux/xattr.h>
> > > #include <linux/ima.h>
> > > #include <linux/fs.h>
> > > #include <linux/iversion.h>
> > > #include <linux/evm.h>
> > > #include <linux/crash_dump.h>
> > > +#include <linux/time64.h>
> > >
> > > #include "ima.h"
> > >
> > > @@ -199,10 +201,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
> > > &iint->atomic_flags);
> > > if ((iint->flags & IMA_NEW_FILE) ||
> > > vfs_getattr_nosec(&file->f_path, &stat,
> > > - STATX_CHANGE_COOKIE,
> > > - AT_STATX_SYNC_AS_STAT) ||
> > > - !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> > > - stat.change_cookie != iint->real_inode.version) {
> > > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > > + AT_STATX_SYNC_AS_STAT) ||
> > > + ((stat.result_mask & STATX_CHANGE_COOKIE) ?
> > > + stat.change_cookie != iint->real_inode.version :
> > > + (!(stat.result_mask & STATX_CTIME) ||
> > > + !timespec64_equal(&stat.ctime,
> > > + &iint->real_inode.ctime)))) {
> > > iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
> > > iint->measured_pcrs = 0;
> > > if (update)
> > > @@ -328,9 +333,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
> > > real_inode = d_real_inode(file_dentry(file));
> > > if (real_inode != inode &&
> > > (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> > > - if (!IS_I_VERSION(real_inode) ||
> > > - integrity_inode_attrs_changed(&iint->real_inode,
> > > - real_inode)) {
> > > + if (integrity_inode_attrs_changed(&iint->real_inode,
> > > + file, real_inode)) {
> > > iint->flags &= ~IMA_DONE_MASK;
> > > iint->measured_pcrs = 0;
> > > }
> > >
> > > ---
> > > base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> > > change-id: 20251212-xfs-ima-fixup-931780a62c2c
> > >
> > > Best regards,
> >
> > Looks like a good change overall. Thanks for fixing this up. I don't
> > know IMA or EVM very well, so FWIW:
>
> Thanks! Fun investigation & fix.
>
> >
> > Acked-by: Jeff Layton <jlayton@kernel.org>
--
Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH net-next v2 2/4] selftests/landlock: Move some UAPI header inclusions after libc ones
From: Mickaël Salaün @ 2026-01-20 21:46 UTC (permalink / raw)
To: Thomas Weißschuh
Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang, Günther Noack,
Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
John Fastabend, Stanislav Fomichev, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
KP Singh, Hao Luo, Jiri Olsa, netdev, linux-kernel, linux-api,
Arnd Bergmann, linux-kselftest, mptcp, linux-security-module, bpf,
libc-alpha, Carlos O'Donell, Adhemerval Zanella, Rich Felker,
klibc, Florian Weimer
In-Reply-To: <20260120-uapi-sockaddr-v2-2-63c319111cf6@linutronix.de>
On Tue, Jan 20, 2026 at 03:10:32PM +0100, Thomas Weißschuh wrote:
> Interleaving inclusions of UAPI headers and libc headers is problematic.
> Both sets of headers define conflicting symbols. To enable their
> coexistence a compatibility-mechanism is in place.
>
> An upcoming change will define 'struct sockaddr' from linux/socket.h.
> However sys/socket.h from libc does not yet handle this case and a
> symbol conflict will arise.
>
> Move the inclusion of all UAPI headers after the inclusion of the glibc
> ones, so the compatibility mechanism from the UAPI headers is used.
>
> Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Reviewed-by: Mickaël Salaün <mic@digikod.net>
Thanks!
> ---
> tools/testing/selftests/landlock/audit.h | 7 ++++---
> 1 file changed, 4 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/landlock/audit.h b/tools/testing/selftests/landlock/audit.h
> index 44eb433e9666..c12b16c690dc 100644
> --- a/tools/testing/selftests/landlock/audit.h
> +++ b/tools/testing/selftests/landlock/audit.h
> @@ -7,9 +7,6 @@
>
> #define _GNU_SOURCE
> #include <errno.h>
> -#include <linux/audit.h>
> -#include <linux/limits.h>
> -#include <linux/netlink.h>
> #include <regex.h>
> #include <stdbool.h>
> #include <stdint.h>
> @@ -20,6 +17,10 @@
> #include <sys/time.h>
> #include <unistd.h>
>
> +#include <linux/audit.h>
> +#include <linux/limits.h>
> +#include <linux/netlink.h>
> +
> #include "kselftest.h"
>
> #ifndef ARRAY_SIZE
>
> --
> 2.52.0
>
>
^ permalink raw reply
* Re: [PATCH v2] ima: Fallback to ctime check for FS without kstat.change_cookie
From: Frederick Lawler @ 2026-01-20 21:49 UTC (permalink / raw)
To: Jeff Layton
Cc: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Darrick J. Wong,
Christian Brauner, Josef Bacik, linux-kernel, linux-integrity,
linux-security-module, kernel-team
In-Reply-To: <1a7985c825cf4af3b2a87e89793ae0daf2bb9c49.camel@kernel.org>
On Tue, Jan 20, 2026 at 04:22:55PM -0500, Jeff Layton wrote:
> On Tue, 2026-01-20 at 14:20 -0600, Frederick Lawler wrote:
> > Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> > introduced a means to track change detection for an inode
> > via ctime updates, opposed to setting kstat.change_cookie to
> > an i_version when calling into xfs_vn_getattr().
> >
> > This introduced a regression for IMA such that an action
> > performed on a LOWER inode on a stacked file systems always
> > requires a re-evaluation if the LOWER file system does not
> > leverage kstat.change_cookie to track inode i_version or lacks
> > i_version support all together.
> >
> > In the case of stacking XFS on XFS, an action on either the LOWER or UPPER
> > will require re-evaluation. Stacking TPMFS on XFS for instance, once the
> > inode is UPPER is mutated, IMA resumes normal behavior because TMPFS
> > leverages generic_fillattr() to update the change cookie.
> >
> > This is because IMA caches kstat.change_cookie to compare against an
> > inode's i_version directly in integrity_inode_attrs_changed(), and thus
> > could be out of date depending on how file systems set
> > kstat.change_cookie.
> >
> > To address this, require integrity_inode_attrs_changed() to query
> > vfs_getattr_nosec() to compare the cached version against
> > kstat.change_cookie directly. This ensures that when updates occur,
> > we're accessing the same changed inode version on changes, and fallback
> > to compare against kstat.ctime when STATX_CHANGE_COOKIE is missing from
> > result mask.
> >
> > Lastly, because EVM still relies on querying and caching a inode's
> > i_version directly, the integrity_inode_attrs_changed() falls back to the
> > original inode.i_version != cached comparison.
> >
> > Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> > Suggested-by: Jeff Layton <jlayton@kernel.org>
> > Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> > ---
> > We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> > struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> > using multigrain ctime (as well as other file systems) for
> > change detection in commit 1cf7e834a6fb ("xfs: switch to
> > multigrain timestamps").
> >
> > Because file systems may implement i_version as they see fit, IMA
> > caching may be behind as well as file systems that don't support/export
> > i_version. Thus we're proposing to compare against the kstat.change_cookie
> > directly to the cached version, and fall back to a ctime guard when
> > that's not updated.
> >
> > EVM is largely left alone since there's no trivial way to query a file
> > directly in the LSM call paths to obtain kstat.change_cookie &
> > kstat.ctime to cache. Thus retains accessing i_version directly.
> >
> > Regression tests will be added to the Linux Test Project instead of
> > selftest to help catch future file system changes that may impact
> > future evaluation of IMA.
> >
> > I'd like this to be backported to at least 6.18 if possible.
> >
> > Below is a simplified test that demonstrates the issue:
> >
> > _fragment.config_
> > CONFIG_XFS_FS=y
> > CONFIG_OVERLAY_FS=y
> > CONFIG_IMA=y
> > CONFIG_IMA_WRITE_POLICY=y
> > CONFIG_IMA_READ_POLICY=y
> >
> > _./test.sh_
> >
> > IMA_POLICY="/sys/kernel/security/ima/policy"
> > TEST_BIN="/bin/date"
> > MNT_BASE="/tmp/ima_test_root"
> >
> > mkdir -p "$MNT_BASE"
> > mount -t tmpfs tmpfs "$MNT_BASE"
> > mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
> >
> > dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
> > mkfs.xfs -q "$MNT_BASE/xfs.img"
> > mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
> > cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
> >
> > mount -t overlay overlay -o \
> > "lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
> > "$MNT_BASE/ovl"
> >
> > echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
> >
> > target_prog="$MNT_BASE/ovl/test_prog"
> > setpriv --reuid nobody "$target_prog"
> > setpriv --reuid nobody "$target_prog"
> > setpriv --reuid nobody "$target_prog"
> >
> > audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
> >
> > if [[ "$audit_count" -eq 1 ]]; then
> > echo "PASS: Found exactly 1 audit event."
> > else
> > echo "FAIL: Expected 1 audit event, but found $audit_count."
> > exit 1
> > fi
> > ---
> > Changes since RFC:
> > - Remove calls to I_IS_VERSION()
> > - Function documentation/comments
> > - Abide IMA/EVM change detection fallback invariants
> > - Combined ctime guard into version for attributes struct
> > - Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
> > ---
> > Changes in v2:
> > - Updated commit description + message to clarify the problem.
> > - compare struct timespec64 to avoid collision possibility [Roberto].
> > - Don't check inode_attr_changed() in ima_check_last_writer()
> > - Link to v1: https://lore.kernel.org/r/20260112-xfs-ima-fixup-v1-1-8d13b6001312@cloudflare.com
> > ---
> > include/linux/integrity.h | 40 ++++++++++++++++++++++++++++++++-----
> > security/integrity/evm/evm_crypto.c | 4 +++-
> > security/integrity/evm/evm_main.c | 5 ++---
> > security/integrity/ima/ima_api.c | 20 +++++++++++++------
> > security/integrity/ima/ima_main.c | 18 ++++++++++-------
> > 5 files changed, 65 insertions(+), 22 deletions(-)
> >
> > diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> > index f5842372359be5341b6870a43b92e695e8fc78af..46f57402b790c9c275b85f0b30819fa196fc20c7 100644
> > --- a/include/linux/integrity.h
> > +++ b/include/linux/integrity.h
> > @@ -9,6 +9,8 @@
> >
> > #include <linux/fs.h>
> > #include <linux/iversion.h>
> > +#include <linux/kernel.h>
> > +#include <linux/time64.h>
> >
> > enum integrity_status {
> > INTEGRITY_PASS = 0,
> > @@ -31,6 +33,7 @@ static inline void integrity_load_keys(void)
> >
> > /* An inode's attributes for detection of changes */
> > struct integrity_inode_attributes {
> > + struct timespec64 ctime;
> > u64 version; /* track inode changes */
> > unsigned long ino;
> > dev_t dev;
> > @@ -42,8 +45,10 @@ struct integrity_inode_attributes {
> > */
> > static inline void
> > integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> > - u64 i_version, const struct inode *inode)
> > + u64 i_version, struct timespec64 ctime,
> > + const struct inode *inode)
> > {
> > + attrs->ctime = ctime;
> > attrs->version = i_version;
> > attrs->dev = inode->i_sb->s_dev;
> > attrs->ino = inode->i_ino;
> > @@ -51,14 +56,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> >
> > /*
> > * On stacked filesystems detect whether the inode or its content has changed.
> > + *
> > + * Must be called in process context.
> > */
> > static inline bool
> > integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> > - const struct inode *inode)
> > + struct file *file, struct inode *inode)
> > {
> > - return (inode->i_sb->s_dev != attrs->dev ||
> > - inode->i_ino != attrs->ino ||
> > - !inode_eq_iversion(inode, attrs->version));
> > + struct kstat stat;
> > +
> > + might_sleep();
> > +
> > + if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> > + return true;
> > +
> > + /*
> > + * EVM currently relies on backing inode i_version. While IS_I_VERSION
> > + * is not a good indicator of i_version support, this still retains
> > + * the logic such that a re-evaluation should still occur for EVM, and
> > + * only for IMA if vfs_getattr_nosec() fails.
> > + */
> > + if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > + AT_STATX_SYNC_AS_STAT))
> > + return !IS_I_VERSION(inode) ||
> > + !inode_eq_iversion(inode, attrs->version);
>
> Seems like a reasonable way to handle getattr failure, given the
> limitations on EVM.
>
> > +
> > + if (stat.result_mask & STATX_CHANGE_COOKIE)
> > + return stat.change_cookie != attrs->version;
> > +
> > + if (stat.result_mask & STATX_CTIME)
> > + return !timespec64_equal(&stat.ctime, &attrs->ctime);
> > +
> > + return true;
> > }
> >
> >
> > diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
> > index a5e730ffda57fbc0a91124adaa77b946a12d08b4..361ee7b216247a0d6d2f518e82fb6e92dc355afe 100644
> > --- a/security/integrity/evm/evm_crypto.c
> > +++ b/security/integrity/evm/evm_crypto.c
> > @@ -297,10 +297,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
> > hmac_add_misc(desc, inode, type, data->digest);
> >
> > if (inode != d_backing_inode(dentry) && iint) {
> > + struct timespec64 ctime = {0};
> > +
> > if (IS_I_VERSION(inode))
> > i_version = inode_query_iversion(inode);
>
> It would be nice if you could change this codepath as well, but that
> looks like a much bigger project. FWIW, I took a quick look:
>
> The problematic codepath is get/setxattr, which can call into this but
> currently only receives a dentry and not a struct path. That would
> probably have to be changed. I think it's doable but it's a fair bit of
> yak shaving.
Agreed. I was looking at that a couple weeks ago to include a patch 2
for EVM, and came to the same conclusion. I did find struct iattr on the
setxattr which has struct file *, but that seemed dubious to at best.
Alternatively, create security_get/setxattr() equivalent hooks, or
have an internal mapping of sorts.
>
> > integrity_inode_attrs_store(&iint->metadata_inode, i_version,
> > - inode);
> > + ctime, inode);
> > }
> >
> > /* Portable EVM signatures must include an IMA hash */
> > diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> > index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> > --- a/security/integrity/evm/evm_main.c
> > +++ b/security/integrity/evm/evm_main.c
> > @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
> > bool ret = false;
> >
> > if (iint) {
> > - ret = (!IS_I_VERSION(metadata_inode) ||
> > - integrity_inode_attrs_changed(&iint->metadata_inode,
> > - metadata_inode));
> > + ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> > + NULL, metadata_inode);
> > if (ret)
> > iint->evm_status = INTEGRITY_UNKNOWN;
> > }
> > diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> > index c35ea613c9f8d404ba4886e3b736c3bab29d1668..0d8e0a3ebd34b70bb1b4cc995aae5d4adc90a585 100644
> > --- a/security/integrity/ima/ima_api.c
> > +++ b/security/integrity/ima/ima_api.c
> > @@ -254,6 +254,7 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> > int length;
> > void *tmpbuf;
> > u64 i_version = 0;
> > + struct timespec64 ctime = {0};
> >
> > /*
> > * Always collect the modsig, because IMA might have already collected
> > @@ -272,10 +273,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> > * to an initial measurement/appraisal/audit, but was modified to
> > * assume the file changed.
> > */
> > - result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> > + result = vfs_getattr_nosec(&file->f_path, &stat,
> > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > AT_STATX_SYNC_AS_STAT);
> > - if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> > - i_version = stat.change_cookie;
> > + if (!result) {
> > + if (stat.result_mask & STATX_CHANGE_COOKIE)
> > + i_version = stat.change_cookie;
> > + if (stat.result_mask & STATX_CTIME)
> > + ctime = stat.ctime;
> > + }
> > hash.hdr.algo = algo;
> > hash.hdr.length = hash_digest_size[algo];
> >
> > @@ -305,11 +311,13 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> >
> > iint->ima_hash = tmpbuf;
> > memcpy(iint->ima_hash, &hash, length);
> > - if (real_inode == inode)
> > + if (real_inode == inode) {
> > iint->real_inode.version = i_version;
> > - else
> > + iint->real_inode.ctime = ctime;
> > + } else {
> > integrity_inode_attrs_store(&iint->real_inode, i_version,
> > - real_inode);
> > + ctime, real_inode);
> > + }
> >
> > /* Possibly temporary failure due to type of read (eg. O_DIRECT) */
> > if (!result)
> > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > index 5770cf691912aa912fc65280c59f5baac35dd725..54b638663c9743d39e5fb65711dbd9698b38e39b 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -22,12 +22,14 @@
> > #include <linux/mount.h>
> > #include <linux/mman.h>
> > #include <linux/slab.h>
> > +#include <linux/stat.h>
> > #include <linux/xattr.h>
> > #include <linux/ima.h>
> > #include <linux/fs.h>
> > #include <linux/iversion.h>
> > #include <linux/evm.h>
> > #include <linux/crash_dump.h>
> > +#include <linux/time64.h>
> >
> > #include "ima.h"
> >
> > @@ -199,10 +201,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
> > &iint->atomic_flags);
> > if ((iint->flags & IMA_NEW_FILE) ||
> > vfs_getattr_nosec(&file->f_path, &stat,
> > - STATX_CHANGE_COOKIE,
> > - AT_STATX_SYNC_AS_STAT) ||
> > - !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> > - stat.change_cookie != iint->real_inode.version) {
> > + STATX_CHANGE_COOKIE | STATX_CTIME,
> > + AT_STATX_SYNC_AS_STAT) ||
> > + ((stat.result_mask & STATX_CHANGE_COOKIE) ?
> > + stat.change_cookie != iint->real_inode.version :
> > + (!(stat.result_mask & STATX_CTIME) ||
> > + !timespec64_equal(&stat.ctime,
> > + &iint->real_inode.ctime)))) {
> > iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
> > iint->measured_pcrs = 0;
> > if (update)
> > @@ -328,9 +333,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
> > real_inode = d_real_inode(file_dentry(file));
> > if (real_inode != inode &&
> > (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> > - if (!IS_I_VERSION(real_inode) ||
> > - integrity_inode_attrs_changed(&iint->real_inode,
> > - real_inode)) {
> > + if (integrity_inode_attrs_changed(&iint->real_inode,
> > + file, real_inode)) {
> > iint->flags &= ~IMA_DONE_MASK;
> > iint->measured_pcrs = 0;
> > }
> >
> > ---
> > base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> > change-id: 20251212-xfs-ima-fixup-931780a62c2c
> >
> > Best regards,
>
> Looks like a good change overall. Thanks for fixing this up. I don't
> know IMA or EVM very well, so FWIW:
Thanks! Fun investigation & fix.
>
> Acked-by: Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* Re: [PATCH v2] ima: Fallback to ctime check for FS without kstat.change_cookie
From: Jeff Layton @ 2026-01-20 21:22 UTC (permalink / raw)
To: Frederick Lawler, Mimi Zohar, Roberto Sassu, Dmitry Kasatkin,
Eric Snowberg, Paul Moore, James Morris, Serge E. Hallyn,
Darrick J. Wong, Christian Brauner, Josef Bacik
Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team
In-Reply-To: <20260120-xfs-ima-fixup-v2-1-f332ead8b043@cloudflare.com>
On Tue, 2026-01-20 at 14:20 -0600, Frederick Lawler wrote:
> Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
> introduced a means to track change detection for an inode
> via ctime updates, opposed to setting kstat.change_cookie to
> an i_version when calling into xfs_vn_getattr().
>
> This introduced a regression for IMA such that an action
> performed on a LOWER inode on a stacked file systems always
> requires a re-evaluation if the LOWER file system does not
> leverage kstat.change_cookie to track inode i_version or lacks
> i_version support all together.
>
> In the case of stacking XFS on XFS, an action on either the LOWER or UPPER
> will require re-evaluation. Stacking TPMFS on XFS for instance, once the
> inode is UPPER is mutated, IMA resumes normal behavior because TMPFS
> leverages generic_fillattr() to update the change cookie.
>
> This is because IMA caches kstat.change_cookie to compare against an
> inode's i_version directly in integrity_inode_attrs_changed(), and thus
> could be out of date depending on how file systems set
> kstat.change_cookie.
>
> To address this, require integrity_inode_attrs_changed() to query
> vfs_getattr_nosec() to compare the cached version against
> kstat.change_cookie directly. This ensures that when updates occur,
> we're accessing the same changed inode version on changes, and fallback
> to compare against kstat.ctime when STATX_CHANGE_COOKIE is missing from
> result mask.
>
> Lastly, because EVM still relies on querying and caching a inode's
> i_version directly, the integrity_inode_attrs_changed() falls back to the
> original inode.i_version != cached comparison.
>
> Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
> Suggested-by: Jeff Layton <jlayton@kernel.org>
> Signed-off-by: Frederick Lawler <fred@cloudflare.com>
> ---
> We uncovered a case in kernels >= 6.13 where XFS is no longer updating
> struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
> using multigrain ctime (as well as other file systems) for
> change detection in commit 1cf7e834a6fb ("xfs: switch to
> multigrain timestamps").
>
> Because file systems may implement i_version as they see fit, IMA
> caching may be behind as well as file systems that don't support/export
> i_version. Thus we're proposing to compare against the kstat.change_cookie
> directly to the cached version, and fall back to a ctime guard when
> that's not updated.
>
> EVM is largely left alone since there's no trivial way to query a file
> directly in the LSM call paths to obtain kstat.change_cookie &
> kstat.ctime to cache. Thus retains accessing i_version directly.
>
> Regression tests will be added to the Linux Test Project instead of
> selftest to help catch future file system changes that may impact
> future evaluation of IMA.
>
> I'd like this to be backported to at least 6.18 if possible.
>
> Below is a simplified test that demonstrates the issue:
>
> _fragment.config_
> CONFIG_XFS_FS=y
> CONFIG_OVERLAY_FS=y
> CONFIG_IMA=y
> CONFIG_IMA_WRITE_POLICY=y
> CONFIG_IMA_READ_POLICY=y
>
> _./test.sh_
>
> IMA_POLICY="/sys/kernel/security/ima/policy"
> TEST_BIN="/bin/date"
> MNT_BASE="/tmp/ima_test_root"
>
> mkdir -p "$MNT_BASE"
> mount -t tmpfs tmpfs "$MNT_BASE"
> mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
>
> dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
> mkfs.xfs -q "$MNT_BASE/xfs.img"
> mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
> cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
>
> mount -t overlay overlay -o \
> "lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
> "$MNT_BASE/ovl"
>
> echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
>
> target_prog="$MNT_BASE/ovl/test_prog"
> setpriv --reuid nobody "$target_prog"
> setpriv --reuid nobody "$target_prog"
> setpriv --reuid nobody "$target_prog"
>
> audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
>
> if [[ "$audit_count" -eq 1 ]]; then
> echo "PASS: Found exactly 1 audit event."
> else
> echo "FAIL: Expected 1 audit event, but found $audit_count."
> exit 1
> fi
> ---
> Changes since RFC:
> - Remove calls to I_IS_VERSION()
> - Function documentation/comments
> - Abide IMA/EVM change detection fallback invariants
> - Combined ctime guard into version for attributes struct
> - Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
> ---
> Changes in v2:
> - Updated commit description + message to clarify the problem.
> - compare struct timespec64 to avoid collision possibility [Roberto].
> - Don't check inode_attr_changed() in ima_check_last_writer()
> - Link to v1: https://lore.kernel.org/r/20260112-xfs-ima-fixup-v1-1-8d13b6001312@cloudflare.com
> ---
> include/linux/integrity.h | 40 ++++++++++++++++++++++++++++++++-----
> security/integrity/evm/evm_crypto.c | 4 +++-
> security/integrity/evm/evm_main.c | 5 ++---
> security/integrity/ima/ima_api.c | 20 +++++++++++++------
> security/integrity/ima/ima_main.c | 18 ++++++++++-------
> 5 files changed, 65 insertions(+), 22 deletions(-)
>
> diff --git a/include/linux/integrity.h b/include/linux/integrity.h
> index f5842372359be5341b6870a43b92e695e8fc78af..46f57402b790c9c275b85f0b30819fa196fc20c7 100644
> --- a/include/linux/integrity.h
> +++ b/include/linux/integrity.h
> @@ -9,6 +9,8 @@
>
> #include <linux/fs.h>
> #include <linux/iversion.h>
> +#include <linux/kernel.h>
> +#include <linux/time64.h>
>
> enum integrity_status {
> INTEGRITY_PASS = 0,
> @@ -31,6 +33,7 @@ static inline void integrity_load_keys(void)
>
> /* An inode's attributes for detection of changes */
> struct integrity_inode_attributes {
> + struct timespec64 ctime;
> u64 version; /* track inode changes */
> unsigned long ino;
> dev_t dev;
> @@ -42,8 +45,10 @@ struct integrity_inode_attributes {
> */
> static inline void
> integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
> - u64 i_version, const struct inode *inode)
> + u64 i_version, struct timespec64 ctime,
> + const struct inode *inode)
> {
> + attrs->ctime = ctime;
> attrs->version = i_version;
> attrs->dev = inode->i_sb->s_dev;
> attrs->ino = inode->i_ino;
> @@ -51,14 +56,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
>
> /*
> * On stacked filesystems detect whether the inode or its content has changed.
> + *
> + * Must be called in process context.
> */
> static inline bool
> integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
> - const struct inode *inode)
> + struct file *file, struct inode *inode)
> {
> - return (inode->i_sb->s_dev != attrs->dev ||
> - inode->i_ino != attrs->ino ||
> - !inode_eq_iversion(inode, attrs->version));
> + struct kstat stat;
> +
> + might_sleep();
> +
> + if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
> + return true;
> +
> + /*
> + * EVM currently relies on backing inode i_version. While IS_I_VERSION
> + * is not a good indicator of i_version support, this still retains
> + * the logic such that a re-evaluation should still occur for EVM, and
> + * only for IMA if vfs_getattr_nosec() fails.
> + */
> + if (!file || vfs_getattr_nosec(&file->f_path, &stat,
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> + AT_STATX_SYNC_AS_STAT))
> + return !IS_I_VERSION(inode) ||
> + !inode_eq_iversion(inode, attrs->version);
Seems like a reasonable way to handle getattr failure, given the
limitations on EVM.
> +
> + if (stat.result_mask & STATX_CHANGE_COOKIE)
> + return stat.change_cookie != attrs->version;
> +
> + if (stat.result_mask & STATX_CTIME)
> + return !timespec64_equal(&stat.ctime, &attrs->ctime);
> +
> + return true;
> }
>
>
> diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
> index a5e730ffda57fbc0a91124adaa77b946a12d08b4..361ee7b216247a0d6d2f518e82fb6e92dc355afe 100644
> --- a/security/integrity/evm/evm_crypto.c
> +++ b/security/integrity/evm/evm_crypto.c
> @@ -297,10 +297,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
> hmac_add_misc(desc, inode, type, data->digest);
>
> if (inode != d_backing_inode(dentry) && iint) {
> + struct timespec64 ctime = {0};
> +
> if (IS_I_VERSION(inode))
> i_version = inode_query_iversion(inode);
It would be nice if you could change this codepath as well, but that
looks like a much bigger project. FWIW, I took a quick look:
The problematic codepath is get/setxattr, which can call into this but
currently only receives a dentry and not a struct path. That would
probably have to be changed. I think it's doable but it's a fair bit of
yak shaving.
> integrity_inode_attrs_store(&iint->metadata_inode, i_version,
> - inode);
> + ctime, inode);
> }
>
> /* Portable EVM signatures must include an IMA hash */
> diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
> index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
> bool ret = false;
>
> if (iint) {
> - ret = (!IS_I_VERSION(metadata_inode) ||
> - integrity_inode_attrs_changed(&iint->metadata_inode,
> - metadata_inode));
> + ret = integrity_inode_attrs_changed(&iint->metadata_inode,
> + NULL, metadata_inode);
> if (ret)
> iint->evm_status = INTEGRITY_UNKNOWN;
> }
> diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
> index c35ea613c9f8d404ba4886e3b736c3bab29d1668..0d8e0a3ebd34b70bb1b4cc995aae5d4adc90a585 100644
> --- a/security/integrity/ima/ima_api.c
> +++ b/security/integrity/ima/ima_api.c
> @@ -254,6 +254,7 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> int length;
> void *tmpbuf;
> u64 i_version = 0;
> + struct timespec64 ctime = {0};
>
> /*
> * Always collect the modsig, because IMA might have already collected
> @@ -272,10 +273,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
> * to an initial measurement/appraisal/audit, but was modified to
> * assume the file changed.
> */
> - result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
> + result = vfs_getattr_nosec(&file->f_path, &stat,
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> AT_STATX_SYNC_AS_STAT);
> - if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
> - i_version = stat.change_cookie;
> + if (!result) {
> + if (stat.result_mask & STATX_CHANGE_COOKIE)
> + i_version = stat.change_cookie;
> + if (stat.result_mask & STATX_CTIME)
> + ctime = stat.ctime;
> + }
> hash.hdr.algo = algo;
> hash.hdr.length = hash_digest_size[algo];
>
> @@ -305,11 +311,13 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
>
> iint->ima_hash = tmpbuf;
> memcpy(iint->ima_hash, &hash, length);
> - if (real_inode == inode)
> + if (real_inode == inode) {
> iint->real_inode.version = i_version;
> - else
> + iint->real_inode.ctime = ctime;
> + } else {
> integrity_inode_attrs_store(&iint->real_inode, i_version,
> - real_inode);
> + ctime, real_inode);
> + }
>
> /* Possibly temporary failure due to type of read (eg. O_DIRECT) */
> if (!result)
> diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> index 5770cf691912aa912fc65280c59f5baac35dd725..54b638663c9743d39e5fb65711dbd9698b38e39b 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -22,12 +22,14 @@
> #include <linux/mount.h>
> #include <linux/mman.h>
> #include <linux/slab.h>
> +#include <linux/stat.h>
> #include <linux/xattr.h>
> #include <linux/ima.h>
> #include <linux/fs.h>
> #include <linux/iversion.h>
> #include <linux/evm.h>
> #include <linux/crash_dump.h>
> +#include <linux/time64.h>
>
> #include "ima.h"
>
> @@ -199,10 +201,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
> &iint->atomic_flags);
> if ((iint->flags & IMA_NEW_FILE) ||
> vfs_getattr_nosec(&file->f_path, &stat,
> - STATX_CHANGE_COOKIE,
> - AT_STATX_SYNC_AS_STAT) ||
> - !(stat.result_mask & STATX_CHANGE_COOKIE) ||
> - stat.change_cookie != iint->real_inode.version) {
> + STATX_CHANGE_COOKIE | STATX_CTIME,
> + AT_STATX_SYNC_AS_STAT) ||
> + ((stat.result_mask & STATX_CHANGE_COOKIE) ?
> + stat.change_cookie != iint->real_inode.version :
> + (!(stat.result_mask & STATX_CTIME) ||
> + !timespec64_equal(&stat.ctime,
> + &iint->real_inode.ctime)))) {
> iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
> iint->measured_pcrs = 0;
> if (update)
> @@ -328,9 +333,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
> real_inode = d_real_inode(file_dentry(file));
> if (real_inode != inode &&
> (action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
> - if (!IS_I_VERSION(real_inode) ||
> - integrity_inode_attrs_changed(&iint->real_inode,
> - real_inode)) {
> + if (integrity_inode_attrs_changed(&iint->real_inode,
> + file, real_inode)) {
> iint->flags &= ~IMA_DONE_MASK;
> iint->measured_pcrs = 0;
> }
>
> ---
> base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
> change-id: 20251212-xfs-ima-fixup-931780a62c2c
>
> Best regards,
Looks like a good change overall. Thanks for fixing this up. I don't
know IMA or EVM very well, so FWIW:
Acked-by: Jeff Layton <jlayton@kernel.org>
^ permalink raw reply
* [PATCH v2] ima: Fallback to ctime check for FS without kstat.change_cookie
From: Frederick Lawler @ 2026-01-20 20:20 UTC (permalink / raw)
To: Mimi Zohar, Roberto Sassu, Dmitry Kasatkin, Eric Snowberg,
Paul Moore, James Morris, Serge E. Hallyn, Darrick J. Wong,
Christian Brauner, Josef Bacik, Jeff Layton
Cc: linux-kernel, linux-integrity, linux-security-module, kernel-team,
Frederick Lawler
Commit 1cf7e834a6fb ("xfs: switch to multigrain timestamps")
introduced a means to track change detection for an inode
via ctime updates, opposed to setting kstat.change_cookie to
an i_version when calling into xfs_vn_getattr().
This introduced a regression for IMA such that an action
performed on a LOWER inode on a stacked file systems always
requires a re-evaluation if the LOWER file system does not
leverage kstat.change_cookie to track inode i_version or lacks
i_version support all together.
In the case of stacking XFS on XFS, an action on either the LOWER or UPPER
will require re-evaluation. Stacking TPMFS on XFS for instance, once the
inode is UPPER is mutated, IMA resumes normal behavior because TMPFS
leverages generic_fillattr() to update the change cookie.
This is because IMA caches kstat.change_cookie to compare against an
inode's i_version directly in integrity_inode_attrs_changed(), and thus
could be out of date depending on how file systems set
kstat.change_cookie.
To address this, require integrity_inode_attrs_changed() to query
vfs_getattr_nosec() to compare the cached version against
kstat.change_cookie directly. This ensures that when updates occur,
we're accessing the same changed inode version on changes, and fallback
to compare against kstat.ctime when STATX_CHANGE_COOKIE is missing from
result mask.
Lastly, because EVM still relies on querying and caching a inode's
i_version directly, the integrity_inode_attrs_changed() falls back to the
original inode.i_version != cached comparison.
Link: https://lore.kernel.org/all/aTspr4_h9IU4EyrR@CMGLRV3
Suggested-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Frederick Lawler <fred@cloudflare.com>
---
We uncovered a case in kernels >= 6.13 where XFS is no longer updating
struct kstat.change_cookie on i_op getattr() access calls. Instead, XFS is
using multigrain ctime (as well as other file systems) for
change detection in commit 1cf7e834a6fb ("xfs: switch to
multigrain timestamps").
Because file systems may implement i_version as they see fit, IMA
caching may be behind as well as file systems that don't support/export
i_version. Thus we're proposing to compare against the kstat.change_cookie
directly to the cached version, and fall back to a ctime guard when
that's not updated.
EVM is largely left alone since there's no trivial way to query a file
directly in the LSM call paths to obtain kstat.change_cookie &
kstat.ctime to cache. Thus retains accessing i_version directly.
Regression tests will be added to the Linux Test Project instead of
selftest to help catch future file system changes that may impact
future evaluation of IMA.
I'd like this to be backported to at least 6.18 if possible.
Below is a simplified test that demonstrates the issue:
_fragment.config_
CONFIG_XFS_FS=y
CONFIG_OVERLAY_FS=y
CONFIG_IMA=y
CONFIG_IMA_WRITE_POLICY=y
CONFIG_IMA_READ_POLICY=y
_./test.sh_
IMA_POLICY="/sys/kernel/security/ima/policy"
TEST_BIN="/bin/date"
MNT_BASE="/tmp/ima_test_root"
mkdir -p "$MNT_BASE"
mount -t tmpfs tmpfs "$MNT_BASE"
mkdir -p "$MNT_BASE"/{xfs_disk,upper,work,ovl}
dd if=/dev/zero of="$MNT_BASE/xfs.img" bs=1M count=300
mkfs.xfs -q "$MNT_BASE/xfs.img"
mount "$MNT_BASE/xfs.img" "$MNT_BASE/xfs_disk"
cp "$TEST_BIN" "$MNT_BASE/xfs_disk/test_prog"
mount -t overlay overlay -o \
"lowerdir=$MNT_BASE/xfs_disk,upperdir=$MNT_BASE/upper,workdir=$MNT_BASE/work" \
"$MNT_BASE/ovl"
echo "audit func=BPRM_CHECK uid=$(id -u nobody)" > "$IMA_POLICY"
target_prog="$MNT_BASE/ovl/test_prog"
setpriv --reuid nobody "$target_prog"
setpriv --reuid nobody "$target_prog"
setpriv --reuid nobody "$target_prog"
audit_count=$(dmesg | grep -c "file=\"$target_prog\"")
if [[ "$audit_count" -eq 1 ]]; then
echo "PASS: Found exactly 1 audit event."
else
echo "FAIL: Expected 1 audit event, but found $audit_count."
exit 1
fi
---
Changes since RFC:
- Remove calls to I_IS_VERSION()
- Function documentation/comments
- Abide IMA/EVM change detection fallback invariants
- Combined ctime guard into version for attributes struct
- Link to RFC: https://lore.kernel.org/r/20251229-xfs-ima-fixup-v1-1-6a717c939f7c@cloudflare.com
---
Changes in v2:
- Updated commit description + message to clarify the problem.
- compare struct timespec64 to avoid collision possibility [Roberto].
- Don't check inode_attr_changed() in ima_check_last_writer()
- Link to v1: https://lore.kernel.org/r/20260112-xfs-ima-fixup-v1-1-8d13b6001312@cloudflare.com
---
include/linux/integrity.h | 40 ++++++++++++++++++++++++++++++++-----
security/integrity/evm/evm_crypto.c | 4 +++-
security/integrity/evm/evm_main.c | 5 ++---
security/integrity/ima/ima_api.c | 20 +++++++++++++------
security/integrity/ima/ima_main.c | 18 ++++++++++-------
5 files changed, 65 insertions(+), 22 deletions(-)
diff --git a/include/linux/integrity.h b/include/linux/integrity.h
index f5842372359be5341b6870a43b92e695e8fc78af..46f57402b790c9c275b85f0b30819fa196fc20c7 100644
--- a/include/linux/integrity.h
+++ b/include/linux/integrity.h
@@ -9,6 +9,8 @@
#include <linux/fs.h>
#include <linux/iversion.h>
+#include <linux/kernel.h>
+#include <linux/time64.h>
enum integrity_status {
INTEGRITY_PASS = 0,
@@ -31,6 +33,7 @@ static inline void integrity_load_keys(void)
/* An inode's attributes for detection of changes */
struct integrity_inode_attributes {
+ struct timespec64 ctime;
u64 version; /* track inode changes */
unsigned long ino;
dev_t dev;
@@ -42,8 +45,10 @@ struct integrity_inode_attributes {
*/
static inline void
integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
- u64 i_version, const struct inode *inode)
+ u64 i_version, struct timespec64 ctime,
+ const struct inode *inode)
{
+ attrs->ctime = ctime;
attrs->version = i_version;
attrs->dev = inode->i_sb->s_dev;
attrs->ino = inode->i_ino;
@@ -51,14 +56,39 @@ integrity_inode_attrs_store(struct integrity_inode_attributes *attrs,
/*
* On stacked filesystems detect whether the inode or its content has changed.
+ *
+ * Must be called in process context.
*/
static inline bool
integrity_inode_attrs_changed(const struct integrity_inode_attributes *attrs,
- const struct inode *inode)
+ struct file *file, struct inode *inode)
{
- return (inode->i_sb->s_dev != attrs->dev ||
- inode->i_ino != attrs->ino ||
- !inode_eq_iversion(inode, attrs->version));
+ struct kstat stat;
+
+ might_sleep();
+
+ if (inode->i_sb->s_dev != attrs->dev || inode->i_ino != attrs->ino)
+ return true;
+
+ /*
+ * EVM currently relies on backing inode i_version. While IS_I_VERSION
+ * is not a good indicator of i_version support, this still retains
+ * the logic such that a re-evaluation should still occur for EVM, and
+ * only for IMA if vfs_getattr_nosec() fails.
+ */
+ if (!file || vfs_getattr_nosec(&file->f_path, &stat,
+ STATX_CHANGE_COOKIE | STATX_CTIME,
+ AT_STATX_SYNC_AS_STAT))
+ return !IS_I_VERSION(inode) ||
+ !inode_eq_iversion(inode, attrs->version);
+
+ if (stat.result_mask & STATX_CHANGE_COOKIE)
+ return stat.change_cookie != attrs->version;
+
+ if (stat.result_mask & STATX_CTIME)
+ return !timespec64_equal(&stat.ctime, &attrs->ctime);
+
+ return true;
}
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index a5e730ffda57fbc0a91124adaa77b946a12d08b4..361ee7b216247a0d6d2f518e82fb6e92dc355afe 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -297,10 +297,12 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
hmac_add_misc(desc, inode, type, data->digest);
if (inode != d_backing_inode(dentry) && iint) {
+ struct timespec64 ctime = {0};
+
if (IS_I_VERSION(inode))
i_version = inode_query_iversion(inode);
integrity_inode_attrs_store(&iint->metadata_inode, i_version,
- inode);
+ ctime, inode);
}
/* Portable EVM signatures must include an IMA hash */
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 73d500a375cb37a54f295b0e1e93fd6e5d9ecddc..6a4e0e246005246d5700b1db590c1759242b9cb6 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -752,9 +752,8 @@ bool evm_metadata_changed(struct inode *inode, struct inode *metadata_inode)
bool ret = false;
if (iint) {
- ret = (!IS_I_VERSION(metadata_inode) ||
- integrity_inode_attrs_changed(&iint->metadata_inode,
- metadata_inode));
+ ret = integrity_inode_attrs_changed(&iint->metadata_inode,
+ NULL, metadata_inode);
if (ret)
iint->evm_status = INTEGRITY_UNKNOWN;
}
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index c35ea613c9f8d404ba4886e3b736c3bab29d1668..0d8e0a3ebd34b70bb1b4cc995aae5d4adc90a585 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -254,6 +254,7 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
int length;
void *tmpbuf;
u64 i_version = 0;
+ struct timespec64 ctime = {0};
/*
* Always collect the modsig, because IMA might have already collected
@@ -272,10 +273,15 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
* to an initial measurement/appraisal/audit, but was modified to
* assume the file changed.
*/
- result = vfs_getattr_nosec(&file->f_path, &stat, STATX_CHANGE_COOKIE,
+ result = vfs_getattr_nosec(&file->f_path, &stat,
+ STATX_CHANGE_COOKIE | STATX_CTIME,
AT_STATX_SYNC_AS_STAT);
- if (!result && (stat.result_mask & STATX_CHANGE_COOKIE))
- i_version = stat.change_cookie;
+ if (!result) {
+ if (stat.result_mask & STATX_CHANGE_COOKIE)
+ i_version = stat.change_cookie;
+ if (stat.result_mask & STATX_CTIME)
+ ctime = stat.ctime;
+ }
hash.hdr.algo = algo;
hash.hdr.length = hash_digest_size[algo];
@@ -305,11 +311,13 @@ int ima_collect_measurement(struct ima_iint_cache *iint, struct file *file,
iint->ima_hash = tmpbuf;
memcpy(iint->ima_hash, &hash, length);
- if (real_inode == inode)
+ if (real_inode == inode) {
iint->real_inode.version = i_version;
- else
+ iint->real_inode.ctime = ctime;
+ } else {
integrity_inode_attrs_store(&iint->real_inode, i_version,
- real_inode);
+ ctime, real_inode);
+ }
/* Possibly temporary failure due to type of read (eg. O_DIRECT) */
if (!result)
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5770cf691912aa912fc65280c59f5baac35dd725..54b638663c9743d39e5fb65711dbd9698b38e39b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -22,12 +22,14 @@
#include <linux/mount.h>
#include <linux/mman.h>
#include <linux/slab.h>
+#include <linux/stat.h>
#include <linux/xattr.h>
#include <linux/ima.h>
#include <linux/fs.h>
#include <linux/iversion.h>
#include <linux/evm.h>
#include <linux/crash_dump.h>
+#include <linux/time64.h>
#include "ima.h"
@@ -199,10 +201,13 @@ static void ima_check_last_writer(struct ima_iint_cache *iint,
&iint->atomic_flags);
if ((iint->flags & IMA_NEW_FILE) ||
vfs_getattr_nosec(&file->f_path, &stat,
- STATX_CHANGE_COOKIE,
- AT_STATX_SYNC_AS_STAT) ||
- !(stat.result_mask & STATX_CHANGE_COOKIE) ||
- stat.change_cookie != iint->real_inode.version) {
+ STATX_CHANGE_COOKIE | STATX_CTIME,
+ AT_STATX_SYNC_AS_STAT) ||
+ ((stat.result_mask & STATX_CHANGE_COOKIE) ?
+ stat.change_cookie != iint->real_inode.version :
+ (!(stat.result_mask & STATX_CTIME) ||
+ !timespec64_equal(&stat.ctime,
+ &iint->real_inode.ctime)))) {
iint->flags &= ~(IMA_DONE_MASK | IMA_NEW_FILE);
iint->measured_pcrs = 0;
if (update)
@@ -328,9 +333,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
real_inode = d_real_inode(file_dentry(file));
if (real_inode != inode &&
(action & IMA_DO_MASK) && (iint->flags & IMA_DONE_MASK)) {
- if (!IS_I_VERSION(real_inode) ||
- integrity_inode_attrs_changed(&iint->real_inode,
- real_inode)) {
+ if (integrity_inode_attrs_changed(&iint->real_inode,
+ file, real_inode)) {
iint->flags &= ~IMA_DONE_MASK;
iint->measured_pcrs = 0;
}
---
base-commit: 8f0b4cce4481fb22653697cced8d0d04027cb1e8
change-id: 20251212-xfs-ima-fixup-931780a62c2c
Best regards,
--
Frederick Lawler <fred@cloudflare.com>
^ permalink raw reply related
* Re: [PATCH tip/locking/core 0/6] compiler-context-analysis: Scoped init guards
From: Bart Van Assche @ 2026-01-20 18:24 UTC (permalink / raw)
To: Marco Elver, Peter Zijlstra, Ingo Molnar
Cc: Thomas Gleixner, Will Deacon, Boqun Feng, Waiman Long,
Christoph Hellwig, Steven Rostedt, kasan-dev, llvm, linux-crypto,
linux-doc, linux-security-module, linux-kernel
In-Reply-To: <20260119094029.1344361-1-elver@google.com>
On 1/19/26 1:05 AM, Marco Elver wrote:
> 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.
Although I haven't had the time yet to do an in-depth review, from a
quick look all patches in this series look good to me.
Thanks,
Bart.
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Lorenzo Stoakes @ 2026-01-20 16:50 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jason Gunthorpe, Andrew Morton, Jarkko Sakkinen, Dave Hansen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, Greg Kroah-Hartman, Dan Williams, Vishal Verma,
Dave Jiang, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Dave Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Christian König, 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 (Red Hat), 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
In-Reply-To: <9ff58468-a72d-4984-95f4-d0a60554705d@app.fastmail.com>
On Tue, Jan 20, 2026 at 05:44:29PM +0100, Arnd Bergmann wrote:
> On Tue, Jan 20, 2026, at 17:22, Lorenzo Stoakes wrote:
> > On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote:
> >> On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
> >> >
> >> > It strikes me that the key optimisation here is the inlining, now if the issue
> >> > is that ye olde compiler might choose not to inline very small functions (seems
> >> > unlikely) we could always throw in an __always_inline?
> >>
> >> I can think of three specific things going wrong with structures passed
> >> by value:
> >
> > I mean now you seem to be talking about it _in general_ which, _in theory_,
> > kills the whole concept of bitmap VMA flags _altogether_ really, or at
> > least any workable version of them.
>
> No, what I'm saying is "understand what the pitfalls are", not
> "don't do it". I think that is what Jason was also getting at.
>
> Arnd
Ack sure and your input is appreciated :) It's important to kick the tyres
and be aware of possible issues.
Actually I think now I understand where Jason's coming from - the by-value
cases will be const value for the most part - which should make life MUCH
easier for the compiler and avoid a lot of the issues you raised.
So _hopefully_ we're mitigated. Again as I said, in cases where we might
not be, I will take action to figure out workarounds.
I'm excited by the proposed approach in general (+ again thanks to Jason to
opening my eyes to the possibility in the first place), so perhaps a
_little_ defensive, as it allows for a like-for-like replacement generally
which should HUGELY speed up + simplify the transition :)
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Lorenzo Stoakes @ 2026-01-20 16:46 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Andrew Morton, 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
In-Reply-To: <20260120152245.GC1134360@nvidia.com>
On Tue, Jan 20, 2026 at 11:22:45AM -0400, Jason Gunthorpe wrote:
> On Tue, Jan 20, 2026 at 03:10:54PM +0000, Lorenzo Stoakes wrote:
> > The natural implication of what you're saying is that we can no longer use this
> > from _anywhere_ because - hey - passing this by value is bad so now _everything_
> > has to be re-written as:
>
> No, I'm not saying that, I'm saying this specific case where you are
> making an accessor to reach an unknown value located on the heap
OK it would have been helpful for you to say that! Sometimes reviews feel
like a ratcheting series of 'what do you actually mean?'s... :)
> should be using a pointer as both a matter of style and to simplify
> life for the compiler.
OK fine.
>
> > vma_flags_t flags_to_set = mk_vma_flags(<flags>);
> >
> > if (vma_flags_test(&flags, &flags_to_set)) { ... }
>
> This is quite a different situation, it is a known const at compile
> time value located on the stack.
Well as a const time thing it'll be optimised to just a value assuming
nothing changes flags_to_set in the mean time. You'd hope.
Note that we have xxx_mask() variants, such that you can do, e.g.:
vma_flags_t flags1 = mk_vma_flags(...);
vma_flags_t flags2 = mk_vma_flags(...);
if (vma_flags_test_mask(flags1, flags2)) {
...
}
ASIDE ->
NOTE: A likely use of this, and one I already added is so we can do
e.g.:
#define VMA_REMAP_FLAGS mk_vma_flags(VMA_IO_BIT, VMA_PFNMAP_BIT, \
VMA_DONTEXPAND_BIT, VMA_DONTDUMP_BIT)
...
if (vma_flagss_test_mask(flags, VMA_REMAP_FLAGS)) { ... }
Which would be effectively a const input anyway.
<- ASIDE
Or in a world where flags1 is a const pointer now:
if (vma_flags_test_mask(&flags1, flags2)) { ... }
Which makes the form... kinda weird. Then again it's consistent with other
forms which update flags1, ofc we name this separately, e.g. flags, to_test
or flags, to_set so I guess not such a problme.
Now, nobody is _likely_ to do e.g.:
if (vma_flags_test_mask(&vma1->flags, vma2->flags)) { ... }
In this situation, but they could.
However perhaps having one value pass-by-const-pointer and the other
by-value essentially documents the fact you're being dumb.
And if somebody really needs something like this (not sure why) we could
add something.
But yeah ok, I'll change this. It's more than this case it's also all the
test stuff but shouldn't be a really huge change.
>
> > If it was just changing this one function I'd still object as it makes it differ
> > from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
> > change it, but surely by this argument you're essentially objecting to the whole
> > series?
>
> I only think that if you are taking a heap input that is not of known
> value you should continue to pass by pointer as is generally expected
> in the C style we use.
Ack.
>
> And it isn't saying anything about the overall technique in the
> series, just a minor note about style.
OK good, though Arnd's reply feels more like a comment on the latter,
though only really doing pass-by-value for const values (in nearly all sane
cases) should hopefully mitigate.
>
> > I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> > conjured. Yes you wouldn't ordinarily pass something larger than a register size
> > by-value, but here the intent is for it to be inlined anyway right?
>
> Well, exactly, we don't normally pass things larger than an interger
> by value, that isn't the style, so I don't think it is such a great
> thing to introduce here kind of unnecessarily.
>
> The troubles I recently had were linked to odd things like gcov and
> very old still supported versions of gcc. Also I saw a power compiler
> make a very strange choice to not inline something that evaluated to a
> constant.
Right ok.
>
> Jason
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Arnd Bergmann @ 2026-01-20 16:44 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: Jason Gunthorpe, Andrew Morton, Jarkko Sakkinen, Dave Hansen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, Greg Kroah-Hartman, Dan Williams, Vishal Verma,
Dave Jiang, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Dave Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Christian König, 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 (Red Hat), 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
In-Reply-To: <44461883-a75c-466b-a278-97c4ab46b461@lucifer.local>
On Tue, Jan 20, 2026, at 17:22, Lorenzo Stoakes wrote:
> On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote:
>> On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
>> >
>> > It strikes me that the key optimisation here is the inlining, now if the issue
>> > is that ye olde compiler might choose not to inline very small functions (seems
>> > unlikely) we could always throw in an __always_inline?
>>
>> I can think of three specific things going wrong with structures passed
>> by value:
>
> I mean now you seem to be talking about it _in general_ which, _in theory_,
> kills the whole concept of bitmap VMA flags _altogether_ really, or at
> least any workable version of them.
No, what I'm saying is "understand what the pitfalls are", not
"don't do it". I think that is what Jason was also getting at.
Arnd
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Lorenzo Stoakes @ 2026-01-20 16:22 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Jason Gunthorpe, Andrew Morton, Jarkko Sakkinen, Dave Hansen,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, x86,
H. Peter Anvin, Greg Kroah-Hartman, Dan Williams, Vishal Verma,
Dave Jiang, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
Dave Airlie, Simona Vetter, Jani Nikula, Joonas Lahtinen,
Rodrigo Vivi, Tvrtko Ursulin, Christian König, 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 (Red Hat), 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
In-Reply-To: <1617ac60-6261-483d-aeb5-13aba5f477af@app.fastmail.com>
On Tue, Jan 20, 2026 at 05:00:28PM +0100, Arnd Bergmann wrote:
> On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
> > On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote:
> >
> > I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> > conjured. Yes you wouldn't ordinarily pass something larger than a register size
> > by-value, but here the intent is for it to be inlined anyway right?
> >
> > It strikes me that the key optimisation here is the inlining, now if the issue
> > is that ye olde compiler might choose not to inline very small functions (seems
> > unlikely) we could always throw in an __always_inline?
>
> I can think of three specific things going wrong with structures passed
> by value:
I mean now you seem to be talking about it _in general_ which, _in theory_,
kills the whole concept of bitmap VMA flags _altogether_ really, or at
least any workable version of them.
But... no.
I'm not going to not do this because of perceived possible issues with ppc
and mips.
It's not reasonable to hold up a necessary change for the future of the
kernel IMO, and we can find workarounds as necessary should anything
problematic actually occur in practice.
I am happy to do so as maintainer of this work :)
>
> - functions that cannot be inlined are bound by the ELF ABI, and
> several of them require structs to be passed on the stack regardless
> of the size. Most of the popular architectures seem fine here, but
> mips and powerpc look like they are affected.
I explicitly checked mips and it seemed fine, but not gone super deep.
>
> - The larger the struct is, the more architectures are affected.
> Parts of the amdgpu driver and the bcachefs file system ran into this
bcachefs is not in the kernel. We don't care about out-of-tree stuff by
convention.
amdgpu is more concerning, but...
> with 64-bit structures passed by value on 32-bit architectures
> causing horrible codegen even with inlining. I think it's
> usually fine up to a single register size.
...32-bit kernels are not ones where you would anticipate incredible
performance for one, for another if any significant issues arise we can
look at arch-specific workarounds.
I already have vma_flags_*_word*() helpers to do things 'the old way' in
the worst case. More can be added if and when anything arises.
Again, I don't think we should hold up the rest of the kernel (being able
to transition to not being arbitrarily limited by VMA count is very
important) on this basis.
Also I've checked 32-bit code generation which _seemed_ fine at a
glance. Of course again I've not good super deep on that.
>
> - clang's inlining algorithm works the other way round from gcc's:
> inlining into the root caller first and sometimes leaving tiny
> leaf function out of line unless you add __always_inline.
I already __always_inline all pertinent funcitons so hopefully that should
be no issue.
And for instance the assembly I shared earlier was built using clang, as I
now use clang for _all_ my builds locally.
>
> Arnd
Thanks, Lorenzo
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Arnd Bergmann @ 2026-01-20 16:00 UTC (permalink / raw)
To: Lorenzo Stoakes, Jason Gunthorpe
Cc: Andrew Morton, Jarkko Sakkinen, Dave Hansen, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, x86, H. Peter Anvin,
Greg Kroah-Hartman, Dan Williams, Vishal Verma, Dave Jiang,
Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann, Dave Airlie,
Simona Vetter, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, Christian König, 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 (Red Hat), 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
In-Reply-To: <488a0fd8-5d64-4907-873b-60cefee96979@lucifer.local>
On Tue, Jan 20, 2026, at 16:10, Lorenzo Stoakes wrote:
> On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote:
>
> I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> conjured. Yes you wouldn't ordinarily pass something larger than a register size
> by-value, but here the intent is for it to be inlined anyway right?
>
> It strikes me that the key optimisation here is the inlining, now if the issue
> is that ye olde compiler might choose not to inline very small functions (seems
> unlikely) we could always throw in an __always_inline?
I can think of three specific things going wrong with structures passed
by value:
- functions that cannot be inlined are bound by the ELF ABI, and
several of them require structs to be passed on the stack regardless
of the size. Most of the popular architectures seem fine here, but
mips and powerpc look like they are affected.
- The larger the struct is, the more architectures are affected.
Parts of the amdgpu driver and the bcachefs file system ran into this
with 64-bit structures passed by value on 32-bit architectures
causing horrible codegen even with inlining. I think it's
usually fine up to a single register size.
- clang's inlining algorithm works the other way round from gcc's:
inlining into the root caller first and sometimes leaving tiny
leaf function out of line unless you add __always_inline.
Arnd
^ permalink raw reply
* [PATCH] cipso: harden use of skb_cow() in cipso_v4_skbuff_setattr()
From: Will Rosenberg @ 2026-01-20 15:57 UTC (permalink / raw)
Cc: Will Rosenberg, Paul Moore, David S. Miller, David Ahern,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman, netdev,
linux-security-module, linux-kernel
In-Reply-To: <CAHC9VhR4d7WXOVR7Y9ee2+=-t2nThzOo-ySMB+5x_87LfBJbZw@mail.gmail.com>
If skb_cow() is passed a headroom <= -NET_SKB_PAD, it will trigger a
BUG. As a result, use cases should avoid calling with a headroom that
is negative to prevent triggering this issue.
This is the same code pattern fixed in Commit 58fc7342b529 ("ipv6:
BUG() in pskb_expand_head() as part of calipso_skbuff_setattr()").
In cipso_v4_skbuff_setattr(), len_delta can become negative, leading to
a negative headroom passed to skb_cow(). However, the BUG is not
triggerable because the condition headroom <= -NET_SKB_PAD cannot be
satisfied due to limits on the IPv4 options header size.
Avoid potential problems in the future by only using skb_cow() to grow
the skb headroom.
Signed-off-by: Will Rosenberg <whrosenb@asu.edu>
---
Notes:
Given that IPv4 option length should not change,
this may not be a worthwhile patch.
Apologies in advance if this ends up being a waste
of time.
net/ipv4/cipso_ipv4.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index 709021197e1c..32b951ebc0c2 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -2196,7 +2196,8 @@ int cipso_v4_skbuff_setattr(struct sk_buff *skb,
/* if we don't ensure enough headroom we could panic on the skb_push()
* call below so make sure we have enough, we are also "mangling" the
* packet so we should probably do a copy-on-write call anyway */
- ret_val = skb_cow(skb, skb_headroom(skb) + len_delta);
+ ret_val = skb_cow(skb,
+ skb_headroom(skb) + (len_delta > 0 ? len_delta : 0));
if (ret_val < 0)
return ret_val;
base-commit: 58bae918d73e3b6cd57d1e39fcf7c75c7dd1a8fe
--
2.34.1
^ permalink raw reply related
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Jason Gunthorpe @ 2026-01-20 15:22 UTC (permalink / raw)
To: Lorenzo Stoakes
Cc: Andrew Morton, 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
In-Reply-To: <488a0fd8-5d64-4907-873b-60cefee96979@lucifer.local>
On Tue, Jan 20, 2026 at 03:10:54PM +0000, Lorenzo Stoakes wrote:
> The natural implication of what you're saying is that we can no longer use this
> from _anywhere_ because - hey - passing this by value is bad so now _everything_
> has to be re-written as:
No, I'm not saying that, I'm saying this specific case where you are
making an accessor to reach an unknown value located on the heap
should be using a pointer as both a matter of style and to simplify
life for the compiler.
> vma_flags_t flags_to_set = mk_vma_flags(<flags>);
>
> if (vma_flags_test(&flags, &flags_to_set)) { ... }
This is quite a different situation, it is a known const at compile
time value located on the stack.
> If it was just changing this one function I'd still object as it makes it differ
> from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
> change it, but surely by this argument you're essentially objecting to the whole
> series?
I only think that if you are taking a heap input that is not of known
value you should continue to pass by pointer as is generally expected
in the C style we use.
And it isn't saying anything about the overall technique in the
series, just a minor note about style.
> I am not sure about this 'idiomatic kernel style' thing either, it feels rather
> conjured. Yes you wouldn't ordinarily pass something larger than a register size
> by-value, but here the intent is for it to be inlined anyway right?
Well, exactly, we don't normally pass things larger than an interger
by value, that isn't the style, so I don't think it is such a great
thing to introduce here kind of unnecessarily.
The troubles I recently had were linked to odd things like gcov and
very old still supported versions of gcc. Also I saw a power compiler
make a very strange choice to not inline something that evaluated to a
constant.
Jason
^ permalink raw reply
* Re: [PATCH RESEND 09/12] mm: make vm_area_desc utilise vma_flags_t only
From: Lorenzo Stoakes @ 2026-01-20 15:10 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Andrew Morton, 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
In-Reply-To: <20260120133619.GZ1134360@nvidia.com>
On Tue, Jan 20, 2026 at 09:36:19AM -0400, Jason Gunthorpe wrote:
> On Tue, Jan 20, 2026 at 09:46:05AM +0000, Lorenzo Stoakes wrote:
> > On Mon, Jan 19, 2026 at 07:14:03PM -0400, Jason Gunthorpe wrote:
> > > On Mon, Jan 19, 2026 at 09:19:11PM +0000, Lorenzo Stoakes wrote:
> > > > +static inline bool is_shared_maywrite(vma_flags_t flags)
> > > > +{
> > >
> > > I'm not sure it is ideal to pass this array by value? Seems like it
> > > might invite some negative optimizations since now the compiler has to
> > > optimze away a copy too.
> >
> > I really don't think so? This is inlined and thus collapses to a totally
> > standard vma_flags_test_all() which passes by value anyway.
>
> > Do you have specific examples or evidence the compiler will optimise poorly here
> > on that basis as compared to pass by reference? And pass by reference would
> > necessitate:
>
> I've recently seen enough cases of older compilers and other arches
> making weird choices to be a little concerened. In the above case
> there is no reason not to use a const pointer (and indeed that would
> be the expected idomatic kernel style), so why take chances is my
> thinking.
With respect Jason, you're going to have to do better than that.
The entire implementation is dependent on passing-by-value.
Right now we can do:
vma_flags_test(&flags, VMA_READ_BIT, VMA_WRITE_BIT, ...);
Which uses mk_vma_flags() in a macro to generalise to:
vma_flags_test(&flags, <vma_flags_t value>);
The natural implication of what you're saying is that we can no longer use this
from _anywhere_ because - hey - passing this by value is bad so now _everything_
has to be re-written as:
vma_flags_t flags_to_set = mk_vma_flags(<flags>);
if (vma_flags_test(&flags, &flags_to_set)) { ... }
Right?
But is even that ok? Because presumably these compilers can inline, so that is
basically equivalent to what the macro's doing so does that rule out the VMA
bitmap flags concept altogether...
For hand-waved 'old compilers' (ok, people who use old compilers should not
expect optimal code) or 'other arches' (unspecified)?
If it was just changing this one function I'd still object as it makes it differ
from _every other test predicate_ using vma_flags_t but maybe to humour you I'd
change it, but surely by this argument you're essentially objecting to the whole
series?
I find it really strange you're going down this road as it was you who suggested
this approach in the first place and had to convince me the compiler would
manage it!...
Maybe I'm missing something here...
I am not sure about this 'idiomatic kernel style' thing either, it feels rather
conjured. Yes you wouldn't ordinarily pass something larger than a register size
by-value, but here the intent is for it to be inlined anyway right?
It strikes me that the key optimisation here is the inlining, now if the issue
is that ye olde compiler might choose not to inline very small functions (seems
unlikely) we could always throw in an __always_inline?
But it seems rather silly for a one-liner?
If the concern is deeper (not optimising the bitmap operations) then aren't you
saying no to the whole concept of the series?
Out of interest I godbolted a bunch of architectures:
x86-64
riscv
mips
s390x
sparc
arm7 32-bit
loongarch
m68k
xtensa
And found the manual method vs. the pass-by-value macro method were equivalent
in each case as far as I could tell.
In the worst case if we hit a weirdo case we can always substitute something
manual I have all the vma_flags_*word*() stuff available (which I recall you
objecting to...!)
I may have completely the wrong end of the stick here?...
>
> Jason
Thanks, Lorenzo
^ permalink raw reply
* [PATCH] apparmor: replace strcpy with strscpy
From: Ryan Foster @ 2026-01-20 14:50 UTC (permalink / raw)
To: john.johansen
Cc: paul, jmorris, serge, apparmor, linux-security-module,
linux-kernel, Ryan Foster
Found by checkpatch. Replace strcpy() with strscpy() for safer
string handling per KSPP recommendations.
Two changes:
- apparmorfs.c: gen_symlink_name() uses tracked buffer size
- lib.c: aa_policy_init() uses exact allocation size
Link: https://github.com/KSPP/linux/issues/88
Signed-off-by: Ryan Foster <foster.ryan.r@gmail.com>
---
security/apparmor/apparmorfs.c | 2 +-
security/apparmor/lib.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 907bd2667e28..f38974231df2 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -1614,7 +1614,7 @@ static char *gen_symlink_name(int depth, const char *dirname, const char *fname)
return ERR_PTR(-ENOMEM);
for (; depth > 0; depth--) {
- strcpy(s, "../../");
+ strscpy(s, "../../", size);
s += 6;
size -= 6;
}
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 82dbb97ad406..7cb393f91a10 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -487,7 +487,7 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix,
} else {
hname = aa_str_alloc(strlen(name) + 1, gfp);
if (hname)
- strcpy(hname, name);
+ strscpy(hname, name, strlen(name) + 1);
}
if (!hname)
return false;
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 4/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-01-20 14:10 UTC (permalink / raw)
To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang,
Mickaël Salaün, Günther Noack, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa
Cc: netdev, linux-kernel, linux-api, Arnd Bergmann, linux-kselftest,
mptcp, linux-security-module, bpf, libc-alpha,
Carlos O'Donell, Adhemerval Zanella, Rich Felker, klibc,
Florian Weimer, Thomas Weißschuh
In-Reply-To: <20260120-uapi-sockaddr-v2-0-63c319111cf6@linutronix.de>
Various UAPI headers reference 'struct sockaddr'. Currently the
definition of this struct is pulled in from the libc header
sys/socket.h. This is problematic as it introduces a dependency
on a full userspace toolchain.
Instead expose a custom but compatible definition of 'struct sockaddr'
in the UAPI headers. It is guarded by the libc compatibility
infrastructure to avoid potential conflicts.
The compatibility symbol won't be supported by glibc right away,
but right now __UAPI_DEF_IF_IFNAMSIZ is not supported either,
so including the libc headers before the UAPI headers is broken anyways.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
include/linux/socket.h | 10 ----------
include/uapi/linux/if.h | 4 ----
include/uapi/linux/libc-compat.h | 12 ++++++++++++
include/uapi/linux/socket.h | 14 ++++++++++++++
4 files changed, 26 insertions(+), 14 deletions(-)
diff --git a/include/linux/socket.h b/include/linux/socket.h
index ec715ad4bf25..8363d4e0a044 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -28,16 +28,6 @@ extern void socket_seq_show(struct seq_file *seq);
typedef __kernel_sa_family_t sa_family_t;
-/*
- * 1003.1g requires sa_family_t and that sa_data is char.
- */
-
-/* Deprecated for in-kernel use. Use struct sockaddr_unsized instead. */
-struct sockaddr {
- sa_family_t sa_family; /* address family, AF_xxx */
- char sa_data[14]; /* 14 bytes of protocol address */
-};
-
/**
* struct sockaddr_unsized - Unspecified size sockaddr for callbacks
* @sa_family: Address family (AF_UNIX, AF_INET, AF_INET6, etc.)
diff --git a/include/uapi/linux/if.h b/include/uapi/linux/if.h
index 797ba2c1562a..a4bc54196a07 100644
--- a/include/uapi/linux/if.h
+++ b/include/uapi/linux/if.h
@@ -25,10 +25,6 @@
#include <linux/socket.h> /* for "struct sockaddr" et al */
#include <linux/compiler.h> /* for "__user" et al */
-#ifndef __KERNEL__
-#include <sys/socket.h> /* for struct sockaddr. */
-#endif
-
#if __UAPI_DEF_IF_IFNAMSIZ
#define IFNAMSIZ 16
#endif /* __UAPI_DEF_IF_IFNAMSIZ */
diff --git a/include/uapi/linux/libc-compat.h b/include/uapi/linux/libc-compat.h
index 0eca95ccb41e..13a06ce4e825 100644
--- a/include/uapi/linux/libc-compat.h
+++ b/include/uapi/linux/libc-compat.h
@@ -140,6 +140,13 @@
#endif /* _NETINET_IN_H */
+/* Definitions for socket.h */
+#if defined(_SYS_SOCKET_H)
+#define __UAPI_DEF_SOCKADDR 0
+#else
+#define __UAPI_DEF_SOCKADDR 1
+#endif
+
/* Definitions for xattr.h */
#if defined(_SYS_XATTR_H)
#define __UAPI_DEF_XATTR 0
@@ -221,6 +228,11 @@
#define __UAPI_DEF_IP6_MTUINFO 1
#endif
+/* Definitions for socket.h */
+#ifndef __UAPI_DEF_SOCKADDR
+#define __UAPI_DEF_SOCKADDR 1
+#endif
+
/* Definitions for xattr.h */
#ifndef __UAPI_DEF_XATTR
#define __UAPI_DEF_XATTR 1
diff --git a/include/uapi/linux/socket.h b/include/uapi/linux/socket.h
index d3fcd3b5ec53..35d7d5f4b1a8 100644
--- a/include/uapi/linux/socket.h
+++ b/include/uapi/linux/socket.h
@@ -2,6 +2,8 @@
#ifndef _UAPI_LINUX_SOCKET_H
#define _UAPI_LINUX_SOCKET_H
+#include <linux/libc-compat.h> /* for compatibility with glibc */
+
/*
* Desired design of maximum size and alignment (see RFC2553)
*/
@@ -26,6 +28,18 @@ struct __kernel_sockaddr_storage {
};
};
+/*
+ * 1003.1g requires sa_family_t and that sa_data is char.
+ */
+
+/* Deprecated for in-kernel use. Use struct sockaddr_unsized instead. */
+#if __UAPI_DEF_SOCKADDR
+struct sockaddr {
+ __kernel_sa_family_t sa_family; /* address family, AF_xxx */
+ char sa_data[14]; /* 14 bytes of protocol address */
+};
+#endif /* __UAPI_DEF_SOCKADDR */
+
#define SOCK_SNDBUF_LOCK 1
#define SOCK_RCVBUF_LOCK 2
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 3/4] samples/bpf: Move some UAPI header inclusions after libc ones
From: Thomas Weißschuh @ 2026-01-20 14:10 UTC (permalink / raw)
To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang,
Mickaël Salaün, Günther Noack, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa
Cc: netdev, linux-kernel, linux-api, Arnd Bergmann, linux-kselftest,
mptcp, linux-security-module, bpf, libc-alpha,
Carlos O'Donell, Adhemerval Zanella, Rich Felker, klibc,
Florian Weimer, Thomas Weißschuh
In-Reply-To: <20260120-uapi-sockaddr-v2-0-63c319111cf6@linutronix.de>
Interleaving inclusions of UAPI headers and libc headers is problematic.
Both sets of headers define conflicting symbols. To enable their
coexistence a compatibility-mechanism is in place.
An upcoming change will define 'struct sockaddr' from linux/socket.h.
However sys/socket.h from libc does not yet handle this case and a
symbol conflict will arise.
Move the inclusion of all UAPI headers after the inclusion of the glibc
ones, so the compatibility mechanism from the UAPI headers is used.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
samples/bpf/xdp_adjust_tail_user.c | 6 ++++--
samples/bpf/xdp_fwd_user.c | 7 ++++---
samples/bpf/xdp_router_ipv4_user.c | 6 +++---
samples/bpf/xdp_sample_user.c | 15 ++++++++-------
samples/bpf/xdp_tx_iptunnel_user.c | 4 ++--
5 files changed, 21 insertions(+), 17 deletions(-)
diff --git a/samples/bpf/xdp_adjust_tail_user.c b/samples/bpf/xdp_adjust_tail_user.c
index e9426bd65420..32d00405debc 100644
--- a/samples/bpf/xdp_adjust_tail_user.c
+++ b/samples/bpf/xdp_adjust_tail_user.c
@@ -5,8 +5,6 @@
* modify it under the terms of version 2 of the GNU General Public
* License as published by the Free Software Foundation.
*/
-#include <linux/bpf.h>
-#include <linux/if_link.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
@@ -18,9 +16,13 @@
#include <netinet/ether.h>
#include <unistd.h>
#include <time.h>
+
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
+#include <linux/bpf.h>
+#include <linux/if_link.h>
+
#define STATS_INTERVAL_S 2U
#define MAX_PCKT_SIZE 600
diff --git a/samples/bpf/xdp_fwd_user.c b/samples/bpf/xdp_fwd_user.c
index 193b3b79b31f..ca55f3eac12a 100644
--- a/samples/bpf/xdp_fwd_user.c
+++ b/samples/bpf/xdp_fwd_user.c
@@ -11,9 +11,6 @@
* General Public License for more details.
*/
-#include <linux/bpf.h>
-#include <linux/if_link.h>
-#include <linux/limits.h>
#include <net/if.h>
#include <errno.h>
#include <stdio.h>
@@ -27,6 +24,10 @@
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
+#include <linux/bpf.h>
+#include <linux/if_link.h>
+#include <linux/limits.h>
+
static __u32 xdp_flags = XDP_FLAGS_UPDATE_IF_NOEXIST;
static int do_attach(int idx, int prog_fd, int map_fd, const char *name)
diff --git a/samples/bpf/xdp_router_ipv4_user.c b/samples/bpf/xdp_router_ipv4_user.c
index 266fdd0b025d..2abc7d294251 100644
--- a/samples/bpf/xdp_router_ipv4_user.c
+++ b/samples/bpf/xdp_router_ipv4_user.c
@@ -1,9 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (C) 2017 Cavium, Inc.
*/
-#include <linux/bpf.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
@@ -25,6 +22,9 @@
#include <libgen.h>
#include <getopt.h>
#include <pthread.h>
+#include <linux/bpf.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
#include "xdp_sample_user.h"
#include "xdp_router_ipv4.skel.h"
diff --git a/samples/bpf/xdp_sample_user.c b/samples/bpf/xdp_sample_user.c
index 158682852162..d9aec2bd372c 100644
--- a/samples/bpf/xdp_sample_user.c
+++ b/samples/bpf/xdp_sample_user.c
@@ -7,13 +7,6 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
-#include <linux/ethtool.h>
-#include <linux/hashtable.h>
-#include <linux/if_link.h>
-#include <linux/jhash.h>
-#include <linux/limits.h>
-#include <linux/list.h>
-#include <linux/sockios.h>
#include <locale.h>
#include <math.h>
#include <net/if.h>
@@ -32,6 +25,14 @@
#include <time.h>
#include <unistd.h>
+#include <linux/ethtool.h>
+#include <linux/hashtable.h>
+#include <linux/if_link.h>
+#include <linux/jhash.h>
+#include <linux/limits.h>
+#include <linux/list.h>
+#include <linux/sockios.h>
+
#include "bpf_util.h"
#include "xdp_sample_user.h"
diff --git a/samples/bpf/xdp_tx_iptunnel_user.c b/samples/bpf/xdp_tx_iptunnel_user.c
index 7e4b2f7108a6..e9503036d0a0 100644
--- a/samples/bpf/xdp_tx_iptunnel_user.c
+++ b/samples/bpf/xdp_tx_iptunnel_user.c
@@ -1,8 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016 Facebook
*/
-#include <linux/bpf.h>
-#include <linux/if_link.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
@@ -16,6 +14,8 @@
#include <time.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
+#include <linux/bpf.h>
+#include <linux/if_link.h>
#include "bpf_util.h"
#include "xdp_tx_iptunnel_common.h"
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 1/4] selftests: net: Move some UAPI header inclusions after libc ones
From: Thomas Weißschuh @ 2026-01-20 14:10 UTC (permalink / raw)
To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang,
Mickaël Salaün, Günther Noack, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa
Cc: netdev, linux-kernel, linux-api, Arnd Bergmann, linux-kselftest,
mptcp, linux-security-module, bpf, libc-alpha,
Carlos O'Donell, Adhemerval Zanella, Rich Felker, klibc,
Florian Weimer, Thomas Weißschuh
In-Reply-To: <20260120-uapi-sockaddr-v2-0-63c319111cf6@linutronix.de>
Interleaving inclusions of UAPI headers and libc headers is problematic.
Both sets of headers define conflicting symbols. To enable their
coexistence a compatibility-mechanism is in place.
An upcoming change will define 'struct sockaddr' from linux/socket.h.
However sys/socket.h from libc does not yet handle this case and a
symbol conflict will arise.
Furthermore libc-compat.h evaluates the state of the libc
inclusions only once, at the point it is included first. If another
problematic header from libc is included later, symbol conflicts arise.
This will trigger other duplicate definitions when linux/libc-compat.h
is added to linux/socket.h
Move the inclusion of UAPI headers after the inclusion of the glibc
ones, so the libc-compat.h continues to work correctly.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/net/af_unix/diag_uid.c | 9 +++++----
tools/testing/selftests/net/busy_poller.c | 3 ++-
tools/testing/selftests/net/mptcp/mptcp_diag.c | 11 ++++++-----
tools/testing/selftests/net/nettest.c | 4 ++--
tools/testing/selftests/net/tcp_ao/icmps-discard.c | 6 +++---
tools/testing/selftests/net/tcp_ao/lib/netlink.c | 9 +++++----
tools/testing/selftests/net/tun.c | 5 +++--
7 files changed, 26 insertions(+), 21 deletions(-)
diff --git a/tools/testing/selftests/net/af_unix/diag_uid.c b/tools/testing/selftests/net/af_unix/diag_uid.c
index da7d50cedee6..05456a205325 100644
--- a/tools/testing/selftests/net/af_unix/diag_uid.c
+++ b/tools/testing/selftests/net/af_unix/diag_uid.c
@@ -5,15 +5,16 @@
#include <sched.h>
#include <unistd.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/sock_diag.h>
-#include <linux/unix_diag.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/un.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/sock_diag.h>
+#include <linux/unix_diag.h>
+
#include "kselftest_harness.h"
FIXTURE(diag_uid)
diff --git a/tools/testing/selftests/net/busy_poller.c b/tools/testing/selftests/net/busy_poller.c
index 3a81f9c94795..34bd8d28808a 100644
--- a/tools/testing/selftests/net/busy_poller.c
+++ b/tools/testing/selftests/net/busy_poller.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <string.h>
#include <unistd.h>
-#include <ynl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
@@ -19,6 +18,8 @@
#include <sys/socket.h>
#include <sys/types.h>
+#include <ynl.h>
+
#include <linux/genetlink.h>
#include <linux/netlink.h>
diff --git a/tools/testing/selftests/net/mptcp/mptcp_diag.c b/tools/testing/selftests/net/mptcp/mptcp_diag.c
index 8e0b1b8d84b6..af25ebfd2915 100644
--- a/tools/testing/selftests/net/mptcp/mptcp_diag.c
+++ b/tools/testing/selftests/net/mptcp/mptcp_diag.c
@@ -1,11 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2025, Kylin Software */
-#include <linux/sock_diag.h>
-#include <linux/rtnetlink.h>
-#include <linux/inet_diag.h>
-#include <linux/netlink.h>
-#include <linux/compiler.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <linux/tcp.h>
@@ -17,6 +12,12 @@
#include <errno.h>
#include <stdio.h>
+#include <linux/sock_diag.h>
+#include <linux/rtnetlink.h>
+#include <linux/inet_diag.h>
+#include <linux/netlink.h>
+#include <linux/compiler.h>
+
#ifndef IPPROTO_MPTCP
#define IPPROTO_MPTCP 262
#endif
diff --git a/tools/testing/selftests/net/nettest.c b/tools/testing/selftests/net/nettest.c
index 1f5227f3d64d..71430403b50b 100644
--- a/tools/testing/selftests/net/nettest.c
+++ b/tools/testing/selftests/net/nettest.c
@@ -10,8 +10,6 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/wait.h>
-#include <linux/tcp.h>
-#include <linux/udp.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -30,6 +28,8 @@
#include <errno.h>
#include <getopt.h>
+#include <linux/tcp.h>
+#include <linux/udp.h>
#include <linux/xfrm.h>
#include <linux/ipsec.h>
#include <linux/pfkeyv2.h>
diff --git a/tools/testing/selftests/net/tcp_ao/icmps-discard.c b/tools/testing/selftests/net/tcp_ao/icmps-discard.c
index 85c1a1e958c6..451ba89914c9 100644
--- a/tools/testing/selftests/net/tcp_ao/icmps-discard.c
+++ b/tools/testing/selftests/net/tcp_ao/icmps-discard.c
@@ -16,12 +16,12 @@
* Author: Dmitry Safonov <dima@arista.com>
*/
#include <inttypes.h>
-#include <linux/icmp.h>
-#include <linux/icmpv6.h>
-#include <linux/ipv6.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
+#include <linux/icmp.h>
+#include <linux/icmpv6.h>
+#include <linux/ipv6.h>
#include "aolib.h"
#include "../../../../include/linux/compiler.h"
diff --git a/tools/testing/selftests/net/tcp_ao/lib/netlink.c b/tools/testing/selftests/net/tcp_ao/lib/netlink.c
index 7f108493a29a..69a05820782a 100644
--- a/tools/testing/selftests/net/tcp_ao/lib/netlink.c
+++ b/tools/testing/selftests/net/tcp_ao/lib/netlink.c
@@ -1,14 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
/* Original from tools/testing/selftests/net/ipsec.c */
-#include <linux/netlink.h>
-#include <linux/random.h>
-#include <linux/rtnetlink.h>
-#include <linux/veth.h>
#include <net/if.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <linux/random.h>
+#include <linux/rtnetlink.h>
+#include <linux/veth.h>
+
#include "aolib.h"
#define MAX_PAYLOAD 2048
diff --git a/tools/testing/selftests/net/tun.c b/tools/testing/selftests/net/tun.c
index 0efc67b0357a..e6e4c52d538e 100644
--- a/tools/testing/selftests/net/tun.c
+++ b/tools/testing/selftests/net/tun.c
@@ -8,12 +8,13 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
#include <linux/if.h>
#include <linux/if_tun.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
#include "kselftest_harness.h"
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 2/4] selftests/landlock: Move some UAPI header inclusions after libc ones
From: Thomas Weißschuh @ 2026-01-20 14:10 UTC (permalink / raw)
To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang,
Mickaël Salaün, Günther Noack, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa
Cc: netdev, linux-kernel, linux-api, Arnd Bergmann, linux-kselftest,
mptcp, linux-security-module, bpf, libc-alpha,
Carlos O'Donell, Adhemerval Zanella, Rich Felker, klibc,
Florian Weimer, Thomas Weißschuh
In-Reply-To: <20260120-uapi-sockaddr-v2-0-63c319111cf6@linutronix.de>
Interleaving inclusions of UAPI headers and libc headers is problematic.
Both sets of headers define conflicting symbols. To enable their
coexistence a compatibility-mechanism is in place.
An upcoming change will define 'struct sockaddr' from linux/socket.h.
However sys/socket.h from libc does not yet handle this case and a
symbol conflict will arise.
Move the inclusion of all UAPI headers after the inclusion of the glibc
ones, so the compatibility mechanism from the UAPI headers is used.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
tools/testing/selftests/landlock/audit.h | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/landlock/audit.h b/tools/testing/selftests/landlock/audit.h
index 44eb433e9666..c12b16c690dc 100644
--- a/tools/testing/selftests/landlock/audit.h
+++ b/tools/testing/selftests/landlock/audit.h
@@ -7,9 +7,6 @@
#define _GNU_SOURCE
#include <errno.h>
-#include <linux/audit.h>
-#include <linux/limits.h>
-#include <linux/netlink.h>
#include <regex.h>
#include <stdbool.h>
#include <stdint.h>
@@ -20,6 +17,10 @@
#include <sys/time.h>
#include <unistd.h>
+#include <linux/audit.h>
+#include <linux/limits.h>
+#include <linux/netlink.h>
+
#include "kselftest.h"
#ifndef ARRAY_SIZE
--
2.52.0
^ permalink raw reply related
* [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-01-20 14:10 UTC (permalink / raw)
To: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
David S. Miller, Jakub Kicinski, Simon Horman, Shuah Khan,
Matthieu Baerts, Mat Martineau, Geliang Tang,
Mickaël Salaün, Günther Noack, Alexei Starovoitov,
Daniel Borkmann, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, KP Singh, Hao Luo,
Jiri Olsa
Cc: netdev, linux-kernel, linux-api, Arnd Bergmann, linux-kselftest,
mptcp, linux-security-module, bpf, libc-alpha,
Carlos O'Donell, Adhemerval Zanella, Rich Felker, klibc,
Florian Weimer, Thomas Weißschuh
Various UAPI headers reference 'struct sockaddr'. Currently the
definition of this struct is pulled in from the libc header
sys/socket.h. This is problematic as it introduces a dependency
on a full userspace toolchain.
Add a definition of 'struct sockaddr' to the UAPI headers.
Before that, reorder some problematic header inclusions in the selftests.
Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
---
Changes in v2:
- Fix compilation failures in BPF samples and selftests
- Link to v1: https://lore.kernel.org/r/20260105-uapi-sockaddr-v1-1-b7653aba12a5@linutronix.de
---
Thomas Weißschuh (4):
selftests: net: Move some UAPI header inclusions after libc ones
selftests/landlock: Move some UAPI header inclusions after libc ones
samples/bpf: Move some UAPI header inclusions after libc ones
net: uapi: Provide an UAPI definition of 'struct sockaddr'
include/linux/socket.h | 10 ----------
include/uapi/linux/if.h | 4 ----
include/uapi/linux/libc-compat.h | 12 ++++++++++++
include/uapi/linux/socket.h | 14 ++++++++++++++
samples/bpf/xdp_adjust_tail_user.c | 6 ++++--
samples/bpf/xdp_fwd_user.c | 7 ++++---
samples/bpf/xdp_router_ipv4_user.c | 6 +++---
samples/bpf/xdp_sample_user.c | 15 ++++++++-------
samples/bpf/xdp_tx_iptunnel_user.c | 4 ++--
tools/testing/selftests/landlock/audit.h | 7 ++++---
tools/testing/selftests/net/af_unix/diag_uid.c | 9 +++++----
tools/testing/selftests/net/busy_poller.c | 3 ++-
tools/testing/selftests/net/mptcp/mptcp_diag.c | 11 ++++++-----
tools/testing/selftests/net/nettest.c | 4 ++--
tools/testing/selftests/net/tcp_ao/icmps-discard.c | 6 +++---
tools/testing/selftests/net/tcp_ao/lib/netlink.c | 9 +++++----
tools/testing/selftests/net/tun.c | 5 +++--
17 files changed, 77 insertions(+), 55 deletions(-)
---
base-commit: 24d479d26b25bce5faea3ddd9fa8f3a6c3129ea7
change-id: 20251222-uapi-sockaddr-cf10e7624729
Best regards,
--
Thomas Weißschuh <thomas.weissschuh@linutronix.de>
^ 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