[RFC PATCH 1/2] LSM: Allow dynamically appendable LSM modules.

Tetsuo Handa penguin-kernel at I-love.SAKURA.ne.jp
Sat Oct 21 14:19:43 UTC 2023


On 2023/10/04 0:09, KP Singh wrote:
>> 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.

Dynamic allocation is not for security blobs. Dynamic allocation is for
holding requested pathnames (short-lived allocation), holding audit logs
(FIFO allocation), holding/appending access control rules (long-lived
allocation).



>> 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.

I was finally able to build and load tools/testing/selftests/bpf/progs/lsm.c and
tools/testing/selftests/bpf/prog_tests/test_lsm.c , and I found fatal limitation
that the program registered is terminated when the file descriptor which refers to
tools/testing/selftests/bpf/lsm.bpf.o is closed (due to e.g. process termination).
That is, eBPF programs are not reliable/robust enough to implement TOMOYO/AKARI/
CaitSith-like programs. Re-registering when the file descriptor is closed is racy
because some critical operations might fail to be traced/checked by the LSM hooks.

Also, I think that automatic cleanup upon closing the file descriptor implies that
allocating resources (or getting reference counts) that are not managed by the BPF
(e.g. files under /sys/kernel/securitytomoyo/ directory) is not permitted. That's
very bad.

> 
>>
>>   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.

TOMOYO/AKARI/CaitSith-like programs do need dynamic memory allocation, as max amount of
memory varies from less than 1MB to more than 10MB. Preallocation is too much wasteful.



> 
>> 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.

I couldn't build tools/testing/selftests/bpf/progs/lsm.c with printk() added.
Sending to /sys/kernel/debug/tracing/trace_pipe via bpf_printk() is not enough for
reporting critical/urgent problems. Synchronous operation is important.

Since printk() is not callable, most of functions which TOMOYO/AKARI/CaitSith-like
programs use seem to be not callable.



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