lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250310.990b29c809af@gnoack.org>
Date: Mon, 10 Mar 2025 14:04:23 +0100
From: Günther Noack <gnoack3000@...il.com>
To: Paul Moore <paul@...l-moore.com>,
	Mickaël Salaün <mic@...ikod.net>,
	sergeh@...nel.org
Cc: David Howells <dhowells@...hat.com>, Kees Cook <keescook@...omium.org>,
	Paul Moore <paul@...l-moore.com>,
	linux-security-module@...r.kernel.org,
	Konstantin Meskhidze <konstantin.meskhidze@...wei.com>,
	Jann Horn <jannh@...gle.com>, linux-kernel@...r.kernel.org,
	Peter Newman <peternewman@...gle.com>
Subject: Re: [RFC 1/2] landlock: Multithreading support for
 landlock_restrict_self()

Hello Paul and Serge!

On Tue, Mar 04, 2025 at 09:25:51PM +0100, Mickaël Salaün wrote:
> On Fri, Feb 28, 2025 at 06:33:55PM +0100, Günther Noack wrote:
> > Hello!
> > 
> > Thanks for the review!
> > 
> > I'm adding David Howells to this thread as well.  David, maybe you can
> > help us and suggest a appropriate way to update the struct cred across
> > multiple threads?

Paul and Serge, since you are volunteering to take ownership of
credentials, maybe you can advise on what is the best approach here?

To summarize the approaches that I have been discussing with Mickaël:

Approach 1: Use the creds API thread-by-thread (implemented here)

  * Each task calls prepare_creds() and commit_creds() on its own, in
    line with the way the API is designed to be used (from a single
    task).
  * Task work gets scheduled with a pseudo-signal and the task that
    invoked the syscall is waiting for all of them to return.
  * Task work can fail at the beginning due to prepare_creds(), in
    which case all tasks have to abort_creds(). Additional
    synchronization is needed for that.

  Drawback: We need to grab the system-global task lock to prevent new
  thread creation and also grab the per-process signal lock to prevent
  races with other creds accesses, for the entire time as we wait for
  each task to do the task work.

Approach 2: Attempt to do the prepare_creds() step in the calling task.

  * Would use an API similar to what keyctl uses for the
    parent-process update.
  * This side-steps the credentials update API as it is documented in
    Documentation, using the cred_alloc_blank() helper and replicating
    some prepare_creds() logic.

  Drawback: This would introduce another use of the cred_alloc_blank()
  API (and the cred_transfer LSM hook), which would otherwise be
  reasonable to delete if we can remove the keyctl use case.
  (https://lore.kernel.org/all/20240805-remove-cred-transfer-v2-0-a2aa1d45e6b8@google.com/)

Approach 3: Store Landlock domains outside of credentials altogether

  * We could also store a task's Landlock domain as a pointer in the
    per-task security blob, and refcount these.  We would need to make
    sure that they get newly referenced and updated in the same
    scenarios as they do within struct cred today.
  * We could then guard accesses to a task's Landlock domain with a
    more classic locking mechanism.  This would make it possible to
    update the Landlock domain of all tasks in a process without
    having to go through pseudo-signals.

  Drawbacks:
  * Would have to make sure that the Landlock domain the task's LSM
    blob behaves exactly the same as before in the struct cred.
  * Potentially slower to access Landlock domains that are guarded by
    a mutex.

I'd be interested to hear your opinion on how we should best approach
this.

P.S. This is probably already clear to everyone who read this far, but
the problem that creds can't be updated across tasks has already lead
to other difficult APIs and also bleeds into user-level interfaces
such as the setuid() family of syscalls as well as capability
updating.  Both of these are solved from user space through the signal
hack documented in nptl(7), which is used in glibc for setuid()-style
calls and in libpsx for capabilities and Landlock's Go library.  If we
had a working way to do these cross-thread updates in the kernel, that
would simplify these userspace implementations.  (There are more links
in the cover letter at the top of this thread.)

Thanks,
–Günther

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ