Linux kernel Bug Fixing Summer 2025 Journey
Starting, motivation and initial journey
When I joined the LXF Mentorship Program – Linux Kernel Bug-Fixing Summer 2025, I wasn’t quite sure what to expect. I knew I would be working with the Linux kernel, fixing bugs, interacting with mentors and fellow mentees, and contributing to a large opensource community. I had submitted some patches to the Linux kernel before, but those were mostly cosmetic changes to fix build errors with the newer GCC release.
Working at SUSE has often brought me face to face with complex kernel crashes and debugging challenges. That experience sparked a desire to truly understand the Linux kernel at a deeper level. So, as part of both my personal learning journey and professional growth, I decided to join the LXF Mentorship Program to strengthen my skills in kernel development.
Receiving the acceptance email from Shuah Khan was incredibly exciting, it marked the official start of my kernel journey in June. The first month was somewhat overwhelming as I focused on setting up my development and testing environments. I primarily used QEMU and Buildroot to reproduce and analyze kernel crashes reported by Syzkaller. For certain cases, I relied on a Debian VM, which proved especially useful when working on eBPF related bugs. I will try to expand on this in the later sections.
Working with the community, and submitting my first patch
With my environment ready, I was all set to start contributing, but reality hit fast; I didn’t know where to begin. The kernel was vast, and I wasn’t yet familiar with any particular subsystem. After exploring LKML threads and kernel documentation, I decided to start small by submitting cosmetic patches to learn the process.
At that time, there was a major effort underway to replace all uses of
the unsafe strcpy() function with its safer counterpart, strscpy().
That seemed like a great place to start. After grepping through the
tree, I sent my very first patch:
f00de8e82cab ALSA: ctxfi: Replace deprecated strcpy() with strscpy()
To my surprise, it was reviewed and merged by my co-worker, Takashi Iwai, whom I later learned is the maintainer of the sound subsystem.
I soon followed up with several other cleanup patches across different parts of the kernel, including:
99e9c5ffbbee net: intel: fm10k: Fix parameter idx set but not used
f117eca965c7 drm/amd/display: clean-up dead code in dml2_mall_phantom
260dcf5b06d5 drm/radeon/r600_cs: clean up of dead code in r600_cs
3193e8942fc7 samples: fix building fs-monitor on musl systems
164299ba1176 btrfs: replace strcpy() with strscpy()
239df3e4b475 samples: mei: Fix building on musl libc
970f8a17c9c8 samples/landlock: Fix building on musl libc
Focusing on eBPF
After spending several months fixing build errors, I realized that I was starting to drift away from my original goal of deepening my understanding of the Linux kernel’s inner workings. To get back on track, I decided to focus on a specific subsystem and tackle real bugs reported by Syzkaller.
Naturally, I gravitated toward eBPF a sub-section that had interested me for quite some time. So, I began exploring Syzkaller’s reports related to the BPF subsystem and came across this bug report d36d5ae81e1b0a53ef58; general protection fault in print_reg_state
At that stage, my understanding of eBPF internals was still developing, and my first patch attempt to fix the issue missed the mark. The eBPF Developers quickly and kindly pointed out the mistake during review, which was a valuable learning experience. Their feedback helped me better understand how the BPF verifier operates and how subtle logic errors can cause verification failures.
Using GDB and QEMU, I went through the reproducer step by step to trace
the exact cause of the bug. I learned that before any eBPF program can
run, it must first pass a strict verification phase handled primarily in
kernel/bpf/verifier.c. This file contains a series of functions that
validate BPF instructions, ensuring they don’t perform unsafe or
invalid operations inside the kernel. One of the key functions in this
process is check_alu_op, which verifies arithmetic and logical
operations (such as BPF_ADD, BPF_SUB, BPF_NEG, and others)
to ensure they are legal for the given register types.
In check_alu_op, the verifier would call check_reg_arg and
adjust_scalar_min_max_vals unconditionally for BPF_NEG operations.
However, if the destination register holds a pointer, these scalar
adjustments are unnecessary and potentially incorrect.
In check_alu_op, we were calling adjust_scalar_min_max_vals when we
get a BPF_NEG as opcode. Which has a call to __mark_reg_known when
opcode is BPF_NEG. And __mark_reg_known clears map_ptr with
/* Clear off and union(map_ptr, range) */
memset(((u8 *)reg) + sizeof(reg->type), 0,
offsetof(struct bpf_reg_state, var_off) - sizeof(reg->type));
Thus, when we would later try to log or use map_ptr, it would result
in a null pointer dereference.
My patch, or the final version of the patch, adds a check to skip the adjustment logic when the destination register contains a pointer.
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -15645,7 +15645,8 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
}
/* check dest operand */
- if (opcode == BPF_NEG) {
+ if (opcode == BPF_NEG &&
+ regs[insn->dst_reg].type == SCALAR_VALUE) {
err = check_reg_arg(env, insn->dst_reg, DST_OP_NO_MARK);
err = err ?: adjust_scalar_min_max_vals(env, insn,
®s[insn->dst_reg],
With encouragement from the developer, I added a self-test, and finally, it was done. With Ack from developers, my first actual fix was merged.
8709c1685220 selftests/bpf: Add test for BPF_NEG alu on CONST_PTR_TO_MAP
34904582b502 bpf: Skip scalar adjustment for BPF_NEG if dst is a pointer
Now, with a better understanding of eBPF, I proceeded to send in a few more patches that were eventually merged into the kernel.
a1e83d4c0361 selftests/bpf: Fix redefinition of 'off' as different kind of symbol
7c33e97a6ef5 bpf: Do not disable preemption in bpf_test_run().
I would like to note that 7c33e97a6ef5 was a collaborative effort with another LFX mentee
Moving forward
After submitting my last few eBPF patches, I gradually slowed down on actively working on Syzkaller bugs. I still contributed occasionally patches, but not with the same pace or intensity as before, mainly due to a mix of professional commitments and personal priorities that needed my attention.
Now that those commitments have wrapped up and I have more free time, I’m eager to continue my journey in kernel development. The mentorship program has given me both the confidence and the curiosity to keep exploring various sub-systems of the kernel, and I look forward to contributing more meaningfully to the community in the future.
This mentorship has been an incredible learning experience, one that reshaped how I look at opensource development. From my first tiny cosmetic patch to diving deep into eBPF internals, every step felt like progress. I’m deeply grateful to my mentors, peers, and reviewers who guided me along the way. With a stronger foundation and renewed motivation, I look forward to continuing this journey, one patch at a time.
My contributions since the start of mentorship
- a1e83d4c0361 selftests/bpf: Fix redefinition of ‘off’ as different kind of symbol
- 7c33e97a6ef5 bpf: Do not disable preemption in bpf_test_run().
- 8709c1685220 selftests/bpf: Add test for BPF_NEG alu on CONST_PTR_TO_MAP
- 34904582b502 bpf: Skip scalar adjustment for BPF_NEG if dst is a pointer
- 99e9c5ffbbee net: intel: fm10k: Fix parameter idx set but not used
- 1beee8d0c263 drm/tegra: hdmi: sor: Fix error: variable ‘j’ set but not used
- f117eca965c7 drm/amd/display: clean-up dead code in dml2_mall_phantom
- 260dcf5b06d5 drm/radeon/r600_cs: clean up of dead code in r600_cs
- 3193e8942fc7 samples: fix building fs-monitor on musl systems
- 164299ba1176 btrfs: replace strcpy() with strscpy()
- 239df3e4b475 samples: mei: Fix building on musl libc
- 970f8a17c9c8 samples/landlock: Fix building on musl libc
- f00de8e82cab ALSA: ctxfi: Replace deprecated strcpy() with strscpy()
Signed-off-by: Brahmajit Das <listout@listout.xyz>