[PATCH bpf-next 0/4] Reduce overhead of LSMs with static calls

Casey Schaufler casey at schaufler-ca.com
Fri Jan 20 01:13:10 UTC 2023


On 1/19/2023 3:10 PM, KP Singh wrote:
> # Background
>
> LSM hooks (callbacks) are currently invoked as indirect function calls. These
> callbacks are registered into a linked list at boot time as the order of the
> LSMs can be configured on the kernel command line with the "lsm=" command line
> parameter.
>
> Indirect function calls have a high overhead due to retpoline mitigation for
> various speculative execution attacks.
>
> Retpolines remain relevant even with newer generation CPUs as recently
> discovered speculative attacks, like Spectre BHB need Retpolines to mitigate
> against branch history injection and still need to be used in combination with
> newer mitigation features like eIBRS.
>
> This overhead is especially significant for the "bpf" LSM which allows the user
> to implement LSM functionality with eBPF program. In order to facilitate this
> the "bpf" LSM provides a default callback for all LSM hooks. When enabled,
> the "bpf" LSM incurs an unnecessary / avoidable indirect call. This is
> especially bad in OS hot paths (e.g. in the networking stack).
> This overhead prevents the adoption of bpf LSM on performance critical
> systems, and also, in general, slows down all LSMs.
>
> Since we know the address of the enabled LSM callbacks at compile time and only
> the order is determined at boot time,

No quite true. A system with Smack and AppArmor compiled in will only
be allowed to use one or the other.

>  the LSM framework can allocate static
> calls for each of the possible LSM callbacks and these calls can be updated once
> the order is determined at boot.

True if you also provide for the single "major" LSM restriction.

> This series is a respin of the RFC proposed by Paul Renauld (renauld at google.com)
> and Brendan Jackman (jackmanb at google.com) [1]
>
> # Performance improvement
>
> With this patch-set some syscalls with lots of LSM hooks in their path
> benefitted at an average of ~3%. Here are the results of the relevant Unixbench
> system benchmarks with BPF LSM and a major LSM (in this case apparmor) enabled
> with and without the series.
>
> Benchmark                                               Delta(%): (+ is better)
> ===============================================================================
> Execl Throughput                                             +2.9015
> File Write 1024 bufsize 2000 maxblocks                       +5.4196
> Pipe Throughput                                              +7.7434
> Pipe-based Context Switching                                 +3.5118
> Process Creation                                             +0.3552
> Shell Scripts (1 concurrent)                                 +1.7106
> System Call Overhead                                         +3.0067
> System Benchmarks Index Score (Partial Only):                +3.1809

How about socket creation and packet delivery impact? You'll need to
use either SELinux or Smack to get those numbers.

> In the best case, some syscalls like eventfd_create benefitted to about ~10%.
> The full analysis can be viewed at https://kpsingh.ch/lsm-perf
>
> [1] https://lore.kernel.org/linux-security-module/20200820164753.3256899-1-jackmanb@chromium.org/
>
> KP Singh (4):
>   kernel: Add helper macros for loop unrolling
>   security: Generate a header with the count of enabled LSMs
>   security: Replace indirect LSM hook calls with static calls
>   bpf: Only enable BPF LSM hooks when an LSM program is attached
>
>  include/linux/bpf.h              |   1 +
>  include/linux/bpf_lsm.h          |   1 +
>  include/linux/lsm_hooks.h        |  94 +++++++++++--
>  include/linux/unroll.h           |  35 +++++
>  kernel/bpf/trampoline.c          |  29 ++++-
>  scripts/Makefile                 |   1 +
>  scripts/security/.gitignore      |   1 +
>  scripts/security/Makefile        |   4 +
>  scripts/security/gen_lsm_count.c |  57 ++++++++
>  security/Makefile                |  11 ++
>  security/bpf/hooks.c             |  26 +++-
>  security/security.c              | 217 ++++++++++++++++++++-----------
>  12 files changed, 386 insertions(+), 91 deletions(-)
>  create mode 100644 include/linux/unroll.h
>  create mode 100644 scripts/security/.gitignore
>  create mode 100644 scripts/security/Makefile
>  create mode 100644 scripts/security/gen_lsm_count.c
>



More information about the Linux-security-module-archive mailing list