FAQ. How to Contribute to the Linux Kernel?
-
Pre-study before kernel contribution
Q&A: Getting Started with AppArmor Contribution
Q. I’m very interested in AppArmor and would like to contribute. How should I prepare, and what is the best way to start contributing to Linux security?
A. I recommend starting by analyzing the interaction between user space and the kernel. Specifically, you should examine the AppArmor-related options in
/procand/sys, and profile the user space applications that control AppArmor using tools liketrace-cmd. This will help you understand the code flow and how policies are enforced.- https://www.trace-cmd.org/
- https://trace-cmd.org/Documentation/trace-cmd/
- https://github.com/rostedt/trace-cmd
- https://kernelshark.org/Documentation.html
- https://wiki.st.com/stm32mpu/wiki/Trace-cmd_and_kernelshark_trace_viewer
To give you more context, here is a breakdown of the key components you should look into:
1. Understanding the Interfaces:
/sysand/proc
AppArmor relies heavily on the SecurityFS interface to interact with the kernel.# With root privilege, For example: $ trace-cmd record -F -p function_graph cat /sys/kernel/security/apparmor/profiles $ trace-cmd report > cat-apparmor.log/sys/kernel/security/apparmor: This is the primary control interface. It is where the kernel exports information about the loaded policies, features, and the interface for loading or replacing profiles. Exploring this directory helps you understand what capabilities the running kernel supports./proc/[pid]/attr/current: This interface shows the AppArmor profile currently applied to a specific process. Monitoring this file is essential for debugging and verifying that process confinement is working as expected.
2. Analyzing User Space Tools
Before diving deep into the kernel code, it is crucial to understand how policies are generated and passed to the kernel. The core component here is the AppArmor Parser.apparmor_parser: This is the user space program responsible for compiling human-readable text profiles into a binary format that the kernel can digest. By tracing this application withtrace-cmd, you can see exactly how it invokes the kernel interfaces to load policies.
- https://documentation.suse.com/ko-kr/sles/12-SP5/html/SLES-all/cha-apparmor-start.html
- https://manpages.debian.org/stretch/apparmor/apparmor.7.en.html
3. Source Code Repository
You can find the source code for the AppArmor user space tools, including the parser and libraries, in their official repository. Studying this code is the best way to understand the mechanism behind policy loading.- AppArmor User Space Repository: https://gitlab.com/apparmor/apparmor
- AppArmor Kernel Source Code: https://elixir.bootlin.com/linux/v6.18.2/source/security/apparmor/apparmorfs.c#L2311
Conclusion
Lastly, keep in mind that this workflow is not specific to AppArmor. Analyzing the/sysand/procinterfaces and profiling the interaction between user space and the kernel is a universally effective approach. It serves as an excellent starting point for analyzing and contributing to any Linux kernel subsystem.P.S.
profiles_open() → seq_read() (call p_start/p_next/p_show/p_stop)// security/apparmor/apparmorfs.c static const struct file_operations aa_sfs_profiles_fops = { .open = profiles_open, .read = seq_read, .llseek = seq_lseek, .release = profiles_release, };- profiles_open(): seq_open() init seq_file.
- seq_read() - VFS read seq_file.
- aa_sfs_profiles_op's callback
- p_start() :Start.
- p_next() : Next profile.
- p_show() : Print profile.
- p_stop() : End
- profiles_release() : Close the file.
-
-
Trace kernel function calls triggered by tcpdump
$trace-cmd record -p function_graph \ -l '__sys_connect' \ -l 'sys_connect' \ -l 'security_socket_connect' \ -l 'apparmor_socket_connect' \ -l 'aa_sk_perm' \ -- tcpdump -i lo -
Convert the recorded trace data into a human-readable report
$trace-cmd report > tcpdump.log
$cat tcpdump.log
cpus=24
tcpdump-8782 [008] 3750.758827: funcgraph_entry: 1.753 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758831: funcgraph_entry: 0.409 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758835: funcgraph_entry: 0.305 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758839: funcgraph_entry: 0.302 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758846: funcgraph_entry: 0.306 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758860: funcgraph_entry: 0.310 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758963: funcgraph_entry: 0.424 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758964: funcgraph_entry: 0.299 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758966: funcgraph_entry: 0.291 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759002: funcgraph_entry: 0.304 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759003: funcgraph_entry: 0.294 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759012: funcgraph_entry: 0.305 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759013: funcgraph_entry: | aa_sk_perm() {
Netlink Monitor-4112 [014] 3750.759013: funcgraph_entry: | aa_sk_perm() {
tcpdump-8782 [008] 3750.759013: funcgraph_exit: 0.390 us | }
tcpdump-8782 [008] 3750.759014: funcgraph_entry: 0.296 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759015: funcgraph_entry: 0.283 us | aa_sk_perm();
Netlink Monitor-4112 [014] 3750.759016: funcgraph_exit: 3.802 us | }
avahi-daemon-1626 [010] 3750.759018: funcgraph_entry: 1.884 us | aa_sk_perm();
wpa_supplicant-1652 [002] 3750.759028: funcgraph_entry: 1.878 us | aa_sk_perm();
wpa_supplicant-1652 [002] 3750.759041: funcgraph_entry: 0.258 us | aa_sk_perm();
NetworkManager-1622 [004] 3750.759066: funcgraph_entry: 1.001 us | aa_sk_perm();
systemd-resolve-1362 [012] 3750.759112: funcgraph_entry: 1.523 us | aa_sk_perm();
systemd-resolve-1362 [012] 3750.759118: funcgraph_entry: 0.200 us | aa_sk_perm();
NetworkManager-1622 [004] 3750.759171: funcgraph_entry: 0.292 us | aa_sk_perm();
tcpdump-8782 [008] 3750.776187: funcgraph_entry: 1.290 us | aa_sk_perm();
tcpdump-8782 [008] 3750.776191: funcgraph_entry: 0.569 us | aa_sk_perm();
tcpdump-8782 [008] 3750.777373: funcgraph_entry: | __sys_connect() {
tcpdump-8782 [008] 3750.777374: funcgraph_entry: | security_socket_connect() {
tcpdump-8782 [008] 3750.777375: funcgraph_entry: 0.708 us | apparmor_socket_connect();
tcpdump-8782 [008] 3750.777376: funcgraph_exit: 2.402 us | }
tcpdump-8782 [008] 3750.777389: funcgraph_exit: + 15.839 us | }
.......
-
-
-
Trace kernel function calls triggered by tcpdump
$trace-cmd record -p function_graph \ -l '__sys_connect' \ -l 'sys_connect' \ -l 'security_socket_connect' \ -l 'apparmor_socket_connect' \ -l 'aa_sk_perm' \ -- tcpdump -i lo -
Convert the recorded trace data into a human-readable report
$trace-cmd report > tcpdump.log
$cat tcpdump.log
cpus=24
tcpdump-8782 [008] 3750.758827: funcgraph_entry: 1.753 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758831: funcgraph_entry: 0.409 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758835: funcgraph_entry: 0.305 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758839: funcgraph_entry: 0.302 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758846: funcgraph_entry: 0.306 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758860: funcgraph_entry: 0.310 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758963: funcgraph_entry: 0.424 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758964: funcgraph_entry: 0.299 us | aa_sk_perm();
tcpdump-8782 [008] 3750.758966: funcgraph_entry: 0.291 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759002: funcgraph_entry: 0.304 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759003: funcgraph_entry: 0.294 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759012: funcgraph_entry: 0.305 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759013: funcgraph_entry: | aa_sk_perm() {
Netlink Monitor-4112 [014] 3750.759013: funcgraph_entry: | aa_sk_perm() {
tcpdump-8782 [008] 3750.759013: funcgraph_exit: 0.390 us | }
tcpdump-8782 [008] 3750.759014: funcgraph_entry: 0.296 us | aa_sk_perm();
tcpdump-8782 [008] 3750.759015: funcgraph_entry: 0.283 us | aa_sk_perm();
Netlink Monitor-4112 [014] 3750.759016: funcgraph_exit: 3.802 us | }
avahi-daemon-1626 [010] 3750.759018: funcgraph_entry: 1.884 us | aa_sk_perm();
wpa_supplicant-1652 [002] 3750.759028: funcgraph_entry: 1.878 us | aa_sk_perm();
wpa_supplicant-1652 [002] 3750.759041: funcgraph_entry: 0.258 us | aa_sk_perm();
NetworkManager-1622 [004] 3750.759066: funcgraph_entry: 1.001 us | aa_sk_perm();
systemd-resolve-1362 [012] 3750.759112: funcgraph_entry: 1.523 us | aa_sk_perm();
systemd-resolve-1362 [012] 3750.759118: funcgraph_entry: 0.200 us | aa_sk_perm();
NetworkManager-1622 [004] 3750.759171: funcgraph_entry: 0.292 us | aa_sk_perm();
tcpdump-8782 [008] 3750.776187: funcgraph_entry: 1.290 us | aa_sk_perm();
tcpdump-8782 [008] 3750.776191: funcgraph_entry: 0.569 us | aa_sk_perm();
tcpdump-8782 [008] 3750.777373: funcgraph_entry: | __sys_connect() {
tcpdump-8782 [008] 3750.777374: funcgraph_entry: | security_socket_connect() {
tcpdump-8782 [008] 3750.777375: funcgraph_entry: 0.708 us | apparmor_socket_connect();
tcpdump-8782 [008] 3750.777376: funcgraph_exit: 2.402 us | }
tcpdump-8782 [008] 3750.777389: funcgraph_exit: + 15.839 us | }
.......
Hi @Jinseok, Thank you for the great sharing!
-