[RFC PATCH 1/2] LSM: Allow dynamically appendable LSM modules.
KP Singh
kpsingh at kernel.org
Tue Oct 3 15:09:10 UTC 2023
On Tue, Oct 3, 2023 at 4:28 PM Tetsuo Handa
<penguin-kernel at i-love.sakura.ne.jp> wrote:
>
> On 2023/10/01 23:43, KP Singh wrote:
> >>> Now, comes the question of whether we need dynamically loaded LSMs, I
> >>> am not in favor of this. Please share your limitations of BPF as you
> >>> mentioned and what's missing to implement dynamic LSMs. My question
> >>> still remains unanswered.
> >>>
> >>> Until I hear the real limitations of using BPF, it's a NAK from me.
> >>
> >> Simple questions that TOMOYO/AKARI/CaitSith LSMs depend:
> >>
> >> Q1: How can the BPF allow allocating permanent memory (e.g. kmalloc()) that remains
> >> the lifetime of the kernel (e.g. before starting the global init process till
> >> the content of RAM is lost by stopping electric power supply) ?
> >
> > This is very much possible using global BPF maps. Maps can be "pinned"
> > so that they remain allocated until explicitly freed [or RAM is lost
> > by stopping electric power supply"]
> >
> > Here's an example of BPF program that allocates maps:
> >
> > https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/bpf/progs/test_pinning.c#L26
> >
> > and the corresponding userspace code that does the pinning:
> >
> > https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/bpf/prog_tests/pinning.c
>
> I know nothing about BPF. But that looks "allocate once" (i.e. almost "static char buf[SIZE]").
Happy to help you here!
> What I expected is "allocate memory where amount is determined at runtime" (e.g. alloc(), realloc()).
One can use dynamically sized allocations on the ring buffer with
dynamic pointers:
http://vger.kernel.org/bpfconf2022_material/lsfmmbpf2022-dynptr.pdf
Furthermore, there are some use cases that seemingly need dynamic
memory allocation but not really. e.g. there was a need to audit
command line arguments and while it seems dynamic and one can chunk
the allocation to finite sizes, put these on a ring buffer and process
the chunks.
It would be nice to see more details of where the dynamic allocation
is needed. Security blobs are allocated dynamically but have a fixed
size.
>
> >
> > Specifically for LSMs, we also added support for security blobs which
> > are tied to a particular object and are free with the object, have a
> > look at the storage which is allocated in the program:
> >
> > https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/bpf/progs/local_storage.c#L79
> >
> > Again, code and context on what you want to do will let me help you more here.
>
> I don't have any BPF code.
> I have several LKM-based LSMs in https://osdn.net/projects/akari/scm/svn/tree/head/branches/ .
Thanks for the pointers, I will read through them.
>
> >
> >>
> >> Q2: How can the BPF allow interacting with other process (e.g. inter process communication
> >> using read()/write()) which involves opening some file on the filesystem and sleeping
> >> for arbitrary duration?
> >
> > The BPF program runs in the kernel context, so yes all of this is
> > possible. IPC can be done with the bpf_ring_buffer / maps and BPF also
> > has the ability to send signals. One can poll on the ring buffer on
> > events and data from the BPF program and do a lots of things.
>
> OK, BPF allows sleeping operations; that's good.
>
> Some of core requirements for implementing TOMOYO/AKARI/CaitSith-like programs
> using BPF will be:
>
> The program registered cannot be stopped/removed by the root user.
> This is made possible by either building the program into vmlinux or loading
> the program as a LKM without module_exit() callback. Is it possible to guaranee
> that a BPF program cannot be stopped/removed by user's operations?
Yes, there is a security_bpf hook where a BPF MAC policy can be
implemented and other LSMs do that already.
>
> The program registered cannot be terminated by safety mechanisms (e.g. excessive
> CPU time consumption). Are there mechanisms in BPF that wouldn't have terminated
> a program if the program were implemented as a LKM rather than a BPF program?
>
The kernel does not terminate BPF LSM programs, once a BPF program is
loaded and attached to the LSM hook, it's JITed into a native code.
>From there onwards, as far as the kernel is concerned it's just like
any other kernel function.
> Ideally, the BPF program is built into vmlinux and is started before the global init
> process starts. (But whether building into vmlinux is possible does not matter here
> because I have trouble building into vmlinux. As a fallback, when we can start matters.)
> When is the earliest timing for starting a BPF program that must remain till stopping
The kernel actually supports preloading certain BPF programs during early init.
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/commit/?id=0bc23a1d1c8a1b4a5e4b973a7a80a6d067bd3eef
This allows you to preload before init.
> electric power supply? Is that when /init in a initramfs starts? Is that when init=
> kernel command line option is processed? More later than when init= is processed?
Also, It depends on whether you trust init or not (e.g. if the init
blob is somehow appraised and measured, then you can trust it to load
the right BPF LSM programs). and then you can choose to not preload
bpf programs in the kernel, rather load them sometime early in /init.
>
> Amount of memory needed for managing data is not known at compile time. Thus, I need
> kmalloc()-like memory allocation mechanism rather than allocating from some pool, and
> manage chunk of memory regions using linked list. Does BPF have kmalloc()-like memory
> allocation mechanism that allows allocating up to 32KB (8 pages if PAGE_SIZE=4096).
>
You use the ring buffer as a large pool and use dynamic pointers to
carve chunks out of it, if truly dynamic memory is needed.
> And maybe somewhere documented question:
>
> What kernel functions can a BPF program call / what kernel data can a BPF program access?
BPF programs can access kernel data dynamically (accesses relocated at
load time without needing a recompile) There are lot of good details
in:
https://nakryiko.com/posts/bpf-core-reference-guide/
> The tools/testing/selftests/bpf/progs/test_d_path.c suggests that a BPF program can call
> d_path() defined in fs/d_path.c . But is that because d_path() is marked as EXPORT_SYMBOL() ?
> Or can a BPF program call almost all functions (like SystemTap script can insert hooks into
> almost all functions)? Even functions / data in LKM can be accessed by a BPF program?
>
It's not all kernel functions, but there is a wide range of helpers
and kfuncs (examples in tools/testing/selftests/bpf) and if there is
something missing, we will help you.
>
>
> On 2023/10/02 22:04, KP Singh wrote:
> >>> There are still a bunch of details (e.g. shared blobs) that it doesn't
> >>> address. On the other hand, your memory management magic doesn't
> >>> address those issues either.
> >>
> >> Security is always trial-and-error. Just give all Linux users chances to continue
> >> trial-and-error. You don't need to forbid LKM-based LSMs just because blob management
> >> is not addressed. Please open the LSM infrastructure to anyone.
> >
> > It already is, the community is already using BPF LSM.
> >
> > e.g. https://github.com/linux-lock/bpflock
> >
>
> Thank you for an example. But the project says
>
> bpflock is not a mandatory access control labeling solution, and it does not
> intent to replace AppArmor, SELinux, and other MAC solutions. bpflock uses a
> simple declarative security profile.
>
> which is different from what I want to know (whether it is realistic to
> implement TOMOYO/AKARI/CaitSith-like programs using BPF).
Agreed, I was sharing it more as a code sample. There is an
interesting talk by Meta at LPC which I quite excited about in this
space:
https://lpc.events/event/17/contributions/1602/
These are just examples of flexible MAC implementations using BPF.
- KP
- KP
>
More information about the Linux-security-module-archive
mailing list