Re: [PATCH bpf-next v1 00/13] MAC and Audit policy using eBPF (KRSI)

From: Stephen Smalley
Date: Wed Jan 08 2020 - 10:25:32 EST


On 12/30/19 2:15 PM, Kees Cook wrote:
On Fri, Dec 20, 2019 at 06:38:45PM +0100, KP Singh wrote:
Hi Casey,

Thanks for taking a look!

On Fri, Dec 20, 2019 at 6:17 PM Casey Schaufler <casey@xxxxxxxxxxxxxxxx> wrote:

On 12/20/2019 7:41 AM, KP Singh wrote:
From: KP Singh <kpsingh@xxxxxxxxxx>

This patch series is a continuation of the KRSI RFC
(https://lore.kernel.org/bpf/20190910115527.5235-1-kpsingh@xxxxxxxxxxxx/)

# Motivation

Google does rich analysis of runtime security data collected from
internal Linux deployments (corporate devices and servers) to detect and
thwart threats in real-time. Currently, this is done in custom kernel
modules but we would like to replace this with something that's upstream
and useful to others.

The current kernel infrastructure for providing telemetry (Audit, Perf
etc.) is disjoint from access enforcement (i.e. LSMs). Augmenting the
information provided by audit requires kernel changes to audit, its
policy language and user-space components. Furthermore, building a MAC
policy based on the newly added telemetry data requires changes to
various LSMs and their respective policy languages.

This patchset proposes a new stackable and privileged LSM which allows
the LSM hooks to be implemented using eBPF. This facilitates a unified
and dynamic (not requiring re-compilation of the kernel) audit and MAC
policy.

# Why an LSM?

Linux Security Modules target security behaviours rather than the
kernel's API. For example, it's easy to miss out a newly added system
call for executing processes (eg. execve, execveat etc.) but the LSM
framework ensures that all process executions trigger the relevant hooks
irrespective of how the process was executed.

Allowing users to implement LSM hooks at runtime also benefits the LSM
eco-system by enabling a quick feedback loop from the security community
about the kind of behaviours that the LSM Framework should be targeting.

# How does it work?

The LSM introduces a new eBPF (https://docs.cilium.io/en/v1.6/bpf/)
program type, BPF_PROG_TYPE_LSM, which can only be attached to a LSM
hook. All LSM hooks are exposed as files in securityfs. Attachment
requires CAP_SYS_ADMIN for loading eBPF programs and CAP_MAC_ADMIN for
modifying MAC policies.

The eBPF programs are passed the same arguments as the LSM hooks and
executed in the body of the hook.

This effectively exposes the LSM hooks as external APIs.
It would mean that we can't change or delete them. That
would be bad.

Perhaps this should have been clearer, we *do not* want to make LSM hooks
a stable API and expect the eBPF programs to adapt when such changes occur.

Based on our comparison with the previous approach, this still ends up
being a better trade-off (w.r.t. maintenance) when compared to adding
specific helpers or verifier logic for each new hook or field that
needs to be exposed.

Given the discussion around tracing and stable ABI at the last kernel
summit, Linus's mandate is mainly around "every day users" and not
around these system-builder-sensitive cases where everyone has a strong
expectation to rebuild their policy when the kernel changes. i.e. it's
not "powertop", which was Linus's example of "and then everyone running
Fedora breaks".

So, while I know we've tried in the past to follow the letter of the
law, it seems Linus really expects this only to be followed when it will
have "real world" impact on unsuspecting end users.

Obviously James Morris has the final say here, but as I understand it,
it is fine to expose these here for the same reasons it's fine to expose
the (ever changing) tracepoints and BPF hooks.

This appears to impose a very different standard to this eBPF-based LSM than has been applied to the existing LSMs, e.g. we are required to preserve SELinux policy compatibility all the way back to Linux 2.6.0 such that new kernel with old policy does not break userspace. If that standard isn't being applied to the eBPF-based LSM, it seems to inhibit its use in major Linux distros, since otherwise users will in fact start experiencing breakage on the first such incompatible change. Not arguing for or against, just trying to make sure I understand correctly...