Linux Security Modules development
 help / color / mirror / Atom feed
* Re: [PATCH v2 03/13] mm: add mk_vma_flags() bitmap flag macro helper
From: Lorenzo Stoakes @ 2026-02-09 14:02 UTC (permalink / raw)
  To: Pedro Falcato
  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, David Howells, Paul Moore, James Morris,
	Serge E . Hallyn, Yury Norov, Rasmus Villemoes, linux-sgx,
	linux-kernel, nvdimm, linux-cxl, dri-devel, intel-gfx,
	linux-fsdevel, linux-aio, linux-erofs, linux-ext4, linux-mm,
	ntfs3, devel, linux-xfs, keyrings, linux-security-module,
	Jason Gunthorpe
In-Reply-To: <mflwgdnyipdf4reufmbx7qarjcgouct5coe2bllticrabcu6rt@vf3bvmpunimw>

On Fri, Feb 06, 2026 at 05:14:10PM +0000, Pedro Falcato wrote:
> On Thu, Jan 22, 2026 at 04:06:12PM +0000, Lorenzo Stoakes wrote:
> > This patch introduces the mk_vma_flags() macro helper to allow easy
> > manipulation of VMA flags utilising the new bitmap representation
> > implemented of VMA flags defined by the vma_flags_t type.
> >
> > It is a variadic macro which provides a bitwise-or'd representation of all
> > of each individual VMA flag specified.
> >
> > Note that, while we maintain VM_xxx flags for backwards compatibility until
> > the conversion is complete, we define VMA flags of type vma_flag_t using
> > VMA_xxx_BIT to avoid confusing the two.
> >
> > This helper macro therefore can be used thusly:
> >
> > vma_flags_t flags = mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT);
> >
> > We allow for up to 5 flags to specified at a time which should accommodate
> > all current kernel uses of combined VMA flags.
> >
>
> How do you allow up to 5 flags? I don't see any such limitation in the code?

Yeah oops :) This is from a previous implementation.

Andrew could you drop this paragraph? Thanks!

>
> > Testing has demonstrated that the compiler optimises this code such that it
> > generates the same assembly utilising this macro as it does if the flags
> > were specified manually, for instance:
> >
> > vma_flags_t get_flags(void)
> > {
> > 	return mk_vma_flags(VMA_READ_BIT, VMA_WRITE_BIT, VMA_EXEC_BIT);
> > }
> >
> > Generates the same code as:
> >
> > vma_flags_t get_flags(void)
> > {
> > 	vma_flags_t flags;
> >
> > 	vma_flags_clear_all(&flags);
> > 	vma_flag_set(&flags, VMA_READ_BIT);
> > 	vma_flag_set(&flags, VMA_WRITE_BIT);
> > 	vma_flag_set(&flags, VMA_EXEC_BIT);
> >
> > 	return flags;
> > }
> >
> > And:
> >
> > vma_flags_t get_flags(void)
> > {
> > 	vma_flags_t flags;
> > 	unsigned long *bitmap = ACCESS_PRIVATE(&flags, __vma_flags);
> >
> > 	*bitmap = 1UL << (__force int)VMA_READ_BIT;
> > 	*bitmap |= 1UL << (__force int)VMA_WRITE_BIT;
> > 	*bitmap |= 1UL << (__force int)VMA_EXEC_BIT;
> >
> > 	return flags;
> > }
> >
> > That is:
> >
> > get_flags:
> >         movl    $7, %eax
> >         ret
> >
> > Suggested-by: Jason Gunthorpe <jgg@nvidia.com>
> > Signed-off-by: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
>
> Reviewed-by: Pedro Falcato <pfalcato@suse.de>

Thanks!

>
> --
> Pedro

Cheers, Lorenzo

^ permalink raw reply

* Re: [RFC PATCH] fs/pidfs: Add permission check to pidfd_info()
From: Christian Brauner @ 2026-02-09 14:01 UTC (permalink / raw)
  To: danieldurning.work
  Cc: linux-fsdevel, linux-security-module, selinux, viro, jack, paul,
	stephen.smalley.work, omosnace, Oleg Nesterov
In-Reply-To: <20260206180248.12418-1-danieldurning.work@gmail.com>

On Fri, Feb 06, 2026 at 06:02:48PM +0000, danieldurning.work@gmail.com wrote:
> From: Daniel Durning <danieldurning.work@gmail.com>
> 
> Added a permission check to pidfd_info(). Originally, process info
> could be retrieved with a pidfd even if proc was mounted with hidepid
> enabled, allowing pidfds to be used to bypass those protections. We
> now call ptrace_may_access() to perform some DAC checking as well
> as call the appropriate LSM hook.
> 
> The downside to this approach is that there are now more restrictions
> on accessing this info from a pidfd than when just using proc (without
> hidepid). I am open to suggestions if anyone can think of a better way
> to handle this.

This isn't really workable since this would regress userspace quite a
bit. I think we need a different approach. I've given it some thought
and everything's kinda ugly but this might work.

In struct pid_namespace record whether anyone ever mounted a procfs
with hidepid turned on for this pidns. In pidfd_info() we check whether
hidepid was ever turned on. If it wasn't we're done and can just return
the info. This will be the common case. If hidepid was ever turned on
use kern_path("/proc") to lookup procfs. If not found check
ptrace_may_access() to decide whether to return the info or not. If
/proc is found check it's hidepid settings and make a decision based on
that.

You can probably reorder this to call ptrace_may_access() first and then
do the procfs lookup dance. Thoughts?

> I have also noticed that it is possible to use pidfds to poll on any
> process regardless of whether the process is a child of the caller,
> has a different UID, or has a different security context. Is this
> also worth addressing? If so, what exactly should the DAC checks be?

Oleg and I had discusses this and decided that such polling isn't
sensitive information so by default this should just work and it's
relied upon in Android and in a bunch of other workloads. An LSM can of
course restrict access via security_file_ioctl().

Fwiw, pidfds now support persistent trusted extended attributes so if
the LSM folks wanted we can add security.* extended attribute support
and they can mark pidfds with persistent security labels - persistent as
in for the lifetime of the task.

> Signed-off-by: Daniel Durning <danieldurning.work@gmail.com>
> ---
>  fs/pidfs.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/fs/pidfs.c b/fs/pidfs.c
> index dba703d4ce4a..058a7d798bca 100644
> --- a/fs/pidfs.c
> +++ b/fs/pidfs.c
> @@ -365,6 +365,13 @@ static long pidfd_info(struct file *file, unsigned int cmd, unsigned long arg)
>  		goto copy_out;
>  	}
>  
> +	/*
> +	 * Do a filesystem cred ptrace check to verify access
> +	 * to the task's info.
> +	 */
> +	if (!ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS))
> +		return -EACCES;
> +
>  	c = get_task_cred(task);
>  	if (!c)
>  		return -ESRCH;
> -- 
> 2.52.0
> 

^ permalink raw reply

* Re: [PATCH net-next v2 0/4] net: uapi: Provide an UAPI definition of 'struct sockaddr'
From: Thomas Weißschuh @ 2026-02-09 13:34 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Eric Dumazet, Kuniyuki Iwashima, Paolo Abeni, Willem de Bruijn,
	David S. Miller, 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, 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: <20260204175516.4fb11966@kernel.org>

On Wed, Feb 04, 2026 at 05:55:16PM -0800, Jakub Kicinski wrote:
> On Wed, 4 Feb 2026 06:51:46 +0100 Thomas Weißschuh wrote:
> > > make -j16 O="$kobj" INSTALL_HDR_PATH="${kobj}/hdr" headers_install
> > > popd
> > > 
> > > pushd uapi
> > > find . -type f -name '*.h' -exec cp -v "${kobj}/hdr/include/{}" {} \;  
> > 
> > Here only those headers which already exist in ethtool's uapi/ directory
> > are copied. As linux/typelimits.h is new, it is now missing.
> > Honestly, if a user fiddles with the internals of the UAPI headers like
> > this, it is on them to update their code if the internal structure
> > changes. In your case a simple 'touch uapi/linux/typelimits.h'
> > before running the script will be enough. Also internal.h now requires
> > an explicit inclusion of <limits.h>, as that is not satisfied by the
> > UAPI anymore.
> 
> Hopefully you understand that while due to uapi header copy this is not
> a huge issue for ethtool itself, but it is a proof that your changes
> can break normal user space applications which do not vendor in uapi.

A regular application which uses a full UAPI headers tree will get
access to the new header automatically.
If the application uses symbols from <limits.h> without including <limits.h>
on its own, it is broken.


Thomas

^ permalink raw reply

* Re: [PATCH v4 2/6] landlock: Control pathname UNIX domain socket resolution by path
From: Justin Suess @ 2026-02-09 13:11 UTC (permalink / raw)
  To: Günther Noack, Günther Noack
  Cc: Mickaël Salaün, John Johansen, Tingmao Wang, Jann Horn,
	linux-security-module, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Tahera Fahimi
In-Reply-To: <aYm1RWtV6Af-zEHf@google.com>

On 2/9/26 05:21, Günther Noack wrote:
> On Mon, Feb 09, 2026 at 12:10:12AM +0100, Günther Noack wrote:
>> +static int hook_unix_find(const struct path *const path, struct sock *other,
>> +			  int flags)
>> +{
>> +	const struct landlock_ruleset *dom_other;
>> +	const struct landlock_cred_security *subject;
>> +	struct layer_access_masks layer_masks;
>> +	struct landlock_request request = {};
>> +	static const struct access_masks fs_resolve_unix = {
>> +		.fs = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
>> +	};
>> +	int type = other->sk_type;
>> +
>> +	/* Lookup for the purpose of saving coredumps is OK. */
>> +	if (flags & SOCK_COREDUMP)
>> +		return 0;   
if (unlikely(flags & SOCK_COREDUMP))
    return 0;
>> +
>> +	/* Only stream, dgram and seqpacket sockets are restricted. */
>> +	if (type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET)
>> +		return 0;
if (unlikely(type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET))
    return 0;
> FYI: This is a (highly speculative) safeguard, because these three
> socket types are the only ones that exist in AF_UNIX (compare unix(7),
> 2nd paragraph).
>
> In the (highly unlikely) case that someone adds a fourth AF_UNIX
> socket type, this means that Landlock will start permitting
> connections to these sockets unconditionally.
>
> I am unsure whether the safeguard is useful, or whether we should
> rather group that (highly unlikely) future socket type together with
> the existing ones.  *If you have opinions, I'd be interested.*
In that case, a new access right could be added for that new socket type.

So we should only handle the ones we expect for now, and reserve the option for future rights
to expand the capability.
>
> The fact that these are the only existing AF_UNIX socket types is also
> the reason why it does not matter that we are now (in v4) taking the
> type value from the server-side sk instead of the client socket.  The
> check will either way always pass as long as only these three types
> are the only ones.
Last time a new socket type for UDS (seqpacket) was added was 2.6.4.
UDS are also part of POSIX, so they're pretty standardized and not exactly likely to change.

>
> For now (and probably for another few decades :)), as long as these
> are the only AF_UNIX types, it does not make a difference though
> whether the check is there or not.
I think this is the correct choice.
>
> —Günther


^ permalink raw reply

* Re: [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Steffen Klassert @ 2026-02-09 11:22 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: Paul Moore, SELinux, linux-security-module, Herbert Xu,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Network Development
In-Reply-To: <85546d35-c7bd-49bf-b0c3-9677bde25859@I-love.SAKURA.ne.jp>

On Mon, Feb 09, 2026 at 07:02:47PM +0900, Tetsuo Handa wrote:
> On 2026/02/09 18:25, Steffen Klassert wrote:
> > The problem is that, with adding IPsec offloads to netdevices, security
> > critical resources came into the netdevices. Someone who has no
> > capabilities to delete xfrm states or xfrm policies should not be able
> > to unregister the netdevice if xfrm states or xfrm policies are
> > offloaded. Unfortunately, unregistering can't be canceled at this stage
> > anymore. So I think we need some netdevice unregistration hook for
> > the LSM subsystem so it can check for xfrm states or xfrm policies
> > and refuse the unregistration before we actually start to remove
> > the device.
> 
> Unfortunately, unregistering is not always triggered by a user's request. ;-)

As far as I remember, a security context is not always tied to a
user request. It can also be attached to system tasks or objects.

> For example, we don't check permission for unmount when a mount is deleted
> due to teardown of a mount namespace. I wonder why you want to check permission
> for unregistering a net_device when triggered by a teardown path.

I just try to find out what's the right thing to do here.
If a policy goes away, packets that match this policy will
find another path through the network stack. As best, they
are dropped somewhere, but they can also leave on some other
device without encryption. A LSM that implements xfrm hooks
must be able to check the permission to delete the xfrm policy
or state.

> 
> > 
> > The same happened btw. when xfrm was made per network namespace.
> > Here we just leak the xfrm states and xfrm policies if some
> > LSM refuses to remove them.
> > 
> > I guess we need a solution for both cases.
> 
> Is replacing the NETDEV_UNREGISTER net_device with the blackhole_netdev applicable
> ( https://elixir.bootlin.com/linux/v6.19-rc5/source/net/xfrm/xfrm_policy.c#L3948 ) ?
> If no, there is no choice but break SELinux's expectation.

That could be an option to not accidentally send out
unencrypted packets. But finding the right place for
these checks would be preferable IMO.

^ permalink raw reply

* Re: [PATCH v4 2/6] landlock: Control pathname UNIX domain socket resolution by path
From: Günther Noack @ 2026-02-09 10:21 UTC (permalink / raw)
  To: Günther Noack
  Cc: Mickaël Salaün, John Johansen, Tingmao Wang,
	Justin Suess, Jann Horn, linux-security-module,
	Samasth Norway Ananda, Matthieu Buffet, Mikhail Ivanov,
	konstantin.meskhidze, Demi Marie Obenour, Alyssa Ross,
	Tahera Fahimi
In-Reply-To: <20260208231017.114343-3-gnoack3000@gmail.com>

On Mon, Feb 09, 2026 at 12:10:12AM +0100, Günther Noack wrote:
> +static int hook_unix_find(const struct path *const path, struct sock *other,
> +			  int flags)
> +{
> +	const struct landlock_ruleset *dom_other;
> +	const struct landlock_cred_security *subject;
> +	struct layer_access_masks layer_masks;
> +	struct landlock_request request = {};
> +	static const struct access_masks fs_resolve_unix = {
> +		.fs = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
> +	};
> +	int type = other->sk_type;
> +
> +	/* Lookup for the purpose of saving coredumps is OK. */
> +	if (flags & SOCK_COREDUMP)
> +		return 0;
> +
> +	/* Only stream, dgram and seqpacket sockets are restricted. */
> +	if (type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET)
> +		return 0;

FYI: This is a (highly speculative) safeguard, because these three
socket types are the only ones that exist in AF_UNIX (compare unix(7),
2nd paragraph).

In the (highly unlikely) case that someone adds a fourth AF_UNIX
socket type, this means that Landlock will start permitting
connections to these sockets unconditionally.

I am unsure whether the safeguard is useful, or whether we should
rather group that (highly unlikely) future socket type together with
the existing ones.  *If you have opinions, I'd be interested.*

The fact that these are the only existing AF_UNIX socket types is also
the reason why it does not matter that we are now (in v4) taking the
type value from the server-side sk instead of the client socket.  The
check will either way always pass as long as only these three types
are the only ones.

For now (and probably for another few decades :)), as long as these
are the only AF_UNIX types, it does not make a difference though
whether the check is there or not.

—Günther

^ permalink raw reply

* Re: [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Tetsuo Handa @ 2026-02-09 10:02 UTC (permalink / raw)
  To: Steffen Klassert, Paul Moore, SELinux, linux-security-module
  Cc: Herbert Xu, David S. Miller, Eric Dumazet, Jakub Kicinski,
	Paolo Abeni, Simon Horman, Network Development
In-Reply-To: <aYmoDwO-YXrc4W1c@secunet.com>

On 2026/02/09 18:25, Steffen Klassert wrote:
> The problem is that, with adding IPsec offloads to netdevices, security
> critical resources came into the netdevices. Someone who has no
> capabilities to delete xfrm states or xfrm policies should not be able
> to unregister the netdevice if xfrm states or xfrm policies are
> offloaded. Unfortunately, unregistering can't be canceled at this stage
> anymore. So I think we need some netdevice unregistration hook for
> the LSM subsystem so it can check for xfrm states or xfrm policies
> and refuse the unregistration before we actually start to remove
> the device.

Unfortunately, unregistering is not always triggered by a user's request. ;-)

For example, we don't check permission for unmount when a mount is deleted
due to teardown of a mount namespace. I wonder why you want to check permission
for unregistering a net_device when triggered by a teardown path.

> 
> The same happened btw. when xfrm was made per network namespace.
> Here we just leak the xfrm states and xfrm policies if some
> LSM refuses to remove them.
> 
> I guess we need a solution for both cases.

Is replacing the NETDEV_UNREGISTER net_device with the blackhole_netdev applicable
( https://elixir.bootlin.com/linux/v6.19-rc5/source/net/xfrm/xfrm_policy.c#L3948 ) ?
If no, there is no choice but break SELinux's expectation.


^ permalink raw reply

* Re: [PATCH] landlock: Add counted_by and fix comment in landlock_ruleset
From: Günther Noack @ 2026-02-09  9:47 UTC (permalink / raw)
  To: Tingmao Wang; +Cc: Mickaël Salaün, linux-security-module
In-Reply-To: <20260208235449.1124354-1-m@maowtm.org>

On Sun, Feb 08, 2026 at 11:54:48PM +0000, Tingmao Wang wrote:
> For a domain, this array stores the access masks for each layer (of
> which there are num_layers of them).  For an unmerged ruleset, we have
> one "layer", and one element in this array.  This annotation serves as
> useful documentation.
> 
> This also removes a comment saying that num_layers = 0 for unmerged
> rulesets, which is incorrect (it is 1).
> 
> Signed-off-by: Tingmao Wang <m@maowtm.org>

Reviewed-by: Günther Noack <gnoack@google.com>

Thank you for fixing this! We should use these bounds check macros
wherever we can, IMHO.  Removing the remark about num_layers=0 is also
correct.

—Günther

^ permalink raw reply

* [bug report] apparmor: add support loading per permission tagging
From: Dan Carpenter @ 2026-02-09  9:44 UTC (permalink / raw)
  To: John Johansen; +Cc: apparmor, linux-security-module, linux-kernel
In-Reply-To: <caa37f28-a2e8-4e0a-a9ce-a365ce805e4b@stanley.mountain>

[ Smatch checking is paused while we raise funding. #SadFace
  https://lore.kernel.org/all/aTaiGSbWZ9DJaGo7@stanley.mountain/ -dan ]

Hello John Johansen,

Commit 3d28e2397af7 ("apparmor: add support loading per permission
tagging") from Apr 1, 2025 (linux-next), leads to the following
Smatch static checker warning:

	security/apparmor/policy_unpack.c:966 unpack_pdb()
	warn: unsigned 'unpack_tags(e, &pdb->tags, info)' is never less than zero.

security/apparmor/policy_unpack.c
    951 static int unpack_pdb(struct aa_ext *e, struct aa_policydb **policy,
    952                       bool required_dfa, bool required_trans,
    953                       const char **info)
    954 {
    955         struct aa_policydb *pdb;
    956         void *pos = e->pos;
    957         int i, flags, error = -EPROTO;
    958         ssize_t size;
    959         u32 version = 0;
    960 
    961         pdb = aa_alloc_pdb(GFP_KERNEL);
    962         if (!pdb)
    963                 return -ENOMEM;
    964 
    965         AA_DEBUG(DEBUG_UNPACK, "unpacking tags");
--> 966         if (unpack_tags(e, &pdb->tags, info) < 0)
                    ^^^^^^^^^^^
Signedness bug.  unpack_tags() is unsigned.

    967                 goto fail;
    968         AA_DEBUG(DEBUG_UNPACK, "done unpacking tags");
    969 
    970         size = unpack_perms_table(e, &pdb->perms);
    971         if (size < 0) {
    972                 error = size;
    973                 pdb->perms = NULL;

regards,
dan carpenter

^ permalink raw reply

* Re: [PATCH] xfrm: kill xfrm_dev_{state,policy}_flush_secctx_check()
From: Steffen Klassert @ 2026-02-09  9:25 UTC (permalink / raw)
  To: Tetsuo Handa
  Cc: Paul Moore, SELinux, linux-security-module, Herbert Xu,
	David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Simon Horman, Network Development
In-Reply-To: <7ef21dab-3805-4eae-80d7-9779aeff3f58@I-love.SAKURA.ne.jp>

On Wed, Feb 04, 2026 at 10:57:30PM +0900, Tetsuo Handa wrote:
> On 2026/02/04 19:15, Tetsuo Handa wrote:
> > On 2026/02/04 7:40, Paul Moore wrote:
> >>         This is not an unusual request for such a proposed change, and
> >> is something that I would expect a LSM maintainer to do without much
> >> hesitation.  If you are unwilling to investigate this, can you explain
> >> why?
> > 
> > Because I'm not familiar with how XFRM works; I'm not a user of LSM XFRM hooks.
> > 
> > I can't judge whether the current code is COMPREHENSIVELY GATING;
> > I can't imagine what the state you call COMPREHENSIVELY GATING is.
> 
> Steffen Klassert worried that killing xfrm_dev_state_flush_secctx_check() and
> xfrm_dev_policy_flush_secctx_check() might violate a LSM policy and you agreed
> ( https://lkml.kernel.org/r/CAHC9VhQ54LRD7k_x6tUju2kPVBEHcdgBh46_hBN8btG0vhfy_w@mail.gmail.com ),
> but the reality is that nobody in the world has enforced an LSM policy for almost 9 years
> that makes xfrm_dev_{state,policy}_flush() no-op. That is, xfrm_dev_state_flush_secctx_check()
> and xfrm_dev_policy_flush_secctx_check() had been effectively unused.
> 
> Killing xfrm_dev_state_flush_secctx_check() and xfrm_dev_policy_flush_secctx_check()
> increases "system's stability" without sacrificing "authorization".
> 
> It is up to SELinux developers to discuss what actions to take as a compensation for
> killing xfrm_dev_state_flush_secctx_check() and xfrm_dev_policy_flush_secctx_check().
> The compensation might be to add LSM hooks to immediately before the point of no return.

The problem is that, with adding IPsec offloads to netdevices, security
critical resources came into the netdevices. Someone who has no
capabilities to delete xfrm states or xfrm policies should not be able
to unregister the netdevice if xfrm states or xfrm policies are
offloaded. Unfortunately, unregistering can't be canceled at this stage
anymore. So I think we need some netdevice unregistration hook for
the LSM subsystem so it can check for xfrm states or xfrm policies
and refuse the unregistration before we actually start to remove
the device.

The same happened btw. when xfrm was made per network namespace.
Here we just leak the xfrm states and xfrm policies if some
LSM refuses to remove them.

I guess we need a solution for both cases.

^ permalink raw reply

* [PATCH] landlock: Add counted_by and fix comment in landlock_ruleset
From: Tingmao Wang @ 2026-02-08 23:54 UTC (permalink / raw)
  To: Mickaël Salaün
  Cc: Tingmao Wang, Günther Noack, linux-security-module

For a domain, this array stores the access masks for each layer (of
which there are num_layers of them).  For an unmerged ruleset, we have
one "layer", and one element in this array.  This annotation serves as
useful documentation.

This also removes a comment saying that num_layers = 0 for unmerged
rulesets, which is incorrect (it is 1).

Signed-off-by: Tingmao Wang <m@maowtm.org>
---

I'm not sure if I should add a Fixes tag, but if I should had, it would
be ae271c1b14 ("landlock: Add ruleset and domain management").

 security/landlock/ruleset.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
index 9d6dc632684c..7005840ac641 100644
--- a/security/landlock/ruleset.h
+++ b/security/landlock/ruleset.h
@@ -168,8 +168,7 @@ struct landlock_ruleset {
 			/**
 			 * @num_layers: Number of layers that are used in this
 			 * ruleset.  This enables to check that all the layers
-			 * allow an access request.  A value of 0 identifies a
-			 * non-merged ruleset (i.e. not a domain).
+			 * allow an access request.
 			 */
 			u32 num_layers;
 			/**
@@ -184,7 +183,8 @@ struct landlock_ruleset {
 			 * layers are set once and never changed for the
 			 * lifetime of the ruleset.
 			 */
-			struct access_masks access_masks[];
+			struct access_masks
+				access_masks[] __counted_by(num_layers);
 		};
 	};
 };

base-commit: f179e1859c711214412876c57f56f9b0cfb13264
-- 
2.53.0

^ permalink raw reply related

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Günther Noack @ 2026-02-08 23:21 UTC (permalink / raw)
  To: Tingmao Wang
  Cc: Mickaël Salaün, Günther Noack, Justin Suess,
	Paul Moore, John Johansen, Demi Marie Obenour, Alyssa Ross,
	Jann Horn, Tahera Fahimi, Matthieu Buffet, linux-security-module
In-Reply-To: <c33926c5-3c7a-40d8-b910-ac99b43576ff@maowtm.org>

On Sun, Feb 08, 2026 at 08:48:22PM +0000, Tingmao Wang wrote:
> On 2/8/26 20:37, Günther Noack wrote:
> > Thank you, Tingmao!
> >
> > So far, the selftests that I already had in fs_test.c were
> > straightforward to extend so that they cover the new cases.  I had a
> > look at your patch set, but found the scoping tests difficult to port
> > to fs_test.c
> 
> I was thinking that the tests in scoped_abstract_unix_test.c could be
> extended to test scoping of pathname UNIX sockets as well (otherwise
> wouldn't you have to write another instance of the scoped_domains test
> based on scoped_base_variants.h, whether you put it in fs_test.c or
> somewhere else?)
> 
> And if you think that is sensible, then I'm hoping that patch 4,5,6 of the
> series would be mostly useful.  But it's up to you :)

I maybe have not wrapped my head around the scoped_test enough; for
now I sent a tentative V4 patch set to the list, so that we can
discuss something concrete.

If you spot things that are missing, or you feel inspired to port your
tests on top, I am still happy to accept that. (But for today it is
too late in the evening here %-))

–Günther

^ permalink raw reply

* [PATCH v4 6/6] landlock: Document design rationale for scoped access rights
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen
  Cc: Günther Noack, linux-security-module, Tingmao Wang,
	Justin Suess, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

Document the (possible future) interaction between scoped flags and
other access rights in struct landlock_ruleset_attr, and summarize the
rationale, as discussed in code review leading up to [1].

Link[1]: https://lore.kernel.org/all/20260205.8531e4005118@gnoack.org/
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
 Documentation/security/landlock.rst | 38 +++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/Documentation/security/landlock.rst b/Documentation/security/landlock.rst
index 3e4d4d04cfae..49ef02d5e272 100644
--- a/Documentation/security/landlock.rst
+++ b/Documentation/security/landlock.rst
@@ -89,6 +89,44 @@ this is required to keep access controls consistent over the whole system, and
 this avoids unattended bypasses through file descriptor passing (i.e. confused
 deputy attack).
 
+Interaction between scoped flags and other access rights
+--------------------------------------------------------
+
+The ``scoped`` flags in ``struct landlock_ruleset_attr`` restrict the
+use of *outgoing* IPC from the created Landlock domain, while they
+permit reaching out to IPC endpoints *within* the created Landlock
+domain.
+
+In the future, scoped flags *may* interact with other access rights,
+e.g. so that abstract UNIX sockets can be allow-listed by name, or so
+that signals can be allow-listed by signal number or target process.
+
+When introducing ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX``, we defined it to
+implicitly have the same scoping semantics as a
+``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` flag would have: connecting to
+UNIX sockets within the same domain (where
+``LANDLOCK_ACCESS_FS_RESOLVE_UNIX`` is used) is unconditionally
+allowed.
+
+The reasoning is:
+
+* Like other IPC mechanisms, connecting to named UNIX sockets in the
+  same domain should be expected and harmless.  (If needed, users can
+  further refine their Landlock policies with nested domains or by
+  restricting ``LANDLOCK_ACCESS_FS_MAKE_SOCK``.)
+* We reserve the option to still introduce
+  ``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` in the future.  (This would
+  be useful if we wanted to have a Landlock rule to permit IPC access
+  to other Landlock domains.)
+* But we can postpone the point in time when users have to deal with
+  two interacting flags visible in the userspace API.  (In particular,
+  it is possible that it won't be needed in practice, in which case we
+  can avoid the second flag altogether.)
+* If we *do* introduce ``LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET`` in the
+  future, setting this scoped flag in a ruleset does *not reduce* the
+  restrictions, because access within the same scope is already
+  allowed based on ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX``.
+
 Tests
 =====
 
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 5/6] landlock: Document FS access right for pathname UNIX sockets
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen
  Cc: Günther Noack, Justin Suess, linux-security-module,
	Tingmao Wang, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
 Documentation/userspace-api/landlock.rst | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/Documentation/userspace-api/landlock.rst b/Documentation/userspace-api/landlock.rst
index 13134bccdd39..3ba73afcbc4b 100644
--- a/Documentation/userspace-api/landlock.rst
+++ b/Documentation/userspace-api/landlock.rst
@@ -77,7 +77,8 @@ to be explicit about the denied-by-default access rights.
             LANDLOCK_ACCESS_FS_MAKE_SYM |
             LANDLOCK_ACCESS_FS_REFER |
             LANDLOCK_ACCESS_FS_TRUNCATE |
-            LANDLOCK_ACCESS_FS_IOCTL_DEV,
+            LANDLOCK_ACCESS_FS_IOCTL_DEV |
+            LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
         .handled_access_net =
             LANDLOCK_ACCESS_NET_BIND_TCP |
             LANDLOCK_ACCESS_NET_CONNECT_TCP,
@@ -127,6 +128,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 7:
+        __attribute__((fallthrough));
+    case 8:
+        /* Removes LANDLOCK_ACCESS_FS_RESOLVE_UNIX for ABI < 8 */
+        ruleset_attr.handled_access_fs &= ~LANDLOCK_ACCESS_FS_RESOLVE_UNIX;
     }
 
 This enables the creation of an inclusive ruleset that will contain our rules.
@@ -685,6 +692,13 @@ enforce Landlock rulesets across all threads of the calling process
 using the ``LANDLOCK_RESTRICT_SELF_TSYNC`` flag passed to
 sys_landlock_restrict_self().
 
+Pathname UNIX sockets (ABI < 9)
+-------------------------------
+
+Starting with the Landlock ABI version 9, it is possible to restrict
+connections to pathname UNIX domain sockets (:manpage:`unix(7)`) using
+the new ``LANDLOCK_ACCESS_FS_RESOLVE_UNIX`` right.
+
 .. _kernel_support:
 
 Kernel support
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 4/6] landlock/selftests: Test named UNIX domain socket restrictions
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen
  Cc: Günther Noack, Justin Suess, linux-security-module,
	Tingmao Wang, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

* Exercise the access right for connect() and sendmsg() on named UNIX
  domain sockets, in various combinations of Landlock domains and
  socket types.
* Extract common helpers from an existing IOCTL test that
  also uses pathname unix(7) sockets.

The tested combinations are the cross product of these sets of fixture
fields:

* {{.handled=RESOLVE_UNIX},
   {.handled=RESOLVE_UNIX, .allowed=RESOLVE_UNIX}}
* {{.sock_type=SOCK_STREAM},
   {.sock_type=SOCK_DGRAM},
   {.sock_type=SOCK_DGRAM, .use_sendto=true},
   {.sock_type=SOCK_SEQPACKET}}
* {{.server_in_same_domain=false},
   {.server_in_same_domain=true}}

Some additional fixtures exercise scenarios with two nested domains.

Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
 tools/testing/selftests/landlock/fs_test.c | 381 ++++++++++++++++++++-
 1 file changed, 365 insertions(+), 16 deletions(-)

diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index b318627e7561..9d3f5dab4567 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -4358,30 +4358,61 @@ TEST_F_FORK(layout1, named_pipe_ioctl)
 	ASSERT_EQ(child_pid, waitpid(child_pid, NULL, 0));
 }
 
+/*
+ * set_up_named_unix_server - Create a pathname unix socket
+ *
+ * If the socket type is not SOCK_DGRAM, also invoke listen(2).
+ *
+ * Return: The listening FD - it is the caller responsibility to close it.
+ */
+static int set_up_named_unix_server(struct __test_metadata *const _metadata,
+				    int type, const char *const path)
+{
+	int fd;
+	struct sockaddr_un addr = {
+		.sun_family = AF_UNIX,
+	};
+
+	fd = socket(AF_UNIX, type, 0);
+	ASSERT_LE(0, fd);
+
+	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+	ASSERT_EQ(0, bind(fd, (struct sockaddr *)&addr, sizeof(addr)));
+
+	if (type != SOCK_DGRAM)
+		ASSERT_EQ(0, listen(fd, 10 /* qlen */));
+	return fd;
+}
+
+/*
+ * test_connect_named_unix - connect to the given named UNIX socket
+ *
+ * Return: The errno from connect(), or 0
+ */
+static int test_connect_named_unix(int fd, const char *const path)
+{
+	struct sockaddr_un addr = {
+		.sun_family = AF_UNIX,
+	};
+	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+
+	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == -1)
+		return errno;
+	return 0;
+}
+
 /* For named UNIX domain sockets, no IOCTL restrictions apply. */
 TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
 {
 	const char *const path = file1_s1d1;
 	int srv_fd, cli_fd, ruleset_fd;
-	struct sockaddr_un srv_un = {
-		.sun_family = AF_UNIX,
-	};
-	struct sockaddr_un cli_un = {
-		.sun_family = AF_UNIX,
-	};
 	const struct landlock_ruleset_attr attr = {
 		.handled_access_fs = LANDLOCK_ACCESS_FS_IOCTL_DEV,
 	};
 
 	/* Sets up a server */
 	ASSERT_EQ(0, unlink(path));
-	srv_fd = socket(AF_UNIX, SOCK_STREAM, 0);
-	ASSERT_LE(0, srv_fd);
-
-	strncpy(srv_un.sun_path, path, sizeof(srv_un.sun_path));
-	ASSERT_EQ(0, bind(srv_fd, (struct sockaddr *)&srv_un, sizeof(srv_un)));
-
-	ASSERT_EQ(0, listen(srv_fd, 10 /* qlen */));
+	srv_fd = set_up_named_unix_server(_metadata, SOCK_STREAM, path);
 
 	/* Enables Landlock. */
 	ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
@@ -4393,9 +4424,7 @@ TEST_F_FORK(layout1, named_unix_domain_socket_ioctl)
 	cli_fd = socket(AF_UNIX, SOCK_STREAM, 0);
 	ASSERT_LE(0, cli_fd);
 
-	strncpy(cli_un.sun_path, path, sizeof(cli_un.sun_path));
-	ASSERT_EQ(0,
-		  connect(cli_fd, (struct sockaddr *)&cli_un, sizeof(cli_un)));
+	ASSERT_EQ(0, test_connect_named_unix(cli_fd, path));
 
 	/* FIONREAD and other IOCTLs should not be forbidden. */
 	EXPECT_EQ(0, test_fionread_ioctl(cli_fd));
@@ -4570,6 +4599,326 @@ TEST_F_FORK(ioctl, handle_file_access_file)
 	ASSERT_EQ(0, close(file_fd));
 }
 
+/* clang-format off */
+FIXTURE(unix_socket) {};
+
+FIXTURE_SETUP(unix_socket) {};
+
+FIXTURE_TEARDOWN(unix_socket) {};
+/* clang-format on */
+
+FIXTURE_VARIANT(unix_socket)
+{
+	const __u64 handled;
+	const __u64 allowed;
+	const __u64 handled2;
+	const __u64 allowed2;
+	const int sock_type;
+	const int expected;
+	const bool use_sendto;
+	const bool server_in_same_domain;
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_handled_not_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_STREAM,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_handled_and_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_STREAM,
+	.expected = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_handled_not_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_DGRAM,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_handled_and_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_DGRAM,
+	.expected = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_sendto_handled_not_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_DGRAM,
+	.use_sendto = true,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_sendto_handled_and_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_DGRAM,
+	.use_sendto = true,
+	.expected = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, seqpacket_handled_not_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_SEQPACKET,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, seqpacket_handled_and_allowed)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_SEQPACKET,
+	.expected = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_handled_not_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_STREAM,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_handled_and_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_STREAM,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_handled_not_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_DGRAM,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_handled_and_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_DGRAM,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_sendto_handled_not_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_DGRAM,
+	.use_sendto = true,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, dgram_sendto_handled_and_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_DGRAM,
+	.use_sendto = true,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, seqpacket_handled_not_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.sock_type = SOCK_SEQPACKET,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, seqpacket_handled_and_allowed_and_same_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_SEQPACKET,
+	.expected = 0,
+	.server_in_same_domain = true,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_nested_domains_scope_path)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.server_in_same_domain = true,
+	.handled2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_STREAM,
+	.expected = 0,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_nested_domains_path_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.server_in_same_domain = true,
+	.handled2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed2 = 0,
+	.sock_type = SOCK_STREAM,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_nested_domains_scope_scope)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = 0,
+	.server_in_same_domain = true,
+	.handled2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed2 = 0,
+	.sock_type = SOCK_STREAM,
+	.expected = EACCES,
+};
+
+/* clang-format off */
+FIXTURE_VARIANT_ADD(unix_socket, stream_nested_domains_path_path)
+{
+	/* clang-format on */
+	.handled = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.server_in_same_domain = true,
+	.handled2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.allowed2 = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	.sock_type = SOCK_STREAM,
+	.expected = 0,
+};
+
+/*
+ * test_sendto_named_unix - sendto to the given named UNIX socket
+ *
+ * sendto() is equivalent to sendmsg() in this respect.
+ *
+ * Return: The errno from sendto(), or 0
+ */
+static int test_sendto_named_unix(int fd, const char *const path)
+{
+	static const char buf[] = "dummy";
+	struct sockaddr_un addr = {
+		.sun_family = AF_UNIX,
+	};
+	strncpy(addr.sun_path, path, sizeof(addr.sun_path));
+
+	if (sendto(fd, buf, sizeof(buf), 0, (struct sockaddr *)&addr,
+		   sizeof(addr)) == -1)
+		return errno;
+	return 0;
+}
+
+TEST_F_FORK(unix_socket, test)
+{
+	const char *const path = "sock";
+	int cli_fd, srv_fd, ruleset_fd, res;
+	struct rule rules[] = {
+		{
+			.path = ".",
+			.access = variant->allowed,
+		},
+		{},
+	};
+
+	/* Sets up a server (in the case where the server is in the parent domain) */
+	if (!variant->server_in_same_domain)
+		srv_fd = set_up_named_unix_server(_metadata, variant->sock_type,
+						  path);
+
+	/* Enables Landlock. */
+	ruleset_fd = create_ruleset(_metadata, variant->handled, rules);
+	ASSERT_LE(0, ruleset_fd);
+	enforce_ruleset(_metadata, ruleset_fd);
+	ASSERT_EQ(0, close(ruleset_fd));
+
+	/* Sets up a server (in the case where the server is in the same domain) */
+	if (variant->server_in_same_domain)
+		srv_fd = set_up_named_unix_server(_metadata, variant->sock_type,
+						  path);
+
+	if (variant->handled2) {
+		/* Enables Landlock another time, if needed. */
+		rules[0].access = variant->allowed2;
+		ruleset_fd =
+			create_ruleset(_metadata, variant->handled2, rules);
+		ASSERT_LE(0, ruleset_fd);
+		enforce_ruleset(_metadata, ruleset_fd);
+		ASSERT_EQ(0, close(ruleset_fd));
+	}
+
+	/* Sets up a client connection to it */
+	cli_fd = socket(AF_UNIX, variant->sock_type, 0);
+	ASSERT_LE(0, cli_fd);
+
+	/* Connecting or sendto to the Unix socket is denied. */
+	if (variant->use_sendto)
+		res = test_sendto_named_unix(cli_fd, path);
+	else
+		res = test_connect_named_unix(cli_fd, path);
+	EXPECT_EQ(variant->expected, res);
+
+	/* Clean up. */
+	EXPECT_EQ(0, close(cli_fd));
+	EXPECT_EQ(0, close(srv_fd));
+	EXPECT_EQ(0, unlink(path));
+}
+
 /* clang-format off */
 FIXTURE(layout1_bind) {};
 /* clang-format on */
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 3/6] samples/landlock: Add support for named UNIX domain socket restrictions
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen
  Cc: Günther Noack, Justin Suess, linux-security-module,
	Tingmao Wang, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

The access right for UNIX domain socket lookups is grouped with the
read-write rights in the sample tool.  Rationale: In the general case,
any operations are possible through a UNIX domain socket, including
data-mutating operations.

Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Mickaël Salaün <mic@digikod.net>
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
 samples/landlock/sandboxer.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/samples/landlock/sandboxer.c b/samples/landlock/sandboxer.c
index e7af02f98208..0bbbc5c9ead6 100644
--- a/samples/landlock/sandboxer.c
+++ b/samples/landlock/sandboxer.c
@@ -111,7 +111,8 @@ static int parse_path(char *env_path, const char ***const path_list)
 	LANDLOCK_ACCESS_FS_WRITE_FILE | \
 	LANDLOCK_ACCESS_FS_READ_FILE | \
 	LANDLOCK_ACCESS_FS_TRUNCATE | \
-	LANDLOCK_ACCESS_FS_IOCTL_DEV)
+	LANDLOCK_ACCESS_FS_IOCTL_DEV | \
+	LANDLOCK_ACCESS_FS_RESOLVE_UNIX)
 
 /* clang-format on */
 
@@ -295,11 +296,12 @@ static bool check_ruleset_scope(const char *const env_var,
 	LANDLOCK_ACCESS_FS_MAKE_SYM | \
 	LANDLOCK_ACCESS_FS_REFER | \
 	LANDLOCK_ACCESS_FS_TRUNCATE | \
-	LANDLOCK_ACCESS_FS_IOCTL_DEV)
+	LANDLOCK_ACCESS_FS_IOCTL_DEV | \
+	LANDLOCK_ACCESS_FS_RESOLVE_UNIX)
 
 /* clang-format on */
 
-#define LANDLOCK_ABI_LAST 7
+#define LANDLOCK_ABI_LAST 9
 
 #define XSTR(s) #s
 #define STR(s) XSTR(s)
@@ -444,6 +446,13 @@ int main(const int argc, char *const argv[], char *const *const envp)
 			"provided by ABI version %d (instead of %d).\n",
 			LANDLOCK_ABI_LAST, abi);
 		__attribute__((fallthrough));
+	case 7:
+		__attribute__((fallthrough));
+	case 8:
+		/* Removes LANDLOCK_ACCESS_FS_RESOLVE_UNIX for ABI < 9 */
+		ruleset_attr.handled_access_fs &=
+			~LANDLOCK_ACCESS_FS_RESOLVE_UNIX;
+		__attribute__((fallthrough));
 	case LANDLOCK_ABI_LAST:
 		break;
 	default:
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 2/6] landlock: Control pathname UNIX domain socket resolution by path
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen
  Cc: Günther Noack, Tingmao Wang, Justin Suess, Jann Horn,
	linux-security-module, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Tahera Fahimi
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

* Add a new access right LANDLOCK_ACCESS_FS_RESOLVE_UNIX, which
  controls the look up operations for named UNIX domain sockets.  The
  resolution happens during connect() and sendmsg() (depending on
  socket type).
* Hook into the path lookup in unix_find_bsd() in af_unix.c, using a
  LSM hook.  Make policy decisions based on the new access rights
* Increment the Landlock ABI version.
* Minor test adaptions to keep the tests working.

With this access right, access is granted if either of the following
conditions is met:

* The target socket's filesystem path was allow-listed using a
  LANDLOCK_RULE_PATH_BENEATH rule, *or*:
* The target socket was created in the same Landlock domain in which
  LANDLOCK_ACCESS_FS_RESOLVE_UNIX was restricted.

In case of a denial, connect() and sendmsg() return EACCES, which is
the same error as it is returned if the user does not have the write
bit in the traditional Unix file system permissions of that file.

This feature was created with substantial discussion and input from
Justin Suess, Tingmao Wang and Mickaël Salaün.

Cc: Tingmao Wang <m@maowtm.org>
Cc: Justin Suess <utilityemal77@gmail.com>
Cc: Mickaël Salaün <mic@digikod.net>
Suggested-by: Jann Horn <jannh@google.com>
Link: https://github.com/landlock-lsm/linux/issues/36
Signed-off-by: Günther Noack <gnoack3000@gmail.com>
---
 include/uapi/linux/landlock.h                |  10 ++
 security/landlock/access.h                   |  11 +-
 security/landlock/audit.c                    |   1 +
 security/landlock/fs.c                       | 107 ++++++++++++++++++-
 security/landlock/limits.h                   |   2 +-
 security/landlock/syscalls.c                 |   2 +-
 tools/testing/selftests/landlock/base_test.c |   2 +-
 tools/testing/selftests/landlock/fs_test.c   |   5 +-
 8 files changed, 133 insertions(+), 7 deletions(-)

diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
index f88fa1f68b77..3a8fc3af0d64 100644
--- a/include/uapi/linux/landlock.h
+++ b/include/uapi/linux/landlock.h
@@ -248,6 +248,15 @@ struct landlock_net_port_attr {
  *
  *   This access right is available since the fifth version of the Landlock
  *   ABI.
+ * - %LANDLOCK_ACCESS_FS_RESOLVE_UNIX: Look up pathname UNIX domain sockets
+ *   (:manpage:`unix(7)`).  On UNIX domain sockets, this restricts both calls to
+ *   :manpage:`connect(2)` as well as calls to :manpage:`sendmsg(2)` with an
+ *   explicit recipient address.
+ *
+ *   This access right only applies to connections to UNIX server sockets which
+ *   were created outside of the newly created Landlock domain (e.g. from within
+ *   a parent domain or from an unrestricted process).  Newly created UNIX
+ *   servers within the same Landlock domain continue to be accessible.
  *
  * Whether an opened file can be truncated with :manpage:`ftruncate(2)` or used
  * with `ioctl(2)` is determined during :manpage:`open(2)`, in the same way as
@@ -333,6 +342,7 @@ struct landlock_net_port_attr {
 #define LANDLOCK_ACCESS_FS_REFER			(1ULL << 13)
 #define LANDLOCK_ACCESS_FS_TRUNCATE			(1ULL << 14)
 #define LANDLOCK_ACCESS_FS_IOCTL_DEV			(1ULL << 15)
+#define LANDLOCK_ACCESS_FS_RESOLVE_UNIX			(1ULL << 16)
 /* clang-format on */
 
 /**
diff --git a/security/landlock/access.h b/security/landlock/access.h
index 42c95747d7bd..9a2991688835 100644
--- a/security/landlock/access.h
+++ b/security/landlock/access.h
@@ -34,7 +34,7 @@
 	LANDLOCK_ACCESS_FS_IOCTL_DEV)
 /* clang-format on */
 
-typedef u16 access_mask_t;
+typedef u32 access_mask_t;
 
 /* Makes sure all filesystem access rights can be stored. */
 static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
@@ -76,6 +76,15 @@ struct layer_access_masks {
 	access_mask_t access[LANDLOCK_MAX_NUM_LAYERS];
 };
 
+static inline bool
+layer_access_masks_empty(const struct layer_access_masks *masks)
+{
+	for (size_t i = 0; i < ARRAY_SIZE(masks->access); i++)
+		if (masks->access[i])
+			return false;
+	return true;
+}
+
 /*
  * Tracks domains responsible of a denied access.  This avoids storing in each
  * object the full matrix of per-layer unfulfilled access rights, which is
diff --git a/security/landlock/audit.c b/security/landlock/audit.c
index 60ff217ab95b..8d0edf94037d 100644
--- a/security/landlock/audit.c
+++ b/security/landlock/audit.c
@@ -37,6 +37,7 @@ static const char *const fs_access_strings[] = {
 	[BIT_INDEX(LANDLOCK_ACCESS_FS_REFER)] = "fs.refer",
 	[BIT_INDEX(LANDLOCK_ACCESS_FS_TRUNCATE)] = "fs.truncate",
 	[BIT_INDEX(LANDLOCK_ACCESS_FS_IOCTL_DEV)] = "fs.ioctl_dev",
+	[BIT_INDEX(LANDLOCK_ACCESS_FS_RESOLVE_UNIX)] = "fs.resolve_unix",
 };
 
 static_assert(ARRAY_SIZE(fs_access_strings) == LANDLOCK_NUM_ACCESS_FS);
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index e764470f588c..053217048ac9 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -27,6 +27,7 @@
 #include <linux/lsm_hooks.h>
 #include <linux/mount.h>
 #include <linux/namei.h>
+#include <linux/net.h>
 #include <linux/path.h>
 #include <linux/pid.h>
 #include <linux/rcupdate.h>
@@ -314,7 +315,8 @@ static struct landlock_object *get_inode_object(struct inode *const inode)
 	LANDLOCK_ACCESS_FS_WRITE_FILE | \
 	LANDLOCK_ACCESS_FS_READ_FILE | \
 	LANDLOCK_ACCESS_FS_TRUNCATE | \
-	LANDLOCK_ACCESS_FS_IOCTL_DEV)
+	LANDLOCK_ACCESS_FS_IOCTL_DEV | \
+	LANDLOCK_ACCESS_FS_RESOLVE_UNIX)
 /* clang-format on */
 
 /*
@@ -1561,6 +1563,108 @@ static int hook_path_truncate(const struct path *const path)
 	return current_check_access_path(path, LANDLOCK_ACCESS_FS_TRUNCATE);
 }
 
+/**
+ * unmask_scoped_access - Remove access right bits in @masks in all layers
+ *                        where @client and @server have the same domain
+ *
+ * This does the same as domain_is_scoped(), but unmasks bits in @masks.
+ * It can not return early as domain_is_scoped() does.
+ *
+ * @client: Client domain
+ * @server: Server domain
+ * @masks: Layer access masks to unmask
+ * @access: Access bit that controls scoping
+ */
+static void unmask_scoped_access(const struct landlock_ruleset *const client,
+				 const struct landlock_ruleset *const server,
+				 struct layer_access_masks *const masks,
+				 const access_mask_t access)
+{
+	int client_layer, server_layer;
+	const struct landlock_hierarchy *client_walker, *server_walker;
+
+	if (WARN_ON_ONCE(!client))
+		return; /* should not happen */
+
+	if (!server)
+		return; /* server has no Landlock domain; nothing to clear */
+
+	client_layer = client->num_layers - 1;
+	client_walker = client->hierarchy;
+	server_layer = server->num_layers - 1;
+	server_walker = server->hierarchy;
+
+	/*
+	 * Clears the access bits at all layers where the client domain is the
+	 * same as the server domain.  We start the walk at min(client_layer,
+	 * server_layer).  The layer bits until there can not be cleared because
+	 * either the client or the server domain is missing.
+	 */
+	for (; client_layer > server_layer; client_layer--)
+		client_walker = client_walker->parent;
+
+	for (; server_layer > client_layer; server_layer--)
+		server_walker = server_walker->parent;
+
+	for (; client_layer >= 0; client_layer--) {
+		if (masks->access[client_layer] & access &&
+		    client_walker == server_walker)
+			masks->access[client_layer] &= ~access;
+
+		client_walker = client_walker->parent;
+		server_walker = server_walker->parent;
+	}
+}
+
+static int hook_unix_find(const struct path *const path, struct sock *other,
+			  int flags)
+{
+	const struct landlock_ruleset *dom_other;
+	const struct landlock_cred_security *subject;
+	struct layer_access_masks layer_masks;
+	struct landlock_request request = {};
+	static const struct access_masks fs_resolve_unix = {
+		.fs = LANDLOCK_ACCESS_FS_RESOLVE_UNIX,
+	};
+	int type = other->sk_type;
+
+	/* Lookup for the purpose of saving coredumps is OK. */
+	if (flags & SOCK_COREDUMP)
+		return 0;
+
+	/* Only stream, dgram and seqpacket sockets are restricted. */
+	if (type != SOCK_STREAM && type != SOCK_DGRAM && type != SOCK_SEQPACKET)
+		return 0;
+
+	/* Access to the same (or a lower) domain is always allowed. */
+	subject = landlock_get_applicable_subject(current_cred(),
+						  fs_resolve_unix, NULL);
+
+	if (!subject)
+		return 0;
+
+	if (!landlock_init_layer_masks(subject->domain, fs_resolve_unix.fs,
+				       &layer_masks, LANDLOCK_KEY_INODE))
+		return 0;
+
+	/* Checks the layers in which we are connecting within the same domain. */
+	dom_other = landlock_cred(other->sk_socket->file->f_cred)->domain;
+	unmask_scoped_access(subject->domain, dom_other, &layer_masks,
+			     fs_resolve_unix.fs);
+
+	if (layer_access_masks_empty(&layer_masks))
+		return 0;
+
+	/* Checks the connections to allow-listed paths. */
+	if (is_access_to_paths_allowed(subject->domain, path,
+				       fs_resolve_unix.fs, &layer_masks,
+				       &request, NULL, 0, NULL, NULL, NULL))
+		return 0;
+
+	landlock_log_denial(subject, &request);
+	return -EACCES;
+}
+
 /* File hooks */
 
 /**
@@ -1838,6 +1942,7 @@ static struct security_hook_list landlock_hooks[] __ro_after_init = {
 	LSM_HOOK_INIT(path_unlink, hook_path_unlink),
 	LSM_HOOK_INIT(path_rmdir, hook_path_rmdir),
 	LSM_HOOK_INIT(path_truncate, hook_path_truncate),
+	LSM_HOOK_INIT(unix_find, hook_unix_find),
 
 	LSM_HOOK_INIT(file_alloc_security, hook_file_alloc_security),
 	LSM_HOOK_INIT(file_open, hook_file_open),
diff --git a/security/landlock/limits.h b/security/landlock/limits.h
index eb584f47288d..b454ad73b15e 100644
--- a/security/landlock/limits.h
+++ b/security/landlock/limits.h
@@ -19,7 +19,7 @@
 #define LANDLOCK_MAX_NUM_LAYERS		16
 #define LANDLOCK_MAX_NUM_RULES		U32_MAX
 
-#define LANDLOCK_LAST_ACCESS_FS		LANDLOCK_ACCESS_FS_IOCTL_DEV
+#define LANDLOCK_LAST_ACCESS_FS		LANDLOCK_ACCESS_FS_RESOLVE_UNIX
 #define LANDLOCK_MASK_ACCESS_FS		((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
 #define LANDLOCK_NUM_ACCESS_FS		__const_hweight64(LANDLOCK_MASK_ACCESS_FS)
 
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 0d66a68677b7..933902d43241 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -164,7 +164,7 @@ static const struct file_operations ruleset_fops = {
  * If the change involves a fix that requires userspace awareness, also update
  * the errata documentation in Documentation/userspace-api/landlock.rst .
  */
-const int landlock_abi_version = 8;
+const int landlock_abi_version = 9;
 
 /**
  * sys_landlock_create_ruleset - Create a new ruleset
diff --git a/tools/testing/selftests/landlock/base_test.c b/tools/testing/selftests/landlock/base_test.c
index 0fea236ef4bd..30d37234086c 100644
--- a/tools/testing/selftests/landlock/base_test.c
+++ b/tools/testing/selftests/landlock/base_test.c
@@ -76,7 +76,7 @@ TEST(abi_version)
 	const struct landlock_ruleset_attr ruleset_attr = {
 		.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
 	};
-	ASSERT_EQ(8, landlock_create_ruleset(NULL, 0,
+	ASSERT_EQ(9, landlock_create_ruleset(NULL, 0,
 					     LANDLOCK_CREATE_RULESET_VERSION));
 
 	ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
diff --git a/tools/testing/selftests/landlock/fs_test.c b/tools/testing/selftests/landlock/fs_test.c
index 968a91c927a4..b318627e7561 100644
--- a/tools/testing/selftests/landlock/fs_test.c
+++ b/tools/testing/selftests/landlock/fs_test.c
@@ -575,9 +575,10 @@ TEST_F_FORK(layout1, inval)
 	LANDLOCK_ACCESS_FS_WRITE_FILE | \
 	LANDLOCK_ACCESS_FS_READ_FILE | \
 	LANDLOCK_ACCESS_FS_TRUNCATE | \
-	LANDLOCK_ACCESS_FS_IOCTL_DEV)
+	LANDLOCK_ACCESS_FS_IOCTL_DEV | \
+	LANDLOCK_ACCESS_FS_RESOLVE_UNIX)
 
-#define ACCESS_LAST LANDLOCK_ACCESS_FS_IOCTL_DEV
+#define ACCESS_LAST LANDLOCK_ACCESS_FS_RESOLVE_UNIX
 
 #define ACCESS_ALL ( \
 	ACCESS_FILE | \
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 1/6] lsm: Add LSM hook security_unix_find
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen, Paul Moore, James Morris,
	Serge E . Hallyn
  Cc: Günther Noack, Tingmao Wang, Justin Suess,
	linux-security-module, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi, Simon Horman, netdev,
	Alexander Viro, Christian Brauner
In-Reply-To: <20260208231017.114343-1-gnoack3000@gmail.com>

From: Justin Suess <utilityemal77@gmail.com>

Add a LSM hook security_unix_find.

This hook is called to check the path of a named unix socket before a
connection is initiated. The peer socket may be inspected as well.

Why existing hooks are unsuitable:

Existing socket hooks, security_unix_stream_connect(),
security_unix_may_send(), and security_socket_connect() don't provide
TOCTOU-free / namespace independent access to the paths of sockets.

(1) We cannot resolve the path from the struct sockaddr in existing hooks.
This requires another path lookup. A change in the path between the
two lookups will cause a TOCTOU bug.

(2) We cannot use the struct path from the listening socket, because it
may be bound to a path in a different namespace than the caller,
resulting in a path that cannot be referenced at policy creation time.

Cc: Günther Noack <gnoack3000@gmail.com>
Cc: Tingmao Wang <m@maowtm.org>
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
 include/linux/lsm_hook_defs.h |  5 +++++
 include/linux/security.h      | 11 +++++++++++
 net/unix/af_unix.c            |  9 +++++++++
 security/security.c           | 20 ++++++++++++++++++++
 4 files changed, 45 insertions(+)

diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 8c42b4bde09c..7a0fd3dbfa29 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -317,6 +317,11 @@ LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
 LSM_HOOK(int, 0, watch_key, struct key *key)
 #endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */
 
+#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
+LSM_HOOK(int, 0, unix_find, const struct path *path, struct sock *other,
+	 int flags)
+#endif /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
+
 #ifdef CONFIG_SECURITY_NETWORK
 LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other,
 	 struct sock *newsk)
diff --git a/include/linux/security.h b/include/linux/security.h
index 83a646d72f6f..99a33d8eb28d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1931,6 +1931,17 @@ static inline int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
 }
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
+
+int security_unix_find(const struct path *path, struct sock *other, int flags);
+
+#else /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
+static inline int security_unix_find(const struct path *path, struct sock *other, int flags)
+{
+	return 0;
+}
+#endif /* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
+
 #ifdef CONFIG_SECURITY_INFINIBAND
 int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey);
 int security_ib_endport_manage_subnet(void *sec, const char *name, u8 port_num);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index d0511225799b..db9d279b3883 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -1226,10 +1226,19 @@ static struct sock *unix_find_bsd(struct sockaddr_un *sunaddr, int addr_len,
 	if (!S_ISSOCK(inode->i_mode))
 		goto path_put;
 
+	err = -ECONNREFUSED;
 	sk = unix_find_socket_byinode(inode);
 	if (!sk)
 		goto path_put;
 
+	/*
+	 * We call the hook because we know that the inode is a socket
+	 * and we hold a valid reference to it via the path.
+	 */
+	err = security_unix_find(&path, sk, flags);
+	if (err)
+		goto sock_put;
+
 	err = -EPROTOTYPE;
 	if (sk->sk_type == type)
 		touch_atime(&path);
diff --git a/security/security.c b/security/security.c
index 31a688650601..9e9515955098 100644
--- a/security/security.c
+++ b/security/security.c
@@ -4731,6 +4731,26 @@ int security_mptcp_add_subflow(struct sock *sk, struct sock *ssk)
 
 #endif	/* CONFIG_SECURITY_NETWORK */
 
+#if defined(CONFIG_SECURITY_NETWORK) && defined(CONFIG_SECURITY_PATH)
+/*
+ * security_unix_find() - Check if a named AF_UNIX socket can connect
+ * @path: path of the socket being connected to
+ * @other: peer sock
+ * @flags: flags associated with the socket
+ *
+ * This hook is called to check permissions before connecting to a named
+ * AF_UNIX socket.
+ *
+ * Return: Returns 0 if permission is granted.
+ */
+int security_unix_find(const struct path *path, struct sock *other, int flags)
+{
+	return call_int_hook(unix_find, path, other, flags);
+}
+EXPORT_SYMBOL(security_unix_find);
+
+#endif	/* CONFIG_SECURITY_NETWORK && CONFIG_SECURITY_PATH */
+
 #ifdef CONFIG_SECURITY_INFINIBAND
 /**
  * security_ib_pkey_access() - Check if access to an IB pkey is allowed
-- 
2.52.0


^ permalink raw reply related

* [PATCH v4 0/6] landlock: UNIX connect() control by pathname and scope
From: Günther Noack @ 2026-02-08 23:10 UTC (permalink / raw)
  To: Mickaël Salaün, John Johansen, Paul Moore, James Morris,
	Serge E . Hallyn
  Cc: Günther Noack, linux-security-module, Tingmao Wang,
	Justin Suess, Samasth Norway Ananda, Matthieu Buffet,
	Mikhail Ivanov, konstantin.meskhidze, Demi Marie Obenour,
	Alyssa Ross, Jann Horn, Tahera Fahimi, Simon Horman, netdev,
	Alexander Viro, Christian Brauner

Hello!

This patch set introduces a filesystem-based Landlock restriction
mechanism for connecting to UNIX domain sockets (or addressing them
with sendmsg(2)).  It introduces the filesystem access right
LANDLOCK_ACCESS_FS_RESOLVE_UNIX.

For the connection-oriented SOCK_STREAM and SOCK_SEQPACKET type
sockets, the access right makes the connect(2) operation fail with
EACCES, if denied.

SOCK_DGRAM-type UNIX sockets can be used both with connect(2), or by
passing an explicit recipient address with every sendmsg(2)
invocation.  In the latter case, the Landlock check is done when an
explicit recipient address is passed to sendmsg(2) and can make
sendmsg(2) return EACCES.  When UNIX datagram sockets are connected
with connect(2), a fixed recipient address is associated with the
socket and the check happens during connect(2) and may return EACCES.

When LANDLOCK_ACCESS_FS_RESOLVE_UNIX is handled within a Landlock
domain, this domain will only allow connect(2) and sendmsg(2) to
server sockets that were created within the same domain.  Or, to
phrase it the other way around: Unless it is allow-listed with a
LANDLOCK_PATH_BENEATH rule, the newly created domain denies connect(2)
and sendmsg(2) actions that are directed *outwards* of that domain.
In that regard, LANDLOCK_ACCESS_FS_RESOLVE_UNIX has the same semantics
as one of the "scoped" access rights.

== Motivation

Currently, landlocked processes can connect to named UNIX sockets
through the BSD socket API described in unix(7), by invoking socket(2)
followed by connect(2) with a suitable struct sockname_un holding the
socket's filename.  This is a surprising gap in Landlock's sandboxing
capabilities for users (e.g. in [1]) and it can be used to escape a
sandbox when a Unix service offers command execution (various such
scenarios were listed by Tingmao Wang in [2]).

The original feature request is at [4].

== Alternatives and Related Work

=== Alternative: Use existing LSM hooks

We have carefully and seriously considered the use of existing LSM
hooks, but still came to the conclusion that a new LSM hook is better
suited in this case:

The existing hooks security_unix_stream_connect(),
security_unix_may_send() and security_socket_connect() do not give
access to the resolved filesystem path.

* Resolving the filesystem path in the struct sockaddr_un again within
  a Landlock would produce a TOCTOU race, so this is not an option.
* We would therefore need to wire through the resolved struct path
  from unix_find_bsd() to one of the existing LSM hooks which get
  called later.  This would be a more substantial change to af_unix.c.

The struct path that is available in the listening-side struct sock is
can be read through the existing hooks, but it is not an option to use
this information: As the listening socket may have been bound from
within a different namespace, the path that was used for that can is
in the general case not meaningful for a sandboxed process.  In
particular, it is not possible to use this path (or prefixes thereof)
when constructing a sandbox policy in the client-side process.

Paul Moore also chimed in in support of adding a new hook, with the
rationale that the simplest change to the LSM hook interface has
traditionally proven to be the most robust. [11]

More details are on the Github issue at [6] and on the LKML at [9].

In a the discussion of the V2 review, started by Christian Brauner
[10], we have further explored the approach of reusing the existing
LSM hooks but still ended up leaning on the side of introducing a new
hook, with Paul Moore and me (gnoack) arguing for that option.

Further insights about the LSM hook were shared in the V3 review by
Tingmao Wang [12], who spotted additional requirements due to the two
approaches being merged into one patch set.  The summary of that
discussion is in [13].

=== Related work: Scope Control for Pathname Unix Sockets

The motivation for this patch is the same as in Tingmao Wang's patch
set for "scoped" control for pathname Unix sockets [2], originally
proposed in the Github feature request [5].

In [14], we have settled on the decision to merge the two patch sets
into this one, whose primary way of controlling connect(2) is
LANDLOCK_ACCESS_FS_RESOLVE_UNIX, but where this flag additionally has
the semantics of only restricting this unix(7) IPC *outwards* of the
created Landlock domain, in line with the logic that exists for the
existing "scoped" flags already.

By having LANDLOCK_ACCESS_FS_RESOLVE_UNIX implement "scoping"
semantics, we can avoid introducing two separate interacting flags for
now, but we retain the option of introducing
LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET at a later point in time, should
such a flag be needed to express additional rules.

== Credits

The feature was originally suggested by Jann Horn in [7].

Tingmao Wang and Demi Marie Obenour have taken the initiative to
revive this discussion again in [1], [4] and [5].

Tingmao Wang has sent the patch set for the scoped access control for
pathname Unix sockets [2] and has contributed substantial insights
during the code review, shaping the form of the LSM hook and agreeing
to merge the pathname and scoped-flag patch sets.

Justin Suess has sent the patch for the LSM hook in [8] and
subsequently through this patch set.

Christian Brauner and Paul Moore have contributed to the design of the
new LSM hook, discussing the tradeoffs in [10].

Ryan Sullivan has started on an initial implementation and has brought
up relevant discussion points on the Github issue at [4].

As maintainer of Landlock, Mickaël Salaün has done the main review so
far and particularly pointed out ways in which the UNIX connect()
patch sets interact with each other and what we need to look for with
regards to UAPI consistency as Landlock evolves.

[1] https://lore.kernel.org/landlock/515ff0f4-2ab3-46de-8d1e-5c66a93c6ede@gmail.com/
[2] Tingmao Wang's "Implement scope control for pathname Unix sockets"
    https://lore.kernel.org/all/cover.1767115163.git.m@maowtm.org/
[3] https://lore.kernel.org/all/20251230.bcae69888454@gnoack.org/
[4] Github issue for FS-based control for named Unix sockets:
    https://github.com/landlock-lsm/linux/issues/36
[5] Github issue for scope-based restriction of named Unix sockets:
    https://github.com/landlock-lsm/linux/issues/51
[6] https://github.com/landlock-lsm/linux/issues/36#issuecomment-2950632277
[7] https://lore.kernel.org/linux-security-module/CAG48ez3NvVnonOqKH4oRwRqbSOLO0p9djBqgvxVwn6gtGQBPcw@mail.gmail.com/
[8] Patch for the LSM hook:
    https://lore.kernel.org/all/20251231213314.2979118-1-utilityemal77@gmail.com/
[9] https://lore.kernel.org/all/20260108.64bd7391e1ae@gnoack.org/
[10] https://lore.kernel.org/all/20260113-kerngesund-etage-86de4a21da24@brauner/
[11] https://lore.kernel.org/all/CAHC9VhQHZCe0LMx4xzSo-h1SWY489U4frKYnxu4YVrcJN3x7nA@mail.gmail.com/
[12] https://lore.kernel.org/all/e6b6b069-384c-4c45-a56b-fa54b26bc72a@maowtm.org/
[13] https://lore.kernel.org/all/aYMenaSmBkAsFowd@google.com/
[14] https://lore.kernel.org/all/20260205.Kiech3gupee1@digikod.net/

---

== Older versions of this patch set

V1: https://lore.kernel.org/all/20260101134102.25938-1-gnoack3000@gmail.com/
V2: https://lore.kernel.org/all/20260110143300.71048-2-gnoack3000@gmail.com/
V3: https://lore.kernel.org/all/20260119203457.97676-2-gnoack3000@gmail.com/

Changes in V4:

Since this version, this patch set subsumes the scoping semantics from
Tingmao Wang's "Scope Control" patch set [2], per discussion with
Tingmao Wang and Mickaël Salaün in [14] and in the thread leading up
to it.

Now, LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET only restricts connect(2) and
sendmsg(2) *outwards* of the domain where it is restricted, *with the
same semantics as a "scoped" flag*.

 * Implement a layer-mask based version of domain_is_scoped():
   unmask_scoped_access().  Rationale: domain_is_scoped() returns
   early, which we can't do in the layer masks based variant.  The two
   variants are similar enough.
 * LSM hook: Replace 'type' argument with 'sk' argument,
   per discussion in [12] and [13].
 * Bump ABI version to 9 (pessimistically assuming that we won't make
   it for 7.0)
 * Documentation fixes in header file and in Documentation/
 * selftests: more test variants, now also parameterizing whether the
   server socket gets created within the Landlock domain or before that
 * selftests: use EXPECT_EQ() for test cleanup

Changes in V3:
 * LSM hook: rename it to security_unix_find() (Justin Suess)
   (resolving the previously open question about the LSM hook name)
   Related discussions:
   https://lore.kernel.org/all/20260112.Wufar9coosoo@digikod.net/
   https://lore.kernel.org/all/CAHC9VhSRiHwLEWfFkQdPEwgB4AXKbXzw_+3u=9hPpvUTnu02Bg@mail.gmail.com/
 * Reunite the three UNIX resolving access rights back into one
   (resolving the previously open question about the access right
   structuring) Related discussion:
   https://lore.kernel.org/all/20260112.Wufar9coosoo@digikod.net/)
 * Sample tool: Add new UNIX lookup access rights to ACCESS_FILE

Changes in V2:
 * Send Justin Suess's LSM hook patch together with the Landlock
   implementation
 * LSM hook: Pass type and flags parameters to the hook, to make the
   access right more generally usable across LSMs, per suggestion from
   Paul Moore (Implemented by Justin)
 * Split the access right into the three types of UNIX domain sockets:
   SOCK_STREAM, SOCK_DGRAM and SOCK_SEQPACKET.
 * selftests: More exhaustive tests.
 * Removed a minor commit from V1 which adds a missing close(fd) to a
   test (it is already in the mic-next branch)

Günther Noack (5):
  landlock: Control pathname UNIX domain socket resolution by path
  samples/landlock: Add support for named UNIX domain socket
    restrictions
  landlock/selftests: Test named UNIX domain socket restrictions
  landlock: Document FS access right for pathname UNIX sockets
  landlock: Document design rationale for scoped access rights

Justin Suess (1):
  lsm: Add LSM hook security_unix_find

 Documentation/security/landlock.rst          |  38 ++
 Documentation/userspace-api/landlock.rst     |  16 +-
 include/linux/lsm_hook_defs.h                |   5 +
 include/linux/security.h                     |  11 +
 include/uapi/linux/landlock.h                |  10 +
 net/unix/af_unix.c                           |   9 +
 samples/landlock/sandboxer.c                 |  15 +-
 security/landlock/access.h                   |  11 +-
 security/landlock/audit.c                    |   1 +
 security/landlock/fs.c                       | 107 ++++-
 security/landlock/limits.h                   |   2 +-
 security/landlock/syscalls.c                 |   2 +-
 security/security.c                          |  20 +
 tools/testing/selftests/landlock/base_test.c |   2 +-
 tools/testing/selftests/landlock/fs_test.c   | 386 ++++++++++++++++++-
 15 files changed, 608 insertions(+), 27 deletions(-)

-- 
2.52.0


^ permalink raw reply

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Tingmao Wang @ 2026-02-08 20:48 UTC (permalink / raw)
  To: Günther Noack
  Cc: Mickaël Salaün, Günther Noack, Justin Suess,
	Paul Moore, John Johansen, Demi Marie Obenour, Alyssa Ross,
	Jann Horn, Tahera Fahimi, Matthieu Buffet, linux-security-module
In-Reply-To: <20260208.4600394b9da7@gnoack.org>

On 2/8/26 20:37, Günther Noack wrote:
> On Sun, Feb 08, 2026 at 02:57:10AM +0000, Tingmao Wang wrote:
>> On 2/5/26 10:27, Mickaël Salaün wrote:
>>> On Thu, Feb 05, 2026 at 09:02:19AM +0100, Günther Noack wrote:
>>>> [...]
>>>>
>>>> The implementation of this approach would be that we would have to
>>>> join the functionality from the scoped and FS-based patch set, but
>>>> without introducing the LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET flag in
>>>> the UAPI.
>>>
>>> Right, this looks good to me.  We'll need to sync both patch series and
>>> remove the scope flag from UAPI.  I'll let you and Tingmao work together
>>> for the next series.  The "IPC scoping" documentation section should
>>> mention LANDLOCK_ACCESS_FS_RESOLVE_UNIX even if it's not a scope flag.
>>
>> This sounds good to me.  I'm not sure how much code we can reuse out of
>> the existing LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET patchset - but I think
>> the selftest patches could still largely be useful (after changing e.g.
>> create_scoped_domain() to use the RESOLVE_UNIX fs access instead of the
>> scope bit for pathname sockets).  The fs-based rules (i.e. "exceptions")
>> can then be tested separately from the scope tests (and would also check
>> for things like path being different across mount namespaces etc).
>>
>> Günther, feel free to take anything out of the existing scope series, if
>> you feel it would be useful.  Also let me know if you would like me to
>> help with any part of the RESOLVE_UNIX series if you feel that would be
>> useful (but you don't have to if not).
>
> Thank you, Tingmao!
>
> So far, the selftests that I already had in fs_test.c were
> straightforward to extend so that they cover the new cases.  I had a
> look at your patch set, but found the scoping tests difficult to port
> to fs_test.c

I was thinking that the tests in scoped_abstract_unix_test.c could be
extended to test scoping of pathname UNIX sockets as well (otherwise
wouldn't you have to write another instance of the scoped_domains test
based on scoped_base_variants.h, whether you put it in fs_test.c or
somewhere else?)

And if you think that is sensible, then I'm hoping that patch 4,5,6 of the
series would be mostly useful.  But it's up to you :)

> , but I'll double check that we don't miss anything.
> Either way, I'll make sure that you'll get appropriate credit for
> it. :)

Thanks!

Tingmao

> ...

^ permalink raw reply

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Günther Noack @ 2026-02-08 20:37 UTC (permalink / raw)
  To: Tingmao Wang
  Cc: Mickaël Salaün, Günther Noack, Justin Suess,
	Paul Moore, John Johansen, Demi Marie Obenour, Alyssa Ross,
	Jann Horn, Tahera Fahimi, Matthieu Buffet, linux-security-module
In-Reply-To: <ee38960f-8670-434b-9cf1-d95995b228da@maowtm.org>

On Sun, Feb 08, 2026 at 02:57:10AM +0000, Tingmao Wang wrote:
> On 2/5/26 10:27, Mickaël Salaün wrote:
> > On Thu, Feb 05, 2026 at 09:02:19AM +0100, Günther Noack wrote:
> >> [...]
> >>
> >> The implementation of this approach would be that we would have to
> >> join the functionality from the scoped and FS-based patch set, but
> >> without introducing the LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET flag in
> >> the UAPI.
> >
> > Right, this looks good to me.  We'll need to sync both patch series and
> > remove the scope flag from UAPI.  I'll let you and Tingmao work together
> > for the next series.  The "IPC scoping" documentation section should
> > mention LANDLOCK_ACCESS_FS_RESOLVE_UNIX even if it's not a scope flag.
> 
> This sounds good to me.  I'm not sure how much code we can reuse out of
> the existing LANDLOCK_SCOPE_PATHNAME_UNIX_SOCKET patchset - but I think
> the selftest patches could still largely be useful (after changing e.g.
> create_scoped_domain() to use the RESOLVE_UNIX fs access instead of the
> scope bit for pathname sockets).  The fs-based rules (i.e. "exceptions")
> can then be tested separately from the scope tests (and would also check
> for things like path being different across mount namespaces etc).
> 
> Günther, feel free to take anything out of the existing scope series, if
> you feel it would be useful.  Also let me know if you would like me to
> help with any part of the RESOLVE_UNIX series if you feel that would be
> useful (but you don't have to if not).

Thank you, Tingmao!

So far, the selftests that I already had in fs_test.c were
straightforward to extend so that they cover the new cases.  I had a
look at your patch set, but found the scoping tests difficult to port
to fs_test.c, but I'll double check that we don't miss anything.
Either way, I'll make sure that you'll get appropriate credit for
it. :)

–Günther

(P.S. If this mail looks familiar, it's because I accidentally replied
with an earlier version of that to the wrong mail earlier today
(https://lore.kernel.org/all/20260208.b25c4105bc03@gnoack.org/) –
Replying here again so that this answer makes more sense.)

^ permalink raw reply

* Re: [PATCH v9 11/11] tpm-buf: Implement managed allocations
From: Jarkko Sakkinen @ 2026-02-08 14:09 UTC (permalink / raw)
  To: linux-integrity
  Cc: Jarkko Sakkinen, Ross Philipson, Stefan Berger, James Bottomley,
	Mimi Zohar, David Howells, Paul Moore, James Morris,
	Serge E. Hallyn, open list:KEYS-TRUSTED,
	open list:SECURITY SUBSYSTEM, open list
In-Reply-To: <20260125192526.782202-12-jarkko@kernel.org>

On Sun, Jan 25, 2026 at 09:25:21PM +0200, Jarkko Sakkinen wrote:
> From: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> 
> Decouple kzalloc from buffer creation, so that a managed allocation can be
> used:
> 
> 	struct tpm_buf *buf __free(kfree) buf = kzalloc(TPM_BUFSIZE,
> 							GFP_KERNEL);
> 	if (!buf)
> 		return -ENOMEM;
> 
> 	tpm_buf_init(buf, TPM_BUFSIZE);
> 
> Alternatively, stack allocations are also possible:
> 
> 	u8 buf_data[512];
> 	struct tpm_buf *buf = (struct tpm_buf *)buf_data;
> 	tpm_buf_init(buf, sizeof(buf_data));
> 
> This is achieved by embedding buffer's header inside the allocated blob,
> instead of having an outer wrapper.
> 
> Cc: Ross Philipson <ross.philipson@oracle.com>
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@opinsys.com>
> Reviewed-by: Stefan Berger <stefanb@linux.ibm.com>

Since rest of the series does not seem to move forward  maybe I should
rebase this to bottom and send it as a separate patch?

This patch eliminates a category of memory bugs and is that way useful.

It also starts to be pretty well stress tested.

BR, Jarkko

^ permalink raw reply

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Günther Noack @ 2026-02-08 13:49 UTC (permalink / raw)
  To: Tingmao Wang
  Cc: Mickaël Salaün, Justin Suess, Günther Noack,
	Demi Marie Obenour, Alyssa Ross, Jann Horn, Tahera Fahimi,
	linux-security-module, Matthieu Buffet
In-Reply-To: <3f9d456f-8343-4b46-8770-38190f838dbe@maowtm.org>

On Sun, Feb 08, 2026 at 02:57:16AM +0000, Tingmao Wang wrote:
> On 2/5/26 19:15, Mickaël Salaün wrote:
> > On Thu, Feb 05, 2026 at 10:18:54AM -0500, Justin Suess wrote:
> >> On 2/4/26 13:28, Mickaël Salaün wrote:
> >>>> Tingmao:
> >>>>
> >>>> For connecting a pathname unix socket, the order of the hooks landlock sees is something like:
> >>>>
> >>>> 1.  security_unix_find. (to look up the paths)
> >>>>
> >>>> 2. security_unix_may_send, security_unix_stream_connect (after the path is looked up)
> 
> btw, ideally for pathname sockets we can leave all the checking in the
> security_unix_find() hook (as newly proposed, with the struct sock *other
> param), and not have to e.g. call domain_is_scoped() again in
> security_unix_may_send and security_unix_stream_connect, right?
> 
> (Although if this changes error codes, we might have to "delay" the denial
> until the may_send/connect hooks...?  Hopefully not but not checked.)

Thank you, Tingmao!

So far, the selftests that I already had in fs_test.c were
straightforward to extend so that they cover the new cases, but I'll
definitely have a look through your patch set and see if there are
parts that we can reuse or that I missed to cover.  Either way, I'll
make sure that you'll get appropriate credit for it. :)

–Günther

^ permalink raw reply

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Günther Noack @ 2026-02-08 13:44 UTC (permalink / raw)
  To: Tingmao Wang, g
  Cc: Mickaël Salaün, Justin Suess, Günther Noack,
	Demi Marie Obenour, Alyssa Ross, Jann Horn, Tahera Fahimi,
	linux-security-module, Matthieu Buffet
In-Reply-To: <3f9d456f-8343-4b46-8770-38190f838dbe@maowtm.org>

On Sun, Feb 08, 2026 at 02:57:16AM +0000, Tingmao Wang wrote:
> On 2/5/26 19:15, Mickaël Salaün wrote:
> > On Thu, Feb 05, 2026 at 10:18:54AM -0500, Justin Suess wrote:
> >> On 2/4/26 13:28, Mickaël Salaün wrote:
> >>>> Tingmao:
> >>>>
> >>>> For connecting a pathname unix socket, the order of the hooks landlock sees is something like:
> >>>>
> >>>> 1.  security_unix_find. (to look up the paths)
> >>>>
> >>>> 2. security_unix_may_send, security_unix_stream_connect (after the path is looked up)
> 
> btw, ideally for pathname sockets we can leave all the checking in the
> security_unix_find() hook (as newly proposed, with the struct sock *other
> param), and not have to e.g. call domain_is_scoped() again in
> security_unix_may_send and security_unix_stream_connect, right?
>
> (Although if this changes error codes, we might have to "delay" the denial
> until the may_send/connect hooks...?  Hopefully not but not checked.)

Yes, absolutely.  I have had a stab at it and will send it soon.

Justin adopted your suggestion from [1] and created an updated LSM
hook patch based on it.  With that, I am doing both checks in the
security_unix_find() hook, based on the resulting struct sock.

[1] https://lore.kernel.org/all/e6b6b069-384c-4c45-a56b-fa54b26bc72a@maowtm.org/#t

–Günther

^ permalink raw reply

* Re: [PATCH v2 0/6] Landlock: Implement scope control for pathname Unix sockets
From: Tingmao Wang @ 2026-02-08  2:57 UTC (permalink / raw)
  To: Mickaël Salaün, Justin Suess, Günther Noack
  Cc: Günther Noack, Demi Marie Obenour, Alyssa Ross, Jann Horn,
	Tahera Fahimi, linux-security-module, Matthieu Buffet
In-Reply-To: <20260205.phohK6hajaih@digikod.net>

On 2/5/26 19:15, Mickaël Salaün wrote:
> On Thu, Feb 05, 2026 at 10:18:54AM -0500, Justin Suess wrote:
>>
>> On 2/4/26 13:28, Mickaël Salaün wrote:
>>
>>>> [...]
>>>> Tingmao:
>>>>
>>>> For connecting a pathname unix socket, the order of the hooks landlock sees is something like:
>>>>
>>>> 1.  security_unix_find. (to look up the paths)
>>>>
>>>> 2. security_unix_may_send, security_unix_stream_connect (after the path is looked up)

btw, ideally for pathname sockets we can leave all the checking in the
security_unix_find() hook (as newly proposed, with the struct sock *other
param), and not have to e.g. call domain_is_scoped() again in
security_unix_may_send and security_unix_stream_connect, right?

(Although if this changes error codes, we might have to "delay" the denial
until the may_send/connect hooks...?  Hopefully not but not checked.)

^ permalink raw reply


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