* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-05 0:20 UTC (permalink / raw)
To: Peter Dolding
Cc: Theodore Ts'o, David Howells, Linus Torvalds, luto,
Ard Biesheuvel, jmorris, Alan Cox, Greg Kroah-Hartman,
Linux Kernel Mailing List, jforbes, linux-man, jlee, LSM List,
linux-api, Kees Cook, linux-efi
In-Reply-To: <CANA3KFWLCfe=KYPBhKj+g698=frt4E-u-Hq2--5jFkHnkNoBnA@mail.gmail.com>
On Wed, Apr 4, 2018 at 5:05 PM Peter Dolding <oiaohm@gmail.com> wrote:
> > If you don't have secure boot then an attacker with root can modify your
> > bootloader or kernel, and on next boot lockdown can be silently
disabled.
> Stop being narrow minded you don't need secure boot to protect
> bootloader or kernel the classic is only boot from read only media.
And if you use another protected path you can set the appropriate bootparam
flag or pass the appropriate kernel command line argument and gain the same
functionality.
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Peter Dolding @ 2018-04-05 0:05 UTC (permalink / raw)
To: Matthew Garrett
Cc: Theodore Tso, David Howells, Linus Torvalds, luto, Ard Biesheuvel,
James Morris, Alan Cox, Greg Kroah-Hartman,
Linux Kernel Mailing List, jforbes, linux-man, jlee, LSM List,
linux-api, Kees Cook, linux-efi
In-Reply-To: <CACdnJuuGRRUt-a3i89o906ka3RDOhs+_7tz_G8LTG8Jc0DXAyQ@mail.gmail.com>
> If you don't have secure boot then an attacker with root can modify your
> bootloader or kernel, and on next boot lockdown can be silently disabled.
Stop being narrow minded you don't need secure boot to protect
bootloader or kernel the classic is only boot from read only media.
Another is network boot using https can coreboot firmware. This
checks the certificate of the https server against selected CA before
downloading anything and as long as the firmware is set read only in
hardware the attack has absolutely nothing to work on.
In fact the network boot form https server is more secure than UEFI
secureboot due to highly limited parties who can alter/provide the
approved boot loader/kernel image.
Having root user rights does not override physical security. The
fact there are other ways of doing bootloader and kernel security
other than UEFI secureboot that are in lots of cases more secure than
UEFI secureboot due to using more limited keys is the absolute reason
why lockdown is required without UEFI secureboot.
It would make sense to extend kexec to support UEFI secureboot
verification and also kexec to have frameworks to support other
security options like https server storage of all kernel images.
Please note kexec supporting UEFI secureboot verification should also
support booting non UEFI secureboot but verified by some other method
and having own PK/KEK set for kexec and this would be when the Linux
kernel is placed in firmware and used instead of EFI firmware..
Please note there are many UEFI firmwares that with secureboot off
allow setting up secure https bootting where you are not in fact
validating the boot loader or kernel but validating the source you get
them from.
There are three different ways to achieve a protected boot process.
1) validate the boot files.(this is like UEFI secure boot and many
other methods)
2) validate source the boot files. Yes this can be apply key check to
image if image is not signed don't boot from it and the image contain
boot loader and kernel then not bother validating the boot loader and
kernel image/parts individually same with https.
3) make boot files read only.
All three achieve the same level of security. If you are using any
of the three lockdown option may provide some benefit.
Yes https network boot effectively does 2 and 3 so making having a
very limit threat against the boot process.
Remember there is more 1 way to skin a cat just like there is more
than 1 way to make a secure system. Currently being too narrow in
methods for doing protected booting.
Peter Dolding.
^ permalink raw reply
* Re: An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: James Morris @ 2018-04-04 23:25 UTC (permalink / raw)
To: David Howells
Cc: Andy Lutomirski, Greg Kroah-Hartman, Theodore Y. Ts'o,
Matthew Garrett, Linus Torvalds, Ard Biesheuvel, Alan Cox,
Linux Kernel Mailing List, Justin Forbes, linux-man, joeyli,
LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <1119.1522858644@warthog.procyon.org.uk>
On Wed, 4 Apr 2018, David Howells wrote:
> > 6. There's a way to *decrease* the lockdown level below the configured
> > value. (This ability itself may be gated by a config option.)
> > Choices include a UEFI protected variable,
>
> By turning secure boot off, maybe?
It's surely reasonable to allow an already secure-booted system to be
debugged without needing to be rebooted.
- James
--
James Morris
<jmorris@namei.org>
^ permalink raw reply
* Re: [PATCH RFC v5] pidns: introduce syscall translate_pid
From: Eric W. Biederman @ 2018-04-04 22:29 UTC (permalink / raw)
To: Nagarathnam Muthusamy
Cc: Konstantin Khlebnikov, linux-api, linux-kernel, Jann Horn,
Serge Hallyn, Oleg Nesterov, Andy Lutomirski, Prakash Sangappa,
Andrew Morton
In-Reply-To: <ba7b704f-1fc4-a08d-e7cf-2766160bd419@oracle.com>
Nagarathnam Muthusamy <nagarathnam.muthusamy@oracle.com> writes:
> On 04/04/2018 12:11 PM, Konstantin Khlebnikov wrote:
>> Each process have different pids, one for each pid namespace it belongs.
>> When interaction happens within single pid-ns translation isn't required.
>> More complicated scenarios needs special handling.
>>
>> For example:
>> - reading pid-files or logs written inside container with pid namespace
>> - attaching with ptrace to tasks from different pid namespace
>> - passing pids across pid namespaces in any kind of API
>>
>> Currently there are several interfaces that could be used here:
>>
>> Pid namespaces are identified by inode number of /proc/[pid]/ns/pid.
Using the inode number in interfaces is not an option. Especially not
withou referencing the device number for the filesystem as well.
>> Pids for nested Pid namespaces are shown in file /proc/[pid]/status.
>> In some cases conversion pid -> vpid could be easily done using this
>> information, but backward translation requires scanning all tasks.
>>
>> Unix socket automatically translates pid attached to SCM_CREDENTIALS.
>> This requires CAP_SYS_ADMIN for sending arbitrary pids and entering
>> into pid namespace, this expose process and could be insecure.
>>
>> This patch adds new syscall for converting pids between pid namespaces:
>>
>> pid_t translate_pid(pid_t pid, int source_type, int source,
>> int target_type, int target);
>>
>> @source_type and @target_type defines type of following arguments:
>>
>> TRANSLATE_PID_CURRENT_PIDNS - current pid namespace, argument is unused
>> TRANSLATE_PID_TASK_PIDNS - task pid-ns, argument is task pid
>
> I believe using pid to represent the namespace has been already
> discussed in V1 of this patch in https://lkml.org/lkml/2015/9/22/1087
> after which we moved on to fd based version of this interface.
Or in short why is the case of pids important?
You Konstantin you almost said why they were important in your message
saying you were going to send this one. However you don't explain in
your description why you want to identify pid namespaces by pid.
Eric
^ permalink raw reply
* Re: An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: David Howells @ 2018-04-04 22:19 UTC (permalink / raw)
To: Jann Horn
Cc: dhowells, Alexei Starovoitov, Andy Lutomirski, Greg Kroah-Hartman,
Theodore Y. Ts'o, Matthew Garrett, Linus Torvalds,
Ard Biesheuvel, James Morris, Alan Cox, Linux Kernel Mailing List,
Justin Forbes, linux-man, joeyli, LSM List, Linux API, Kees Cook,
linux-efi
In-Reply-To: <CAG48ez3edmZo1iFXqpvzOKNY0jLzcqa18KuoRrBaPyfp=7huZQ@mail.gmail.com>
Jann Horn <jannh@google.com> wrote:
> > Uh, no. bpf, for example, can be used to modify kernel memory.
>
> I'm pretty sure bpf isn't supposed to be able to modify arbitrary
> kernel memory. AFAIU if you can use BPF to write to arbitrary kernel
> memory, that's a bug; with CAP_SYS_ADMIN, you can read from userspace,
> write to userspace, and read from kernelspace, but you shouldn't be
> able to write to kernelspace.
Ah - you may be right. I seem to have misremembered what Joey Lee wrote in
his patch description.
David
^ permalink raw reply
* Re: [PATCH RFC v5] pidns: introduce syscall translate_pid
From: Nagarathnam Muthusamy @ 2018-04-04 20:31 UTC (permalink / raw)
To: Konstantin Khlebnikov, linux-api, linux-kernel
Cc: Jann Horn, Serge Hallyn, Oleg Nesterov, Andy Lutomirski,
Eric W. Biederman, Prakash Sangappa, Andrew Morton
In-Reply-To: <152286911105.615669.14053871624892399807.stgit@buzz>
On 04/04/2018 12:11 PM, Konstantin Khlebnikov wrote:
> Each process have different pids, one for each pid namespace it belongs.
> When interaction happens within single pid-ns translation isn't required.
> More complicated scenarios needs special handling.
>
> For example:
> - reading pid-files or logs written inside container with pid namespace
> - attaching with ptrace to tasks from different pid namespace
> - passing pids across pid namespaces in any kind of API
>
> Currently there are several interfaces that could be used here:
>
> Pid namespaces are identified by inode number of /proc/[pid]/ns/pid.
>
> Pids for nested Pid namespaces are shown in file /proc/[pid]/status.
> In some cases conversion pid -> vpid could be easily done using this
> information, but backward translation requires scanning all tasks.
>
> Unix socket automatically translates pid attached to SCM_CREDENTIALS.
> This requires CAP_SYS_ADMIN for sending arbitrary pids and entering
> into pid namespace, this expose process and could be insecure.
>
> This patch adds new syscall for converting pids between pid namespaces:
>
> pid_t translate_pid(pid_t pid, int source_type, int source,
> int target_type, int target);
>
> @source_type and @target_type defines type of following arguments:
>
> TRANSLATE_PID_CURRENT_PIDNS - current pid namespace, argument is unused
> TRANSLATE_PID_TASK_PIDNS - task pid-ns, argument is task pid
I believe using pid to represent the namespace has been already
discussed in V1 of this patch in https://lkml.org/lkml/2015/9/22/1087
after which we moved on to fd based version of this interface.
-Nagarathnam.
> TRANSLATE_PID_FD_PIDNS - pidns fd, argument is file descriptor
>
> Syscall returns pid in target pid-ns or zero if task have no pid there.
>
> Error codes:
> -EINVAL - @source or @target couldn't be resolved into pid namespace
> -ESRCH - task with @pid is not found in @source pid-namespace
>
> Other pid namespaces are referenced either by pid of any process who
> lives inside it or by file descriptor pointing to /proc/[pid]/ns/pid.
> Latter method provides better protection against races but in some
> cases requires CAP_SYS_PTRACE.
>
> Translate_pid could breach pid isolation and return pids from outer pid
> namespaces iff process already has file descriptor pointing to them.
>
>
> Examples:
>
> - get pid in current pid namespace
>
> translate_pid(pid, TRANSLATE_PID_FD_PIDNS, ns_fd,
> TRANSLATE_PID_CURRENT_PIDNS, 0)
> or
> translate_pid(pid, TRANSLATE_PID_TASK_PIDNS, ns_pid,
> TRANSLATE_PID_CURRENT_PIDNS, 0)
>
> - get pid in other pid namespace
>
> translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
> TRANSLATE_PID_FD_PIDNS, ns_fd)
> or
> translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
> TRANSLATE_PID_TASK_PIDNS, ns_pid)
>
> - get deepest pid
>
> translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
> TRANSLATE_PID_TASK_PIDNS, pid)
>
> - get pid of init task for namespace
>
> translate_pid(1, TRANSLATE_PID_FD_PIDNS, ns_fd,
> TRANSLATE_PID_CURRENT_PIDNS, 0)
>
>
> This syscall also could be used for checking topology of pid namespaces:
>
> - ns1 nests inside ns2
>
> translate_pid(1, TRANSLATE_PID_FD_PIDNS, ns1_fd,
> TRANSLATE_PID_FD_PIDNS, ns2_fd) > 1
>
> - task1 lives in same pid-namespace as task2
>
> translate_pid(1, TRANSLATE_PID_TASK_PIDNS, task1_pid,
> TRANSLATE_PID_TASK_PIDNS, task2_pid) == 1
>
> - task1 is isolated from task2
>
> translate_pid(task1_pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
> TRANSLATE_PID_TASK_PIDNS, task2_pid) == 0
>
> - pid is reachable from ns
>
> translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
> TRANSLATE_PID_FD_PIDNS, ns_fd) > 0
>
> Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
>
> ---
>
> v1: https://lkml.org/lkml/2015/9/15/411
> v2: https://lkml.org/lkml/2015/9/24/278
> * use namespace-fd as second/third argument
> * add -pid for getting parent pid
> * move code into kernel/sys.c next to getppid
> * drop ifdef CONFIG_PID_NS
> * add generic syscall
> v3: https://lkml.org/lkml/2015/9/28/3
> * use proc_ns_fdget()
> * update description
> * rebase to next-20150925
> * fix conflict with mlock2
> v4: https://lkml.org/lkml/2017/10/16/852
> * rename into translate_pid()
> * remove syscall if CONFIG_PID_NS=n
> * drop -pid for parent task
> * drop fget-fdget optimizations
> * add helper get_pid_ns_by_fd()
> * wire only into x86
> v5:
> * rewrite commit message
> * resolve pidns by task pid or by pidns fd
> * add arguments source_type and target_type
>
> --- sample tool translate_pid.c ---
>
> #define _GNU_SOURCE
> #include <sys/syscall.h>
> #include <sys/types.h>
> #include <sys/stat.h>
> #include <sched.h>
> #include <fcntl.h>
> #include <err.h>
> #include <unistd.h>
> #include <stdlib.h>
> #include <stdio.h>
>
> #ifndef SYS_translate_pid
> #ifdef __x86_64__
> #define SYS_translate_pid 333
> #endif
> #endif
>
> #ifndef TRANSLATE_PID_CURRENT_PIDNS
> #define TRANSLATE_PID_CURRENT_PIDNS 0
> #define TRANSLATE_PID_TASK_PIDNS 1
> #define TRANSLATE_PID_FD_PIDNS 2
> #endif
>
> pid_t translate_pid(pid_t pid, int source_type, int source,
> int target_type, int target) {
> return syscall(SYS_translate_pid, pid, source_type, source,
> target_type, target);
> }
>
> int main(int argc, char **argv) {
> int pid, source, target;
> char buf[64];
>
> if (argc != 4)
> errx(1, "usage: %s <pid> <source> <traget>", argv[0]);
>
> pid = atoi(argv[1]);
> int source_type, target_type;
> source = atoi(argv[2]);
> target = atoi(argv[3]);
>
> if (source < 0) {
> source_type = TRANSLATE_PID_TASK_PIDNS;
> source = -source;
> } else if (source > 0) {
> source_type = TRANSLATE_PID_FD_PIDNS;
> sprintf(buf, "/proc/%d/ns/pid", source);
> source = open(buf, O_RDONLY);
> if (source < 0)
> err(2, "open source %s", buf);
> } else {
> source_type = TRANSLATE_PID_CURRENT_PIDNS;
> }
>
> if (target < 0) {
> target_type = TRANSLATE_PID_TASK_PIDNS;
> target = -target;
> } else if (target > 0) {
> target_type = TRANSLATE_PID_FD_PIDNS;
> sprintf(buf, "/proc/%d/ns/pid", target);
> target = open(buf, O_RDONLY);
> if (target < 0)
> err(2, "open target %s", buf);
> } else {
> target_type = TRANSLATE_PID_CURRENT_PIDNS;
> }
>
> pid = translate_pid(pid, source_type, source, target_type, target);
> if (pid < 0)
> err(2, "translate");
>
> printf("%d\n", pid);
> return 0;
> }
>
> ---
> ---
> arch/x86/entry/syscalls/syscall_32.tbl | 1 +
> arch/x86/entry/syscalls/syscall_64.tbl | 1 +
> include/linux/syscalls.h | 4 ++
> include/uapi/linux/sched.h | 7 ++++
> kernel/pid_namespace.c | 64 ++++++++++++++++++++++++++++++++
> kernel/sys_ni.c | 3 ++
> 6 files changed, 80 insertions(+)
>
> diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
> index c58f75b088c5..aef52c709845 100644
> --- a/arch/x86/entry/syscalls/syscall_32.tbl
> +++ b/arch/x86/entry/syscalls/syscall_32.tbl
> @@ -391,3 +391,4 @@
> 382 i386 pkey_free sys_pkey_free
> 383 i386 statx sys_statx
> 384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl
> +385 i386 translate_pid sys_translate_pid
> diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
> index 5aef183e2f85..1ebdab83c6f4 100644
> --- a/arch/x86/entry/syscalls/syscall_64.tbl
> +++ b/arch/x86/entry/syscalls/syscall_64.tbl
> @@ -339,6 +339,7 @@
> 330 common pkey_alloc sys_pkey_alloc
> 331 common pkey_free sys_pkey_free
> 332 common statx sys_statx
> +333 common translate_pid sys_translate_pid
>
> #
> # x32-specific system call numbers start at 512 to avoid cache impact
> diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
> index b961184f597a..d189a1f61160 100644
> --- a/include/linux/syscalls.h
> +++ b/include/linux/syscalls.h
> @@ -553,6 +553,10 @@ asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
> /* kernel/printk.c */
> asmlinkage long sys_syslog(int type, char __user *buf, int len);
>
> +/* kernel/pid_namespace.c */
> +asmlinkage long sys_translate_pid(pid_t pid, int source_type, int source,
> + int target_type, int target);
> +
> /* kernel/ptrace.c */
> asmlinkage long sys_ptrace(long request, long pid, unsigned long addr,
> unsigned long data);
> diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
> index 22627f80063e..7c45fd8d33d7 100644
> --- a/include/uapi/linux/sched.h
> +++ b/include/uapi/linux/sched.h
> @@ -55,4 +55,11 @@
> SCHED_FLAG_RECLAIM | \
> SCHED_FLAG_DL_OVERRUN)
>
> +/*
> + * For translate_pid()
> + */
> +#define TRANSLATE_PID_CURRENT_PIDNS 0 /* Current pid namespace */
> +#define TRANSLATE_PID_TASK_PIDNS 1 /* Namespace by task pid */
> +#define TRANSLATE_PID_FD_PIDNS 2 /* Namespace by pidns fd */
> +
> #endif /* _UAPI_LINUX_SCHED_H */
> diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
> index 2a2ac53d8b8b..84c8b47289d5 100644
> --- a/kernel/pid_namespace.c
> +++ b/kernel/pid_namespace.c
> @@ -13,6 +13,7 @@
> #include <linux/user_namespace.h>
> #include <linux/syscalls.h>
> #include <linux/cred.h>
> +#include <linux/file.h>
> #include <linux/err.h>
> #include <linux/acct.h>
> #include <linux/slab.h>
> @@ -380,6 +381,69 @@ static void pidns_put(struct ns_common *ns)
> put_pid_ns(to_pid_ns(ns));
> }
>
> +/* Under rcu_read_lock(). Returns pointer to pid_namespace or NULL. */
> +static struct pid_namespace *resolve_pid_ns(int type, int fd_or_pid)
> +{
> + struct pid_namespace *current_ns = task_active_pid_ns(current);
> + struct pid_namespace *pidns = NULL;
> + struct ns_common *ns;
> + struct file *file;
> +
> + switch (type) {
> + case TRANSLATE_PID_CURRENT_PIDNS:
> + pidns = current_ns;
> + break;
> + case TRANSLATE_PID_TASK_PIDNS:
> + pidns = ns_of_pid(find_pid_ns(fd_or_pid, current_ns));
> + break;
> + case TRANSLATE_PID_FD_PIDNS:
> + file = proc_ns_fget(fd_or_pid);
> + if (!IS_ERR(file)) {
> + ns = get_proc_ns(file_inode(file));
> + if (ns->ops->type == CLONE_NEWPID)
> + pidns = to_pid_ns(ns);
> + fput(file);
> + }
> + break;
> + }
> +
> + return pidns;
> +}
> +
> +/*
> + * translate_pid - convert pid in source pid-ns into target pid-ns.
> + * @pid: pid for translation
> + * @source_type: one of TRANSLATE_PID_*
> + * @source: depending on @source_type pid-ns fd, pid, or nothing
> + * @target_type: one of TRANSLATE_PID_*
> + * @target: depending on @target_type pid-ns fd, pid, or nothing
> + *
> + * Returns pid in @target pid-ns, zero if task have no pid there,
> + * or -ESRCH if task with @pid does not found in @source pid-ns,
> + * or -EINVAL if @source or @target couldn't be resolved into pid-ns.
> + */
> +SYSCALL_DEFINE5(translate_pid, pid_t, pid,
> + int, source_type, int, source,
> + int, target_type, int, target)
> +{
> + struct pid_namespace *source_ns, *target_ns;
> + struct pid *struct_pid;
> + pid_t result = -EINVAL;
> +
> + rcu_read_lock();
> + source_ns = resolve_pid_ns(source_type, source);
> + if (!source_ns)
> + goto out;
> + target_ns = resolve_pid_ns(target_type, target);
> + if (!target_ns)
> + goto out;
> + struct_pid = find_pid_ns(pid, source_ns);
> + result = struct_pid ? pid_nr_ns(struct_pid, target_ns) : -ESRCH;
> +out:
> + rcu_read_unlock();
> + return result;
> +}
> +
> static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns)
> {
> struct pid_namespace *active = task_active_pid_ns(current);
> diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
> index 6cafc008f6db..777689bce406 100644
> --- a/kernel/sys_ni.c
> +++ b/kernel/sys_ni.c
> @@ -146,6 +146,9 @@ COND_SYSCALL(delete_module);
> /* kernel/printk.c */
> COND_SYSCALL(syslog);
>
> +/* kernel/pid_namespace.c */
> +COND_SYSCALL(sys_translate_pid);
> +
> /* kernel/ptrace.c */
>
> /* kernel/sched/core.c */
>
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 20:18 UTC (permalink / raw)
To: tglx
Cc: pjones, luto, David Howells, Ard Biesheuvel, jmorris, Alan Cox,
Linus Torvalds, Greg Kroah-Hartman, Linux Kernel Mailing List,
jforbes, linux-man, jlee, LSM List, linux-api, Kees Cook,
linux-efi
In-Reply-To: <alpine.DEB.2.21.1804042148480.1492@nanos.tec.linutronix.de>
On Wed, Apr 4, 2018 at 1:01 PM Thomas Gleixner <tglx@linutronix.de> wrote:
> Now where the disagreement lies is the way how the uid/ring0 aspect is
tied
> to secure boot, which makes it impossible to be useful independent of
> Secure Boot.
It doesn't - you can pass a command line parameter that enables it, or your
bootloader can set the bootparams flag. I don't see a fundamental problem
with offering the opportunity to change it at runtime, other than that some
stuff that was previously initialised may have to be torn down. The reason
for having the UEFI boot stub *optionally* check the secure boot state
itself and make a policy decision (rather than having the signed bootloader
do so) is because the kernel can be launched directly by the firmware.
^ permalink raw reply
* Re: [PATCH v4 04/24] fpga: add device feature list support
From: Alan Tull @ 2018-04-04 20:06 UTC (permalink / raw)
To: Wu Hao
Cc: Moritz Fischer, linux-fpga, linux-kernel, linux-api, Kang, Luwei,
Zhang, Yi Z, Tim Whisonant, Enno Luebbers, Shiva Rao,
Christopher Rauer, Xiao Guangrong
In-Reply-To: <20180403013646.GA31760@hao-dev>
On Mon, Apr 2, 2018 at 8:36 PM, Wu Hao <hao.wu@intel.com> wrote:
> On Mon, Apr 02, 2018 at 02:06:56PM -0500, Alan Tull wrote:
>> On Sun, Apr 1, 2018 at 11:22 PM, Wu Hao <hao.wu@intel.com> wrote:
>> > On Thu, Mar 29, 2018 at 04:57:22PM -0500, Alan Tull wrote:
>> >> On Mon, Mar 26, 2018 at 9:35 PM, Wu Hao <hao.wu@intel.com> wrote:
>> >>
>> >> Hi Hao,
>> >>
>> >> Currently there is one set of functions that handles port enable,
>> >> disable, and reset and it's in dfl.c and dfl.h, so that's not in any
>> >> driver module that can be switched out if necessary for a different
>> >> implementation of the port. Finding a way for this patchset to be
>> >> structured for DFL to control what low level manager/port drivers are
>> >> used is the current challenge that I've got a lot of my attention on.
>> >>
>> >> Thanks for the explanations on how virtualization affects how this can
>> >> be implemented.
>> >>
>> >> > On Mon, Mar 26, 2018 at 12:21:23PM -0500, Alan Tull wrote:
>> >> >> On Thu, Mar 22, 2018 at 11:33 PM, Wu Hao <hao.wu@intel.com> wrote:
>> >> >>
>> >> >> >> > +
>> >> >> >> > +/*
>> >> >> >> > + * This function resets the FPGA Port and its accelerator (AFU) by function
>> >> >> >> > + * __fpga_port_disable and __fpga_port_enable (set port soft reset bit and
>> >> >> >> > + * then clear it). Userspace can do Port reset at any time, e.g during DMA
>> >> >> >> > + * or Partial Reconfiguration. But it should never cause any system level
>> >> >> >> > + * issue, only functional failure (e.g DMA or PR operation failure) and be
>> >> >> >> > + * recoverable from the failure.
>> >> >> >> > + *
>> >> >> >> > + * Note: the accelerator (AFU) is not accessible when its port is in reset
>> >> >> >> > + * (disabled). Any attempts on MMIO access to AFU while in reset, will
>> >> >> >> > + * result errors reported via port error reporting sub feature (if present).
>> >> >> >> > + */
>> >> >> >> > +static inline int __fpga_port_reset(struct platform_device *pdev)
>> >> >> >> > +{
>> >> >> >> > + int ret;
>> >> >> >> > +
>> >> >> >> > + ret = __fpga_port_disable(pdev);
>> >> >> >> > + if (ret)
>> >> >> >> > + return ret;
>> >> >> >> > +
>> >> >> >> > + __fpga_port_enable(pdev);
>> >> >> >> > +
>> >> >> >> > + return 0;
>> >> >> >> > +}
>> >> >> >> > +
>> >> >> >> > +static inline int fpga_port_reset(struct platform_device *pdev)
>> >> >> >> > +{
>> >> >> >> > + struct feature_platform_data *pdata = dev_get_platdata(&pdev->dev);
>> >> >> >> > + int ret;
>> >> >> >> > +
>> >> >> >> > + mutex_lock(&pdata->lock);
>> >> >> >> > + ret = __fpga_port_reset(pdev);
>> >> >> >> > + mutex_unlock(&pdata->lock);
>> >> >> >> > +
>> >> >> >> > + return ret;
>> >> >> >> > +}
>> >> >> >>
>> >> >> >> I'm still scratching my head about how the enumeration code also has
>> >> >> >> code that handles resetting the PL in a FPGA region and
>> >> >> >> enabling/disabling the bridge. We've discussed this before [1] and I
>> >> >> >> know you've looked into it, I'm still trying to figure out how this
>> >> >> >> can be made modular, so when someone needs to support a different port
>> >> >> >> in the future, it isn't a complete rewrite.
>> >> >> >>
>> >> >> >> Speaking of resets, one way forward would be to create a reset
>> >> >> >> controller for the port (and if possible move the port code to the
>> >> >> >> bridge platform driver). The current linux-next repo adds support for
>> >> >> >> reset lookups, so that reset controllers are supported for non-DT
>> >> >> >> platforms [2].
>> >> >> >>
>> >> >> >> So the bridge driver would implement the enable/disable functions and
>> >> >> >> create a reset controller, the fpga-region (or whoever else needs it)
>> >> >> >> could look the reset controller and use the reset. By using the
>> >> >> >> kernel reset framework, we don't have to have that piece of code
>> >> >> >> shared around by having a reset function in a .h file. And it avoids
>> >> >> >> adding extra dependencies between modules. Also, where necessary, I'd
>> >> >> >> rather add functionality to the existing bridge/mgr/region frameworks,
>> >> >> >> adding common interfaces at that level to allow reuse (like adding
>> >> >> >> status to fpga-mgr). Ideally, this DFL framework would sit on top of
>> >> >> >> mgr and bridge and allow those to be swapped out for reuse of the DFL
>> >> >> >> framework on other devices. Also it will save future headaches as mgr
>> >> >> >> or port implementations evolve.
>> >> >> >
>> >> >> > Thanks a lot for the suggestion. I really really appreciate this.
>> >> >>
>> >> >> Yes, this is a good discussion, thanks.
>> >> >>
>> >> >> >
>> >> >> > Actually if we consider the virutalization case as I mentioned in [1] below,
>> >> >> > that means AFU and its Port will be turned into a PCI VF and assigned (passed
>> >> >> > through) to a virtual machine. There is no FME block on that PCI VF device,
>> >> >> > (the FME is always kept in PCI PF device in the host) and currently the bridge
>> >> >> > is created by FME module for PR functionatily. So in the guest virtual machine,
>> >> >> > nobody creates the reset controller actually.
>> >> >> >
>> >> >> > As I mentioned in [1], one possible method is, put these port reset functions to
>> >> >> > AFU (Port) module, and share those functions with FME bridge module.
>> >> >>
>> >> >> Yes, the port reset functions could move into an AFU driver, and then
>> >> >> also the AFU driver could also create a reset controller and register
>> >> >> a lookup [2] for the reset. That would be just a few lines of code.
>> >> >> The reset controller would control enabling/disabling the port. The
>> >> >> bridge driver could get the reset controller to use during FPGA
>> >> >> programming. That is instead of sharing a reset function with the
>> >> >> bridge driver. It decouples the FPGA bridge driver and simplifies it
>> >> >> to be something that just needs to control a reset instead of needing
>> >> >> to include a specific .h file that makes a port reset function
>> >> >> available.
>> >> >
>> >> > Hi Alan
>> >> >
>> >> > Thanks a lot for the feedback. :)
>> >> >
>> >> > The major concern here is, for virtualization case, after we enable the SRIOV
>> >> > to create VFs, AFUs(and ports) are turned into VFs from PF. Once AFUs are moved
>> >> > from PF to VFs, then we should remove all related user interfaces exported by
>> >> > the afu platform device under PF by unregistering these platform devices from
>> >> > the system. So in this case the reset controller created by the AFU platform
>> >> > driver, should be removed when the AFU platform devices are deleted from the
>> >> > system in this case, but we still have FME and FME bridge present on PF, then
>> >> > FME bridge can't find the reset controller any longer to do port enable/disable.
>> >>
>> >> OK
>> >>
>> >> >
>> >> > Sorry, I found my previous description is not accurate.
>> >> >
>> >> > VFs could be passed through to a virtual machine, if we let AFU/Port create
>> >> > reset controller, then the reset controllers are created in the virtual machine.
>> >> > And FME is always in PF in the host, so FME bridge in host have no access to the
>> >> > reset controllers in the virtual machine.
>> >>
>> >> Thanks for the explanation. Does the current implementation allows
>> >> the port's PORT_CTRL_SFTRST reset bit to be controlled by PF and VF at
>> >> the same time?
>> >
>> > Yes, it allows it to be accessed by PF and VF at the same time, only for Port
>> > Registers, not for AFU registers (any access will cause errors reported by HW).
>>
>> OK that explains a lot.
>>
>> >
>> >> Or is the idea that the VF has to be given up in order to allow the FME PF to
>> >> be able to reprogram?
>> >
>> > Without any notification mechanism between PF and VFs, the safe way of doing the
>> > PR to AFUs (accelerators) on VFs is, 1) hot-unplug the AFU (VF) from the VM,
>> > 2) turn the AFU back to PF from VF, 3) PR to the AFU on PF, 4) turn that AFU to
>> > VF again, 5) hot-plug the AFU (VF) to target VM again. We tested this flow, it
>> > works and doesn't need to shutdown the VM.
>>
>> That sounds like a lot of trouble.
>
> Without notification mechanism, this is the safe way of doing PR. We can't PR a
> AFU (assigned to VM) directly without any notification to VM, as VM owns this
> device (AFU). SW works on guest may get troubles if PR is done at unexpected
> time. For above flow, it's just the pcie hot plug function, and we tested it
> works fine as we expected.
>
>>
>> > But once we have implemented some
>> > methods to notification between PF and VFs, we don't have to do these steps.
>>
>> See below. Let's get aligned with what we're trying to architect first.
>
> Sure.
>
>>
>> >
>> >> After the AFU and port is turned into a VF, is the port's memory range is
>> >> mapped in both the PF and the VF?
>> >
>> > Yes.
>> >
>> >>
>> >> >
>> >> >>
>> >> >> > I think
>> >> >> > that will make the code in the common DFL framework a little more clean,
>> >> >>
>> >> >> Yes, IIUC that may also make it easier as the port/AFU gets added
>> >> >> functionality that is intended to be controlled by the VF anyway
>> >> >> (while the only port-related thing that is needed by the FME is port
>> >> >> enable/disable).
>> >> >>
>> >> >> > but it
>> >> >> > will introduce some module dependency here for sure, (e.g FME modules can't
>> >> >> > finish PR without AFU (Port) Module loaded).
>> >> >>
>> >> >> That sounds like an OK type of dependency, i.e. if the modules are not
>> >> >> all loaded, it doesn't work. :-)
>> >> >
>> >> > Find a reset controller by lookup, if not found, return error code. It seems
>> >> > not a really hard module dependency between port/afu and FME bridge modules.
>> >>
>> >> That was what I was hoping would work here. But if the module isn't
>> >> loaded because it failed due to the reset controller in the AFU driver
>> >> went away, then, yes, that won't work.
>> >>
>> >> > But if in FME bridge, it uses functions exposed by port/afu module, that's a
>> >> > hard dependency. : )
>> >>
>> >> Yes I'm trying to find ways to get away from that kind of hard
>> >> dependency. So when someone uses this with a different port, it won't
>> >> be a huge rewrite of dfl.c and dfl.h. I understand that the port is
>> >> used by both the AFU and the PR code, that's why it's in a file that
>> >> is included by both of them. That's going to be a problem as soon as
>> >> this is used with a different port.
>> >
>> > or we could add some callbacks, and let port driver register its own function
>> > for enable/disable operation? But then dfl.c / dfl.h will still see some common
>> > port code there.
>> >
>> >>
>> >> >
>> >> > I can try to move related code to afu/port driver instead in the next version
>> >> > for sure, but I can't create the reset controller per the reason above. Please
>> >> > let me know if more thoughts on this. : )
>> >>
>> >> Maybe that is the way forward. I'm still thinking about this. So the
>> >> DFL will create a AFU driver that includes the port. If someone
>> >> implements a different port, there would be a different id to cause
>> >> that AFU driver to be loaded instead. It seems a shame that more of
>> >> the AFU code couldn't be reused. That was the original idea of
>> >> fpga-bridge. Unfortunately it seems that the bridge is needed by both
>> >> the VF and PF so it's complicated by that.
>> >>
>> >> >
>> >> >>
>> >> >> > But anyway it may be still
>> >> >> > acceptable for users as all these modules could be loaded automatically. How do
>> >> >> > you think? :)
>> >> >>
>> >> >> The other thing I want to get right now is if there is a different
>> >> >> AFU/port that needs a different driver. Can the DFL be changed to
>> >> >> specify what AFU/port to load? I really really want to avoid large
>> >> >> code rewrites in the future that we can anticipate now. Such as
>> >> >> someone implements their own static image, it has DFL, but the port is
>> >> >> somewhat different. Instead of seeing features as just something that
>> >> >> gets added, the DFL also specifies what port driver and mgr driver to
>> >> >> load. The stuff we discussed above is a good step towards that, but
>> >> >> not all of it.
>> >> >
>> >> > I'm not sure if any vendor
>> >>
>> >> Since this is open source, it's important to remember that vendors
>> >> aren't the only ones driving development of Linux. Any user of FPGA
>> >> under Linux can (and has) come along and add to this subsystem. This
>> >> code should not discourage that.
>> >
>> > Agree.
>> >
>> >>
>> >> > wants to create a totally different port here, if
>> >> > yes, then it could have a different feature id in Device Feature Header (DFH).
>> >> > I think it's possible to use that feature id to decide which driver to load
>> >> > (or which platform device to create).
>> >>
>> >> I think it's what we need.
>> >
>> > Yes.
>> >
>> >>
>> >> > But vendors don't have to do that, as it
>> >> > could reuse current port driver and private features added already, or even
>> >> > add some new vendor specific private feature under the port to save cost.
>> >>
>> >> They would have to implement a static image with port registers that
>> >> function the same way for at least port enable/disable/reset. If they
>> >> need to tweak the driver implementation for their hardware then that's
>> >> not possible or it's ugly at least.
>> >
>> > Agree, in that case, it's better to use a new feature id with a different
>> > port implementation.
>> >
>> >> This is also the case if you have some newer version of you port while
>> >> keeping legacy support for your original port.
>> >
>> > In Device Feature Header, there is a field to indicate the revision of
>> > this Port (private feature has revision bit in DFH too). But we should
>> > not use this field to indicate a totally different implementation.
>> >
>> >>
>> >> I understand that virtualization is making this hard. Thanks for
>> >> thinking about how this can move forward on this issue.
>> >
>> > Yes, I will try to move the actual port related code into AFU/port driver
>> > in the next version, thanks for the comments and suggestions.
>>
>> I have some serious doubts that's the direction to go in. Before you
>> do a lot of work in that direction, let me explain again the larger
>> context and what's motivating my comments.
>>
>> The point of having a FPGA framework (fpga-bridge.c, fpga-manager.c,
>> and fpga-region.c) is to separate the layers above the framework
>> (enumeration and interfaces) from the layer below the framework (low
>> level FPGA bridge/manager/region drivers). The layer above and the
>> layer below shouldn't share code or talk directly to each other. That
>> kind of workaround defeats the purpose of having a framework and
>> prevents reuse. If you need a workaround like that, it's probably a
>> case where the framework needs some added functionality that's
>> generally usable. For example, we've run into that before, in v1,
>> your FPGA manager driver was returning status via its private data.
>> We discussed it and added status to the fpga-mgr framework so you
>> wouldn't need to do that.
>>
>> So implementing fpga_port_enable in the enumeration code and then
>> accessing that code in both the AFU code (upper layer) and the FME
>> bridge driver (lower layer) beaks the model. When an implementation
>> works around a framework to do what it wants, that mean that none of
>> that implementation is reusable. A lot of this review has been me
>> trying to understand and untangle that. I'm trying to guide the
>> development of the FPGA framework to have reusibility.
>>
>> The 'port' is really what the existing FPGA framework calls an FPGA
>> bridge (with added functionality). The port code should go into the
>> bridge driver dfl-fme-br.c. There will need to be some new
>> functionality needed for fpga-bridge.c to be able to do what you want
>> - some way of making a reset function available for VF while
>> enable/disable is still available as PF for the fpga-region.c to
>> control.
>
> Understand, actually I have considered to move bridge creation from FME
> to Port, but it's facing the same problem as reset controller, as port
> platform device should be unregisted from system in virtualization case.
> Let me consider further to see if any better approach on this implementation.
> May be back to this thread later for discussion.
It appears that a lot of effort is going into working around the
current BBS limitations with regards to virtualization. One direct
way for this all to move forward would be to defer virtualization
support for later. That would involve moving the port code to
dfl-fme-br.c and adding resets to the fpga-bridge framework for the
AFU. (Also add selection of low level mgr and br driver to DFL).
That gets something working that is modular, just doesn't include
virtualization for the moment.
Alan
>
> Thanks
> Hao
>
>>
>> Thanks,
>> Alan
>>
>> >
>> > Thanks
>> > Hao
>> >
>> >>
>> >> Alan
>> >>
>> >> >
>> >> > Thanks
>> >> > Hao
>> >> >
>> >> >>
>> >> >> Alan
>> >> >>
>> >> >> >
>> >> >> > Thanks
>> >> >> > Hao
>> >> >> >
>> >> >> >
>> >> >> >>
>> >> >> >> Alan
>> >> >> >>
>> >> >> >> [1] https://lkml.org/lkml/2017/12/22/398
>> >> >> >> [2] https://patchwork.kernel.org/patch/10247475/
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Thomas Gleixner @ 2018-04-04 20:01 UTC (permalink / raw)
To: Peter Jones
Cc: Andy Lutomirski, Matthew Garrett, David Howells, Ard Biesheuvel,
James Morris, Alan Cox, Linus Torvalds, Greg Kroah-Hartman,
Linux Kernel Mailing List, Justin Forbes, linux-man, joeyli,
LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <20180404184255.exdrtpqnxlqme7tl@redhat.com>
On Wed, 4 Apr 2018, Peter Jones wrote:
> That is to say, as a result of the way malware has been written, our way
> of thinking about it is often that it's a way to build a boot loader for
> a malicious kernel, so that's how we wind up talking about it. Are we
> concerned with malware stealing your data? Yes, but Secure Boot is only
> indirectly about that. It's primarily about denying the malware easy
> mechanisms to build a persistence mechanism. The uid-0 != ring-0 aspect
> is useful independent of Secure Boot, but Secure Boot without it falls
> way short of accomplishing its goal.
I think we can all agree that
The uid-0 != ring-0 aspect is useful independent of Secure Boot
There is probably resonable consensus about the second part of this
sentence as well:
but Secure Boot without it falls way short of accomplishing its goal.
Now where the disagreement lies is the way how the uid/ring0 aspect is tied
to secure boot, which makes it impossible to be useful independent of
Secure Boot.
So the real question is, how can we make 'lockdown' usable and useful
without Secure Boot and at the same time not violate the constraints of
the Secure Boot scenario.
If we can agree on the above then I hope that we can focus on the technical
problems instead of arguing in circles.
Thanks,
tglx
^ permalink raw reply
* [PATCH RFC v5] pidns: introduce syscall translate_pid
From: Konstantin Khlebnikov @ 2018-04-04 19:11 UTC (permalink / raw)
To: linux-api, linux-kernel
Cc: Jann Horn, Serge Hallyn, Oleg Nesterov, Andy Lutomirski,
Nagarathnam Muthusamy, Eric W. Biederman, Prakash Sangappa,
Andrew Morton
Each process have different pids, one for each pid namespace it belongs.
When interaction happens within single pid-ns translation isn't required.
More complicated scenarios needs special handling.
For example:
- reading pid-files or logs written inside container with pid namespace
- attaching with ptrace to tasks from different pid namespace
- passing pids across pid namespaces in any kind of API
Currently there are several interfaces that could be used here:
Pid namespaces are identified by inode number of /proc/[pid]/ns/pid.
Pids for nested Pid namespaces are shown in file /proc/[pid]/status.
In some cases conversion pid -> vpid could be easily done using this
information, but backward translation requires scanning all tasks.
Unix socket automatically translates pid attached to SCM_CREDENTIALS.
This requires CAP_SYS_ADMIN for sending arbitrary pids and entering
into pid namespace, this expose process and could be insecure.
This patch adds new syscall for converting pids between pid namespaces:
pid_t translate_pid(pid_t pid, int source_type, int source,
int target_type, int target);
@source_type and @target_type defines type of following arguments:
TRANSLATE_PID_CURRENT_PIDNS - current pid namespace, argument is unused
TRANSLATE_PID_TASK_PIDNS - task pid-ns, argument is task pid
TRANSLATE_PID_FD_PIDNS - pidns fd, argument is file descriptor
Syscall returns pid in target pid-ns or zero if task have no pid there.
Error codes:
-EINVAL - @source or @target couldn't be resolved into pid namespace
-ESRCH - task with @pid is not found in @source pid-namespace
Other pid namespaces are referenced either by pid of any process who
lives inside it or by file descriptor pointing to /proc/[pid]/ns/pid.
Latter method provides better protection against races but in some
cases requires CAP_SYS_PTRACE.
Translate_pid could breach pid isolation and return pids from outer pid
namespaces iff process already has file descriptor pointing to them.
Examples:
- get pid in current pid namespace
translate_pid(pid, TRANSLATE_PID_FD_PIDNS, ns_fd,
TRANSLATE_PID_CURRENT_PIDNS, 0)
or
translate_pid(pid, TRANSLATE_PID_TASK_PIDNS, ns_pid,
TRANSLATE_PID_CURRENT_PIDNS, 0)
- get pid in other pid namespace
translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
TRANSLATE_PID_FD_PIDNS, ns_fd)
or
translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
TRANSLATE_PID_TASK_PIDNS, ns_pid)
- get deepest pid
translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
TRANSLATE_PID_TASK_PIDNS, pid)
- get pid of init task for namespace
translate_pid(1, TRANSLATE_PID_FD_PIDNS, ns_fd,
TRANSLATE_PID_CURRENT_PIDNS, 0)
This syscall also could be used for checking topology of pid namespaces:
- ns1 nests inside ns2
translate_pid(1, TRANSLATE_PID_FD_PIDNS, ns1_fd,
TRANSLATE_PID_FD_PIDNS, ns2_fd) > 1
- task1 lives in same pid-namespace as task2
translate_pid(1, TRANSLATE_PID_TASK_PIDNS, task1_pid,
TRANSLATE_PID_TASK_PIDNS, task2_pid) == 1
- task1 is isolated from task2
translate_pid(task1_pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
TRANSLATE_PID_TASK_PIDNS, task2_pid) == 0
- pid is reachable from ns
translate_pid(pid, TRANSLATE_PID_CURRENT_PIDNS, 0,
TRANSLATE_PID_FD_PIDNS, ns_fd) > 0
Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
---
v1: https://lkml.org/lkml/2015/9/15/411
v2: https://lkml.org/lkml/2015/9/24/278
* use namespace-fd as second/third argument
* add -pid for getting parent pid
* move code into kernel/sys.c next to getppid
* drop ifdef CONFIG_PID_NS
* add generic syscall
v3: https://lkml.org/lkml/2015/9/28/3
* use proc_ns_fdget()
* update description
* rebase to next-20150925
* fix conflict with mlock2
v4: https://lkml.org/lkml/2017/10/16/852
* rename into translate_pid()
* remove syscall if CONFIG_PID_NS=n
* drop -pid for parent task
* drop fget-fdget optimizations
* add helper get_pid_ns_by_fd()
* wire only into x86
v5:
* rewrite commit message
* resolve pidns by task pid or by pidns fd
* add arguments source_type and target_type
--- sample tool translate_pid.c ---
#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sched.h>
#include <fcntl.h>
#include <err.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#ifndef SYS_translate_pid
#ifdef __x86_64__
#define SYS_translate_pid 333
#endif
#endif
#ifndef TRANSLATE_PID_CURRENT_PIDNS
#define TRANSLATE_PID_CURRENT_PIDNS 0
#define TRANSLATE_PID_TASK_PIDNS 1
#define TRANSLATE_PID_FD_PIDNS 2
#endif
pid_t translate_pid(pid_t pid, int source_type, int source,
int target_type, int target) {
return syscall(SYS_translate_pid, pid, source_type, source,
target_type, target);
}
int main(int argc, char **argv) {
int pid, source, target;
char buf[64];
if (argc != 4)
errx(1, "usage: %s <pid> <source> <traget>", argv[0]);
pid = atoi(argv[1]);
int source_type, target_type;
source = atoi(argv[2]);
target = atoi(argv[3]);
if (source < 0) {
source_type = TRANSLATE_PID_TASK_PIDNS;
source = -source;
} else if (source > 0) {
source_type = TRANSLATE_PID_FD_PIDNS;
sprintf(buf, "/proc/%d/ns/pid", source);
source = open(buf, O_RDONLY);
if (source < 0)
err(2, "open source %s", buf);
} else {
source_type = TRANSLATE_PID_CURRENT_PIDNS;
}
if (target < 0) {
target_type = TRANSLATE_PID_TASK_PIDNS;
target = -target;
} else if (target > 0) {
target_type = TRANSLATE_PID_FD_PIDNS;
sprintf(buf, "/proc/%d/ns/pid", target);
target = open(buf, O_RDONLY);
if (target < 0)
err(2, "open target %s", buf);
} else {
target_type = TRANSLATE_PID_CURRENT_PIDNS;
}
pid = translate_pid(pid, source_type, source, target_type, target);
if (pid < 0)
err(2, "translate");
printf("%d\n", pid);
return 0;
}
---
---
arch/x86/entry/syscalls/syscall_32.tbl | 1 +
arch/x86/entry/syscalls/syscall_64.tbl | 1 +
include/linux/syscalls.h | 4 ++
include/uapi/linux/sched.h | 7 ++++
kernel/pid_namespace.c | 64 ++++++++++++++++++++++++++++++++
kernel/sys_ni.c | 3 ++
6 files changed, 80 insertions(+)
diff --git a/arch/x86/entry/syscalls/syscall_32.tbl b/arch/x86/entry/syscalls/syscall_32.tbl
index c58f75b088c5..aef52c709845 100644
--- a/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/arch/x86/entry/syscalls/syscall_32.tbl
@@ -391,3 +391,4 @@
382 i386 pkey_free sys_pkey_free
383 i386 statx sys_statx
384 i386 arch_prctl sys_arch_prctl compat_sys_arch_prctl
+385 i386 translate_pid sys_translate_pid
diff --git a/arch/x86/entry/syscalls/syscall_64.tbl b/arch/x86/entry/syscalls/syscall_64.tbl
index 5aef183e2f85..1ebdab83c6f4 100644
--- a/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/arch/x86/entry/syscalls/syscall_64.tbl
@@ -339,6 +339,7 @@
330 common pkey_alloc sys_pkey_alloc
331 common pkey_free sys_pkey_free
332 common statx sys_statx
+333 common translate_pid sys_translate_pid
#
# x32-specific system call numbers start at 512 to avoid cache impact
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index b961184f597a..d189a1f61160 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -553,6 +553,10 @@ asmlinkage long sys_clock_nanosleep(clockid_t which_clock, int flags,
/* kernel/printk.c */
asmlinkage long sys_syslog(int type, char __user *buf, int len);
+/* kernel/pid_namespace.c */
+asmlinkage long sys_translate_pid(pid_t pid, int source_type, int source,
+ int target_type, int target);
+
/* kernel/ptrace.c */
asmlinkage long sys_ptrace(long request, long pid, unsigned long addr,
unsigned long data);
diff --git a/include/uapi/linux/sched.h b/include/uapi/linux/sched.h
index 22627f80063e..7c45fd8d33d7 100644
--- a/include/uapi/linux/sched.h
+++ b/include/uapi/linux/sched.h
@@ -55,4 +55,11 @@
SCHED_FLAG_RECLAIM | \
SCHED_FLAG_DL_OVERRUN)
+/*
+ * For translate_pid()
+ */
+#define TRANSLATE_PID_CURRENT_PIDNS 0 /* Current pid namespace */
+#define TRANSLATE_PID_TASK_PIDNS 1 /* Namespace by task pid */
+#define TRANSLATE_PID_FD_PIDNS 2 /* Namespace by pidns fd */
+
#endif /* _UAPI_LINUX_SCHED_H */
diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c
index 2a2ac53d8b8b..84c8b47289d5 100644
--- a/kernel/pid_namespace.c
+++ b/kernel/pid_namespace.c
@@ -13,6 +13,7 @@
#include <linux/user_namespace.h>
#include <linux/syscalls.h>
#include <linux/cred.h>
+#include <linux/file.h>
#include <linux/err.h>
#include <linux/acct.h>
#include <linux/slab.h>
@@ -380,6 +381,69 @@ static void pidns_put(struct ns_common *ns)
put_pid_ns(to_pid_ns(ns));
}
+/* Under rcu_read_lock(). Returns pointer to pid_namespace or NULL. */
+static struct pid_namespace *resolve_pid_ns(int type, int fd_or_pid)
+{
+ struct pid_namespace *current_ns = task_active_pid_ns(current);
+ struct pid_namespace *pidns = NULL;
+ struct ns_common *ns;
+ struct file *file;
+
+ switch (type) {
+ case TRANSLATE_PID_CURRENT_PIDNS:
+ pidns = current_ns;
+ break;
+ case TRANSLATE_PID_TASK_PIDNS:
+ pidns = ns_of_pid(find_pid_ns(fd_or_pid, current_ns));
+ break;
+ case TRANSLATE_PID_FD_PIDNS:
+ file = proc_ns_fget(fd_or_pid);
+ if (!IS_ERR(file)) {
+ ns = get_proc_ns(file_inode(file));
+ if (ns->ops->type == CLONE_NEWPID)
+ pidns = to_pid_ns(ns);
+ fput(file);
+ }
+ break;
+ }
+
+ return pidns;
+}
+
+/*
+ * translate_pid - convert pid in source pid-ns into target pid-ns.
+ * @pid: pid for translation
+ * @source_type: one of TRANSLATE_PID_*
+ * @source: depending on @source_type pid-ns fd, pid, or nothing
+ * @target_type: one of TRANSLATE_PID_*
+ * @target: depending on @target_type pid-ns fd, pid, or nothing
+ *
+ * Returns pid in @target pid-ns, zero if task have no pid there,
+ * or -ESRCH if task with @pid does not found in @source pid-ns,
+ * or -EINVAL if @source or @target couldn't be resolved into pid-ns.
+ */
+SYSCALL_DEFINE5(translate_pid, pid_t, pid,
+ int, source_type, int, source,
+ int, target_type, int, target)
+{
+ struct pid_namespace *source_ns, *target_ns;
+ struct pid *struct_pid;
+ pid_t result = -EINVAL;
+
+ rcu_read_lock();
+ source_ns = resolve_pid_ns(source_type, source);
+ if (!source_ns)
+ goto out;
+ target_ns = resolve_pid_ns(target_type, target);
+ if (!target_ns)
+ goto out;
+ struct_pid = find_pid_ns(pid, source_ns);
+ result = struct_pid ? pid_nr_ns(struct_pid, target_ns) : -ESRCH;
+out:
+ rcu_read_unlock();
+ return result;
+}
+
static int pidns_install(struct nsproxy *nsproxy, struct ns_common *ns)
{
struct pid_namespace *active = task_active_pid_ns(current);
diff --git a/kernel/sys_ni.c b/kernel/sys_ni.c
index 6cafc008f6db..777689bce406 100644
--- a/kernel/sys_ni.c
+++ b/kernel/sys_ni.c
@@ -146,6 +146,9 @@ COND_SYSCALL(delete_module);
/* kernel/printk.c */
COND_SYSCALL(syslog);
+/* kernel/pid_namespace.c */
+COND_SYSCALL(sys_translate_pid);
+
/* kernel/ptrace.c */
/* kernel/sched/core.c */
^ permalink raw reply related
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Peter Jones @ 2018-04-04 18:42 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Matthew Garrett, David Howells, Ard Biesheuvel, James Morris,
Alan Cox, Linus Torvalds, Greg Kroah-Hartman,
Linux Kernel Mailing List, Justin Forbes, linux-man, joeyli,
LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <CALCETrVR_EcbKv5-4AR6Zm02XHhJQQGNDeO8FGkMbYozmuDTJw@mail.gmail.com>
On Tue, Apr 03, 2018 at 02:51:23PM -0700, Andy Lutomirski wrote:
> On Tue, Apr 3, 2018 at 12:29 PM, Matthew Garrett <mjg59@google.com> wrote:
> > On Tue, Apr 3, 2018 at 9:46 AM Andy Lutomirski <luto@kernel.org> wrote:
> >> On Tue, Apr 3, 2018 at 9:29 AM, Matthew Garrett <mjg59@google.com> wrote:
> >> > A kernel that allows users arbitrary access to ring 0 is just an
> >> > overfeatured bootloader. Why would you want secure boot in that case?
> >
> >> To get a chain of trust. I can provision a system with some public
> >> keys, stored in UEFI authenticated variables, such that the system
> >> will only boot a signed image. That signed image, can, in turn, load
> >> a signed (or hashed or otherwise verfified) kernel and a verified
> >> initramfs. The initramfs can run a full system from a verified (using
> >> dm-verity or similar) filesystem, for example. Now it's very hard to
> >> persistently attack this system. Chromium OS does something very much
> >> like this, except that it doesn't use UEFI as far as I know. So does
> >> iOS, and so do some Android versions. None of this requires lockdown,
> >> or even a separation between usermode and kernelmode, to work
> >> correctly. One could even do this on an MMU-less system if one really
> >> cared to. More usefully, someone probably has done this using a
> >> unikernel.
> >
> > That's only viable if you're the only person with the ability to sign stuff
> > for your machine - the moment there are generic distributions that your
> > machine trusts, an attacker can use one as a bootloader to compromise your
> > trust chain.
>
>
> If you removed "as a bootloader", then I agree with that sentence.
>
> Can someone please explain why the UEFI crowd cares so much about "as
> a bootloader"? Once I'm able to install an OS (Linux kernel +
> bootloader, Windows embedded doodad, OpenBSD, whatever) on your
> machine, I can use your peripherals, read your data, write your data,
> see your keystrokes, use your network connection, re-flash your BIOS
> (at least as well as any OS can), run VMs, and generally own your
> system. Somehow you all seem fine with all of this, except that the
> fact that I can chainload something else gives UEFI people the
> willies.
>
> Can someone explain why?
There's no inherent difference, in terms of the trust chain, between
compromising it to use the machine as a toaster or to run a botnet - the
trust chain is compromised either way. But you're much more likely to
notice if your desktop starts producing bread products than if it hides
some malware and keeps on booting, and the second one is much more
attractive to attackers anyway.
The reason we talk about it as a bootloader is because of the model
employed by malware. I'm sure you know that one kind of malware that
exists in the wild, a so-called "boot kit", operates by modifying a
kernel during load (or on disk before loading) so that it has some
malicious payload, like exfiltrating user data or allowing a way to
install software that the kernel hides or *whatever*, and incorporating
some way to achieve relative persistence on the system - for example
hiding the real boot settings and loading a kernel with a different than
normal initramfs that loads an exploit before continuing with a normal
looking boot.
As Kees has pointed out, the lockdown portion of this is about
separating uid-0 from ring-0. There are a lot of reasons to want to do
that, of course. But the reason Secure Boot exists, and ultimately the
reason we started trying to do this, is so you can't build the
persistence mechanism for a boot kit by using a trusted kernel to
springboard into a modified one, even if it's the same kernel just
modified before kexec. If you can do that, you can use that to build
the persistence mechanism in a boot kit.
That is to say, as a result of the way malware has been written, our way
of thinking about it is often that it's a way to build a boot loader for
a malicious kernel, so that's how we wind up talking about it. Are we
concerned with malware stealing your data? Yes, but Secure Boot is only
indirectly about that. It's primarily about denying the malware easy
mechanisms to build a persistence mechanism. The uid-0 != ring-0 aspect
is useful independent of Secure Boot, but Secure Boot without it falls
way short of accomplishing its goal.
--
Peter
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Justin Forbes @ 2018-04-04 16:46 UTC (permalink / raw)
To: Andy Lutomirski
Cc: Matthew Garrett, Ted Ts'o, David Howells, Linus Torvalds,
Ard Biesheuvel, James Morris, Alan Cox, Greg Kroah-Hartman,
Linux Kernel Mailing List, linux-man, joeyli, LSM List, Linux API,
Kees Cook, linux-efi
In-Reply-To: <CALCETrXwp1faWnqRJ5iLeo6bOOrRS_-L74_xnRAN1Md1YZW8Tg@mail.gmail.com>
On Wed, Apr 4, 2018 at 11:39 AM, Andy Lutomirski <luto@kernel.org> wrote:
> On Wed, Apr 4, 2018 at 9:22 AM, Matthew Garrett <mjg59@google.com> wrote:
>> On Wed, Apr 4, 2018 at 6:52 AM Theodore Y. Ts'o <tytso@mit.edu> wrote:
>>
>>> On Wed, Apr 04, 2018 at 02:33:37PM +0100, David Howells wrote:
>>> > Theodore Y. Ts'o <tytso@mit.edu> wrote:
>>> >
>>> > > Whoa. Why doesn't lockdown prevent kexec? Put another away, why
>>> > > isn't this a problem for people who are fearful that Linux could be
>>> > > used as part of a Windows boot virus in a Secure UEFI context?
>>> >
>>> > Lockdown mode restricts kexec to booting an authorised image (where the
>>> > authorisation may be by signature or by IMA).
>>
>>> If that's true, then Matthew's assertion that lockdown w/o secure boot
>>> is insecure goes away, no?
>>
>> If you don't have secure boot then an attacker with root can modify your
>> bootloader or kernel, and on next boot lockdown can be silently disabled.
>
> This has been rebutted over and over and over. Secure boot is not the
> only verified boot mechanism in the world. Other, better, much more
> auditable, and much simpler mechanisms have been around for a long,
> long time.
>
That is certainly the case, and one of the main reasons for the
secureboot patchset being split out and lockdown taking a different
name. The problem is, right now, secure boot is the only thing using
lockdown. I certainly wouldn't go through any effort to tie into it
with any other mechanism knowing that this patch set has been delayed
upstream for years. I would hope and expect that once lockdown is in
mainline, other verified boot mechanisms would leverage it as well.
>>> The fact that this Verified Boot on, lockdown off causes trouble
>>> points to a clear problem. User owns the hardware they should have
>>> the right to defeat secureboot if they wish to.
>>
>> Which is why Shim allows you to disable validation if you prove physical
>> user presence.
>
> And that's a giant hack. The actual feature should be that a user
> proves physical presence and thus disables lockdown *without*
> disabling verification.
>
> --Andy
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 16:42 UTC (permalink / raw)
To: luto
Cc: tytso, David Howells, Linus Torvalds, Ard Biesheuvel, jmorris,
Alan Cox, Greg Kroah-Hartman, Linux Kernel Mailing List, jforbes,
linux-man, jlee, LSM List, linux-api, Kees Cook, linux-efi
In-Reply-To: <CALCETrXwp1faWnqRJ5iLeo6bOOrRS_-L74_xnRAN1Md1YZW8Tg@mail.gmail.com>
On Wed, Apr 4, 2018 at 9:39 AM Andy Lutomirski <luto@kernel.org> wrote:
> On Wed, Apr 4, 2018 at 9:22 AM, Matthew Garrett <mjg59@google.com> wrote:
> > If you don't have secure boot then an attacker with root can modify your
> > bootloader or kernel, and on next boot lockdown can be silently
disabled.
> This has been rebutted over and over and over. Secure boot is not the
> only verified boot mechanism in the world. Other, better, much more
> auditable, and much simpler mechanisms have been around for a long,
> long time.
Right and if you *know* that you're in that situation then you either turn
it on in bootparams from the verified bootloader (which we can't do in UEFI
because the *firmware* can be the bootloader thanks to the EFI boot stub)
or you enable it from userland later (I can't remember if this version of
the patchset provides that functionality, but a previous one did).
> > Which is why Shim allows you to disable validation if you prove physical
> > user presence.
> And that's a giant hack. The actual feature should be that a user
> proves physical presence and thus disables lockdown *without*
> disabling verification.
That's a completely reasonable feature request.
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Andy Lutomirski @ 2018-04-04 16:39 UTC (permalink / raw)
To: Matthew Garrett
Cc: Ted Ts'o, David Howells, Linus Torvalds, Andrew Lutomirski,
Ard Biesheuvel, James Morris, Alan Cox, Greg Kroah-Hartman,
Linux Kernel Mailing List, Justin Forbes, linux-man, joeyli,
LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <CACdnJuuGRRUt-a3i89o906ka3RDOhs+_7tz_G8LTG8Jc0DXAyQ@mail.gmail.com>
On Wed, Apr 4, 2018 at 9:22 AM, Matthew Garrett <mjg59@google.com> wrote:
> On Wed, Apr 4, 2018 at 6:52 AM Theodore Y. Ts'o <tytso@mit.edu> wrote:
>
>> On Wed, Apr 04, 2018 at 02:33:37PM +0100, David Howells wrote:
>> > Theodore Y. Ts'o <tytso@mit.edu> wrote:
>> >
>> > > Whoa. Why doesn't lockdown prevent kexec? Put another away, why
>> > > isn't this a problem for people who are fearful that Linux could be
>> > > used as part of a Windows boot virus in a Secure UEFI context?
>> >
>> > Lockdown mode restricts kexec to booting an authorised image (where the
>> > authorisation may be by signature or by IMA).
>
>> If that's true, then Matthew's assertion that lockdown w/o secure boot
>> is insecure goes away, no?
>
> If you don't have secure boot then an attacker with root can modify your
> bootloader or kernel, and on next boot lockdown can be silently disabled.
This has been rebutted over and over and over. Secure boot is not the
only verified boot mechanism in the world. Other, better, much more
auditable, and much simpler mechanisms have been around for a long,
long time.
>> The fact that this Verified Boot on, lockdown off causes trouble
>> points to a clear problem. User owns the hardware they should have
>> the right to defeat secureboot if they wish to.
>
> Which is why Shim allows you to disable validation if you prove physical
> user presence.
And that's a giant hack. The actual feature should be that a user
proves physical presence and thus disables lockdown *without*
disabling verification.
--Andy
^ permalink raw reply
* Re: An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: Andy Lutomirski @ 2018-04-04 16:36 UTC (permalink / raw)
To: David Howells
Cc: Andy Lutomirski, Greg Kroah-Hartman, Theodore Y. Ts'o,
Matthew Garrett, Linus Torvalds, Ard Biesheuvel, James Morris,
Alan Cox, Linux Kernel Mailing List, Justin Forbes, linux-man,
joeyli, LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <1119.1522858644@warthog.procyon.org.uk>
On Wed, Apr 4, 2018 at 9:17 AM, David Howells <dhowells@redhat.com> wrote:
> Andy Lutomirski <luto@kernel.org> wrote:
>
>> Since this thread has devolved horribly, I'm going to propose a solution.
>>
>> 1. Split the "lockdown" state into three levels: (please don't
>> bikeshed about the names right now.)
>>
>> LOCKDOWN_NONE: normal behavior
>>
>> LOCKDOWN_PROTECT_INTEGREITY: kernel tries to keep root from writing to
>> kernel memory
>>
>> LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY: kernel tries to keep root from
>> reading or writing kernel memory.
>
> In theory, it's good idea, but in practice it's not as easy to implement as I
> think you think.
[...]
so do your best. The whole lockdown patchset is a best-effort thing,
not a "we did it and it's done" thing.
> Note that /dev/mem can be used to access MMIO devices (I'm not sure about
> /dev/kmem, though). Even reads through /dev/mem can do this. I'm not sure
> whether that's sufficient to actually affect a modification, though.
So turn it off in both modes. /dev/mem is basically obsolete anyway.
Or restrict it to actual memory, or whatever.
>
>> 2. The kexec protocol gets a new flag min_lockdown_level. A kexeced
>> kernel will boot with at least that lockdown level regardless of its
>> configuration. kexec sets min_lockdown_level to the running kernels'
>> lockdown_level. Some future API could allow kexec with a higher
>> min_lockdown_level. An even fancier future API could allow a
>> LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY kernel to kexec with
>> min_lockdown_level == LOCKDOWN_PROTECT_INTEGRITY if there's some
>> mechanism that guarantees that memory gets zeroed in the process.
>
> Note that on x86 we already have an allocated flag for passing the secure boot
> flag from kexec/bootloader to the kernel being booted, and what you're
> proposing ought to be redundant. See boot_params::secure_boot.
Incorrect. Linus is rejecting the idea that secure boot implies
lockdown. I strongly agree with him. I also think that trying to
make security decisions in a kexeced kernel based on whether the
previous kernel was secure booted is a bad idea, so I'm suggesting a
new feature. I don't really care what value is passed in
boot_params::secure_boot for a kexeced kernel, but I think it should
not be used for lockdown.
So I stand by my proposal.
>
>> 3. All the bpf and tracing stuf, etc, gets changed so it only takes
>> effect when LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY is set.
>
> Uh, no. bpf, for example, can be used to modify kernel memory.
Really? If that is, in fact, true, then turn *that* feature off when
LOCKDOWN_PROTECT_INTEGRITY is set.
>> This removes a giant annoyance on distro kernels that are likely to want to
>> enable LOCKDOWN_PROTECT_INTEGRITY.
>
> *shrug* Distros have been running with the full set for a while. I haven't
> seen many complaints.
As Linus noted, that's because a lot of users who care have already
turned off secure boot. Once this whole thing gets sorted out, the
hackish dependence of lockdown and secure boot can go away, so it's
time to think about making lockdown less annoying.
>
>> If you load a key into the kernel, and you want to keep that key safe, you
>> can enable LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY at that time. After all,
>> if root is compromised before that, root can just remember a copu of the key
>> in user memory or email it to someone.
>
> If your key needs to be truly protected, it should never be seen unencrypted
> in userspace, rather it should be decrypted in the TPM and then retained in
> kernel memory only.
You keep making claims like this with no justification whatsoever.
>
>> ...
>> 6. There's a way to *decrease* the lockdown level below the configured
>> value. (This ability itself may be gated by a config option.)
>> Choices include a UEFI protected variable,
>
> By turning secure boot off, maybe?
No.
>
>> an authenticated flag passed by the bootloader,
>
> Authenticated how? How do you stop the running system from passing this to
> the bootloader next time it is run? I guess you're thinking of a bootloader
> "command" that can only be passed by someone sat at a keyboard and never read
> from the config file.
What I meant was some channel that the bootloader can use to securely
communicate options to the running kernel. The concept of "secure"
here is obviously debatable. Something in boot_params would work.
Some specially namespaced command line option could work. Some whole
new "authenticated data from bootloader" block could work.
>
>> and even just some special flag in the boot handoff protocol.
>
> We already have that with secure boot.
No. That has been rejected over and over in this thread. I'm
proposing an alternative here.
>
>> 7. kexec does not attempt to think about "secure boot" at all.
>> They're totally separate.
>
> Except that they're not. The boot_params flag must be set to something by
> kexec on x86 for transfer along the chain.
How about setting it unconditionally to false?
>> What do you all think? I think that this checks basically all the
>> boxes, is a lot more user friendly than the current patchset or what
>> distros do, and actually makes some sense from a security perspective.
>
> You haven't really defined well what's allowed in _INTEGRITY mode verses
> _SECRECY mode.
_INTEGRITY means "make a best effort to keep root from writing kernel
memory, talking directly to non-IOMMU-protected devices, writing MSRs,
or otherwise corrupting state". _INTEGRITY_AND_SECRECY means "do all
that and also make a best effort to keep root from reading kernel
memory".
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 16:26 UTC (permalink / raw)
To: oiaohm
Cc: Linus Torvalds, luto, David Howells, Ard Biesheuvel, jmorris,
Alan Cox, Greg Kroah-Hartman, Linux Kernel Mailing List, jforbes,
linux-man, jlee, LSM List, linux-api, Kees Cook, linux-efi
In-Reply-To: <CANA3KFXyUH4cEJVTH-yoTwqAnZ+-9h-uboYTzO642Uo78H_wqg@mail.gmail.com>
On Tue, Apr 3, 2018 at 11:56 PM Peter Dolding <oiaohm@gmail.com> wrote:
> On Wed, Apr 4, 2018 at 11:13 AM, Matthew Garrett <mjg59@google.com> wrote:
> > There are four cases:
> >
> > Verified Boot off, lockdown off: Status quo in distro and mainline
kernels
> > Verified Boot off, lockdown on: Perception of security improvement
that's
> > trivially circumvented (and so bad)
> > Verified Boot on, lockdown off: Perception of security improvement
that's
> > trivially circumvented (and so bad), status quo in mainline kernels
> > Verified Boot on, lockdown on: Security improvement, status quo in
distro
> > kernels
> >
> > Of these four options, only two make sense. The most common
implementation
> > of Verified Boot on x86 platforms is UEFI Secure Boot,
> Stop right there. Verified boot does not have to be UEFI secureboot.
> You could be using a uboot verified boot or
> https://www.coreboot.org/git-docs/Intel/vboot.html google vboot.
> Neither of these provide flags to kernel to say they have been
> performed.
They can be modified to set the appropriate bit in the bootparams - the
reason we can't do that in the UEFI case is that Linux can be built as a
UEFI binary that the firmware execute directly, and so the firmware has no
way to set that flag.
> Now Verified Boot on, lockdown off. Insanely this can be required in
> diagnostic on some embedded platform because EFI secureboot does not
> have a off switch. These are platforms where they don't boot if
> they don't have a PK and KEK set installed. Yes some of these is jtag
> the PK and KEK set in.
> The fact that this Verified Boot on, lockdown off causes trouble
> points to a clear problem. User owns the hardware they should have
> the right to defeat secureboot if they wish to.
Which is why Shim allows you to disable validation if you prove physical
user presence.
^ permalink raw reply
* Re: An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: Jann Horn @ 2018-04-04 16:23 UTC (permalink / raw)
To: David Howells, Alexei Starovoitov
Cc: Andy Lutomirski, Greg Kroah-Hartman, Theodore Y. Ts'o,
Matthew Garrett, Linus Torvalds, Ard Biesheuvel, James Morris,
Alan Cox, Linux Kernel Mailing List, Justin Forbes, linux-man,
joeyli, LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <1119.1522858644@warthog.procyon.org.uk>
+ast@kernel.org
On Wed, Apr 4, 2018 at 6:17 PM, David Howells <dhowells@redhat.com> wrote:
> Andy Lutomirski <luto@kernel.org> wrote:
[...]
>> 3. All the bpf and tracing stuf, etc, gets changed so it only takes
>> effect when LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY is set.
>
> Uh, no. bpf, for example, can be used to modify kernel memory.
I'm pretty sure bpf isn't supposed to be able to modify arbitrary
kernel memory. AFAIU if you can use BPF to write to arbitrary kernel
memory, that's a bug; with CAP_SYS_ADMIN, you can read from userspace,
write to userspace, and read from kernelspace, but you shouldn't be
able to write to kernelspace.
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 16:22 UTC (permalink / raw)
To: tytso, David Howells, Linus Torvalds, luto, Ard Biesheuvel,
jmorris, Alan Cox, Greg Kroah-Hartman, Linux Kernel Mailing List,
jforbes, linux-man, jlee, LSM List, linux-api, Kees Cook,
linux-efi
In-Reply-To: <20180404135251.GD16242@thunk.org>
On Wed, Apr 4, 2018 at 6:52 AM Theodore Y. Ts'o <tytso@mit.edu> wrote:
> On Wed, Apr 04, 2018 at 02:33:37PM +0100, David Howells wrote:
> > Theodore Y. Ts'o <tytso@mit.edu> wrote:
> >
> > > Whoa. Why doesn't lockdown prevent kexec? Put another away, why
> > > isn't this a problem for people who are fearful that Linux could be
> > > used as part of a Windows boot virus in a Secure UEFI context?
> >
> > Lockdown mode restricts kexec to booting an authorised image (where the
> > authorisation may be by signature or by IMA).
> If that's true, then Matthew's assertion that lockdown w/o secure boot
> is insecure goes away, no?
If you don't have secure boot then an attacker with root can modify your
bootloader or kernel, and on next boot lockdown can be silently disabled.
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 16:20 UTC (permalink / raw)
To: tytso, Linus Torvalds, luto, David Howells, Ard Biesheuvel,
jmorris, Alan Cox, Greg Kroah-Hartman, Linux Kernel Mailing List,
jforbes, linux-man, jlee, LSM List, linux-api, Kees Cook,
linux-efi
In-Reply-To: <20180404125743.GB16242@thunk.org>
On Wed, Apr 4, 2018 at 5:57 AM Theodore Y. Ts'o <tytso@mit.edu> wrote:
> On Wed, Apr 04, 2018 at 04:30:18AM +0000, Matthew Garrett wrote:
> > What I'm afraid of is this turning into a "security" feature that ends
up
> > being circumvented in most scenarios where it's currently deployed - eg,
> > module signatures are mostly worthless in the non-lockdown case because
you
> > can just grab the sig_enforce symbol address and then kexec a preamble
that
> > flips it back to N regardless of the kernel config.
> Whoa. Why doesn't lockdown prevent kexec? Put another away, why
> isn't this a problem for people who are fearful that Linux could be
> used as part of a Windows boot virus in a Secure UEFI context?
It does - I was talking about the non-lockdown case. In the lockdown case
you can only kexec images you trust, so there's no problem. Red Hat have
been shipping a signed kdump image for years.
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Matthew Garrett @ 2018-04-04 16:17 UTC (permalink / raw)
To: Linus Torvalds
Cc: luto, David Howells, Ard Biesheuvel, jmorris, Alan Cox,
Greg Kroah-Hartman, Linux Kernel Mailing List, jforbes, linux-man,
jlee, LSM List, linux-api, Kees Cook, linux-efi
In-Reply-To: <CA+55aFyyom+jje0Q8xwLfKCWGkRbWC2Gan6xPOPWaqBCSS=5Ow@mail.gmail.com>
On Wed, Apr 4, 2018 at 9:09 AM Linus Torvalds
<torvalds@linux-foundation.org>
wrote:
> On Tue, Apr 3, 2018 at 9:30 PM, Matthew Garrett <mjg59@google.com> wrote:
> >
> > Bear in mind that I'm talking about defaults here
> Mattyhew, I really want you to look yourself in the mirror.
> Those defaults are really horrible defautls for real technical reasons.
> You asked me why when I questioned this, but then when I replied, you
> entirely ignored it.
> So let me repeat: the defaults are *horrible*. They are horrible for a
> very simple reason: kernel behavior changes that depend on some subtle
> boot difference are truly nasty to debug, and nasty to get coverage
> for.
They're the defaults that the mainline distros have been shipping for
years. So what are you actually asking for here? If you're saying that it
should be possible to enable the lockdown functionality even in the absence
of any kind of verified boot, then yes, I agree - I just think it makes a
poor distro default to have that be the case out of the box. If you're
saying that it should be possible to disable the lockdown functionality
even in the presence of any kind of verified boot, then yes, I agree - I
just think it makes a poor distro default to have that be the case out of
the box. You're arguing against a patch that provides the default policy
that distros want to ship.
^ permalink raw reply
* Re: An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: David Howells @ 2018-04-04 16:17 UTC (permalink / raw)
To: Andy Lutomirski
Cc: dhowells, Greg Kroah-Hartman, Theodore Y. Ts'o,
Matthew Garrett, Linus Torvalds, Ard Biesheuvel, James Morris,
Alan Cox, Linux Kernel Mailing List, Justin Forbes, linux-man,
joeyli, LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <CALCETrUVQLDC6_VEvuAbdCOuGrmcxohqTB6P8eyNojm9AryNkg@mail.gmail.com>
Andy Lutomirski <luto@kernel.org> wrote:
> Since this thread has devolved horribly, I'm going to propose a solution.
>
> 1. Split the "lockdown" state into three levels: (please don't
> bikeshed about the names right now.)
>
> LOCKDOWN_NONE: normal behavior
>
> LOCKDOWN_PROTECT_INTEGREITY: kernel tries to keep root from writing to
> kernel memory
>
> LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY: kernel tries to keep root from
> reading or writing kernel memory.
In theory, it's good idea, but in practice it's not as easy to implement as I
think you think.
Let me list here the things that currently get restricted by lockdown:
(1) Manipulation of devices to access the kernel image:
- Ioports & ioperm
- /dev/ports
- /dev/mem
- PCI Bar
- Some debugfs files
- pcmcia_cis
- Driver hardware parameters
- ISA drivers
- TIOCSSERIAL
- SCSI EATA driver
- testmmiotrace
- firmware
(2) Direct kernel memory modification:
- /dev/mem
- /dev/kmem
- bpf
- kprobes
(3) Direct kernel memory reading:
- /dev/mem
- /dev/kmem
- /dev/kcore
- bpf
- kprobes
- perf
(4) Indirect kernel access:
- Modules
- MSRs
- Suspend to disk
- ACPI (custom_method, RSDP, table override, error injection)
(5) Kexec.
Note that /dev/mem can be used to access MMIO devices (I'm not sure about
/dev/kmem, though). Even reads through /dev/mem can do this. I'm not sure
whether that's sufficient to actually affect a modification, though.
Debugfs is particularly icky. It contains at least a couple of thousand
files, a few of which provide direct access to hardware, some of which change
driver behaviour and some of which just give information. Auditing that pile
isn't something I really want to have to do. I'd rather just turn the whole
lot off, but got persuaded otherwise by people who have been using it to
provide mechanisms that programs rely on - hence the only allow files that
have 0444 (and even that is iffy as some of these files have side effects and
write ops anyway).
> 2. The kexec protocol gets a new flag min_lockdown_level. A kexeced
> kernel will boot with at least that lockdown level regardless of its
> configuration. kexec sets min_lockdown_level to the running kernels'
> lockdown_level. Some future API could allow kexec with a higher
> min_lockdown_level. An even fancier future API could allow a
> LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY kernel to kexec with
> min_lockdown_level == LOCKDOWN_PROTECT_INTEGRITY if there's some
> mechanism that guarantees that memory gets zeroed in the process.
Note that on x86 we already have an allocated flag for passing the secure boot
flag from kexec/bootloader to the kernel being booted, and what you're
proposing ought to be redundant. See boot_params::secure_boot.
> 3. All the bpf and tracing stuf, etc, gets changed so it only takes
> effect when LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY is set.
Uh, no. bpf, for example, can be used to modify kernel memory. I think only
the following are safe from being able to talk directly to devices:
/dev/kmem (O_RDONLY only)
/dev/kcore
perf
some debugfs files
> This removes a giant annoyance on distro kernels that are likely to want to
> enable LOCKDOWN_PROTECT_INTEGRITY.
*shrug* Distros have been running with the full set for a while. I haven't
seen many complaints.
> If you load a key into the kernel, and you want to keep that key safe, you
> can enable LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY at that time. After all,
> if root is compromised before that, root can just remember a copu of the key
> in user memory or email it to someone.
If your key needs to be truly protected, it should never be seen unencrypted
in userspace, rather it should be decrypted in the TPM and then retained in
kernel memory only.
> ...
> 6. There's a way to *decrease* the lockdown level below the configured
> value. (This ability itself may be gated by a config option.)
> Choices include a UEFI protected variable,
By turning secure boot off, maybe?
> an authenticated flag passed by the bootloader,
Authenticated how? How do you stop the running system from passing this to
the bootloader next time it is run? I guess you're thinking of a bootloader
"command" that can only be passed by someone sat at a keyboard and never read
from the config file.
> and even just some special flag in the boot handoff protocol.
We already have that with secure boot.
> It would be really quite useful for a user to be able to ask their
> bootloader to reduce the lockdown level for the purpose of a particular boot
> for debugging.
This I shall grant you - but you have to be able to prevent an attacker inside
the system from making use of it. There's a SysRq provided to drop out of
lockdown mode - in theory only usable if you're sat at a wired keyboard
connected to the computer.
> 7. kexec does not attempt to think about "secure boot" at all.
> They're totally separate.
Except that they're not. The boot_params flag must be set to something by
kexec on x86 for transfer along the chain. However, we can leave secure boot
out for now - that can be treated as a separate issue.
Note that whether you like it or not, distribution kernels already work this
way and propagate the boot_params flag over kexec.
> What do you all think? I think that this checks basically all the
> boxes, is a lot more user friendly than the current patchset or what
> distros do, and actually makes some sense from a security perspective.
You haven't really defined well what's allowed in _INTEGRITY mode verses
_SECRECY mode.
I'm currently in the throes of modifying my patchset to make it more inline
with what Linus mandates: dropping the enablement from secure boot; dropping
the propagation of the flag over kexec; providing a config option to make it
mandatory. There is already a command line option to trigger it.
David
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Linus Torvalds @ 2018-04-04 16:09 UTC (permalink / raw)
To: Matthew Garrett
Cc: Andrew Lutomirski, David Howells, Ard Biesheuvel, James Morris,
Alan Cox, Greg Kroah-Hartman, Linux Kernel Mailing List,
Justin Forbes, linux-man, joeyli, LSM List, Linux API, Kees Cook,
linux-efi
In-Reply-To: <CACdnJutuBaE3RaDx0KM5vDF9Sinrp=3tG9csrS-H3eU-J7-Utw@mail.gmail.com>
On Tue, Apr 3, 2018 at 9:30 PM, Matthew Garrett <mjg59@google.com> wrote:
>
> Bear in mind that I'm talking about defaults here
Mattyhew, I really want you to look yourself in the mirror.
Those defaults are really horrible defautls for real technical reasons.
You asked me why when I questioned this, but then when I replied, you
entirely ignored it.
So let me repeat: the defaults are *horrible*. They are horrible for a
very simple reason: kernel behavior changes that depend on some subtle
boot difference are truly nasty to debug, and nasty to get coverage
for.
And this "subtle boot difference" is really bad because it's a
difference that has a particularly bad pattern: pretty much not a
single mainline kernel developer will have secure boot enabled,
exactly because it's so inconvenient for testing.
So what does that mean?
It means that the default is *actively* bad for kernel development. It
means that the people who do kernel development will not be testing
the behavior that "normal" users will actually see.
If you do not see why that is a HORRIBLY BAD THING, I don't know what to say.
Seriously. It's a nasty nasty default behavior. It's absolutely
disastrously wrong.
And then when people call you out on this bad linkage of this feature
with secure boot, you spent a *LOT* of time being dishonest about it.
Instead of answeing a simple technical question, you did just about
everything you could to avoid answering it.
You initially turned the question back into a "Why would you want to?"
rather than just answering.
Then you spent a whole lot of time coming up with completely wrong
excuses that had no actual technical reason for them.
And even now, you're trying to ignore the question, and the REASON for
the question.
See above: the default is really horrendously bad, and is just about
the *worst* default you could ever pick from a kernel development
angle.
So when a kernel developer - both me and Andy - ask you about the
reason for that HORRIBLY BAD default, then you had better stop dancing
around the issue, and be honesy.
Instead, you bring up complete red herrings:
> If a user has a configuration where you're able to verify that userspace
> has some degree of protection (eg, disk encryption keys are in the TPM and
> won't unseal if someone's switched out the kernel) then it's reasonable for
> userland (or a kernel command line option) to enable the functionality.
This line of arguyment of yours ends up STILL being complete and utter garbage.
There is not a single shred of evidence that there is some kind of
"reasonable to enable the functionality" based on completely unrelated
matters.
See above on why such stupid linkages are a bad bad idea. Absolutely
*ANY* time you make that decision silently for a user, you will just
be doing the wrong thing.
You will do the wrong thing for security, but equally importantly, you
will be doing the wrong thing just for *development* and *test
coverage*.
> What I'm afraid of is this turning into a "security" feature that ends up
> being circumvented in most scenarios where it's currently deployed - eg,
> module signatures are mostly worthless in the non-lockdown case because you
> can just grab the sig_enforce symbol address and then kexec a preamble that
> flips it back to N regardless of the kernel config.
Honestyly, all of your arguments are made up shit.
This argument, for example, is just a complete red herring.
Do you want to protect against somebody flipping "sig_enforce"? Makes
perfect sense to me.
Then WHY is that not just a config option for extra hardening?
Seriously. I'd use it. I have never *ever* felt the need to switch
"sig_enforce" off, and I always build with MODULE_SIG_FORCE and
MODULE_SIG_ALL.
Getting rid of that switch entirely for security reasons sounds just
_fine_ to me.
So you use these *stupid* things as "arguments" for why you think you
want to do something. But you're putting the cart before the horse:
you have a particular end result you want to get to, and then you make
up arguments for why you want to get there.
Seriously, go back to that coverage and testing issue. Go back to the
*fundamental* technical issue that we want kernel developers to
actually *test* the code that users are running.
*Gasp*.
Yeah, I know, it's a completely radical idea, but it's true. Having
developers test and run the code actual real humans are using is a
truly revolutionary concept in security too.
> I'm making this argument from the perspective of "What should the kernel do
> when it has no additional information".
And I'm telling you that you're ignoring the fact that you picked a
truly horrendously shitty default.
And then you spent a *lot* of time giving misleading and bad
information about why you picked that shitty default, and instead just
questioning the people who asked you an actual and really simply
technical question.
Linus
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: Eric W. Biederman @ 2018-04-04 15:43 UTC (permalink / raw)
To: David Howells
Cc: Andy Lutomirski, Jann Horn, Linus Torvalds, Matthew Garrett,
Ard Biesheuvel, James Morris, Alan Cox, Greg Kroah-Hartman,
Linux Kernel Mailing List, Justin Forbes, linux-man, joeyli,
LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <20736.1522829117@warthog.procyon.org.uk>
David Howells <dhowells@redhat.com> writes:
> Andy Lutomirski <luto@kernel.org> wrote:
>
>> As far as I can tell, what's really going on here is that there's a
>> significant contingent here that wants to prevent Linux from
>> chainloading something that isn't Linux.
>
> You have completely the wrong end of the stick. No one has said that or even
> implied that. You are alleging dishonesty on our part.
>
> What we *have* said is that *if* we want to pass the secure boot state across
> kexec, then we have to make sure that:
>
> (1) no one tampers with the intermediate kernel between boot and kexec
> otherwise the secure boot state is effectively invalidated, and
>
> (2) the image that gets kexec'ed is trusted.
>
> Remember: you cannot know (2) if you don't have (1).
>
> And if someone tampers with the aim of breaking, say, Windows, then someone,
> e.g. Microsoft, might blacklist the shim.
*Wow* You just denied this isn't about not booting Windows and a few
lines later said that is your concern.
I was thinking I would have to dig up old archives where I had been told
this before, but you just nicely repeated all of the old arguments so I
don't see the point.
Eric
^ permalink raw reply
* An actual suggestion (Re: [GIT PULL] Kernel lockdown for secure boot)
From: Andy Lutomirski @ 2018-04-04 14:49 UTC (permalink / raw)
To: Greg Kroah-Hartman
Cc: Theodore Y. Ts'o, Matthew Garrett, Linus Torvalds,
Andrew Lutomirski, David Howells, Ard Biesheuvel, James Morris,
Alan Cox, Linux Kernel Mailing List, Justin Forbes, linux-man,
joeyli, LSM List, Linux API, Kees Cook, linux-efi
Since this thread has devolved horribly, I'm going to propose a solution.
1. Split the "lockdown" state into three levels: (please don't
bikeshed about the names right now.)
LOCKDOWN_NONE: normal behavior
LOCKDOWN_PROTECT_INTEGREITY: kernel tries to keep root from writing to
kernel memory
LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY: kernel tries to keep root from
reading or writing kernel memory.
2. The kexec protocol gets a new flag min_lockdown_level. A kexeced
kernel will boot with at least that lockdown level regardless of its
configuration. kexec sets min_lockdown_level to the running kernels'
lockdown_level. Some future API could allow kexec with a higher
min_lockdown_level. An even fancier future API could allow a
LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY kernel to kexec with
min_lockdown_level == LOCKDOWN_PROTECT_INTEGRITY if there's some
mechanism that guarantees that memory gets zeroed in the process.
3. All the bpf and tracing stuf, etc, gets changed so it only takes
effect when LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY is set. This
removes a giant annoyance on distro kernels that are likely to want to
enable LOCKDOWN_PROTECT_INTEGRITY. If you load a key into the kernel,
and you want to keep that key safe, you can enable
LOCKDOWN_PROTECT_INTEGRITY_AND_SECRECY at that time. After all, if
root is compromised before that, root can just remember a copu of the
key in user memory or email it to someone.
4. There's a kernel config option for the default lockdown level.
This operates completely independently of secure boot.
5. There's a command line option to increase the lockdown level above
the default level. No particular authentication is needed for this
option to work.
6. There's a way to *decrease* the lockdown level below the configured
value. (This ability itself may be gated by a config option.)
Choices include a UEFI protected variable, an authenticated flag
passed by the bootloader, and even just some special flag in the boot
handoff protocol. It would be really quite useful for a user to be
able to ask their bootloader to reduce the lockdown level for the
purpose of a particular boot for debugging. I read the docs on
mokutil --disable-validation, and it's quite messy. Let's have a way
to do this that is mostly independent of the particular firmware in
use.
I can imagine a grub option that decreases lockdown level along with a
rule that grub will *not* load that option from its config, for
example.
7. kexec does not attempt to think about "secure boot" at all.
They're totally separate.
What do you all think? I think that this checks basically all the
boxes, is a lot more user friendly than the current patchset or what
distros do, and actually makes some sense from a security perspective.
--Andy
^ permalink raw reply
* Re: [GIT PULL] Kernel lockdown for secure boot
From: David Howells @ 2018-04-04 14:44 UTC (permalink / raw)
To: Andy Lutomirski
Cc: dhowells, Andy Lutomirski, Jann Horn, Linus Torvalds,
Matthew Garrett, Ard Biesheuvel, James Morris, Alan Cox,
Greg Kroah-Hartman, Linux Kernel Mailing List, Justin Forbes,
linux-man, joeyli, LSM List, Linux API, Kees Cook, linux-efi
In-Reply-To: <CALCETrUaKOG1q43W=UBPue5TAL61zzwzgr8QeH3Yh6KsMUA2aQ@mail.gmail.com>
Andy Lutomirski <luto@amacapital.net> wrote:
> > Andy Lutomirski <luto@kernel.org> wrote:
> >
> >> As far as I can tell, what's really going on here is that there's a
> >> significant contingent here that wants to prevent Linux from
> >> chainloading something that isn't Linux.
> >
> > You have completely the wrong end of the stick. No one has said that or
> > even implied that. You are alleging dishonesty on our part.
>
> I'm alleging that the idea that Linux seems some particular policy to
> avoid being blacklisted keeps being brought up as a justification for
> these patches.
No, you were alleging that "[we want] to prevent Linux from chainloading
something that isn't Linux.".
This is not true - at least, it's not true on my part; I cannot speak for what
other people may think privately.
David
^ 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