* Re: [PATCH] ima: Allow to import the blacklisted cert signed by secondary CA cert
From: Jia Zhang @ 2019-08-02 1:42 UTC (permalink / raw)
To: Mimi Zohar, dhowells, dmitry.kasatkin
Cc: keyrings, linux-security-module, linux-integrity, linux-kernel,
Mark D. Baushke, Petko Manolov
In-Reply-To: <1564700229.11223.9.camel@linux.ibm.com>
On 2019/8/2 上午6:57, Mimi Zohar wrote:
> Hi Jia,
>
> On Thu, 2019-08-01 at 09:23 +0800, Jia Zhang wrote:
>> Similar to .ima, the cert imported to .ima_blacklist is able to be
>> authenticated by a secondary CA cert.
>>
>> Signed-off-by: Jia Zhang <zhang.jia@linux.alibaba.com>
>
> The IMA blacklist, which is defined as experimental for a reason, was
> upstreamed prior to the system blacklist. Any reason you're not using
> the system blacklist? Before making this sort of change, I'd like
> some input from others.
In our trusted cloud service, the IMA private key is controlled by
tenant for some reason. Some unprofessional operations made by tenant
may lead to the leakage of IMA private key. So the need for importing
the blacklisted is necessary,without system/kexec reboot, on the
contrary, the system blacklist needs a kernel rebuild and system/kexec
reboot, without runtime and fine-grained control.
The secondary CA cert has a similar story, but it is not controlled by
tenant. It is always imported during system/kexec boot to serve
importing IMA trusted cert and IMA blacklisted cert.
Jia
>
> thanks,
>
> Mimi
>
^ permalink raw reply
* [GIT PULL] SELinux fixes for v5.3 (#2)
From: Paul Moore @ 2019-08-01 23:01 UTC (permalink / raw)
To: Linus Torvalds; +Cc: selinux, linux-security-module, linux-kernel
Hi Linus,
One more small patch for Linux v5.3-rcX to fix a potential memory leak
in an error path. Please merge.
Thanks,
-Paul
--
The following changes since commit acbc372e6109c803cbee4733769d02008381740f:
selinux: check sidtab limit before adding a new entry
(2019-07-24 11:13:34 -0400)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git
tags/selinux-pr-20190801
for you to fetch changes up to 45385237f65aeee73641f1ef737d7273905a233f:
selinux: fix memory leak in policydb_init() (2019-07-31 16:51:23 -0400)
----------------------------------------------------------------
selinux/stable-5.3 PR 20190801
----------------------------------------------------------------
Ondrej Mosnacek (1):
selinux: fix memory leak in policydb_init()
security/selinux/ss/policydb.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [PATCH] ima: Allow to import the blacklisted cert signed by secondary CA cert
From: Mimi Zohar @ 2019-08-01 22:57 UTC (permalink / raw)
To: Jia Zhang, dhowells, dmitry.kasatkin
Cc: keyrings, linux-security-module, linux-integrity, linux-kernel,
Mark D. Baushke, Petko Manolov
In-Reply-To: <1564622625-112173-1-git-send-email-zhang.jia@linux.alibaba.com>
Hi Jia,
On Thu, 2019-08-01 at 09:23 +0800, Jia Zhang wrote:
> Similar to .ima, the cert imported to .ima_blacklist is able to be
> authenticated by a secondary CA cert.
>
> Signed-off-by: Jia Zhang <zhang.jia@linux.alibaba.com>
The IMA blacklist, which is defined as experimental for a reason, was
upstreamed prior to the system blacklist. Any reason you're not using
the system blacklist? Before making this sort of change, I'd like
some input from others.
thanks,
Mimi
^ permalink raw reply
* Re: Security labeling in NFS4 - who owns it?
From: Casey Schaufler @ 2019-08-01 22:47 UTC (permalink / raw)
To: Paul Moore
Cc: linux-nfs, Linux Security Module list, SELinux, Trond Myklebust,
Anna Schumaker, casey
In-Reply-To: <CAHC9VhQRUGbU70p8p+zoxqgAF-W92Zz=rOjFB68JsaitrfQt_g@mail.gmail.com>
On 8/1/2019 3:02 PM, Paul Moore wrote:
> On Thu, Aug 1, 2019 at 3:39 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>> As part of my work on LSM stacking I've encountered some issues with
>> the Linux implementation of NFS4 security labels. For example, the LFS
>> data is ignored, so even if the client and server are willing to identify
>> the kind of information they are passing, the identity information isn't
>> available. The code asks if attributes requested are mandatory access
>> control attributes, but cannot differentiate between which of the possible
>> security attribute the other end is providing.
>>
>> Is anyone actively owing the NFS labeling code? I'd like to bounce an
>> idea or two around before committing too much time to my ideas of
>> solutions.
> I guess it all depends on what you mean by "own". Historically it has
> been a mix of the NFS and SELinux folks that have worked on it and
> contributed patches, with code sprinkled between the two subsystems
> (and possibly elsewhere too).
>
> I suspect a better question would be: who should you work with to
> discuss issues the labeled NFS code? I don't want to assume too much,
> but I think you know the answer to that one already ;)
I know you have many balls in the air and don't want to pester you
with every issue, but since you (sort of) volunteered ...
The labeled NFS code provides support for a single "security label".
When an extended attribute (xattr) is requested on an NFS4.2 or later
filesystem the NFS code calls security_ismaclabel(attrname) to determine
if the requested attrname is recognized as the name of the one attribute
whose value is maintained as the "security label". This works swimmingly
so long as all the NFS servers and all the NFS clients are sharing the
same attrname.
On a system with multiple security modules that provide ismaclabel hooks
we encounter ambiguity. If SELinux and Smack are both available
security_ismaclabel("selinux") and security_ismaclabel("SMACK64") will
both return success, and the NFS xattr code will set/get the network
resident value for either. Of course, only one can be correct, but there
does not appear to be any way to determine which it is. The protocol
provides an "LFS" to identify format the data being transmitted, but
it is not used in the Linux implementation.
It is reasonable (to the extent running SELinux and Smack together is
reasonable) for a program to ask for all the security attributes on a
file. It would be perfectly reasonable for a program like ls or systemd
to ask for both values.
There's an easy workaround, which is to assume that the first security
module that provides the ismaclabel hook will be the NFS using LSM.
Or, that the last security module with a hook gets the data. A slightly
more difficult option is to have a mount option ( -o nfslsm=selinux )
or a system wide setting (echo selinux > /sys/kernel/security/nfslsm)
or some other way to tell the system which to do.
Adding LFS management could be tricky in light of the compatibility
issues that will arise when talking to a server that doesn't do it.
I'm looking at it makes sense to "fix" the NFS implementation
to identify the data format with the LFS value. That is probably a
bigger job than I want to take on. If not, I solicit opinions regarding
which of the workarounds is most likely to be agreeable.
^ permalink raw reply
* Re: Security labeling in NFS4 - who owns it?
From: Paul Moore @ 2019-08-01 22:02 UTC (permalink / raw)
To: Casey Schaufler
Cc: linux-nfs, Linux Security Module list, SELinux, Trond Myklebust,
Anna Schumaker
In-Reply-To: <2d7f0c7e-a82a-5adb-df94-3ac4fa6b0dfe@schaufler-ca.com>
On Thu, Aug 1, 2019 at 3:39 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> As part of my work on LSM stacking I've encountered some issues with
> the Linux implementation of NFS4 security labels. For example, the LFS
> data is ignored, so even if the client and server are willing to identify
> the kind of information they are passing, the identity information isn't
> available. The code asks if attributes requested are mandatory access
> control attributes, but cannot differentiate between which of the possible
> security attribute the other end is providing.
>
> Is anyone actively owing the NFS labeling code? I'd like to bounce an
> idea or two around before committing too much time to my ideas of
> solutions.
I guess it all depends on what you mean by "own". Historically it has
been a mix of the NFS and SELinux folks that have worked on it and
contributed patches, with code sprinkled between the two subsystems
(and possibly elsewhere too).
I suspect a better question would be: who should you work with to
discuss issues the labeled NFS code? I don't want to assume too much,
but I think you know the answer to that one already ;)
--
paul moore
www.paul-moore.com
^ permalink raw reply
* Re: [PATCH V37 19/29] Lock down module params that specify hardware parameters (eg. ioport)
From: Matthew Garrett @ 2019-08-01 20:44 UTC (permalink / raw)
To: Jessica Yu
Cc: James Morris, LSM List, Linux Kernel Mailing List, Linux API,
David Howells, Alan Cox, Kees Cook
In-Reply-To: <20190801161933.GB5834@linux-8ccs>
On Thu, Aug 1, 2019 at 9:19 AM Jessica Yu <jeyu@kernel.org> wrote:
> Hm, I don't think the doing parameter ended up being used in this function?
Thanks for catching that, I'll fix.
^ permalink raw reply
* Re: [PATCH V37 04/29] Enforce module signatures if the kernel is locked down
From: Matthew Garrett @ 2019-08-01 20:42 UTC (permalink / raw)
To: Jessica Yu
Cc: James Morris, LSM List, Linux Kernel Mailing List, Linux API,
David Howells, Kees Cook
In-Reply-To: <20190801142157.GA5834@linux-8ccs>
On Thu, Aug 1, 2019 at 7:22 AM Jessica Yu <jeyu@kernel.org> wrote:
> Apologies if this was addressed in another patch in your series (I've
> only skimmed the first few), but what should happen if the kernel is
> locked down, but CONFIG_MODULE_SIG=n? Or shouldn't CONFIG_SECURITY_LOCKDOWN_LSM
> depend on CONFIG_MODULE_SIG? Otherwise I think we'll end up calling
> the empty !CONFIG_MODULE_SIG module_sig_check() stub even though
> lockdown is enabled.
Hm. Someone could certainly configure their kernel in that way. I'm
not sure that tying CONFIG_SECURITY_LOCKDOWN_LSM to CONFIG_MODULE_SIG
is the right solution, since the new LSM approach means that any other
LSM could also impose the same policy. Perhaps we should just document
this?
^ permalink raw reply
* Security labeling in NFS4 - who owns it?
From: Casey Schaufler @ 2019-08-01 19:39 UTC (permalink / raw)
To: linux-nfs, Linux Security Module list, SELinux, Trond Myklebust,
Anna Schumaker
Cc: casey
As part of my work on LSM stacking I've encountered some issues with
the Linux implementation of NFS4 security labels. For example, the LFS
data is ignored, so even if the client and server are willing to identify
the kind of information they are passing, the identity information isn't
available. The code asks if attributes requested are mandatory access
control attributes, but cannot differentiate between which of the possible
security attribute the other end is providing.
Is anyone actively owing the NFS labeling code? I'd like to bounce an
idea or two around before committing too much time to my ideas of
solutions.
^ permalink raw reply
* Re: [GIT PULL] SafeSetID MAINTAINERS file update for v5.3
From: Micah Morton @ 2019-08-01 18:11 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-security-module, Linux Kernel Mailing List
In-Reply-To: <CAHk-=whZzJ8WxAeHcirUghcbeOYxmpCr+XxeS9ngH3df3+=p2Q@mail.gmail.com>
Sorry about that. To fix it I did a "git reset hard" to before any of
those commits by Jann Horn, then fast-forwarded to the v5.3-rc2 tag
and force pushed that to my origin/master then pushed a new branch up
with my MAINTAINERS file changes. Hopefully this is a valid fix.
--
The following changes since commit 609488bc979f99f805f34e9a32c1e3b71179d10b:
Linux 5.3-rc2 (2019-07-28 12:47:02 -0700)
are available in the Git repository at:
https://github.com/micah-morton/linux.git
tags/safesetid-maintainers-correction-5.3-rc2
for you to fetch changes up to fc5b34a35458314df1dd00281f6e41f419581aa9:
Add entry in MAINTAINERS file for SafeSetID LSM (2019-08-01 10:30:57 -0700)
----------------------------------------------------------------
Add entry in MAINTAINERS file for SafeSetID LSM.
Has not had any bake time or testing, since its just changes to a text file.
----------------------------------------------------------------
Micah Morton (1):
Add entry in MAINTAINERS file for SafeSetID LSM
MAINTAINERS | 6 ++++++
1 file changed, 6 insertions(+)
On Thu, Aug 1, 2019 at 6:25 AM Linus Torvalds
<torvalds@linux-foundation.org> wrote:
>
> On Wed, Jul 31, 2019 at 2:30 PM Micah Morton <mortonm@chromium.org> wrote:
> >
> > You mentioned a couple weeks ago it would be good if I added myself to
> > the MAINTAINERS file for the SafeSetID LSM. Here's the pull request
> > for v5.3.
>
> There's a lot more than the maintainer ID in there. You've rebased old
> patches that I already had etc:
>
> Jann Horn (10):
> LSM: SafeSetID: fix pr_warn() to include newline
> LSM: SafeSetID: fix check for setresuid(new1, new2, new3)
> LSM: SafeSetID: refactor policy hash table
> LSM: SafeSetID: refactor safesetid_security_capable()
> LSM: SafeSetID: refactor policy parsing
> LSM: SafeSetID: fix userns handling in securityfs
> LSM: SafeSetID: rewrite userspace API to atomic updates
> LSM: SafeSetID: add read handler
> LSM: SafeSetID: verify transitive constrainedness
> LSM: SafeSetID: fix use of literal -1 in capable hook
>
> Micah Morton (2):
> Merge commit 'v5.3-rc2^0'
> Add entry in MAINTAINERS file for SafeSetID LSM
>
> Not pulled.
>
> Linus
^ permalink raw reply
* Re: [PATCH bpf-next v10 10/10] landlock: Add user and kernel documentation for Landlock
From: Randy Dunlap @ 2019-08-01 17:49 UTC (permalink / raw)
To: Mickaël Salaün, Mickaël Salaün, linux-kernel
Cc: Alexander Viro, Alexei Starovoitov, Andrew Morton,
Andy Lutomirski, Arnaldo Carvalho de Melo, Casey Schaufler,
Daniel Borkmann, David Drysdale, David S . Miller,
Eric W . Biederman, James Morris, Jann Horn, John Johansen,
Jonathan Corbet, Kees Cook, Michael Kerrisk, Paul Moore,
Sargun Dhillon, Serge E . Hallyn, Shuah Khan, Stephen Smalley,
Tejun Heo, Tetsuo Handa, Thomas Graf, Tycho Andersen, Will Drewry,
kernel-hardening, linux-api, linux-fsdevel, linux-security-module,
netdev
In-Reply-To: <2ced8fc8-79a6-b0fb-70fe-6716fae92aa7@ssi.gouv.fr>
On 8/1/19 10:03 AM, Mickaël Salaün wrote:
>>> +Ptrace restrictions
>>> +-------------------
>>> +
>>> +A landlocked process has less privileges than a non-landlocked process and must
>>> +then be subject to additional restrictions when manipulating another process.
>>> +To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
>>> +process, a landlocked process must have a subset of the target process programs.
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> Maybe that last statement is correct, but it seems to me that it is missing something.
> What about this:
>
> To be allowed to trace a process (using :manpage:`ptrace(2)`), a
> landlocked tracer process must only be constrained by a subset (possibly
> empty) of the Landlock programs which are also applied to the tracee.
> This ensure that the tracer has less or the same constraints than the
ensures
> tracee, hence protecting against privilege escalation.
Yes, better. Thanks.
--
~Randy
^ permalink raw reply
* Re: [PATCH bpf-next v10 06/10] bpf,landlock: Add a new map type: inode
From: Alexei Starovoitov @ 2019-08-01 17:35 UTC (permalink / raw)
To: Mickaël Salaün
Cc: Mickaël Salaün, LKML, Alexander Viro,
Alexei Starovoitov, Andrew Morton, Andy Lutomirski,
Arnaldo Carvalho de Melo, Casey Schaufler, Daniel Borkmann,
David Drysdale, David S . Miller, Eric W . Biederman,
James Morris, Jann Horn, John Johansen, Jonathan Corbet,
Kees Cook, Michael Kerrisk, Paul Moore, Sargun Dhillon,
Serge E . Hallyn, Shuah Khan, Stephen Smalley, Tejun Heo,
Tetsuo Handa, Thomas Graf, Tycho Andersen, Will Drewry,
Kernel Hardening, Linux API, Linux-Fsdevel, LSM List,
Network Development
In-Reply-To: <59e8fab9-34df-0ebe-ca6b-8b34bf582b75@ssi.gouv.fr>
On Wed, Jul 31, 2019 at 09:11:10PM +0200, Mickaël Salaün wrote:
>
>
> On 31/07/2019 20:58, Alexei Starovoitov wrote:
> > On Wed, Jul 31, 2019 at 11:46 AM Mickaël Salaün
> > <mickael.salaun@ssi.gouv.fr> wrote:
> >>>> + for (i = 0; i < htab->n_buckets; i++) {
> >>>> + head = select_bucket(htab, i);
> >>>> + hlist_nulls_for_each_entry_safe(l, n, head, hash_node) {
> >>>> + landlock_inode_remove_map(*((struct inode **)l->key), map);
> >>>> + }
> >>>> + }
> >>>> + htab_map_free(map);
> >>>> +}
> >>>
> >>> user space can delete the map.
> >>> that will trigger inode_htab_map_free() which will call
> >>> landlock_inode_remove_map().
> >>> which will simply itereate the list and delete from the list.
> >>
> >> landlock_inode_remove_map() removes the reference to the map (being
> >> freed) from the inode (with an RCU lock).
> >
> > I'm going to ignore everything else for now and focus only on this bit,
> > since it's fundamental issue to address before this discussion can
> > go any further.
> > rcu_lock is not a spin_lock. I'm pretty sure you know this.
> > But you're arguing that it's somehow protecting from the race
> > I mentioned above?
> >
>
> I was just clarifying your comment to avoid misunderstanding about what
> is being removed.
>
> As said in the full response, there is currently a race but, if I add a
> bpf_map_inc() call when the map is referenced by inode->security, then I
> don't see how a race could occur because such added map could only be
> freed in a security_inode_free() (as long as it retains a reference to
> this inode).
then it will be a cycle and a map will never be deleted?
closing map_fd should delete a map. It cannot be alive if it's not
pinned in bpffs, there are no FDs that are holding it, and no progs using it.
So the map deletion will iterate over inodes that belong to this map.
In parallel security_inode_free() will be called that will iterate
over its link list that contains elements from different maps.
So the same link list is modified by two cpus.
Where is a lock that protects from concurrent links list manipulations?
> Les données à caractère personnel recueillies et traitées dans le cadre de cet échange, le sont à seule fin d’exécution d’une relation professionnelle et s’opèrent dans cette seule finalité et pour la durée nécessaire à cette relation. Si vous souhaitez faire usage de vos droits de consultation, de rectification et de suppression de vos données, veuillez contacter contact.rgpd@sgdsn.gouv.fr. Si vous avez reçu ce message par erreur, nous vous remercions d’en informer l’expéditeur et de détruire le message. The personal data collected and processed during this exchange aims solely at completing a business relationship and is limited to the necessary duration of that relationship. If you wish to use your rights of consultation, rectification and deletion of your data, please contact: contact.rgpd@sgdsn.gouv.fr. If you have received this message in error, we thank you for informing the sender and destroying the message.
Please get rid of this. It's absolutely not appropriate on public mailing list.
Next time I'd have to ignore emails that contain such disclaimers.
^ permalink raw reply
* Re: [RFC/RFT v2 1/2] KEYS: trusted: create trusted keys subsystem
From: Jarkko Sakkinen @ 2019-08-01 17:24 UTC (permalink / raw)
To: Sumit Garg
Cc: keyrings, linux-integrity, linux-crypto, linux-security-module,
dhowells, herbert, davem, jejb, zohar, jmorris, serge, casey,
ard.biesheuvel, daniel.thompson, linux-kernel, tee-dev
In-Reply-To: <1563449086-13183-2-git-send-email-sumit.garg@linaro.org>
On Thu, Jul 18, 2019 at 04:54:45PM +0530, Sumit Garg wrote:
> Move existing code to trusted keys subsystem. Also, rename files with
> "tpm" as suffix which provides the underlying implementation.
>
> Suggested-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Signed-off-by: Sumit Garg <sumit.garg@linaro.org>
What about TPM2 trusted keys code?
/Jarkko
^ permalink raw reply
* Re: [PATCH bpf-next v10 10/10] landlock: Add user and kernel documentation for Landlock
From: Mickaël Salaün @ 2019-08-01 17:03 UTC (permalink / raw)
To: Randy Dunlap, Mickaël Salaün, linux-kernel
Cc: Alexander Viro, Alexei Starovoitov, Andrew Morton,
Andy Lutomirski, Arnaldo Carvalho de Melo, Casey Schaufler,
Daniel Borkmann, David Drysdale, David S . Miller,
Eric W . Biederman, James Morris, Jann Horn, John Johansen,
Jonathan Corbet, Kees Cook, Michael Kerrisk, Paul Moore,
Sargun Dhillon, Serge E . Hallyn, Shuah Khan, Stephen Smalley,
Tejun Heo, Tetsuo Handa, Thomas Graf, Tycho Andersen, Will Drewry,
kernel-hardening, linux-api, linux-fsdevel, linux-security-module,
netdev
In-Reply-To: <88e90c22-1b78-c2f2-8823-fa776265361c@infradead.org>
Thanks for this spelling fixes. Some comments:
On 31/07/2019 03:53, Randy Dunlap wrote:
> On 7/21/19 2:31 PM, Mickaël Salaün wrote:
>> This documentation can be built with the Sphinx framework.
>>
>> Signed-off-by: Mickaël Salaün <mic@digikod.net>
>> Cc: Alexei Starovoitov <ast@kernel.org>
>> Cc: Andy Lutomirski <luto@amacapital.net>
>> Cc: Daniel Borkmann <daniel@iogearbox.net>
>> Cc: David S. Miller <davem@davemloft.net>
>> Cc: James Morris <jmorris@namei.org>
>> Cc: Jonathan Corbet <corbet@lwn.net>
>> Cc: Kees Cook <keescook@chromium.org>
>> Cc: Serge E. Hallyn <serge@hallyn.com>
>> ---
>>
>> Changes since v9:
>> * update with expected attach type and expected attach triggers
>>
>> Changes since v8:
>> * remove documentation related to chaining and tagging according to this
>> patch series
>>
>> Changes since v7:
>> * update documentation according to the Landlock revamp
>>
>> Changes since v6:
>> * add a check for ctx->event
>> * rename BPF_PROG_TYPE_LANDLOCK to BPF_PROG_TYPE_LANDLOCK_RULE
>> * rename Landlock version to ABI to better reflect its purpose and add a
>> dedicated changelog section
>> * update tables
>> * relax no_new_privs recommendations
>> * remove ABILITY_WRITE related functions
>> * reword rule "appending" to "prepending" and explain it
>> * cosmetic fixes
>>
>> Changes since v5:
>> * update the rule hierarchy inheritance explanation
>> * briefly explain ctx->arg2
>> * add ptrace restrictions
>> * explain EPERM
>> * update example (subtype)
>> * use ":manpage:"
>> ---
>> Documentation/security/index.rst | 1 +
>> Documentation/security/landlock/index.rst | 20 +++
>> Documentation/security/landlock/kernel.rst | 99 ++++++++++++++
>> Documentation/security/landlock/user.rst | 147 +++++++++++++++++++++
>> 4 files changed, 267 insertions(+)
>> create mode 100644 Documentation/security/landlock/index.rst
>> create mode 100644 Documentation/security/landlock/kernel.rst
>> create mode 100644 Documentation/security/landlock/user.rst
>
>
>> diff --git a/Documentation/security/landlock/kernel.rst b/Documentation/security/landlock/kernel.rst
>> new file mode 100644
>> index 000000000000..7d1e06d544bf
>> --- /dev/null
>> +++ b/Documentation/security/landlock/kernel.rst
>> @@ -0,0 +1,99 @@
>> +==============================
>> +Landlock: kernel documentation
>> +==============================
>> +
>> +eBPF properties
>> +===============
>> +
>> +To get an expressive language while still being safe and small, Landlock is
>> +based on eBPF. Landlock should be usable by untrusted processes and must
>> +therefore expose a minimal attack surface. The eBPF bytecode is minimal,
>> +powerful, widely used and designed to be used by untrusted applications. Thus,
>> +reusing the eBPF support in the kernel enables a generic approach while
>> +minimizing new code.
>> +
>> +An eBPF program has access to an eBPF context containing some fields used to
>> +inspect the current object. These arguments can be used directly (e.g. cookie)
>> +or passed to helper functions according to their types (e.g. inode pointer). It
>> +is then possible to do complex access checks without race conditions or
>> +inconsistent evaluation (i.e. `incorrect mirroring of the OS code and state
>> +<https://www.ndss-symposium.org/ndss2003/traps-and-pitfalls-practical-problems-system-call-interposition-based-security-tools/>`_).
>> +
>> +A Landlock hook describes a particular access type. For now, there is two
>
> there are two
>
>> +hooks dedicated to filesystem related operations: LANDLOCK_HOOK_FS_PICK and
>> +LANDLOCK_HOOK_FS_WALK. A Landlock program is tied to one hook. This makes it
>> +possible to statically check context accesses, potentially performed by such
>> +program, and hence prevents kernel address leaks and ensure the right use of
>
> ensures
>
>> +hook arguments with eBPF functions. Any user can add multiple Landlock
>> +programs per Landlock hook. They are stacked and evaluated one after the
>> +other, starting from the most recent program, as seccomp-bpf does with its
>> +filters. Underneath, a hook is an abstraction over a set of LSM hooks.
>> +
>> +
>> +Guiding principles
>> +==================
>> +
>> +Unprivileged use
>> +----------------
>> +
>> +* Landlock helpers and context should be usable by any unprivileged and
>> + untrusted program while following the system security policy enforced by
>> + other access control mechanisms (e.g. DAC, LSM).
>> +
>> +
>> +Landlock hook and context
>> +-------------------------
>> +
>> +* A Landlock hook shall be focused on access control on kernel objects instead
>> + of syscall filtering (i.e. syscall arguments), which is the purpose of
>> + seccomp-bpf.
>> +* A Landlock context provided by a hook shall express the minimal and more
>> + generic interface to control an access for a kernel object.
>> +* A hook shall guaranty that all the BPF function calls from a program are> + safe. Thus, the related Landlock context arguments shall always be of the
>> + same type for a particular hook. For example, a network hook could share
>> + helpers with a file hook because of UNIX socket. However, the same helpers
>> + may not be compatible for a file system handle and a net handle.
>> +* Multiple hooks may use the same context interface.
>> +
>> +
>> +Landlock helpers
>> +----------------
>> +
>> +* Landlock helpers shall be as generic as possible while at the same time being
>> + as simple as possible and following the syscall creation principles (cf.
>> + *Documentation/adding-syscalls.txt*).
>> +* The only behavior change allowed on a helper is to fix a (logical) bug to
>> + match the initial semantic.
>> +* Helpers shall be reentrant, i.e. only take inputs from arguments (e.g. from
>> + the BPF context), to enable a hook to use a cache. Future program options
>> + might change this cache behavior.
>> +* It is quite easy to add new helpers to extend Landlock. The main concern
>> + should be about the possibility to leak information from the kernel that may
>> + not be accessible otherwise (i.e. side-channel attack).
>> +
>> +
>> +Questions and answers
>> +=====================
>> +
>> +Why not create a custom hook for each kind of action?
>> +-----------------------------------------------------
>> +
>> +Landlock programs can handle these checks. Adding more exceptions to the
>> +kernel code would lead to more code complexity. A decision to ignore a kind of
>> +action can and should be done at the beginning of a Landlock program.
>> +
>> +
>> +Why a program does not return an errno or a kill code?
>> +------------------------------------------------------
>> +
>> +seccomp filters can return multiple kind of code, including an errno value or a
>
> kinds
>
>> +kill signal, which may be convenient for access control. Those return codes
>> +are hardwired in the userland ABI. Instead, Landlock's approach is to return a
>> +boolean to allow or deny an action, which is much simpler and more generic.
>> +Moreover, we do not really have a choice because, unlike to seccomp, Landlock
>> +programs are not enforced at the syscall entry point but may be executed at any
>> +point in the kernel (through LSM hooks) where an errno return code may not make
>> +sense. However, with this simple ABI and with the ability to call helpers,
>> +Landlock may gain features similar to seccomp-bpf in the future while being
>> +compatible with previous programs.
>> diff --git a/Documentation/security/landlock/user.rst b/Documentation/security/landlock/user.rst
>> new file mode 100644
>> index 000000000000..14c4f3b377bd
>> --- /dev/null
>> +++ b/Documentation/security/landlock/user.rst
>> @@ -0,0 +1,147 @@
>> +================================
>> +Landlock: userland documentation
>> +================================
>> +
>> +Landlock programs
>> +=================
>> +
>> +eBPF programs are used to create security programs. They are contained and can
>> +call only a whitelist of dedicated functions. Moreover, they can only loop
>> +under strict conditions, which protects from denial of service. More
>> +information on BPF can be found in *Documentation/networking/filter.txt*.
>> +
>> +
>> +Writing a program
>> +-----------------
>> +
>> +To enforce a security policy, a thread first needs to create a Landlock program.
>> +The easiest way to write an eBPF program depicting a security program is to write
>> +it in the C language. As described in *samples/bpf/README.rst*, LLVM can
>> +compile such programs. Files *samples/bpf/landlock1_kern.c* and those in
>> +*tools/testing/selftests/landlock/* can be used as examples.
>> +
>> +Once the eBPF program is created, the next step is to create the metadata
>> +describing the Landlock program. This metadata includes an expected attach type which
>> +contains the hook type to which the program is tied, and expected attach
>> +triggers which identify the actions for which the program should be run.
>> +
>> +A hook is a policy decision point which exposes the same context type for
>> +each program evaluation.
>> +
>> +A Landlock hook describes the kind of kernel object for which a program will be
>> +triggered to allow or deny an action. For example, the hook
>> +BPF_LANDLOCK_FS_PICK can be triggered every time a landlocked thread performs a
>> +set of action related to the filesystem (e.g. open, read, write, mount...).
>
> actions
>
>> +This actions are identified by the `triggers` bitfield.
>> +
>> +The next step is to fill a :c:type:`struct bpf_load_program_attr
>> +<bpf_load_program_attr>` with BPF_PROG_TYPE_LANDLOCK_HOOK, the expected attach
>> +type and other BPF program metadata. This bpf_attr must then be passed to the
>> +:manpage:`bpf(2)` syscall alongside the BPF_PROG_LOAD command. If everything
>> +is deemed correct by the kernel, the thread gets a file descriptor referring to
>> +this program.
>> +
>> +In the following code, the *insn* variable is an array of BPF instructions
>> +which can be extracted from an ELF file as is done in bpf_load_file() from
>> +*samples/bpf/bpf_load.c*.
>
> A little confusing. Is there a mixup of <insn> and <insns>?
Indeed, a typo was inserted with a rewrite of this part.
>
>> +
>> +.. code-block:: c
>> +
>> + int prog_fd;
>> + struct bpf_load_program_attr load_attr;
>> +
>> + memset(&load_attr, 0, sizeof(struct bpf_load_program_attr));
>> + load_attr.prog_type = BPF_PROG_TYPE_LANDLOCK_HOOK;
>> + load_attr.expected_attach_type = BPF_LANDLOCK_FS_PICK;
>> + load_attr.expected_attach_triggers = LANDLOCK_TRIGGER_FS_PICK_OPEN;
>> + load_attr.insns = insns;
>> + load_attr.insns_cnt = sizeof(insn) / sizeof(struct bpf_insn);
>> + load_attr.license = "GPL";
>> +
>> + prog_fd = bpf_load_program_xattr(&load_attr, log_buf, log_buf_sz);
>> + if (prog_fd == -1)
>> + exit(1);
>> +
>> +
>> +Enforcing a program
>> +-------------------
>> +
>> +Once the Landlock program has been created or received (e.g. through a UNIX
>> +socket), the thread willing to sandbox itself (and its future children) should
>> +perform the following two steps.
>> +
>> +The thread should first request to never be allowed to get new privileges with a
>> +call to :manpage:`prctl(2)` and the PR_SET_NO_NEW_PRIVS option. More
>> +information can be found in *Documentation/prctl/no_new_privs.txt*.
>> +
>> +.. code-block:: c
>> +
>> + if (prctl(PR_SET_NO_NEW_PRIVS, 1, NULL, 0, 0))
>> + exit(1);
>> +
>> +A thread can apply a program to itself by using the :manpage:`seccomp(2)` syscall.
>> +The operation is SECCOMP_PREPEND_LANDLOCK_PROG, the flags must be empty and the
>> +*args* argument must point to a valid Landlock program file descriptor.
>> +
>> +.. code-block:: c
>> +
>> + if (seccomp(SECCOMP_PREPEND_LANDLOCK_PROG, 0, &fd))
>> + exit(1);
>> +
>> +If the syscall succeeds, the program is now enforced on the calling thread and
>> +will be enforced on all its subsequently created children of the thread as
>> +well. Once a thread is landlocked, there is no way to remove this security
>> +policy, only stacking more restrictions is allowed. The program evaluation is
>> +performed from the newest to the oldest.
>> +
>> +When a syscall ask for an action on a kernel object, if this action is denied,
>
> asks
>
>> +then an EACCES errno code is returned through the syscall.
>> +
>> +
>> +.. _inherited_programs:
>> +
>> +Inherited programs
>> +------------------
>> +
>> +Every new thread resulting from a :manpage:`clone(2)` inherits Landlock program
>> +restrictions from its parent. This is similar to the seccomp inheritance as
>> +described in *Documentation/prctl/seccomp_filter.txt*.
>> +
>> +
>> +Ptrace restrictions
>> +-------------------
>> +
>> +A landlocked process has less privileges than a non-landlocked process and must
>> +then be subject to additional restrictions when manipulating another process.
>> +To be allowed to use :manpage:`ptrace(2)` and related syscalls on a target
>> +process, a landlocked process must have a subset of the target process programs.
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> Maybe that last statement is correct, but it seems to me that it is missing something.
What about this:
To be allowed to trace a process (using :manpage:`ptrace(2)`), a
landlocked tracer process must only be constrained by a subset (possibly
empty) of the Landlock programs which are also applied to the tracee.
This ensure that the tracer has less or the same constraints than the
tracee, hence protecting against privilege escalation.
>
>> +
>> +
>> +Landlock structures and constants
>> +=================================
>> +
>> +Hook types
>> +----------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_hook_type
>> +
>> +
>> +Contexts
>> +--------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_ctx_fs_pick landlock_ctx_fs_walk landlock_ctx_fs_get
>> +
>> +
>> +Triggers for fs_pick
>> +--------------------
>> +
>> +.. kernel-doc:: include/uapi/linux/landlock.h
>> + :functions: landlock_triggers
>> +
>> +
>> +Additional documentation
>> +========================
>> +
>> +See https://landlock.io
>>
>
>
--
Mickaël Salaün
ANSSI/SDE/ST/LAM
Les données à caractère personnel recueillies et traitées dans le cadre de cet échange, le sont à seule fin d’exécution d’une relation professionnelle et s’opèrent dans cette seule finalité et pour la durée nécessaire à cette relation. Si vous souhaitez faire usage de vos droits de consultation, de rectification et de suppression de vos données, veuillez contacter contact.rgpd@sgdsn.gouv.fr. Si vous avez reçu ce message par erreur, nous vous remercions d’en informer l’expéditeur et de détruire le message. The personal data collected and processed during this exchange aims solely at completing a business relationship and is limited to the necessary duration of that relationship. If you wish to use your rights of consultation, rectification and deletion of your data, please contact: contact.rgpd@sgdsn.gouv.fr. If you have received this message in error, we thank you for informing the sender and destroying the message.
^ permalink raw reply
* Re: [RFC PATCH v3 04/12] x86/sgx: Require userspace to define enclave pages' protection bits
From: Jarkko Sakkinen @ 2019-08-01 16:38 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Sean Christopherson, Schaufler, Casey, James Morris, linux-sgx,
Dave Hansen, Cedric Xing, Jethro Beekman, Dr . Greg Wettstein,
Stephen Smalley, LSM List
In-Reply-To: <CALCETrXMAwHod_KZYPGWjTjg-fxOb1=02=Qj2g1o624wOPfPZQ@mail.gmail.com>
On Mon, Jul 15, 2019 at 03:29:23PM -0700, Andy Lutomirski wrote:
> I would say it differently: regardless of exactly how /dev/sgx/enclave
> is wired up under the hood, we want a way that a process can be
> granted permission to usefully run enclaves without being granted
> permission to execute whatever bytes of code it wants. Preferably
> without requiring LSMs to maintain some form of enclave signature
> whitelist.
Would it be better to have a signer whitelist instead or some
combination? E.g. you could whiteliste either by signer or
enclave signature.
/Jarkko
^ permalink raw reply
* Re: [PATCH] KEYS: trusted: allow module init if TPM is inactive or deactivated
From: Jarkko Sakkinen @ 2019-08-01 16:32 UTC (permalink / raw)
To: Roberto Sassu
Cc: jejb, zohar, jgg, linux-integrity, linux-security-module,
keyrings, linux-kernel, crazyt2019+lml, tyhicks, nayna,
silviu.vlasceanu
In-Reply-To: <b4454a78-1f1b-cc75-114a-99926e097b05@huawei.com>
On Mon, Jul 15, 2019 at 06:44:28PM +0200, Roberto Sassu wrote:
> According to the bug report at https://bugs.archlinux.org/task/62678,
> the trusted module is a dependency of the ecryptfs module. We should
> load the trusted module even if the TPM is inactive or deactivated.
>
> Given that commit 782779b60faa ("tpm: Actually fail on TPM errors during
> "get random"") changes the return code of tpm_get_random(), the patch
> should be modified to ignore the -EIO error. I will send a new version.
Do you have information where this dependency comes from?
/Jarkko
^ permalink raw reply
* Re: [PATCH V37 19/29] Lock down module params that specify hardware parameters (eg. ioport)
From: Jessica Yu @ 2019-08-01 16:19 UTC (permalink / raw)
To: Matthew Garrett
Cc: jmorris, linux-security-module, linux-kernel, linux-api,
David Howells, Alan Cox, Matthew Garrett, Kees Cook
In-Reply-To: <20190731221617.234725-20-matthewgarrett@google.com>
+++ Matthew Garrett [31/07/19 15:16 -0700]:
>From: David Howells <dhowells@redhat.com>
>
>Provided an annotation for module parameters that specify hardware
>parameters (such as io ports, iomem addresses, irqs, dma channels, fixed
>dma buffers and other types).
>
>Suggested-by: Alan Cox <gnomes@lxorguk.ukuu.org.uk>
>Signed-off-by: David Howells <dhowells@redhat.com>
>Signed-off-by: Matthew Garrett <mjg59@google.com>
>Reviewed-by: Kees Cook <keescook@chromium.org>
>Cc: Jessica Yu <jeyu@kernel.org>
>---
> include/linux/security.h | 1 +
> kernel/params.c | 28 +++++++++++++++++++++++-----
> security/lockdown/lockdown.c | 1 +
> 3 files changed, 25 insertions(+), 5 deletions(-)
>
>diff --git a/include/linux/security.h b/include/linux/security.h
>index 8f7048395114..43fa3486522b 100644
>--- a/include/linux/security.h
>+++ b/include/linux/security.h
>@@ -113,6 +113,7 @@ enum lockdown_reason {
> LOCKDOWN_ACPI_TABLES,
> LOCKDOWN_PCMCIA_CIS,
> LOCKDOWN_TIOCSSERIAL,
>+ LOCKDOWN_MODULE_PARAMETERS,
> LOCKDOWN_INTEGRITY_MAX,
> LOCKDOWN_CONFIDENTIALITY_MAX,
> };
>diff --git a/kernel/params.c b/kernel/params.c
>index cf448785d058..f2779a76d39a 100644
>--- a/kernel/params.c
>+++ b/kernel/params.c
>@@ -12,6 +12,7 @@
> #include <linux/err.h>
> #include <linux/slab.h>
> #include <linux/ctype.h>
>+#include <linux/security.h>
>
> #ifdef CONFIG_SYSFS
> /* Protects all built-in parameters, modules use their own param_lock */
>@@ -96,13 +97,20 @@ bool parameq(const char *a, const char *b)
> return parameqn(a, b, strlen(a)+1);
> }
>
>-static void param_check_unsafe(const struct kernel_param *kp)
>+static bool param_check_unsafe(const struct kernel_param *kp,
>+ const char *doing)
Hm, I don't think the doing parameter ended up being used in this function?
> {
>+ if (kp->flags & KERNEL_PARAM_FL_HWPARAM &&
>+ security_locked_down(LOCKDOWN_MODULE_PARAMETERS))
>+ return false;
>+
> if (kp->flags & KERNEL_PARAM_FL_UNSAFE) {
> pr_notice("Setting dangerous option %s - tainting kernel\n",
> kp->name);
> add_taint(TAINT_USER, LOCKDEP_STILL_OK);
> }
>+
>+ return true;
> }
>
> static int parse_one(char *param,
>@@ -132,8 +140,10 @@ static int parse_one(char *param,
> pr_debug("handling %s with %p\n", param,
> params[i].ops->set);
> kernel_param_lock(params[i].mod);
>- param_check_unsafe(¶ms[i]);
>- err = params[i].ops->set(val, ¶ms[i]);
>+ if (param_check_unsafe(¶ms[i], doing))
>+ err = params[i].ops->set(val, ¶ms[i]);
>+ else
>+ err = -EPERM;
> kernel_param_unlock(params[i].mod);
> return err;
> }
>@@ -541,6 +551,12 @@ static ssize_t param_attr_show(struct module_attribute *mattr,
> return count;
> }
>
>+#ifdef CONFIG_MODULES
>+#define mod_name(mod) ((mod)->name)
>+#else
>+#define mod_name(mod) "unknown"
>+#endif
>+
> /* sysfs always hands a nul-terminated string in buf. We rely on that. */
> static ssize_t param_attr_store(struct module_attribute *mattr,
> struct module_kobject *mk,
>@@ -553,8 +569,10 @@ static ssize_t param_attr_store(struct module_attribute *mattr,
> return -EPERM;
>
> kernel_param_lock(mk->mod);
>- param_check_unsafe(attribute->param);
>- err = attribute->param->ops->set(buf, attribute->param);
>+ if (param_check_unsafe(attribute->param, mod_name(mk->mod)))
>+ err = attribute->param->ops->set(buf, attribute->param);
>+ else
>+ err = -EPERM;
> kernel_param_unlock(mk->mod);
> if (!err)
> return len;
>diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
>index 00a3a6438dd2..5177938cfa0d 100644
>--- a/security/lockdown/lockdown.c
>+++ b/security/lockdown/lockdown.c
>@@ -28,6 +28,7 @@ static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
> [LOCKDOWN_ACPI_TABLES] = "modifying ACPI tables",
> [LOCKDOWN_PCMCIA_CIS] = "direct PCMCIA CIS storage",
> [LOCKDOWN_TIOCSSERIAL] = "reconfiguration of serial port IO",
>+ [LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters",
> [LOCKDOWN_INTEGRITY_MAX] = "integrity",
> [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
> };
>--
>2.22.0.770.g0f2c4a37fd-goog
>
^ permalink raw reply
* [RFC PATCH v2] security,capability: pass object information to security_capable
From: Aaron Goidel @ 2019-08-01 14:43 UTC (permalink / raw)
To: paul
Cc: selinux, linux-security-module, luto, jmorris, sds, keescook,
serge, john.johansen, casey, mortonm, rgb, Nicholas Franck,
Aaron Goidel
From: Nicholas Franck <nhfran2@tycho.nsa.gov>
At present security_capable does not pass any object information
and therefore can neither audit the particular object nor take it
into account. Augment the security_capable interface to support
passing supplementary data. Use this facility initially to convey
the inode for capability checks relevant to inodes. This only
addresses capable_wrt_inode_uidgid calls; other capability checks
relevant to inodes will be addressed in subsequent changes. In the
future, this will be further extended to pass object information for
other capability checks such as the target task for CAP_KILL.
In SELinux this new information is leveraged here to include the inode
in the audit message. In the future, it could also be used to perform
a per inode capability checks.
It would be possible to fold the existing opts argument into this new
supplementary data structure. This was omitted from this change to
minimize changes.
Signed-off-by: Nicholas Franck <nhfran2@tycho.nsa.gov>
Signed-off-by: Aaron Goidel <acgoide@tycho.nsa.gov>
---
v2:
- Changed order of audit prints so optional information comes second
---
include/linux/capability.h | 7 ++++++
include/linux/lsm_audit.h | 5 +++-
include/linux/lsm_hooks.h | 3 ++-
include/linux/security.h | 23 +++++++++++++-----
kernel/capability.c | 33 ++++++++++++++++++--------
kernel/seccomp.c | 2 +-
security/apparmor/capability.c | 8 ++++---
security/apparmor/include/capability.h | 4 +++-
security/apparmor/ipc.c | 2 +-
security/apparmor/lsm.c | 5 ++--
security/apparmor/resource.c | 2 +-
security/commoncap.c | 11 +++++----
security/lsm_audit.c | 21 ++++++++++++++--
security/safesetid/lsm.c | 3 ++-
security/security.c | 5 ++--
security/selinux/hooks.c | 20 +++++++++-------
security/smack/smack_access.c | 2 +-
17 files changed, 110 insertions(+), 46 deletions(-)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index ecce0f43c73a..f72de64c179d 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -211,6 +211,8 @@ extern bool capable(int cap);
extern bool ns_capable(struct user_namespace *ns, int cap);
extern bool ns_capable_noaudit(struct user_namespace *ns, int cap);
extern bool ns_capable_setid(struct user_namespace *ns, int cap);
+extern bool ns_capable_inode(struct user_namespace *ns, int cap,
+ const struct inode *inode);
#else
static inline bool has_capability(struct task_struct *t, int cap)
{
@@ -246,6 +248,11 @@ static inline bool ns_capable_setid(struct user_namespace *ns, int cap)
{
return true;
}
+static bool ns_capable_inode(struct user_namespace *ns, int cap,
+ const struct inode *inode)
+{
+ return true;
+}
#endif /* CONFIG_MULTIUSER */
extern bool privileged_wrt_inode_uidgid(struct user_namespace *ns, const struct inode *inode);
extern bool capable_wrt_inode_uidgid(const struct inode *inode, int cap);
diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 915330abf6e5..15d2a62639f0 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -79,7 +79,10 @@ struct common_audit_data {
struct dentry *dentry;
struct inode *inode;
struct lsm_network_audit *net;
- int cap;
+ struct {
+ int cap;
+ struct cap_aux_data *cad;
+ } cap_struct;
int ipc_id;
struct task_struct *tsk;
#ifdef CONFIG_KEYS
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index ead98af9c602..3270b8af3498 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1472,7 +1472,8 @@ union security_list_options {
int (*capable)(const struct cred *cred,
struct user_namespace *ns,
int cap,
- unsigned int opts);
+ unsigned int opts,
+ struct cap_aux_data *cad);
int (*quotactl)(int cmds, int type, int id, struct super_block *sb);
int (*quota_on)(struct dentry *dentry);
int (*syslog)(int type);
diff --git a/include/linux/security.h b/include/linux/security.h
index 7d9c1da1f659..a37377065401 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -77,9 +77,18 @@ enum lsm_event {
LSM_POLICY_CHANGE,
};
+
+struct cap_aux_data {
+ char type;
+#define CAP_AUX_DATA_INODE 1
+ union {
+ const struct inode *inode;
+ } u;
+};
+
/* These functions are in security/commoncap.c */
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
- int cap, unsigned int opts);
+ int cap, unsigned int opts, struct cap_aux_data *cad);
extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz);
extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
extern int cap_ptrace_traceme(struct task_struct *parent);
@@ -215,9 +224,10 @@ int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *inheritable,
const kernel_cap_t *permitted);
int security_capable(const struct cred *cred,
- struct user_namespace *ns,
- int cap,
- unsigned int opts);
+ struct user_namespace *ns,
+ int cap,
+ unsigned int opts,
+ struct cap_aux_data *cad);
int security_quotactl(int cmds, int type, int id, struct super_block *sb);
int security_quota_on(struct dentry *dentry);
int security_syslog(int type);
@@ -478,9 +488,10 @@ static inline int security_capset(struct cred *new,
static inline int security_capable(const struct cred *cred,
struct user_namespace *ns,
int cap,
- unsigned int opts)
+ unsigned int opts,
+ struct cap_aux_data *cad)
{
- return cap_capable(cred, ns, cap, opts);
+ return cap_capable(cred, ns, cap, opts, NULL);
}
static inline int security_quotactl(int cmds, int type, int id,
diff --git a/kernel/capability.c b/kernel/capability.c
index 1444f3954d75..c3723443904a 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -297,7 +297,7 @@ bool has_ns_capability(struct task_struct *t,
int ret;
rcu_read_lock();
- ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE);
+ ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NONE, NULL);
rcu_read_unlock();
return (ret == 0);
@@ -338,7 +338,7 @@ bool has_ns_capability_noaudit(struct task_struct *t,
int ret;
rcu_read_lock();
- ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT);
+ ret = security_capable(__task_cred(t), ns, cap, CAP_OPT_NOAUDIT, NULL);
rcu_read_unlock();
return (ret == 0);
@@ -363,7 +363,8 @@ bool has_capability_noaudit(struct task_struct *t, int cap)
static bool ns_capable_common(struct user_namespace *ns,
int cap,
- unsigned int opts)
+ unsigned int opts,
+ struct cap_aux_data *cad)
{
int capable;
@@ -372,7 +373,7 @@ static bool ns_capable_common(struct user_namespace *ns,
BUG();
}
- capable = security_capable(current_cred(), ns, cap, opts);
+ capable = security_capable(current_cred(), ns, cap, opts, cad);
if (capable == 0) {
current->flags |= PF_SUPERPRIV;
return true;
@@ -393,7 +394,7 @@ static bool ns_capable_common(struct user_namespace *ns,
*/
bool ns_capable(struct user_namespace *ns, int cap)
{
- return ns_capable_common(ns, cap, CAP_OPT_NONE);
+ return ns_capable_common(ns, cap, CAP_OPT_NONE, NULL);
}
EXPORT_SYMBOL(ns_capable);
@@ -411,7 +412,7 @@ EXPORT_SYMBOL(ns_capable);
*/
bool ns_capable_noaudit(struct user_namespace *ns, int cap)
{
- return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT);
+ return ns_capable_common(ns, cap, CAP_OPT_NOAUDIT, NULL);
}
EXPORT_SYMBOL(ns_capable_noaudit);
@@ -430,7 +431,7 @@ EXPORT_SYMBOL(ns_capable_noaudit);
*/
bool ns_capable_setid(struct user_namespace *ns, int cap)
{
- return ns_capable_common(ns, cap, CAP_OPT_INSETID);
+ return ns_capable_common(ns, cap, CAP_OPT_INSETID, NULL);
}
EXPORT_SYMBOL(ns_capable_setid);
@@ -470,7 +471,7 @@ bool file_ns_capable(const struct file *file, struct user_namespace *ns,
if (WARN_ON_ONCE(!cap_valid(cap)))
return false;
- if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE) == 0)
+ if (security_capable(file->f_cred, ns, cap, CAP_OPT_NONE, NULL) == 0)
return true;
return false;
@@ -503,7 +504,8 @@ bool capable_wrt_inode_uidgid(const struct inode *inode, int cap)
{
struct user_namespace *ns = current_user_ns();
- return ns_capable(ns, cap) && privileged_wrt_inode_uidgid(ns, inode);
+ return ns_capable_inode(ns, cap, inode) &&
+ privileged_wrt_inode_uidgid(ns, inode);
}
EXPORT_SYMBOL(capable_wrt_inode_uidgid);
@@ -524,7 +526,18 @@ bool ptracer_capable(struct task_struct *tsk, struct user_namespace *ns)
cred = rcu_dereference(tsk->ptracer_cred);
if (cred)
ret = security_capable(cred, ns, CAP_SYS_PTRACE,
- CAP_OPT_NOAUDIT);
+ CAP_OPT_NOAUDIT, NULL);
rcu_read_unlock();
return (ret == 0);
}
+
+bool ns_capable_inode(struct user_namespace *ns, int cap,
+ const struct inode *inode)
+{
+ struct cap_aux_data cad;
+
+ cad.type = CAP_AUX_DATA_INODE;
+ cad.u.inode = inode;
+ return ns_capable_common(ns, cap, CAP_OPT_NONE, &cad);
+}
+EXPORT_SYMBOL(ns_capable_inode);
diff --git a/kernel/seccomp.c b/kernel/seccomp.c
index 811b4a86cdf6..d59dd7079ece 100644
--- a/kernel/seccomp.c
+++ b/kernel/seccomp.c
@@ -446,7 +446,7 @@ static struct seccomp_filter *seccomp_prepare_filter(struct sock_fprog *fprog)
*/
if (!task_no_new_privs(current) &&
security_capable(current_cred(), current_user_ns(),
- CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) != 0)
+ CAP_SYS_ADMIN, CAP_OPT_NOAUDIT, NULL) != 0)
return ERR_PTR(-EACCES);
/* Allocate a new seccomp_filter */
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 752f73980e30..c45192a16733 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -50,7 +50,7 @@ static void audit_cb(struct audit_buffer *ab, void *va)
struct common_audit_data *sa = va;
audit_log_format(ab, " capname=");
- audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
+ audit_log_untrustedstring(ab, capability_names[sa->u.cap_struct.cap]);
}
/**
@@ -148,13 +148,15 @@ static int profile_capable(struct aa_profile *profile, int cap,
*
* Returns: 0 on success, or else an error code.
*/
-int aa_capable(struct aa_label *label, int cap, unsigned int opts)
+int aa_capable(struct aa_label *label, int cap, unsigned int opts,
+ struct cap_aux_data *cad)
{
struct aa_profile *profile;
int error = 0;
DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_CAP, OP_CAPABLE);
- sa.u.cap = cap;
+ sa.u.cap_struct.cap = cap;
+ sa.u.cap_struct.cad = cad;
error = fn_for_each_confined(label, profile,
profile_capable(profile, cap, opts, &sa));
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
index 1b3663b6ab12..d888f09d76d1 100644
--- a/security/apparmor/include/capability.h
+++ b/security/apparmor/include/capability.h
@@ -20,6 +20,7 @@
#include "apparmorfs.h"
struct aa_label;
+struct cap_aux_data;
/* aa_caps - confinement data for capabilities
* @allowed: capabilities mask
@@ -40,7 +41,8 @@ struct aa_caps {
extern struct aa_sfs_entry aa_sfs_entry_caps[];
-int aa_capable(struct aa_label *label, int cap, unsigned int opts);
+int aa_capable(struct aa_label *label, int cap, unsigned int opts,
+ struct cap_aux_data *cad);
static inline void aa_free_cap_rules(struct aa_caps *caps)
{
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
index aacd1e95cb59..deb5267ca695 100644
--- a/security/apparmor/ipc.c
+++ b/security/apparmor/ipc.c
@@ -108,7 +108,7 @@ static int profile_tracer_perm(struct aa_profile *tracer,
aad(sa)->peer = tracee;
aad(sa)->request = 0;
aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
- CAP_OPT_NONE);
+ CAP_OPT_NONE, NULL);
return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
}
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index 87500bde5a92..82790accb679 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -172,14 +172,15 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
}
static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
- int cap, unsigned int opts)
+ int cap, unsigned int opts,
+ struct cap_aux_data *cad)
{
struct aa_label *label;
int error = 0;
label = aa_get_newest_cred_label(cred);
if (!unconfined(label))
- error = aa_capable(label, cap, opts);
+ error = aa_capable(label, cap, opts, cad);
aa_put_label(label);
return error;
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
index 552ed09cb47e..9b3d4b4437f2 100644
--- a/security/apparmor/resource.c
+++ b/security/apparmor/resource.c
@@ -124,7 +124,7 @@ int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
*/
if (label != peer &&
- aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
+ aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT, NULL) != 0)
error = fn_for_each(label, profile,
audit_resource(profile, resource,
new_rlim->rlim_max, peer,
diff --git a/security/commoncap.c b/security/commoncap.c
index c477fb673701..1860ea50f473 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -68,7 +68,7 @@ static void warn_setuid_and_fcaps_mixed(const char *fname)
* kernel's capable() and has_capability() returns 1 for this case.
*/
int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
- int cap, unsigned int opts)
+ int cap, unsigned int opts, struct cap_aux_data *cad)
{
struct user_namespace *ns = targ_ns;
@@ -226,7 +226,7 @@ static inline int cap_inh_is_capped(void)
* capability
*/
if (cap_capable(current_cred(), current_cred()->user_ns,
- CAP_SETPCAP, CAP_OPT_NONE) == 0)
+ CAP_SETPCAP, CAP_OPT_NONE, NULL) == 0)
return 0;
return 1;
}
@@ -1211,7 +1211,8 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
|| (cap_capable(current_cred(),
current_cred()->user_ns,
CAP_SETPCAP,
- CAP_OPT_NONE) != 0) /*[4]*/
+ CAP_OPT_NONE,
+ NULL) != 0) /*[4]*/
/*
* [1] no changing of bits that are locked
* [2] no unlocking of locks
@@ -1307,7 +1308,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
int cap_sys_admin = 0;
if (cap_capable(current_cred(), &init_user_ns,
- CAP_SYS_ADMIN, CAP_OPT_NOAUDIT) == 0)
+ CAP_SYS_ADMIN, CAP_OPT_NOAUDIT, NULL) == 0)
cap_sys_admin = 1;
return cap_sys_admin;
@@ -1328,7 +1329,7 @@ int cap_mmap_addr(unsigned long addr)
if (addr < dac_mmap_min_addr) {
ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
- CAP_OPT_NONE);
+ CAP_OPT_NONE, NULL);
/* set PF_SUPERPRIV if it turns out we allow the low mmap */
if (ret == 0)
current->flags |= PF_SUPERPRIV;
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 33028c098ef3..18cc7c956b69 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -229,9 +229,26 @@ static void dump_common_audit_data(struct audit_buffer *ab,
case LSM_AUDIT_DATA_IPC:
audit_log_format(ab, " key=%d ", a->u.ipc_id);
break;
- case LSM_AUDIT_DATA_CAP:
- audit_log_format(ab, " capability=%d ", a->u.cap);
+ case LSM_AUDIT_DATA_CAP: {
+ const struct inode *inode;
+
+ audit_log_format(ab, " capability=%d ", a->u.cap_struct.cap);
+ if (a->u.cap_struct.cad) {
+ switch (a->u.cap_struct.cad->type) {
+ case CAP_AUX_DATA_INODE: {
+ inode = a->u.cap_struct.cad->u.inode;
+
+ audit_log_format(ab, " dev=");
+ audit_log_untrustedstring(ab,
+ inode->i_sb->s_id);
+ audit_log_format(ab, " ino=%lu",
+ inode->i_ino);
+ break;
+ }
+ }
+ }
break;
+ }
case LSM_AUDIT_DATA_PATH: {
struct inode *inode;
diff --git a/security/safesetid/lsm.c b/security/safesetid/lsm.c
index cecd38e2ac80..c74ed83e9501 100644
--- a/security/safesetid/lsm.c
+++ b/security/safesetid/lsm.c
@@ -80,7 +80,8 @@ static bool check_setuid_policy_hashtable_key_value(kuid_t parent,
static int safesetid_security_capable(const struct cred *cred,
struct user_namespace *ns,
int cap,
- unsigned int opts)
+ unsigned int opts,
+ struct cap_aux_data *cad)
{
if (cap == CAP_SETUID &&
check_setuid_policy_hashtable_key(cred->uid)) {
diff --git a/security/security.c b/security/security.c
index 30687e1366b7..e5e0637f43ac 100644
--- a/security/security.c
+++ b/security/security.c
@@ -691,9 +691,10 @@ int security_capset(struct cred *new, const struct cred *old,
int security_capable(const struct cred *cred,
struct user_namespace *ns,
int cap,
- unsigned int opts)
+ unsigned int opts,
+ struct cap_aux_data *cad)
{
- return call_int_hook(capable, 0, cred, ns, cap, opts);
+ return call_int_hook(capable, 0, cred, ns, cap, opts, cad);
}
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index a1aaf79421df..1816402a6b8a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1620,7 +1620,10 @@ static inline u32 signal_to_av(int sig)
/* Check whether a task is allowed to use a capability. */
static int cred_has_capability(const struct cred *cred,
- int cap, unsigned int opts, bool initns)
+ int cap,
+ unsigned int opts,
+ bool initns,
+ struct cap_aux_data *cad)
{
struct common_audit_data ad;
struct av_decision avd;
@@ -1630,7 +1633,8 @@ static int cred_has_capability(const struct cred *cred,
int rc;
ad.type = LSM_AUDIT_DATA_CAP;
- ad.u.cap = cap;
+ ad.u.cap_struct.cad = cad;
+ ad.u.cap_struct.cap = cap;
switch (CAP_TO_INDEX(cap)) {
case 0:
@@ -2167,9 +2171,9 @@ static int selinux_capset(struct cred *new, const struct cred *old,
*/
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
- int cap, unsigned int opts)
+ int cap, unsigned int opts, struct cap_aux_data *cad)
{
- return cred_has_capability(cred, cap, opts, ns == &init_user_ns);
+ return cred_has_capability(cred, cap, opts, ns == &init_user_ns, cad);
}
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
@@ -2243,7 +2247,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
int rc, cap_sys_admin = 0;
rc = cred_has_capability(current_cred(), CAP_SYS_ADMIN,
- CAP_OPT_NOAUDIT, true);
+ CAP_OPT_NOAUDIT, true, NULL);
if (rc == 0)
cap_sys_admin = 1;
@@ -3103,9 +3107,9 @@ static bool has_cap_mac_admin(bool audit)
const struct cred *cred = current_cred();
unsigned int opts = audit ? CAP_OPT_NONE : CAP_OPT_NOAUDIT;
- if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts))
+ if (cap_capable(cred, &init_user_ns, CAP_MAC_ADMIN, opts, NULL))
return false;
- if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true))
+ if (cred_has_capability(cred, CAP_MAC_ADMIN, opts, true, NULL))
return false;
return true;
}
@@ -3609,7 +3613,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
case KDSKBENT:
case KDSKBSENT:
error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
- CAP_OPT_NONE, true);
+ CAP_OPT_NONE, true, NULL);
break;
/* default case assumes that the command will go
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index fe2ce3a65822..e961bfe8f00a 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -640,7 +640,7 @@ bool smack_privileged_cred(int cap, const struct cred *cred)
struct smack_known_list_elem *sklep;
int rc;
- rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE);
+ rc = cap_capable(cred, &init_user_ns, cap, CAP_OPT_NONE, NULL);
if (rc)
return false;
--
2.21.0
^ permalink raw reply related
* Re: [PATCH V37 04/29] Enforce module signatures if the kernel is locked down
From: Jessica Yu @ 2019-08-01 14:21 UTC (permalink / raw)
To: Matthew Garrett
Cc: jmorris, linux-security-module, linux-kernel, linux-api,
David Howells, Kees Cook
In-Reply-To: <20190731221617.234725-5-matthewgarrett@google.com>
+++ Matthew Garrett [31/07/19 15:15 -0700]:
>From: David Howells <dhowells@redhat.com>
>
>If the kernel is locked down, require that all modules have valid
>signatures that we can verify.
>
>I have adjusted the errors generated:
>
> (1) If there's no signature (ENODATA) or we can't check it (ENOPKG,
> ENOKEY), then:
>
> (a) If signatures are enforced then EKEYREJECTED is returned.
>
> (b) If there's no signature or we can't check it, but the kernel is
> locked down then EPERM is returned (this is then consistent with
> other lockdown cases).
>
> (2) If the signature is unparseable (EBADMSG, EINVAL), the signature fails
> the check (EKEYREJECTED) or a system error occurs (eg. ENOMEM), we
> return the error we got.
>
>Note that the X.509 code doesn't check for key expiry as the RTC might not
>be valid or might not have been transferred to the kernel's clock yet.
>
> [Modified by Matthew Garrett to remove the IMA integration. This will
> be replaced with integration with the IMA architecture policy
> patchset.]
>
>Signed-off-by: David Howells <dhowells@redhat.com>
>Signed-off-by: Matthew Garrett <matthewgarrett@google.com>
>Reviewed-by: Kees Cook <keescook@chromium.org>
>Cc: Jessica Yu <jeyu@kernel.org>
>---
> include/linux/security.h | 1 +
> kernel/module.c | 37 +++++++++++++++++++++++++++++-------
> security/lockdown/lockdown.c | 1 +
> 3 files changed, 32 insertions(+), 7 deletions(-)
>
>diff --git a/include/linux/security.h b/include/linux/security.h
>index 54a0532ec12f..8e70063074a1 100644
>--- a/include/linux/security.h
>+++ b/include/linux/security.h
>@@ -103,6 +103,7 @@ enum lsm_event {
> */
> enum lockdown_reason {
> LOCKDOWN_NONE,
>+ LOCKDOWN_MODULE_SIGNATURE,
> LOCKDOWN_INTEGRITY_MAX,
> LOCKDOWN_CONFIDENTIALITY_MAX,
> };
>diff --git a/kernel/module.c b/kernel/module.c
>index cd8df516666d..318209889e26 100644
>--- a/kernel/module.c
>+++ b/kernel/module.c
>@@ -2771,8 +2771,9 @@ static inline void kmemleak_load_module(const struct module *mod,
> #ifdef CONFIG_MODULE_SIG
> static int module_sig_check(struct load_info *info, int flags)
> {
>- int err = -ENOKEY;
>+ int err = -ENODATA;
> const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
>+ const char *reason;
> const void *mod = info->hdr;
>
> /*
>@@ -2787,16 +2788,38 @@ static int module_sig_check(struct load_info *info, int flags)
> err = mod_verify_sig(mod, info);
> }
>
>- if (!err) {
>+ switch (err) {
>+ case 0:
> info->sig_ok = true;
> return 0;
>- }
>
>- /* Not having a signature is only an error if we're strict. */
>- if (err == -ENOKEY && !is_module_sig_enforced())
>- err = 0;
>+ /* We don't permit modules to be loaded into trusted kernels
>+ * without a valid signature on them, but if we're not
>+ * enforcing, certain errors are non-fatal.
>+ */
>+ case -ENODATA:
>+ reason = "Loading of unsigned module";
>+ goto decide;
>+ case -ENOPKG:
>+ reason = "Loading of module with unsupported crypto";
>+ goto decide;
>+ case -ENOKEY:
>+ reason = "Loading of module with unavailable key";
>+ decide:
>+ if (is_module_sig_enforced()) {
>+ pr_notice("%s is rejected\n", reason);
>+ return -EKEYREJECTED;
>+ }
>
>- return err;
>+ return security_locked_down(LOCKDOWN_MODULE_SIGNATURE);
>+
>+ /* All other errors are fatal, including nomem, unparseable
>+ * signatures and signature check failures - even if signatures
>+ * aren't required.
>+ */
>+ default:
>+ return err;
>+ }
> }
> #else /* !CONFIG_MODULE_SIG */
> static int module_sig_check(struct load_info *info, int flags)
Hi Matthew!
Apologies if this was addressed in another patch in your series (I've
only skimmed the first few), but what should happen if the kernel is
locked down, but CONFIG_MODULE_SIG=n? Or shouldn't CONFIG_SECURITY_LOCKDOWN_LSM
depend on CONFIG_MODULE_SIG? Otherwise I think we'll end up calling
the empty !CONFIG_MODULE_SIG module_sig_check() stub even though
lockdown is enabled.
Thanks,
Jessica
>diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
>index d30c4d254b5f..2c53fd9f5c9b 100644
>--- a/security/lockdown/lockdown.c
>+++ b/security/lockdown/lockdown.c
>@@ -18,6 +18,7 @@ static enum lockdown_reason kernel_locked_down;
>
> static char *lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = {
> [LOCKDOWN_NONE] = "none",
>+ [LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",
> [LOCKDOWN_INTEGRITY_MAX] = "integrity",
> [LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",
> };
>--
>2.22.0.770.g0f2c4a37fd-goog
>
^ permalink raw reply
* Re: [GIT PULL] SafeSetID MAINTAINERS file update for v5.3
From: Linus Torvalds @ 2019-08-01 13:25 UTC (permalink / raw)
To: Micah Morton; +Cc: linux-security-module, Linux Kernel Mailing List
In-Reply-To: <CAJ-EccMXEVktpuPS5BwkGqTo++dGcpHAuSUZo7WgJhAzFByz0g@mail.gmail.com>
On Wed, Jul 31, 2019 at 2:30 PM Micah Morton <mortonm@chromium.org> wrote:
>
> You mentioned a couple weeks ago it would be good if I added myself to
> the MAINTAINERS file for the SafeSetID LSM. Here's the pull request
> for v5.3.
There's a lot more than the maintainer ID in there. You've rebased old
patches that I already had etc:
Jann Horn (10):
LSM: SafeSetID: fix pr_warn() to include newline
LSM: SafeSetID: fix check for setresuid(new1, new2, new3)
LSM: SafeSetID: refactor policy hash table
LSM: SafeSetID: refactor safesetid_security_capable()
LSM: SafeSetID: refactor policy parsing
LSM: SafeSetID: fix userns handling in securityfs
LSM: SafeSetID: rewrite userspace API to atomic updates
LSM: SafeSetID: add read handler
LSM: SafeSetID: verify transitive constrainedness
LSM: SafeSetID: fix use of literal -1 in capable hook
Micah Morton (2):
Merge commit 'v5.3-rc2^0'
Add entry in MAINTAINERS file for SafeSetID LSM
Not pulled.
Linus
^ permalink raw reply
* Re: [PATCH] fanotify, inotify, dnotify, security: add security hook for fs notifications
From: Paul Moore @ 2019-08-01 12:47 UTC (permalink / raw)
To: Stephen Smalley
Cc: Casey Schaufler, Aaron Goidel, selinux, linux-security-module,
linux-fsdevel, dhowells, jack, amir73il, James Morris,
linux-kernel
In-Reply-To: <66fbc35c-6cc8-bd08-9bf9-aa731dc3ff09@tycho.nsa.gov>
On Thu, Aug 1, 2019 at 7:31 AM Stephen Smalley <sds@tycho.nsa.gov> wrote:
> On 7/31/19 8:27 PM, Paul Moore wrote:
> > On Wed, Jul 31, 2019 at 1:26 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >> On 7/31/2019 8:34 AM, Aaron Goidel wrote:
...
> >>> +static int selinux_path_notify(const struct path *path, u64 mask,
> >>> + unsigned int obj_type)
> >>> +{
> >>> + int ret;
> >>> + u32 perm;
> >>> +
> >>> + struct common_audit_data ad;
> >>> +
> >>> + ad.type = LSM_AUDIT_DATA_PATH;
> >>> + ad.u.path = *path;
> >>> +
> >>> + /*
> >>> + * Set permission needed based on the type of mark being set.
> >>> + * Performs an additional check for sb watches.
> >>> + */
> >>> + switch (obj_type) {
> >>> + case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
> >>> + perm = FILE__WATCH_MOUNT;
> >>> + break;
> >>> + case FSNOTIFY_OBJ_TYPE_SB:
> >>> + perm = FILE__WATCH_SB;
> >>> + ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
> >>> + FILESYSTEM__WATCH, &ad);
> >>> + if (ret)
> >>> + return ret;
> >>> + break;
> >>> + case FSNOTIFY_OBJ_TYPE_INODE:
> >>> + perm = FILE__WATCH;
> >>> + break;
> >>> + default:
> >>> + return -EINVAL;
> >>> + }
> >>> +
> >>> + // check if the mask is requesting ability to set a blocking watch
> >
> > ... in the future please don't use "// XXX", use "/* XXX */" instead :)
> >
> > Don't respin the patch just for this, but if you have to do it for
> > some other reason please fix the C++ style comments. Thanks.
>
> This was discussed during the earlier RFC series but ultimately someone
> pointed to:
> https://lkml.org/lkml/2016/7/8/625
> where Linus blessed the use of C++/C99 style comments. And checkpatch
> accepts them these days.
Yep, I'm aware of both, it is simply a personal preference of mine.
I'm not going to reject patches with C++ style comments, but I would
ask people to stick to the good ol' fashioned comments for patches
they submit.
> Obviously if you truly don't want them in the SELinux code, that's your
> call. But note that all files now have at least one such comment as a
> result of the mass SPDX license headers that were added throughout the
> tree using that style.
FYI, the sky is blue.
It isn't just the license headers either, Al dropped one into hooks.c
:). Just like I don't plan to reject patches due only to the comment
style, you don't see me pushing patches to change the C++ comments.
--
paul moore
www.paul-moore.com
^ permalink raw reply
* [PATCH] tomoyo: Use error code from kern_path() rather than -ENOENT.
From: Tetsuo Handa @ 2019-08-01 11:35 UTC (permalink / raw)
To: linux-security-module
Cc: Tetsuo Handa, Al Viro, Alexei Starovoitov, Takeshi Misawa
In-Reply-To: <20190801030323.GA1958@DESKTOP>
Takeshi Misawa has pointed out that tomoyo_find_next_domain() is returning
-ENOENT when tomoyo_realpath_nofollow() failed [1]. That error code was
chosen based on an assumption that when tomoyo_realpath_nofollow() fails,
the cause of failure is kern_path() failure due to a race window that
the pathname used for do_open_execat() from __do_execve_file() was removed
before tomoyo_find_next_domain() is called.
Since tomoyo_realpath_nofollow() is called by tomoyo_find_next_domain()
only, and __do_execve_file() makes sure that bprm->filename != NULL, let's
inline tomoyo_realpath_nofollow() into tomoyo_find_next_domain().
It seems that tomoyo_realpath_nofollow() is currently broken by
commit 449325b52b7a6208 ("umh: introduce fork_usermode_blob() helper")
when do_execve_file() is used. To fix it, we will need to know whether
do_open_execat() was called before tomoyo_find_next_domain() is called.
To fix it in a more accurate and race-free way, we will need to calculate
both LOOKUP_FOLLOW pathname and !LOOKUP_FOLLOW pathname at the same time.
[1] https://lkml.kernel.org/r/20190801030323.GA1958@DESKTOP
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Reported-by: Takeshi Misawa <jeliantsurux@gmail.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Alexei Starovoitov <ast@kernel.org>
---
security/tomoyo/common.h | 1 -
security/tomoyo/domain.c | 18 ++++++++++++++----
security/tomoyo/realpath.c | 20 --------------------
3 files changed, 14 insertions(+), 25 deletions(-)
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h
index 050473df5809..58b51a21cf9c 100644
--- a/security/tomoyo/common.h
+++ b/security/tomoyo/common.h
@@ -957,7 +957,6 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt,
va_list args);
char *tomoyo_read_token(struct tomoyo_acl_param *param);
char *tomoyo_realpath_from_path(const struct path *path);
-char *tomoyo_realpath_nofollow(const char *pathname);
const char *tomoyo_get_exe(void);
const char *tomoyo_yesno(const unsigned int value);
const struct tomoyo_path_info *tomoyo_compare_name_union
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 8526a0a74023..5cd06bfd46c7 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -721,10 +721,20 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm)
ee->r.obj = &ee->obj;
ee->obj.path1 = bprm->file->f_path;
/* Get symlink's pathname of program. */
- retval = -ENOENT;
- exename.name = tomoyo_realpath_nofollow(original_name);
- if (!exename.name)
- goto out;
+ {
+ struct path path;
+ int ret = kern_path(original_name, 0, &path);
+
+ if (ret) {
+ retval = ret;
+ exename.name = NULL;
+ goto out;
+ }
+ exename.name = tomoyo_realpath_from_path(&path);
+ path_put(&path);
+ if (!exename.name) /* retval was initialized with -ENONEM */
+ goto out;
+ }
tomoyo_fill_path_info(&exename);
retry:
/* Check 'aggregator' directive. */
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c
index e7832448d721..70d456348e1c 100644
--- a/security/tomoyo/realpath.c
+++ b/security/tomoyo/realpath.c
@@ -321,23 +321,3 @@ char *tomoyo_realpath_from_path(const struct path *path)
tomoyo_warn_oom(__func__);
return name;
}
-
-/**
- * tomoyo_realpath_nofollow - Get realpath of a pathname.
- *
- * @pathname: The pathname to solve.
- *
- * Returns the realpath of @pathname on success, NULL otherwise.
- */
-char *tomoyo_realpath_nofollow(const char *pathname)
-{
- struct path path;
-
- if (pathname && kern_path(pathname, 0, &path) == 0) {
- char *buf = tomoyo_realpath_from_path(&path);
-
- path_put(&path);
- return buf;
- }
- return NULL;
-}
--
2.16.5
^ permalink raw reply related
* Re: [PATCH] fanotify, inotify, dnotify, security: add security hook for fs notifications
From: Stephen Smalley @ 2019-08-01 11:31 UTC (permalink / raw)
To: Paul Moore, Casey Schaufler
Cc: Aaron Goidel, selinux, linux-security-module, linux-fsdevel,
dhowells, jack, amir73il, James Morris, linux-kernel
In-Reply-To: <CAHC9VhS6cfMw5ZUkOSov6hexh9QpnpKwipP7L7ZYGCVLCHGfFQ@mail.gmail.com>
On 7/31/19 8:27 PM, Paul Moore wrote:
> On Wed, Jul 31, 2019 at 1:26 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
>> On 7/31/2019 8:34 AM, Aaron Goidel wrote:
>>> As of now, setting watches on filesystem objects has, at most, applied a
>>> check for read access to the inode, and in the case of fanotify, requires
>>> CAP_SYS_ADMIN. No specific security hook or permission check has been
>>> provided to control the setting of watches. Using any of inotify, dnotify,
>>> or fanotify, it is possible to observe, not only write-like operations, but
>>> even read access to a file. Modeling the watch as being merely a read from
>>> the file is insufficient for the needs of SELinux. This is due to the fact
>>> that read access should not necessarily imply access to information about
>>> when another process reads from a file. Furthermore, fanotify watches grant
>>> more power to an application in the form of permission events. While
>>> notification events are solely, unidirectional (i.e. they only pass
>>> information to the receiving application), permission events are blocking.
>>> Permission events make a request to the receiving application which will
>>> then reply with a decision as to whether or not that action may be
>>> completed. This causes the issue of the watching application having the
>>> ability to exercise control over the triggering process. Without drawing a
>>> distinction within the permission check, the ability to read would imply
>>> the greater ability to control an application. Additionally, mount and
>>> superblock watches apply to all files within the same mount or superblock.
>>> Read access to one file should not necessarily imply the ability to watch
>>> all files accessed within a given mount or superblock.
>>>
>>> In order to solve these issues, a new LSM hook is implemented and has been
>>> placed within the system calls for marking filesystem objects with inotify,
>>> fanotify, and dnotify watches. These calls to the hook are placed at the
>>> point at which the target path has been resolved and are provided with the
>>> path struct, the mask of requested notification events, and the type of
>>> object on which the mark is being set (inode, superblock, or mount). The
>>> mask and obj_type have already been translated into common FS_* values
>>> shared by the entirety of the fs notification infrastructure. The path
>>> struct is passed rather than just the inode so that the mount is available,
>>> particularly for mount watches. This also allows for use of the hook by
>>> pathname-based security modules. However, since the hook is intended for
>>> use even by inode based security modules, it is not placed under the
>>> CONFIG_SECURITY_PATH conditional. Otherwise, the inode-based security
>>> modules would need to enable all of the path hooks, even though they do not
>>> use any of them.
>>>
>>> This only provides a hook at the point of setting a watch, and presumes
>>> that permission to set a particular watch implies the ability to receive
>>> all notification about that object which match the mask. This is all that
>>> is required for SELinux. If other security modules require additional hooks
>>> or infrastructure to control delivery of notification, these can be added
>>> by them. It does not make sense for us to propose hooks for which we have
>>> no implementation. The understanding that all notifications received by the
>>> requesting application are all strictly of a type for which the application
>>> has been granted permission shows that this implementation is sufficient in
>>> its coverage.
>>>
>>> Security modules wishing to provide complete control over fanotify must
>>> also implement a security_file_open hook that validates that the access
>>> requested by the watching application is authorized. Fanotify has the issue
>>> that it returns a file descriptor with the file mode specified during
>>> fanotify_init() to the watching process on event. This is already covered
>>> by the LSM security_file_open hook if the security module implements
>>> checking of the requested file mode there. Otherwise, a watching process
>>> can obtain escalated access to a file for which it has not been authorized.
>>>
>>> The selinux_path_notify hook implementation works by adding five new file
>>> permissions: watch, watch_mount, watch_sb, watch_reads, and watch_with_perm
>>> (descriptions about which will follow), and one new filesystem permission:
>>> watch (which is applied to superblock checks). The hook then decides which
>>> subset of these permissions must be held by the requesting application
>>> based on the contents of the provided mask and the obj_type. The
>>> selinux_file_open hook already checks the requested file mode and therefore
>>> ensures that a watching process cannot escalate its access through
>>> fanotify.
>>>
>>> The watch, watch_mount, and watch_sb permissions are the baseline
>>> permissions for setting a watch on an object and each are a requirement for
>>> any watch to be set on a file, mount, or superblock respectively. It should
>>> be noted that having either of the other two permissions (watch_reads and
>>> watch_with_perm) does not imply the watch, watch_mount, or watch_sb
>>> permission. Superblock watches further require the filesystem watch
>>> permission to the superblock. As there is no labeled object in view for
>>> mounts, there is no specific check for mount watches beyond watch_mount to
>>> the inode. Such a check could be added in the future, if a suitable labeled
>>> object existed representing the mount.
>>>
>>> The watch_reads permission is required to receive notifications from
>>> read-exclusive events on filesystem objects. These events include accessing
>>> a file for the purpose of reading and closing a file which has been opened
>>> read-only. This distinction has been drawn in order to provide a direct
>>> indication in the policy for this otherwise not obvious capability. Read
>>> access to a file should not necessarily imply the ability to observe read
>>> events on a file.
>>>
>>> Finally, watch_with_perm only applies to fanotify masks since it is the
>>> only way to set a mask which allows for the blocking, permission event.
>>> This permission is needed for any watch which is of this type. Though
>>> fanotify requires CAP_SYS_ADMIN, this is insufficient as it gives implicit
>>> trust to root, which we do not do, and does not support least privilege.
>>>
>>> Signed-off-by: Aaron Goidel <acgoide@tycho.nsa.gov>
>>
>> I can't say that I accept your arguments that this is sufficient,
>> but as you point out, the SELinux team does, and if I want more
>> for Smack that's my fish to fry.
>>
>> Acked-by: Casey Schaufler <casey@schaufler-ca.com>
>
> Thanks Aaron. Thanks Casey.
>
> I think we also want an ACK from the other LSMs, what say all of you?
> Can you live with the new security_path_notify() hook?
>
> Aaron, you'll also need to put together a test for the
> selinux-testsuite to exercise this code. If you already sent it to
> the list, my apologies but I don't see it anywhere. If you get stuck
> on the test, let me know and I'll try to help out.
>
> Oh, one more thing ...
>
>>> +static int selinux_path_notify(const struct path *path, u64 mask,
>>> + unsigned int obj_type)
>>> +{
>>> + int ret;
>>> + u32 perm;
>>> +
>>> + struct common_audit_data ad;
>>> +
>>> + ad.type = LSM_AUDIT_DATA_PATH;
>>> + ad.u.path = *path;
>>> +
>>> + /*
>>> + * Set permission needed based on the type of mark being set.
>>> + * Performs an additional check for sb watches.
>>> + */
>>> + switch (obj_type) {
>>> + case FSNOTIFY_OBJ_TYPE_VFSMOUNT:
>>> + perm = FILE__WATCH_MOUNT;
>>> + break;
>>> + case FSNOTIFY_OBJ_TYPE_SB:
>>> + perm = FILE__WATCH_SB;
>>> + ret = superblock_has_perm(current_cred(), path->dentry->d_sb,
>>> + FILESYSTEM__WATCH, &ad);
>>> + if (ret)
>>> + return ret;
>>> + break;
>>> + case FSNOTIFY_OBJ_TYPE_INODE:
>>> + perm = FILE__WATCH;
>>> + break;
>>> + default:
>>> + return -EINVAL;
>>> + }
>>> +
>>> + // check if the mask is requesting ability to set a blocking watch
>
> ... in the future please don't use "// XXX", use "/* XXX */" instead :)
>
> Don't respin the patch just for this, but if you have to do it for
> some other reason please fix the C++ style comments. Thanks.
This was discussed during the earlier RFC series but ultimately someone
pointed to:
https://lkml.org/lkml/2016/7/8/625
where Linus blessed the use of C++/C99 style comments. And checkpatch
accepts them these days.
Obviously if you truly don't want them in the SELinux code, that's your
call. But note that all files now have at least one such comment as a
result of the mass SPDX license headers that were added throughout the
tree using that style.
>
>>> + if (mask & (ALL_FSNOTIFY_PERM_EVENTS))
>>> + perm |= FILE__WATCH_WITH_PERM; // if so, check that permission
>>> +
>>> + // is the mask asking to watch file reads?
>>> + if (mask & (FS_ACCESS | FS_ACCESS_PERM | FS_CLOSE_NOWRITE))
>>> + perm |= FILE__WATCH_READS; // check that permission as well
>>> +
>>> + return path_has_perm(current_cred(), path, perm);
>>> +}
>
^ permalink raw reply
* Re: [PATCH] tomoyo: common: Fix potential Spectre v1 vulnerability
From: Tetsuo Handa @ 2019-08-01 11:02 UTC (permalink / raw)
To: Gustavo A. R. Silva, Dan Carpenter
Cc: Kentaro Takeda, James Morris, Serge E. Hallyn,
linux-security-module, linux-kernel
In-Reply-To: <20190731185457.GA21407@embeddedor>
Hello.
Thanks for a patch, but I have a question.
On 2019/08/01 3:54, Gustavo A. R. Silva wrote:
> profile is controlled by user-space via /sys/kernel/security/tomoyo/profile,
It is true that "profile" value is given from user-space, and it will be true
that speculative execution would access "ns->profile_ptr[profile]" before whether
"profile >= TOMOYO_MAX_PROFILES" is true is concluded. But
> hence leading to a potential exploitation of the Spectre variant 1
> vulnerability.
which memory address is vulnerable to Spectre variant 1 attack? How can an attacker
gain information from memory speculatively accessed by "ns->profile_ptr[profile]" ?
Where is the memory access which corresponds to "arr2->data[index2]" demonstrated at
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html ?
Since I'm not familiar with Spectre/Meltdown problem, this patch sounds as if
"Oh, let's suppress Smatch warning". I want to know whether this problem is real
and this patch is worth keeping stable@vger.kernel.org ...
> @@ -488,13 +489,15 @@ static void tomoyo_print_number_union(struct tomoyo_io_buffer *head,
> * Returns pointer to "struct tomoyo_profile" on success, NULL otherwise.
> */
> static struct tomoyo_profile *tomoyo_assign_profile
> -(struct tomoyo_policy_namespace *ns, const unsigned int profile)
> +(struct tomoyo_policy_namespace *ns, unsigned int profile)
> {
> struct tomoyo_profile *ptr;
> struct tomoyo_profile *entry;
>
> if (profile >= TOMOYO_MAX_PROFILES)
> return NULL;
> + profile = array_index_nospec(profile, TOMOYO_MAX_PROFILES);
> +
> ptr = ns->profile_ptr[profile];
> if (ptr)
> return ptr;
>
By the way, since /sys/kernel/security/tomoyo/profile is writable by only explicitly
whitelisted domains/programs (&& by only root user by default), I think that it is
OK to treat this "profile" value as trusted.
^ permalink raw reply
* Re: [RFC v2 0/6] Introduce TEE based Trusted Keys support
From: Janne Karhunen @ 2019-08-01 10:40 UTC (permalink / raw)
To: Sumit Garg
Cc: keyrings, linux-integrity, linux-security-module, Jens Wiklander,
Jonathan Corbet, dhowells, jejb, Jarkko Sakkinen, Mimi Zohar,
James Morris, Serge E. Hallyn, Casey Schaufler, Ard Biesheuvel,
Daniel Thompson, Linux Doc Mailing List,
Linux Kernel Mailing List, linux-arm-kernel,
tee-dev @ lists . linaro . org
In-Reply-To: <CAFA6WYOwcO5-cyaJf3tMMAdyVHJo=BzmCWtsjA3S8aj5g-GZxQ@mail.gmail.com>
On Thu, Aug 1, 2019 at 1:00 PM Sumit Garg <sumit.garg@linaro.org> wrote:
> > > Here TEE isn't similar to a user-space crypto library. In our case TEE
> > > is based on ARM TrustZone which only allows TEE communications to be
> > > initiated from privileged mode. So why would you like to route
> > > communications via user-mode (which is less secure) when we have
> > > standardised TEE interface available in kernel?
> >
> > The physical access guards for reading/writing the involved critical
> > memory are identical as far as I know? Layered security is generally a
> > good thing, and the userspace pass actually adds a layer, so not sure
> > which is really safer?
>
> AFAIK, layered security is better in case we move from lower privilege
> level to higher privilege level rather than in reverse order.
You can look at this in many ways. Another way to look at it is that
the services should be provided with the least amount of permissions
required for the task. Further you can containerize something, the
better.
As for your PLATFORMS support: it is all nice, but there is no way to
convince op-tee or any other tee to be adopted by many real users.
Every serious user can and will do their own thing, or at very best,
buy it from someone who did their own thing and is trusted. There is
zero chance that samsung, huawei, apple, nsa, google, rambus, payment
system vendors, .. would actually share the tee (or probably even the
interfaces). It is just too vital and people do not trust each other
anymore :(
Anyway, enough about the topic from my side. I guess people will tell
what they want, I'm fine with any, and it is all progress from the
current state :)
--
Janne
^ permalink raw reply
* Re: [Tee-dev] [RFC v2 0/6] Introduce TEE based Trusted Keys support
From: Sumit Garg @ 2019-08-01 10:27 UTC (permalink / raw)
To: Janne Karhunen
Cc: Rouven Czerwinski, tee-dev @ lists . linaro . org,
Daniel Thompson, Jonathan Corbet, jejb, Ard Biesheuvel,
Linux Doc Mailing List, Jarkko Sakkinen,
Linux Kernel Mailing List, dhowells, linux-security-module,
keyrings, Mimi Zohar, Casey Schaufler, linux-integrity,
linux-arm-kernel, Serge E. Hallyn
In-Reply-To: <CAE=NcrbujsM8wYJXq+s=o5Vy1xY1b0uKYBGvp6UP5ex70HrB2Q@mail.gmail.com>
On Thu, 1 Aug 2019 at 14:00, Janne Karhunen <janne.karhunen@gmail.com> wrote:
>
> On Thu, Aug 1, 2019 at 10:58 AM Sumit Garg <sumit.garg@linaro.org> wrote:
>
> > > Anyway, just my .02c. I guess having any new support in the kernel for
> > > new trust sources is good and improvement from the current state. I
> > > can certainly make my stuff work with your setup as well, what ever
> > > people think is the best.
> >
> > Yes your implementation can very well fit under trusted keys
> > abstraction framework without creating a new keytype: "ext-trusted".
>
> The fundamental problem with the 'standardized kernel tee' still
> exists - it will never be generic in real life. Getting all this in
> the kernel will solve your problem and sell this particular product,
> but it is quite unlikely to help that many users. If the security is
> truly important to you, would you really trust any of this code to
> someone else? In this day and age, I really doubt many do.
There are already multiple platforms supported by OP-TEE [1] which
could benefit from this trusted keys interface.
> Everyone
> does their own thing, so this is why I really see all that as a
> userspace problem.
>
IMO, we should try to use standardized interfaces which are well
thought off rather than implementing your own.
[1] https://optee.readthedocs.io/general/platforms.html
-Sumit
>
> --
> Janne
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox