[PATCH v11 1/8] Landlock: Add abstract UNIX socket restriction

Tahera Fahimi fahimitahera at gmail.com
Mon Sep 16 12:32:27 UTC 2024


On Fri, Sep 13, 2024 at 03:32:59PM +0200, Mickaël Salaün wrote:
> On Wed, Sep 04, 2024 at 06:13:55PM -0600, Tahera Fahimi wrote:
> > This patch introduces a new "scoped" attribute to the
> > landlock_ruleset_attr that can specify
> > "LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET" to scope abstract UNIX sockets
> > from connecting to a process outside of the same Landlock domain. It
> > implements two hooks, unix_stream_connect and unix_may_send to enforce
> > this restriction.
> > 
> > Closes: https://github.com/landlock-lsm/linux/issues/7
> > Signed-off-by: Tahera Fahimi <fahimitahera at gmail.com>
> > 
> > ---
> > v11:
> > - For a connected abstract datagram socket, the hook_unix_may_send
> >   allows the socket to send a data. (it is treated as a connected stream
> >   socket)
> > - Minor comment revision.
> > v10:
> > - Minor code improvement based on reviews on v9.
> > v9:
> > - Editting inline comments.
> > - Major refactoring in domain_is_scoped() and is_abstract_socket
> > v8:
> > - Code refactoring (improve code readability, renaming variable, etc.)
> >   based on reviews by Mickaël Salaün on version 7.
> > - Adding warn_on_once to check (impossible) inconsistencies.
> > - Adding inline comments.
> > - Adding check_unix_address_format to check if the scoping socket is an
> >   abstract UNIX sockets.
> > v7:
> > - Using socket's file credentials for both connected(STREAM) and
> >   non-connected(DGRAM) sockets.
> > - Adding "domain_sock_scope" instead of the domain scoping mechanism
> >   used in ptrace ensures that if a server's domain is accessible from
> >   the client's domain (where the client is more privileged than the
> >   server), the client can connect to the server in all edge cases.
> > - Removing debug codes.
> > v6:
> > - Removing curr_ruleset from landlock_hierarchy, and switching back to
> >   use the same domain scoping as ptrace.
> > - code clean up.
> > v5:
> > - Renaming "LANDLOCK_*_ACCESS_SCOPE" to "LANDLOCK_*_SCOPE"
> > - Adding curr_ruleset to hierarachy_ruleset structure to have access
> >   from landlock_hierarchy to its respective landlock_ruleset.
> > - Using curr_ruleset to check if a domain is scoped while walking in the
> >   hierarchy of domains.
> > - Modifying inline comments.
> > v4:
> > - Rebased on Günther's Patch:
> >   https://lore.kernel.org/all/20240610082115.1693267-1-gnoack@google.com/
> >   so there is no need for "LANDLOCK_SHIFT_ACCESS_SCOPE", then it is
> >   removed.
> > - Adding get_scope_accesses function to check all scoped access masks in
> >   a ruleset.
> > - Using socket's file credentials instead of credentials stored in
> >   peer_cred for datagram sockets. (see discussion in [1])
> > - Modifying inline comments.
> > V3:
> > - Improving commit description.
> > - Introducing "scoped" attribute to landlock_ruleset_attr for IPC
> >   scoping purpose, and adding related functions.
> > - Changing structure of ruleset based on "scoped".
> > - Removing rcu lock and using unix_sk lock instead.
> > - Introducing scoping for datagram sockets in unix_may_send.
> > V2:
> > - Removing wrapper functions
> > 
> > [1]https://lore.kernel.org/all/20240610.Aifee5ingugh@digikod.net/
> > ---
> >  include/uapi/linux/landlock.h                |  28 ++++
> >  security/landlock/limits.h                   |   3 +
> >  security/landlock/ruleset.c                  |   7 +-
> >  security/landlock/ruleset.h                  |  24 +++-
> >  security/landlock/syscalls.c                 |  17 ++-
> >  security/landlock/task.c                     | 136 +++++++++++++++++++
> >  tools/testing/selftests/landlock/base_test.c |   2 +-
> >  7 files changed, 208 insertions(+), 9 deletions(-)
> > 
> > diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> > index 2c8dbc74b955..dfd48d722834 100644
> > --- a/include/uapi/linux/landlock.h
> > +++ b/include/uapi/linux/landlock.h
> > @@ -44,6 +44,12 @@ struct landlock_ruleset_attr {
> >  	 * flags`_).
> >  	 */
> >  	__u64 handled_access_net;
> > +	/**
> > +	 * @scoped: Bitmask of scopes (cf. `Scope flags`_)
> > +	 * restricting a Landlock domain from accessing outside
> > +	 * resources(e.g. IPCs).
> > +	 */
> > +	__u64 scoped;
> >  };
> >  
> >  /*
> > @@ -274,4 +280,26 @@ struct landlock_net_port_attr {
> >  #define LANDLOCK_ACCESS_NET_BIND_TCP			(1ULL << 0)
> >  #define LANDLOCK_ACCESS_NET_CONNECT_TCP			(1ULL << 1)
> >  /* clang-format on */
> > +
> > +/**
> > + * DOC: scope
> > + *
> > + * Scope flags
> > + * ~~~~~~~~~~~
> > + *
> > + * These flags enable to restrict a sandboxed process from a set of IPC
> > + * actions. Setting a flag for a ruleset will isolate the Landlock domain
> > + * to forbid connections to resources outside the domain.
> > + *
> > + * IPCs with scoped actions:
> > + *
> > + * - %LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET: Restrict a sandboxed process
> > + *   from connecting to an abstract unix socket created by a process
> > + *   outside the related Landlock domain (e.g. a parent domain or a
> > + *   non-sandboxed process).
> > + */
> > +/* clang-format off */
> > +#define LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET		(1ULL << 0)
> 
> Thinking more about it, it makes more sense to rename it to
> LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET (s/SCOPED/SCOPE/) because it
> express a scope (not a "scoped") and it allign with the current
> LANDLOCK_ACCESS_* and other internal variables such as
> LANDLOCK_LAST_SCOPE...
> 
> However, it still makes sense to keep the "scoped" ruleset's field,
> which is pretty similar to the "handled_*" semantic: it describes what
> will be *scoped* by the ruleset.
The proposed changes make sense. They are applied in commit
[0b365024c726277eb73e461849709605d1819977]/next branch, and look good
to me.

> > +/* clang-format on*/
> > +
> >  #endif /* _UAPI_LINUX_LANDLOCK_H */
> > diff --git a/security/landlock/limits.h b/security/landlock/limits.h
> > index 4eb643077a2a..eb01d0fb2165 100644
> > --- a/security/landlock/limits.h
> > +++ b/security/landlock/limits.h
> > @@ -26,6 +26,9 @@
> >  #define LANDLOCK_MASK_ACCESS_NET	((LANDLOCK_LAST_ACCESS_NET << 1) - 1)
> >  #define LANDLOCK_NUM_ACCESS_NET		__const_hweight64(LANDLOCK_MASK_ACCESS_NET)
> >  
> > +#define LANDLOCK_LAST_SCOPE		LANDLOCK_SCOPED_ABSTRACT_UNIX_SOCKET
> > +#define LANDLOCK_MASK_SCOPE		((LANDLOCK_LAST_SCOPE << 1) - 1)
> > +#define LANDLOCK_NUM_SCOPE		__const_hweight64(LANDLOCK_MASK_SCOPE)
> >  /* clang-format on */



More information about the Linux-security-module-archive mailing list