From: Tahera Fahimi <fahimitahera@gmail.com>
To: "Mickaël Salaün" <mic@digikod.net>
Cc: "Günther Noack" <gnoack@google.com>,
"Paul Moore" <paul@paul-moore.com>,
"James Morris" <jmorris@namei.org>,
"Serge E. Hallyn" <serge@hallyn.com>,
linux-security-module@vger.kernel.org,
linux-kernel@vger.kernel.org,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Jann Horn" <jannh@google.com>,
outreachy@lists.linux.dev, netdev@vger.kernel.org
Subject: Re: [PATCH v6] landlock: Add abstract unix socket connect restriction
Date: Wed, 10 Jul 2024 11:20:44 -0600 [thread overview]
Message-ID: <Zo7C7MUfnPApp0Np@tahera-OptiPlex-5000> (raw)
In-Reply-To: <20240704.uab4aveeYad0@digikod.net>
On Mon, Jul 08, 2024 at 05:35:48PM +0200, Mickaël Salaün wrote:
> Please add a user documentation with the next version. You can take
> some inspiration in commits that changed
> Documentation/userspace-api/landlock.rst
>
> You also need to extend samples/landlock/sandboxer.c with this new
> feature. You might want to use a new environment variable (LL_SCOPED)
> with "a" (for abstract unix socket) as the only valid content. New kind
> of sopping could add new characters. I'm not sure this is the most
> ergonomic, but let's go this way unless you have something else in mind.
Thanks for the feedback.
This will be added in the next patch.
> All the related patches (kernel change, tests, sample, documentation)
> should be in the same patch series, with a cover letter introducing the
> feature and pointing to the previous versions with links to
> https://lore.kernel.org/r/...
Noted.
>
> On Thu, Jun 27, 2024 at 05:30:17PM -0600, Tahera Fahimi wrote:
> > Abstract unix sockets are used for local inter-process communications
> > without a filesystem. Currently a sandboxed process can connect to a
>
> "local inter-process communications independant of the filesystem."
>
> > socket outside of the sandboxed environment, since Landlock has no
> > restriction for connecting to an abstract socket address. Access to
> > such sockets for a sandboxed process should be scoped the same way
> > ptrace is limited.
> >
> > Because of compatibility reasons and since landlock should be flexible,
>
> Landlock
[...]
> > diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h
> > index 68625e728f43..010aaca5b05a 100644
> > --- a/include/uapi/linux/landlock.h
> > +++ b/include/uapi/linux/landlock.h
> > @@ -37,6 +37,12 @@ struct landlock_ruleset_attr {
> > * rule explicitly allow them.
> > */
> > __u64 handled_access_net;
> > + /**
> > + * @scoped: Bitmask of scopes (cf. `Scope flags`_)
> > + * restricting a Landlock domain from accessing outside
> > + * resources(e.g. IPCs).
>
> A space is missing.
>
> > + */
> > + __u64 scoped;
> > };
> >
> > /*
> > @@ -266,4 +272,27 @@ 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
> > + *
> > + * .scoped attribute handles a set of restrictions on kernel IPCs through
> > + * the following flags.
>
> I think you can remove this sentence.
>
[...]
> > diff --git a/security/landlock/task.c b/security/landlock/task.c
> > index 849f5123610b..acc6e0fbc111 100644
> > --- a/security/landlock/task.c
> > +++ b/security/landlock/task.c
> > @@ -13,6 +13,8 @@
> > #include <linux/lsm_hooks.h>
> > #include <linux/rcupdate.h>
> > #include <linux/sched.h>
> > +#include <net/sock.h>
> > +#include <net/af_unix.h>
> >
> > #include "common.h"
> > #include "cred.h"
> > @@ -108,9 +110,69 @@ static int hook_ptrace_traceme(struct task_struct *const parent)
> > return task_ptrace(parent, current);
> > }
> >
> > +static access_mask_t
> > +get_scoped_accesses(const struct landlock_ruleset *const domain)
> > +{
> > + access_mask_t access_dom = 0;
> > + size_t layer_level;
> > +
> > + for (layer_level = 0; layer_level < domain->num_layers; layer_level++)
> > + access_dom |= landlock_get_scope_mask(domain, layer_level);
> > + return access_dom;
> > +}
> > +
> > +static bool sock_is_scoped(struct sock *const other)
> > +{
> > + const struct landlock_ruleset *dom_other;
> > + const struct landlock_ruleset *const dom =
> > + landlock_get_current_domain();
> > +
> > + /* quick return if there is no domain or .scoped is not set */
> > + if (!dom || !get_scoped_accesses(dom))
> > + return true;
> > +
> > + /* the credentials will not change */
> > + lockdep_assert_held(&unix_sk(other)->lock);
> > + if (other->sk_type != SOCK_DGRAM) {
> > + dom_other = landlock_cred(other->sk_peer_cred)->domain;
>
> Why using different credentials for connected or not connected sockets?
> We should use the same consistent logic for both:
> other->sk_socket->file->f_cred (the process that created the socket, not
> the one listening).
The aim was to use the process's credential that utilized the socket for
connected sockets, and the process's credential created the socket for
non-connected sockets. However, I will change it and use the same
credential to keep it consistent for both cases.
> > + } else {
> > + dom_other =
> > + landlock_cred(other->sk_socket->file->f_cred)->domain;
> > + }
> > +
> > + if (!dom_other || !get_scoped_accesses(dom_other))
>
> What if only one layer in dom_other is scoped?
The function `get_scoped_accesses()` cover this.
> > + return false;
> > +
> > + /* other is scoped, they connect if they are in the same domain */
>
> This doesn't fit with each domain's scoping. It only considers no
> scopping for all domains, or all domains as scopped if any of them is.
> domain_scope_le() needs to be changed to follow each domain's contract.
Noted.
> > + return domain_scope_le(dom, dom_other);
> > +}
> > +
> > +static int hook_unix_stream_connect(struct sock *const sock,
> > + struct sock *const other,
> > + struct sock *const newsk)
> > +{
> > + if (sock_is_scoped(other))
> > + return 0;
> > +
> > + return -EPERM;
> > +}
> > +
> > +static int hook_unix_may_send(struct socket *const sock,
> > + struct socket *const other)
> > +{
> > + pr_warn("XXX %s:%d sock->file:%p other->file:%p\n", __func__, __LINE__,
> > + sock->file, other->file);
>
> Please remove debug code.
>
> > + if (sock_is_scoped(other->sk))
> > + return 0;
> > +
> > + return -EPERM;
> > +}
> > +
> > static struct security_hook_list landlock_hooks[] __ro_after_init = {
> > LSM_HOOK_INIT(ptrace_access_check, hook_ptrace_access_check),
> > LSM_HOOK_INIT(ptrace_traceme, hook_ptrace_traceme),
> > + LSM_HOOK_INIT(unix_stream_connect, hook_unix_stream_connect),
> > + LSM_HOOK_INIT(unix_may_send, hook_unix_may_send),
> > };
> >
> > __init void landlock_add_task_hooks(void)
> > --
> > 2.34.1
> >
> >
prev parent reply other threads:[~2024-07-10 17:20 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-06-27 23:30 [PATCH v6] landlock: Add abstract unix socket connect restriction Tahera Fahimi
2024-07-08 15:35 ` Mickaël Salaün
2024-07-10 17:20 ` Tahera Fahimi [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Zo7C7MUfnPApp0Np@tahera-OptiPlex-5000 \
--to=fahimitahera@gmail.com \
--cc=bjorn3_gh@protonmail.com \
--cc=gnoack@google.com \
--cc=jannh@google.com \
--cc=jmorris@namei.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mic@digikod.net \
--cc=netdev@vger.kernel.org \
--cc=outreachy@lists.linux.dev \
--cc=paul@paul-moore.com \
--cc=serge@hallyn.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.